Fix memory leak issues
[platform/core/uifw/anthy.git] / test / main.c
1 /* ¥é¥¤¥Ö¥é¥ê¤Î´Ø¿ô¸Æ¤Ó½Ð¤·¤Î¥Æ¥¹¥È
2  *
3  * ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¡¢test.txt¤«¤é1¹Ô¤º¤ÄÆɤ߹þ¤ó¤ÇÊÑ´¹¤ò¹Ô¤¦¡£
4  * ÊÑ´¹Á°¤Îʸ»úÎó¤ÈÊÑ´¹¤ò¹Ô¤Ã¤¿·ë²Ì¤òtest.exp¤«¤éõ¤·¡¢
5  * ÊÑ´¹·ë²Ì¤¬¹ç¤Ã¤Æ¤¤¤ë¤«¤ò¥«¥¦¥ó¥È¤·¤ÆºÇ¸å¤Ë½ÐÎϤ¹¤ë¡£
6  *
7  * ./anthy --from 1 --to 10 ¤Î¤è¤¦¤Ë¼Â¹Ô¤¹¤ë¤Ètest.txt¤ÎºÇ½é¤Î10¸Ä¤Î
8  *  ¹Ô¤ÎÊÑ´¹¥Æ¥¹¥È¤¬¹Ô¤ï¤ì¤Þ¤¹¡£
9  *
10  * --ask¥ª¥×¥·¥ç¥ó¤òÉÕ¤±¤Æ¼Â¹Ô¤¹¤ë¤È¡¢·ë²Ì¤¬¹ç¤Ã¤Æ¤¤¤ë¤«¤ÎȽÃǤò
11  * ÀßÄꤹ¤ë¥â¡¼¥É¤Ë¤Ê¤ë¤Î¤Ç¡¢É½¼¨¤µ¤ì¤¿·ë²Ì¤ËÂФ¹¤ëȽÃǤò
12  * É¸½àÆþÎϤ«¤é'y', 'n', 'd', 'q'¤ÇÆþÎϤ·¤Æ¤¯¤À¤µ¤¤¡£
13  * 'd' dont care, 'q' quit
14  * È½ÃǤǤ­¤Ê¤¤¾ì¹ç¤Ï¤½¤Î¾¤Îʸ»ú¤òÆþÎϤ·¤Æ¤¯¤À¤µ¤¤¡£
15  *
16  * Copyright (C) 2000-2006 TABATA Yusuke
17  * Copyright (C) 2004-2006 YOSHIDA Yuichi
18  * Copyright (C) 2001-2002 TAKAI Kosuke
19  *
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <time.h>
26
27 #include <anthy/anthy.h>
28 #include <anthy/convdb.h>
29 #include <config.h>
30
31 /* Makefile ¤Î $(srcdir) (ÀÅŪ¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤Î´ð½à¥Ç¥£¥ì¥¯¥È¥ê) */
32 #ifndef SRCDIR
33 # define SRCDIR "."
34 #endif
35 /* ¥Ó¥ë¥É»þ¤Î¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê (¤³¤³¤Ë .anthy ¤òºî¤ë) */
36 #ifndef TEST_HOME
37 # define TEST_HOME "."          /* FIXME: ¼ÂºÝ¤ÏÁêÂХѥ¹¤À¤È¸íÆ°ºî¤¹¤ë */
38 #endif
39
40 /* ¥Æ¥¹¥È¥Ç¡¼¥¿¤È¤Ê¤ëÊÑ´¹Á°¤Îʸ»úÎó */
41 #define TESTDATA "test.txt"
42 const char *testdata = SRCDIR "/" TESTDATA;
43
44 /* ÊÑ´¹¸å¤Îʸ»úÎó¤¬ÂÅÅö¤«¤É¤¦¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë¤¿¤á¤Î¥Ç¡¼¥¿ */
45 #define EXPDATA "test.exp"
46 const char *expdata = SRCDIR "/" EXPDATA;
47
48 struct input {
49   char *str;
50   int serial;
51 };
52
53 /* ¥Æ¥¹¥È¤ò¹Ô¤¦¾ò·ï */
54 struct condition {
55   /* conversion condition */
56   int serial;
57   int from;
58   int to;
59   /* operation */
60   int ask;
61   int quiet;
62   int miss_only;
63   int use_utf8;
64 };
65
66 static int
67 read_file(FILE *fp, struct input *in)
68 {
69   char buf[256];
70   while(fgets(buf, 256, fp)) {
71     switch(buf[0]){
72     case '#':
73     case ':':
74     case '-':
75       break;
76     case '*':
77       if (in->str) {
78         free(in->str);
79         in->str = 0;
80       }
81       buf[strlen(buf)-1] = 0;
82       in->str = strdup(&buf[1]);
83       in->serial ++;
84       return 0;
85       break;
86     }
87   }
88   return -1;
89 }
90
91 static int
92 check_cond(struct condition *cond, struct input *in)
93 {
94   if (in->serial == cond->serial) {
95     return 1;
96   }
97   if (in->serial <= cond->to && in->serial >= cond->from) {
98     return 1;
99   }
100   return 0;
101 }
102
103 static void
104 log_print(int lv, const char *msg)
105 {
106   printf("log:%d:%s\n", lv, msg);
107 }
108
109 static anthy_context_t
110 init_lib(int use_utf8)
111 {
112   anthy_context_t ac;
113   /* ´û¤Ë¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤Î±Æ¶Á¤ò¼õ¤±¤Ê¤¤¤è¤¦¤Ë¤¹¤ë */
114   anthy_conf_override("CONFFILE", "../anthy-conf");
115   anthy_conf_override("HOME", TEST_HOME);
116   anthy_conf_override("DIC_FILE", "../mkanthydic/anthy.dic");
117   anthy_set_logger(log_print, 0);
118   if (anthy_init()) {
119     printf("failed to init anthy\n");
120     exit(0);
121   }
122   anthy_set_personality("");
123
124   ac = anthy_create_context();
125   if (use_utf8) {
126     anthy_context_set_encoding(ac, ANTHY_UTF8_ENCODING);
127   } else {
128     anthy_context_set_encoding(ac, ANTHY_EUC_JP_ENCODING);
129   }
130   return ac;
131 }
132
133 static void
134 print_usage(void)
135 {
136   printf("Anthy "VERSION"\n"
137          "./anthy [test-id]\n"
138          " For example.\n"
139          "  ./anthy 1\n"
140          "  ./anthy --to 100\n"
141          "  ./anthy --from 10 --to 100\n"
142          "  ./anthy --all --print-miss-only --ask\n"
143          "  ./anthy --ll 1\n\n");
144   exit(0);
145 }
146
147 static void
148 parse_args(struct condition *cond, int argc, char **argv)
149 {
150   int i;
151   char *arg;
152   for (i = 1; i < argc; i++) {
153     arg = argv[i];
154     if (!strncmp(arg, "--", 2)) {
155       arg = &arg[2];
156       if (!strcmp(arg, "help") || !strcmp(arg, "version")) {
157         print_usage();
158       }
159       if (!strcmp(arg, "all")) {
160         cond->from = 0;
161         cond->to = 100000000;
162       } else if (!strcmp(arg, "quiet")) {
163         cond->quiet = 1;
164       } else if (!strcmp(arg, "ask") ||
165                  !strcmp(arg, "query")) {
166         cond->ask = 1;
167       } else if (!strcmp(arg, "print-miss-only")) {
168         cond->miss_only = 1;
169       } else if (!strcmp(arg, "utf8")) {
170         cond->use_utf8 = 1;
171       }
172
173       if (i + 1 < argc) {
174         if (!strcmp(arg, "from")){
175           cond->from = atoi(argv[i+1]);
176           i++;
177         }else if (!strcmp(arg, "to")){
178           cond->to = atoi(argv[i+1]);
179           i++;
180         }else if (!strcmp(arg, "ll")) {
181           anthy_set_logger(NULL, atoi(argv[i+1]));
182           i++;
183         }
184       }
185     } else {
186       int num = atoi(arg);
187       if (num) {
188         cond->serial = num;
189       } else {
190         char *buf = alloca(strlen(SRCDIR)+strlen(arg) + 10);
191         sprintf(buf, SRCDIR "/%s.txt", arg);
192         testdata = strdup(buf);
193       }
194     }
195   }
196 }
197
198 static void
199 print_run_env(void)
200 {
201   time_t t;
202   const char *env;
203   env = getenv("ANTHY_ENABLE_DEBUG_PRINT");
204   if (!env) {
205     env = "";
206   }
207   printf("ANTHY_ENABLE_DEBUG_PRINT=(%s)\n", env);
208   env = getenv("ANTHY_SPLITTER_PRINT");
209   if (!env) {
210     env = "";
211   }
212   printf("ANTHY_SPLITTER_PRINT=(%s)\n", env);
213   printf("SRCDIR=(%s)\n", SRCDIR);
214   t = time(&t);
215   printf(PACKAGE "-" VERSION " %s", ctime(&t));
216 }
217
218 static void
219 sum_up(struct res_db *db, struct conv_res *cr)
220 {
221   int is_split;
222   struct res_stat *rs;
223   cr->used = 1;
224   db->total ++;
225   if (cr->res_str[0] == '|') {
226     rs = &db->split;
227     is_split = 1;
228   } else {
229     rs = &db->res;
230     is_split = 0;
231   }
232   if (cr->check == CHK_OK) {
233     rs->ok ++;
234   } else if (cr->check == CHK_MISS) {
235     rs->miss ++;
236   } else if (cr->check == CHK_DONTCARE) {
237     rs->dontcare ++;
238   } else {
239     rs->unknown ++;
240   }
241 }
242
243 static void
244 set_string(struct condition *cond, struct res_db *db,
245            struct input *in, anthy_context_t ac)
246 {
247   struct conv_res *cr1, *cr2;
248   int pr;
249
250   anthy_set_string(ac, in->str);
251
252   /* result */
253   cr1 = find_conv_res(db, ac, in->str, 1);
254   sum_up(db, cr1);
255   /* split */
256   cr2 = find_conv_res(db, ac, in->str, 0);
257   sum_up(db, cr2);
258
259   /**/
260   pr = 0;
261   if (cond->miss_only) {
262     if (cr1->check == CHK_MISS ||
263         cr2->check == CHK_MISS) {
264       pr = 1;
265     }
266   } else if (!cond->quiet) {
267     pr = 1;
268   }
269
270   if (pr) {
271     printf("%d:(%s)\n", in->serial, in->str);
272     anthy_print_context(ac);
273   }
274   anthy_reset_context(ac);
275 }
276
277
278 static void
279 dump_res(FILE *fp, struct conv_res *r)
280 {
281   fprintf(fp, "%s %s ", r->src_str, r->res_str);
282   if (r->check == CHK_MISS) {
283     fprintf(fp, "X");
284   } else if (r->check == CHK_OK) {
285     fprintf(fp, "OK");
286   } else if (r->check == CHK_DONTCARE) {
287     fprintf(fp, "*");
288   } else {
289     fprintf(fp, "?");
290   }
291   fprintf(fp, "\n");
292 }
293
294 static void
295 save_db(const char *fn, struct res_db *db)
296 {
297   FILE *fp = fopen(fn, "w");
298   struct conv_res *cr;
299   if (!fp) {
300     printf("failed to open (%s) to write\n", fn);
301     return ;
302   }
303   for (cr = db->res_list.next; cr; cr = cr->next) {
304     dump_res(fp, cr);
305   }
306   fclose(fp);
307 }
308
309 static void
310 ask_results(struct res_db *db)
311 {
312   struct conv_res *cr;
313   for (cr = db->res_list.next; cr; cr = cr->next) {
314     if (cr->check == CHK_UNKNOWN && cr->used == 1) {
315       char buf[256];
316       printf("%s -> %s (y/n/d/q)\n", cr->src_str, cr->res_str);
317       fgets(buf, 256, stdin);
318       if (buf[0] == 'y') {
319         cr->check = CHK_OK;
320       } else if (buf[0] == 'n') {
321         cr->check = CHK_MISS;
322       } else if (buf[0] == 'd') {
323         cr->check = CHK_DONTCARE;
324       } else if (buf[0] == 'q') {
325         return ;
326       }
327     }
328   }
329 }
330
331 static void
332 show_stat(struct res_db *db)
333 {
334   struct res_stat *rs;
335   int i;
336   /**/
337   printf("%d items\n", db->total);
338   for (i = 0; i < 2; i++) {
339     if (i == 0) {
340       printf("conversion result\n");
341       rs = &db->res;
342     } else {
343       printf("split result\n");
344       rs = &db->split;
345     }
346     printf("ok : %d\n", rs->ok);
347     printf("miss : %d\n", rs->miss);
348     printf("unknown : %d\n", rs->unknown);
349     printf("\n");
350   }
351 }
352
353 static void
354 init_condition(struct condition *cond)
355 {
356   cond->serial = 0;
357   cond->from = 0;
358   cond->to = 0;
359   /**/
360   cond->quiet = 0;
361   cond->ask = 0;
362   cond->miss_only = 0;
363   cond->use_utf8 = 0;
364 }
365
366 int
367 main(int argc,char **argv)
368 {
369   anthy_context_t ac;
370   FILE *fp;
371   struct input cur_input;
372   struct res_db *db;
373   struct condition cond;
374
375   cur_input.serial = 0;
376   cur_input.str = 0;
377   init_condition(&cond);
378
379   parse_args(&cond, argc, argv);
380   db = create_db();
381   read_db(db, expdata);
382
383   printf("./test_anthy --help to print usage.\n");
384
385   print_run_env();
386
387   fp = fopen(testdata, "r");
388   if (!fp) {
389     printf("failed to open %s.\n", testdata);
390     return 0;
391   }
392   
393   ac = init_lib(cond.use_utf8);
394
395   /* ¥Õ¥¡¥¤¥ë¤òÆɤó¤Ç¤¤¤¯¥ë¡¼¥× */
396   while (!read_file(fp, &cur_input)) {
397     if (check_cond(&cond, &cur_input)) {
398       set_string(&cond, db, &cur_input, ac);
399     }
400   }
401
402   anthy_release_context(ac);
403   anthy_quit();
404
405   if (cond.ask) {
406     /* ¥æ¡¼¥¶¤Ëʹ¤¯ */
407     ask_results(db);
408   }
409
410   show_stat(db);
411   save_db(expdata, db);
412
413   return 0;
414 }