1 /* Copyright (c) 2013 - The libcangjie authors.
2 *
3 * This file is part of libcangjie.
4 *
5 * libcangjie is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * libcangjie is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with libcangjie. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20 #include <getopt.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <libgen.h>
24
25 #include <cangjie.h>
26
27
28
29 typedef enum CangjieCliMode {
30 CANGJIE_CLI_MODE_CODE = 0,
31 CANGJIE_CLI_MODE_SHORTCODE = 1,
32 CANGJIE_CLI_MODE_RADICAL = 2,
33 } CangjieCliMode;
34
35
usage(char * progname)36 void usage(char *progname) {
37 printf("Usage: %s [OPTIONS]... CODE\n", basename(progname));
38 printf("A CLI interface of libcangjie cangjie code query\n\n");
39 printf("-f, --filter=FILTER1,FILTER2... specify the filters used in the query\n");
40 printf(" default: big5,hkscs\n");
41 printf(" acceptable values:\n");
42 printf(" big5, hkscs, punctuation, chinese,\n");
43 printf(" zhuyin, kanji, katakana, hiragana,\n");
44 printf(" symbols\n");
45 printf("-m, --mode=MODE specify the mode of query\n");
46 printf(" default: code\n");
47 printf(" acceptable values:\n");
48 printf(" code, shortcode, radical\n");
49 printf("-C, --cj-version=VERSION specify the version of Cangjie used\n");
50 printf(" default: 3\n");
51 printf(" acceptable values: 3, 5\n");
52 printf("-h, --help print this help message and leave\n");
53 printf("\nFor complete documentation, please go to our website: \n");
54 printf("<http://cangjians.github.io/>\n");
55 }
56
57
print_error(char * msg)58 void print_error(char *msg) {
59 printf("libcangjie_cli: %s\n", msg);
60 printf("Try 'libcangjie_cli --help' for more information\n");
61 }
62
63
main(int argc,char ** argv)64 int main(int argc, char **argv) {
65 char *code;
66 Cangjie *cj;
67 int ret;
68 CangjieCharList *chars;
69 CangjieCharList *iter;
70 CangjieChar *c;
71
72 // variables to parse options
73 int opt;
74 int option_index;
75
76 // option flags
77 int opt_filter;
78 CangjieCliMode opt_mode;
79 int opt_cj_version;
80
81 // helper variable(s)
82 char errmsg[255];
83 char *code_ptr;
84 char *ptr_radical;
85
86 // available options
87 static struct option long_options[] = {
88 {"filter", required_argument, 0, 'f'},
89 {"mode", required_argument, 0, 'm'},
90 {"cj-version", required_argument, 0, 'C'},
91 {"help", no_argument, 0, 'h'},
92 {0, 0, 0, 0},
93 };
94
95 // default options
96 opt_filter = CANGJIE_FILTER_BIG5 | CANGJIE_FILTER_HKSCS;
97 opt_mode = CANGJIE_CLI_MODE_CODE;
98 opt_cj_version = CANGJIE_VERSION_3;
99
100 // read options
101 while (1) {
102 option_index = 0;
103 opt = getopt_long(argc, argv, "f:m:C:h", long_options, &option_index);
104
105 if (opt == -1) {
106 break;
107 }
108
109 switch (opt) {
110 case 'f':
111 opt_filter = 0;
112 if (strstr(optarg, "big5") != NULL) {
113 opt_filter = opt_filter | CANGJIE_FILTER_BIG5;
114 }
115 if (strstr(optarg, "hkscs") != NULL) {
116 opt_filter = opt_filter | CANGJIE_FILTER_HKSCS;
117 }
118 if (strstr(optarg, "punctuation") != NULL) {
119 opt_filter = opt_filter | CANGJIE_FILTER_PUNCTUATION;
120 }
121 if (strstr(optarg, "chinese") != NULL) {
122 opt_filter = opt_filter | CANGJIE_FILTER_CHINESE;
123 }
124 if (strstr(optarg, "zhuyin") != NULL) {
125 opt_filter = opt_filter | CANGJIE_FILTER_ZHUYIN;
126 }
127 if (strstr(optarg, "kanji") != NULL) {
128 opt_filter = opt_filter | CANGJIE_FILTER_KANJI;
129 }
130 if (strstr(optarg, "katakana") != NULL) {
131 opt_filter = opt_filter | CANGJIE_FILTER_KATAKANA;
132 }
133 if (strstr(optarg, "hiragana") != NULL) {
134 opt_filter = opt_filter | CANGJIE_FILTER_HIRAGANA;
135 }
136 if (strstr(optarg, "symbols") != NULL) {
137 opt_filter = opt_filter | CANGJIE_FILTER_SYMBOLS;
138 }
139 if (opt_filter == 0) {
140 sprintf(errmsg, "Invalid filter option '%s'", optarg);
141 print_error(errmsg);
142 return -1;
143 }
144 break;
145 case 'm':
146 if (strcmp(optarg, "code") == 0) {
147 opt_mode = CANGJIE_CLI_MODE_CODE;
148 } else if (strcmp(optarg, "shortcode") == 0) {
149 opt_mode = CANGJIE_CLI_MODE_SHORTCODE;
150 } else if (strcmp(optarg, "radical") == 0) {
151 opt_mode = CANGJIE_CLI_MODE_RADICAL;
152 } else {
153 sprintf(errmsg, "Invalid query mode '%s'", optarg);
154 print_error(errmsg);
155 return -1;
156 }
157 break;
158 case 'C':
159 if (*optarg == '3') {
160 opt_cj_version = CANGJIE_VERSION_3;
161 } else if (*optarg == '5') {
162 opt_cj_version = CANGJIE_VERSION_5;
163 } else {
164 sprintf(errmsg, "Invalid Cangjie version '%s'", optarg);
165 print_error(errmsg);
166 return -1;
167 }
168 break;
169 case '?':
170 printf("Try 'libcangjie_cli --help' for more information\n");
171 return -1;
172 break;
173 case 'h':
174 default:
175 usage(argv[0]);
176 return (opt == 'h') ? 0 : -1;
177 }
178 }
179
180 // check if query provided
181 if (optind == argc) {
182 print_error("missing query code");
183 return -1;
184 }
185
186 code = argv[optind];
187
188 ret = cangjie_new(&cj, opt_cj_version, opt_filter);
189
190 if (ret == CANGJIE_DBOPEN) {
191 printf("Could not open the Cangjie database\n");
192 return ret;
193 } else if (ret != CANGJIE_OK) {
194 printf("Unhandled error while creating the Cangjie object: %d\n", ret);
195 return ret;
196 }
197
198
199 if (opt_mode == CANGJIE_CLI_MODE_RADICAL) {
200 code_ptr = code;
201 for (; *code_ptr != '\0'; code_ptr++) {
202 ret = cangjie_get_radical(cj, *code_ptr, &ptr_radical);
203 if (ret == CANGJIE_OK) {
204 printf("code: '%c', radical: '%s'\n", *code_ptr, ptr_radical);
205 } else {
206 printf("Query error (%d)\n", ret);
207 return ret;
208 }
209 }
210 return ret;
211 } else {
212 if (opt_mode == CANGJIE_CLI_MODE_CODE) {
213 ret = cangjie_get_characters(cj, code, &chars);
214 } else if (opt_mode == CANGJIE_CLI_MODE_SHORTCODE) {
215 ret = cangjie_get_characters_by_shortcode(cj, code, &chars);
216 }
217
218 if (ret == CANGJIE_NOCHARS) {
219 printf("No chars with code '%s'\n", code);
220
221 cangjie_free(cj);
222 return CANGJIE_NOCHARS;
223 } else if (ret == CANGJIE_INVALID) {
224 printf("Invalid code '%s'\n", code);
225
226 cangjie_free(cj);
227 return CANGJIE_INVALID;
228 } else if (ret != CANGJIE_OK) {
229 printf("Other error %d with code '%s'\n", ret, code);
230
231 cangjie_free(cj);
232 return ret;
233 }
234
235 iter = chars;
236
237 while (1) {
238 if (iter == NULL) {
239 break;
240 }
241
242 c = iter->c;
243 printf("Char: %s, code: '%s', classic frequency: %d\n",
244 c->chchar, c->code, c->frequency);
245
246 iter = iter->next;
247 }
248
249 cangjie_char_list_free(chars);
250 }
251
252 cangjie_free(cj);
253
254 return CANGJIE_OK;
255 }
256