Applied fPIE, pie compier option
[platform/core/uifw/anthy.git] / src-worddic / record.c
1 /*
2  * ³Ø½¬¤ÎÍúÎò¤Ê¤É¤ò´ÉÍý¤¹¤ë¤¿¤á¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹
3  * Ê¸»úÎó(xstr)¤ò¥­¡¼¤Ë¤·¤Æ¹â®¤Ë¹Ô(row)¤ò¸¡º÷¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡¥
4  * Ê£¿ô¤Î¥»¥¯¥·¥ç¥ó¤ò¤â¤Ä¤³¤È¤¬¤Ç¤­¡¤³Ø½¬¤Î°ã¤¦¥Õ¥§¡¼¥º¤Ê¤É¤ËÂбþ¤¹¤ë
5  *  (¥»¥¯¥·¥ç¥ó * Ê¸»úÎó -> ¹Ô)
6  * ³Æ¹Ô¤Ïʸ»úÎ󤫿ô¤ò»ý¤ÄÇÛÎó¤Ë¤Ê¤Ã¤Æ¤¤¤ë
7  *
8  * ¡Ö¥Ñ¥È¥ê¥·¥¢¡¦¥È¥é¥¤¡×¤È¤¤¤¦¥Ç¡¼¥¿¹½Â¤¤ò»ÈÍѤ·¤Æ¤¤¤ë¡£
9  * ¼«Á³¸À¸ì¤Î¸¡º÷¤Ê¤É¤ò°·¤Ã¤Æ¤¤¤ë¶µ²Ê½ñ¤ò»²¾È¤Î¤³¤È
10  */
11 /*
12   This library is free software; you can redistribute it and/or
13   modify it under the terms of the GNU Lesser General Public
14   License as published by the Free Software Foundation; either
15   version 2 of the License, or (at your option) any later version.
16
17   This library is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20   Lesser General Public License for more details.
21
22   You should have received a copy of the GNU Lesser General Public
23   License along with this library; if not, write to the Free Software
24   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
25  */
26 /*
27  * Funded by IPA̤Ƨ¥½¥Õ¥È¥¦¥§¥¢ÁϤ»ö¶È 2002 1/18
28  * Funded by IPA̤Ƨ¥½¥Õ¥È¥¦¥§¥¢ÁϤ»ö¶È 2005
29  * Copyright (C) 2005 YOSHIDA Yuichi
30  * Copyright (C) 2000-2006 TABATA Yusuke
31  * Copyright (C) 2000-2003 UGAWA Tomoharu
32  * Copyright (C) 2001-2002 TAKAI Kosuke
33  */
34 /*
35  * ¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£""¤Ïƿ̾¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£¤Ç¤¢¤ê¡¤
36  * ¥Õ¥¡¥¤¥ë¤Ø¤ÎÆɤ߽ñ¤­¤Ï¹Ô¤ï¤Ê¤¤¡¥
37  */
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45
46 #include "config.h"
47 #include <anthy/anthy.h>
48 #include <anthy/dic.h>
49 #include <anthy/alloc.h>
50 #include <anthy/conf.h>
51 #include <anthy/ruleparser.h>
52 #include <anthy/record.h>
53 #include <anthy/logger.h>
54 #include <anthy/prediction.h>
55
56 #include "dic_main.h"
57 #include "dic_personality.h"
58
59 /* ¸Ä¿Í¼­½ñ¤ò¥»¡¼¥Ö¤¹¤ë¥Õ¥¡¥¤¥ë̾¤Îsuffix */
60 #define ENCODING_SUFFIX ".utf8"
61
62
63 enum val_type {
64   RT_EMPTY, RT_VAL, RT_XSTR, RT_XSTRP
65 };
66
67 /* ÃÍ */
68 struct record_val {
69   enum val_type type;
70   union {
71     xstr str;
72     int val;
73     xstr* strp;
74   } u;
75 };
76
77 /* ¹Ô */
78 struct record_row {
79   xstr key;
80   int nr_vals;
81   struct record_val *vals;
82 };
83
84 /* trie node´ÉÍýÍÑ */
85 struct trie_node {
86   struct trie_node *l;
87   struct trie_node *r;
88   int bit;
89   struct record_row row;
90   struct trie_node *lru_prev, *lru_next; /* Î¾Ã¼¥ë¡¼¥× */
91   int dirty; /* LRU ¤Î¤¿¤á¤Î used, sused ¥Ó¥Ã¥È */
92 };
93
94 /* trie tree¤Îroot */
95 struct trie_root {
96   struct trie_node root;
97   allocator node_ator;
98 };
99
100 #define LRU_USED  0x01
101 #define LRU_SUSED 0x02
102 #define PROTECT   0x04 /* º¹Ê¬½ñ¤­½Ð¤·»þ¤Ë»È¤¦(LRU¤È¤Ï´Ø·¸¤Ê¤¤)
103                         *   º¹Ê¬½ñ¤­½Ð¤·¤Ç¤Ï¡¢¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹Á°¤Ë
104                         *   ¥Õ¥¡¥¤¥ë¾å¤Ë¾¤Î¥×¥í¥»¥¹¤¬µ­Ï¿¤·¤¿¹¹¿·¤ò
105                         *   Æɤ߹þ¤à¡£¤½¤ì¤Ë¤è¤Ã¤Æ¡¢¤³¤ì¤«¤éÄɲä·¤è
106                         *   ¤¦¤È¤¹¤ë¥Î¡¼¥É¤¬¾Ã¤µ¤ì¤ë¤Î¤òËɤ°
107                         */
108 /*
109  * LRU:
110  *   USED:  ¥á¥â¥ê¾å¤Ç»È¤ï¤ì¤¿
111  *   SUSED: Êݸ¤µ¤ì¤¿ used ¥Ó¥Ã¥È
112  *
113  * LRU¥ê¥¹¥È¾å¤Ç¤Ï¡¢ USED ¤Ïɬ¤º¥ê¥¹¥ÈÀèƬ¤Ëʤó¤Ç¤¤¤ë¤¬¡¢ SUSED ¤Ï
114  * ¥Õ¥é¥°¤Ê¤·¤Î¥Î¡¼¥É¤Èº®ºß¤·¤Æ¤¤¤ë²ÄǽÀ­¤¬¤¢¤ë¡£
115  *
116  * n¸Ä¤ò»Ä¤¹¤è¤¦¤Ë»ØÄꤵ¤ì¤¿»þ¤ÎÆ°ºî
117  *    1. used > n
118  *        LRU ¥ê¥¹¥È¤ÎÀèƬ¤«¤é n ÈÖÌܰʹߤò¾Ã¤¹
119  *    2. used + sused > n
120  *        used -> »Ä¤¹
121  *        sused -> sused ¥Õ¥é¥°¤òÍ
122  *        ¤½¤ì°Ê³° -> ¾Ã¤¹
123  *    3. ¤½¤ì°Ê³°
124  *        Á´¤Æ»Ä¤¹
125  * ¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹»þ¤Ë¡¢ used || sused -> sused ¤È¤·¤Æ½ñ¤­½Ð¤¹
126  */
127
128 /** ¥»¥¯¥·¥ç¥ó */
129 struct record_section {
130   const char *name;
131   struct trie_root cols;
132   struct record_section *next;
133   int lru_nr_used, lru_nr_sused; /* LRU ÍÑ */
134 };
135
136 /** ¥Ç¡¼¥¿¥Ù¡¼¥¹ */
137 struct record_stat {
138   struct record_section section_list; /* section¤Î¥ê¥¹¥È*/
139   struct record_section *cur_section;
140   struct trie_root xstrs; /* xstr ¤ò intern ¤¹¤ë¤¿¤á¤Î trie */
141   struct trie_node *cur_row;
142   int row_dirty; /* cur_row ¤¬Êݸ¤ÎɬÍפ¬¤¢¤ë¤« */
143   int encoding;
144   /**/
145   int is_anon;
146   const char *id;         /* ¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£¤Îid */
147   char *base_fn; /* ´ðËÜ¥Õ¥¡¥¤¥ë ÀäÂХѥ¹ */
148   char *journal_fn; /* º¹Ê¬¥Õ¥¡¥¤¥ë ÀäÂХѥ¹ */
149   /**/
150   time_t base_timestamp; /* ´ðËÜ¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥× */
151   int last_update;  /* º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ¸å¤ËÆɤó¤À°ÌÃÖ */
152   time_t journal_timestamp; /* º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥× */
153 };
154
155 /* º¹Ê¬¤¬100KB±Û¤¨¤¿¤é´ðËÜ¥Õ¥¡¥¤¥ë¤Ø¥Þ¡¼¥¸ */
156 #define FILE2_LIMIT 102400
157
158
159 /*
160  * xstr ¤Î intern:
161  *  ¸Ä¿Í¤´¤È( record_stat ¤´¤È)¤Ëʸ»úÎó¤ò intern ¤¹¤ë¡£¤³¤ì¤Ï¡¢
162  *  ¥á¥â¥ê¤ÎÀáÌó¤Î¾¤Ë¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush »þ¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ë
163  *  Í³Í褹¤ë xstr ¤¬Ìµ¸ú¤Ë¤Ê¤ë¤Î¤òËɤ°ÌÜŪ¤¬¤¢¤ë¡£
164  *  ¤·¤¿¤¬¤Ã¤Æ¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush »þ¤Ç¤â xstr ¤Î intern ÍÑ
165  *  ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹ xstrs ¤Ï¤½¤Î¤Þ¤ÞÊݸ¤¹¤ë¡£
166  *  
167  *  xstrs: xstr ¤Î intern ÍѤΥǡ¼¥¿¥Ù¡¼¥¹
168  *         row ¤Î key ¤ò intern ¤µ¤ì¤¿ xstr ¤È¤·¤Æ»È¤¦¡£
169  *         row ¤Ë value ¤Ï»ý¤¿¤Ê¤¤¡£
170  *                    (¾­ÍèŪ¤Ë¤Ï»²¾È¥«¥¦¥ó¥¿¤ò¤Ä¤±¤Æ¤â¤¤¤¤¤«¤â)
171  *  »²¾È: intern_xstr()
172  */
173
174 /*
175  * º¹Ê¬½ñ¤­½Ð¤·:
176  *  ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÎÊݸ¡¢Ê£¿ô¤Î anthy ¥é¥¤¥Ö¥é¥ê¤ò¥ê¥ó¥¯¤·¤¿
177  *  ¥×¥í¥»¥¹¤Î³Ø½¬ÍúÎò¤ÎƱ´ü¤Î¤¿¤á¤Ë¡¢³Ø½¬ÍúÎò¤Î¹¹¿·¾ðÊó¤ò
178  *  Ãà°ì¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹¡£
179  *
180  * ¡¦´ðËÜ¥Õ¥¡¥¤¥ë  ¸Å¤¤ anthy ¤Î³Ø½¬ÍúÎò¤ÈƱ¤¸·Á¼°¡£
181  *                 º¹Ê¬¾ðÊó¤òŬÍѤ¹¤ë¸µ¤È¤Ê¤ë¥Õ¥¡¥¤¥ë¡£
182  *                 ´ðËÜŪ¤Ë¤Ïµ¯Æ°»þ¤À¤±¤ËÆɤ߹þ¤à¡£
183  *                 ¤³¤Î¥×¥í¥°¥é¥àÃæ¤Ç¥Õ¥¡¥¤¥ë1¡¤base¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
184  * ¡¦º¹Ê¬¥Õ¥¡¥¤¥ë  ´ðËÜ¥Õ¥¡¥¤¥ë¤ËÂФ¹¤ë¹¹¿·¾ðÊó¡£
185  *                 ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ¹¤ë¹¹¿·¤¬¥³¥ß¥Ã¥È¤µ¤ì¤ë¤¿¤Ó¤Ë
186  *                 Æɤ߽ñ¤­¤µ¤ì¤ë¡£
187  *                 ¤³¤Î¥×¥í¥°¥é¥àÃæ¤Ç¥Õ¥¡¥¤¥ë2¡¤journal¤È¸Æ¤Ö¤³¤È¤¬¤¢¤ë¡£
188  *  ´ðËÜÊý¿Ë:
189  *     ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ¹¤ë¹¹¿·¤¬¥³¥ß¥Ã¥È¤µ¤ì¤ë¤È¡¢¤Þ¤ºº¹Ê¬¥Õ¥¡¥¤¥ë
190  *     ¤Ë¾¤Î¥×¥í¥»¥¹¤¬Äɲä·¤¿¹¹¿·¾ðÊó¤òÆɤ߹þ¤ß¡¢¤½¤Î¸å¤Ë¼«Ê¬¤Î
191  *     ¥³¥ß¥Ã¥È¤·¤¿¹¹¿·¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤¹¡£
192  *     ¤³¤ì¤é¤Ï¥í¥Ã¥¯¥Õ¥¡¥¤¥ë¤òÍѤ¤¤Æ¥¢¥È¥ß¥Ã¥¯¤Ë¹Ô¤ï¤ì¤ë¡£¤Þ¤¿¡¢
193  *     ´ðËÜ¥Õ¥¡¥¤¥ë¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤È¤â¡¢¥í¥Ã¥¯¤ò¼è¤Ã¤Æ¤¤¤ë´Ö¤·¤«
194  *     ¥ª¡¼¥×¥ó¤·¤Æ¤¤¤Æ¤Ï¤¤¤±¤Ê¤¤¡£
195  *  ÄɲäȺï½ü:
196  *     ÄɲäϤ¹¤Ç¤Ë¥á¥â¥ê¾å¤Ç¹¹¿·¤µ¤ì¤¿ row ¤ò¥³¥ß¥Ã¥È¤Ë¤è¤Ã¤Æ
197  *     ¥á¥â¥ê¤Ë½ñ¤­½Ð¤¹¤¿¤á¡¢
198  *       1. ¥³¥ß¥Ã¥ÈÂоݠrow °Ê³°¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Î¾ðÊó¤Ç
199  *       2. ¥³¥ß¥Ã¥ÈÂоݠrow ¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤·
200  *     ¤È¤¹¤ë¡£ºï½ü¤Ï¤Þ¤À¥á¥â¥ê¾å¤Ë row ¤¬»Ä¤Ã¤Æ¤¤¤ë¾õÂ֤ǥ³¥ß¥Ã¥È
201  *     ¤¬¹Ô¤ï¤ì¤ë(ºï½üÍ×µá¤ò¥³¥ß¥Ã¥È¤È¤·¤Æ°·¤¦)¤¿¤á¡¢
202  *       1. ºï½ü¤Î¾ðÊó¤òº¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤·
203  *       2. º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¤Ë¤è¤êºï½üÍ×µá¤â¼Â¹Ô¤¹¤ë
204  *     ¤È¤¹¤ë¡£
205  *  ´ðËÜ¥Õ¥¡¥¤¥ë¤Î¹¹¿·:
206  *     º¹Ê¬¥Õ¥¡¥¤¥ë¤¬¤¢¤ëÄøÅÙÈîÂç²½¤¹¤ë¤È¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¾ðÊó¤ò
207  *     ´ðËÜ¥Õ¥¡¥¤¥ë¤ËÈ¿±Ç¤·¤Æº¹Ê¬¥Õ¥¡¥¤¥ë¤ò¶õ¤Ë¤¹¤ë¡£
208  *     ¹¹¿·¤¹¤ë¥×¥í¥»¥¹:
209  *       º¹Ê¬¥Õ¥¡¥¤¥ë¤Ë½ñ¤­½Ð¤·¤ò¹Ô¤Ã¤¿¸å¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÂ礭¤µ¤òÄ´¤Ù¡¢
210  *       ÈîÂç²½¤·¤Æ¤¤¤ì¤Ð¡¢¤½¤Î¤È¤­¤Î¥á¥â¥ê¾å¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹(¤³¤ì¤Ë¤Ï
211  *       Á´¤Æ¤Îº¹Ê¬¥Õ¥¡¥¤¥ë¤Î¹¹¿·¤¬Å¬ÍѤµ¤ì¤Æ¤¤¤ë)¤ò´ðËÜ¥Õ¥¡¥¤¥ë¤Ë
212  *       ½ñ¤­½Ð¤¹¡£
213  *     ¤½¤ì°Ê³°¤Î¥×¥í¥»¥¹:
214  *       º¹Ê¬¥Õ¥¡¥¤¥ë¤òÆɤàÁ°¤Ë¡¢´ðËÜ¥Õ¥¡¥¤¥ë¤¬¹¹¿·¤µ¤ì¤Æ¤¤¤ë¤«¤ò
215  *       ¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥à¥¹¥¿¥ó¥×¤ÇÄ´¤Ù¡¢¹¹¿·¤µ¤ì¤Æ¤¤¤ì¤Ð¡¢¥³¥ß¥Ã¥È
216  *       ¤µ¤ì¤¿¹¹¿·¾ðÊó¤òľ¤Á¤Ë¹¹¿·¥Õ¥¡¥¤¥ë¤ËÄɲä·¡¢¥á¥â¥ê¾å¤Î
217  *       ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò flush ¤·¤¿¸å´ðËÜ¥Õ¥¡¥¤¥ë¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤ò
218  *       Æɤ߹þ¤ßľ¤¹¡£
219  *       ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î flush ¤Ë¤è¤ê¡¢ 
220  *           ¡¦cur_row ¤¬Ìµ¸ú¤Ë¤Ê¤ë (NULL ¤Ë¤Ê¤ë)
221  *           ¡¦cur_section ¤ÎÍ­¸úÀ­¤ÏÊݸ¤µ¤ì¤ë(section¤Ï²òÊü¤·¤Ê¤¤)
222  *           ¡¦xstr ¤Ï intern ¤·¤Æ¤¤¤ì¤ÐÊݸ¤µ¤ì¤ë
223  *                              (¤¹¤Ù¤Æ¤Î xstr ¤Ï intern ¤µ¤ì¤Æ¤¤¤ë¤Ï¤º)
224  *   ·ë¶É¡¢¼¡¤ÎÍͤˤʤë:
225  *     if (´ðËÜ¥Õ¥¡¥¤¥ë¤¬¹¹¿·¤µ¤ì¤Æ¤¤¤ë) {
226  *             º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¥³¥ß¥Ã¥È¤µ¤ì¤¿¹¹¿·¤ò½ñ¤­½Ð¤¹;
227  *             ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î¥Õ¥é¥Ã¥·¥å;
228  *             ´ðËÜ¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¥¯¥ê¥¢;
229  *             º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
230  *     } else {
231  *             if (ÄɲÃ) {
232  *                     º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
233  *                     º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤­½Ð¤·;
234  *             } else {
235  *                     º¹Ê¬¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤­½Ð¤·;
236  *                     º¹Ê¬¥Õ¥¡¥¤¥ë¤ÎÆɹþ¤Èº¹Ê¬¥Õ¥¡¥¤¥ë¤ÎºÇ½ªÆɹþ°ÌÃÖ¹¹¿·;
237  *             }
238  *     }
239  *     if (º¹Ê¬¥Õ¥¡¥¤¥ë¤¬Â礭¤¤) {
240  *             ´ðËÜ¥Õ¥¡¥¤¥ë¤Ø¤Î½ñ¤­½Ð¤·;
241  *             º¹Ê¬¥Õ¥¡¥¤¥ë¤Î¥¯¥ê¥¢;
242  *     }
243  */
244
245 static allocator record_ator;
246
247 /* trieÁàºîÍÑ */
248 static void init_trie_root(struct trie_root *n);
249 static int trie_key_nth_bit(xstr* key, int n);
250 static int trie_key_first_diff_bit_1byte(xchar c1, xchar c2);
251 static int trie_key_first_diff_bit(xstr *k1, xstr *k2);
252 static int trie_key_cmp(xstr *k1, xstr *k2);
253 static void trie_key_dup(xstr *dst, xstr *src);
254 static void trie_row_init(struct record_row *rc);
255 static void trie_row_free(struct record_row *rc);
256 static struct trie_node *trie_find(struct trie_root *root, xstr *key);
257 static struct trie_node *trie_insert(struct trie_root *root, xstr *key,
258                                      int dirty, int *nr_used, int *nr_sused);
259 static void trie_remove(struct trie_root *root, xstr *key,
260                         int *nr_used, int *nr_sused);
261 static struct trie_node *trie_first(struct trie_root *root);
262 static struct trie_node *trie_next(struct trie_root *root,
263                                    struct trie_node *cur);
264 static void trie_remove_all(struct trie_root *root,
265                             int *nr_used, int *nr_sused);
266 static void trie_remove_old(struct trie_root *root, int count,
267                             int* nr_used, int* nr_sused);
268 static void trie_mark_used(struct trie_root *root, struct trie_node *n,
269                            int *nr_used, int *nr_sused);
270
271
272 /* 
273  * ¥È¥é¥¤¤Î¼ÂÁõ
274  * struct trie_node¤Î¤¦¤Árow°Ê³°¤ÎÉôʬ¤Èrow.key¤ò»ÈÍÑ
275  * ºï½ü¤Î»þ¤Ïtrie_row_free¤ò»È¤Ã¤Ærow¤ÎÆâÍƤò²òÊü
276  */
277
278 #define PUTNODE(x) ((x) == &root->root ? printf("root\n") : anthy_putxstrln(&(x)->row.key))
279 static int
280 debug_trie_dump(FILE* fp, struct trie_node* n, int encoding)
281 {
282   int cnt = 0;
283   char buf[1024];
284
285   if (n->l->bit > n->bit) {
286     cnt = debug_trie_dump(fp, n->l, encoding);
287   } else {
288     if (n->l->row.key.len == -1) {
289       if (fp) {
290         fprintf(fp, "root\n");
291       }
292     } else {
293       if (fp) {
294         anthy_sputxstr(buf, &n->l->row.key, encoding);
295         fprintf(fp, "%s\n", buf);
296       }
297       cnt = 1;
298     }
299   }
300
301   if (n->r->bit > n->bit) {
302     return cnt + debug_trie_dump(fp, n->r, encoding);
303   } else {
304     if (n->r->row.key.len == -1) {
305       if(fp) {
306         fprintf(fp, "root\n");
307       }
308     } else {
309       if(fp) {
310         anthy_sputxstr(buf, &n->r->row.key, encoding);
311         fprintf(fp, "%s\n", buf);
312       }
313       return cnt + 1;
314     }
315   }
316
317   return cnt;
318 }
319
320 static void
321 init_trie_root(struct trie_root *root)
322 {
323   struct trie_node* n;
324   root->node_ator = anthy_create_allocator(sizeof(struct trie_node), NULL);
325   n = &root->root;
326   n->l = n;
327   n->r = n;
328   n->bit = 0;
329   n->lru_next = n;
330   n->lru_prev = n;
331   n->dirty = 0;
332   trie_row_init(&n->row);
333   n->row.key.len = -1;
334 }
335
336 /*
337  * bit0: 0
338  * bit1: head¤Î¥­¡¼¤À¤±0
339  * bit2: Ê¸»úÎó¤Î¥Ó¥Ã¥È0
340  * bit3: Ê¸»úÎó¤Î¥Ó¥Ã¥È1
341  *   ...
342  * Ê¸»úÎóŤò±Û¤¨¤ë¤È0
343  */
344 static int
345 trie_key_nth_bit(xstr* key, int n)
346 {
347   switch (n) {
348   case 0:
349     return 0;
350   case 1:
351     return key->len + 1; /* key->len == -1 ? 0 : non-zero */
352   default:
353     {
354       int pos;
355       n -= 2;
356       pos = n / (sizeof(xchar) << 3);
357       if (pos >= key->len) {
358         return 0;
359       }
360       return key->str[pos] & (1 << (n % (sizeof(xchar) << 3)));
361     }
362   }
363 }
364
365 /* c1 == c2 ¤Ç¤Ï¸Æ¤ó¤Ç¤Ï¤¤¤±¤Ê¤¤ */
366 static int
367 trie_key_first_diff_bit_1byte(xchar c1, xchar c2)
368 {
369   int i;
370   int ptn;
371   for (i = 0, ptn = c1 ^ c2; !(ptn & 1); i++, ptn >>= 1 )
372     ;
373   return i;
374 }
375
376 /*
377  * k1 == k2 ¤Ç¤Ï¸Æ¤ó¤Ç¤Ï¤¤¤±¤Ê¤¤
378  * ki->str[0 .. (ki->len - 1)]¤Ë0¤Ï¤Ê¤¤¤È²¾Äê
379  */
380 #define MIN(a,b) ((a)<(b)?(a):(b))
381 static int
382 trie_key_first_diff_bit(xstr *k1, xstr *k2)
383 {
384   int len;
385   int i;
386
387   len = MIN(k1->len, k2->len);
388   if (len == -1) {
389     return 1;
390   }
391   for ( i = 0 ; i < len ; i++ ){
392     if (k1->str[i] != k2->str[i]) {
393       return (2 + (i * (sizeof(xchar) << 3)) + 
394               trie_key_first_diff_bit_1byte(k1->str[i], k2->str[i]));
395     }
396   }
397   if (k1->len < k2->len) {
398     return (2 + (i * (sizeof(xchar) << 3)) +
399             trie_key_first_diff_bit_1byte(0, k2->str[i]));
400   } else {
401     return (2 + (i * (sizeof(xchar) << 3)) +
402             trie_key_first_diff_bit_1byte(k1->str[i], 0));
403   }
404 }
405 #undef MIN
406
407 static int
408 trie_key_cmp(xstr *k1, xstr *k2)
409 {
410   if (k1->len == -1 || k2->len == -1) {
411     return k1->len - k2->len;
412   }
413   return anthy_xstrcmp(k1, k2);
414 }
415
416 static void
417 trie_key_dup(xstr *dst, xstr *src)
418 {
419   dst->str = anthy_xstr_dup_str(src);
420   dst->len = src->len;
421 }
422
423 /*
424  * ¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð 0 
425  */
426 static struct trie_node *
427 trie_find(struct trie_root *root, xstr *key)
428 {
429   struct trie_node *p;
430   struct trie_node *q;
431
432   p = &root->root;
433   q = p->l;
434   while (p->bit < q->bit) {
435     p = q;
436     q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
437   }
438   return trie_key_cmp(&q->row.key,key) ? NULL : q; 
439 }
440
441 /*
442  * ºÇĹ¥Þ¥Ã¥Á¤Î¤¿¤á¤ÎÊä½õ´Ø¿ô
443  *  key ¤Çõº÷¤·¤Æ¡¢»Ï¤á¤Æ°ìÃפ·¤Ê¤¯¤Ê¤Ã¤¿¥Î¡¼¥É¤òÊÖ¤¹¡£
444  */
445 static struct trie_node *
446 trie_find_longest (struct trie_root* root, xstr *key)
447 {
448   struct trie_node *p;
449   struct trie_node *q;
450
451   p = &root->root;
452   q = p->l;
453   while (p->bit < q->bit) {
454     p = q;
455     q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
456   }
457
458   return q;
459 }
460
461 /* 
462  * Äɲä·¤¿¥Î¡¼¥É¤òÊÖ¤¹
463  * ¤¹¤Ç¤ËƱ¤¸¥­¡¼¤ò¤â¤Ä¥Î¡¼¥É¤¬¤¢¤ë¤È¤­¤Ï¡¢Äɲ令º¤Ë0¤òÊÖ¤¹
464  */
465 static struct trie_node *
466 trie_insert(struct trie_root *root, xstr *key,
467             int dirty, int *nr_used, int *nr_sused)
468 {
469   struct trie_node *n;
470   struct trie_node *p;
471   struct trie_node *q;
472   int i;
473
474   p = &root->root;
475   q = p->l;
476   while (p->bit < q->bit) {
477     p = q;
478     q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
479   }
480   if (trie_key_cmp(&q->row.key,key) == 0) {
481     /* USED > SUSED > 0 ¤Ç¶¯¤¤Êý¤ò»Ä¤¹ */
482     if (dirty == LRU_USED) {
483       trie_mark_used(root, q, nr_used, nr_sused);
484     } else if (q->dirty == 0) {
485       q->dirty = dirty;
486     }
487     return 0;
488   }
489   i = trie_key_first_diff_bit(&q->row.key, key);
490   p = &root->root;
491   q = p->l;
492   while (p->bit < q->bit && i > q->bit) {
493     p = q;
494     q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
495   }
496   n = anthy_smalloc(root->node_ator);
497   trie_row_init(&n->row);
498   trie_key_dup(&n->row.key, key);
499   n->bit = i;
500   if (trie_key_nth_bit(key, i)) {
501     n->l = q;
502     n->r = n;
503   } else {
504     n->l = n;
505     n->r = q;
506   }
507   if (p->l == q) {
508     p->l = n;
509   } else {
510     p->r = n;
511   }
512
513   /* LRU ¤Î½èÍý */
514   if (dirty == LRU_USED) {
515     root->root.lru_next->lru_prev = n;
516     n->lru_prev = &root->root;
517     n->lru_next = root->root.lru_next;
518     root->root.lru_next = n;
519     (*nr_used)++;
520   } else {
521     root->root.lru_prev->lru_next = n;
522     n->lru_next = &root->root;
523     n->lru_prev = root->root.lru_prev;
524     root->root.lru_prev = n;
525     if (dirty == LRU_SUSED) {
526       (*nr_sused)++;
527     }
528   }
529   n->dirty = dirty;
530   return n;
531 }
532
533 /* 
534  * ¥Î¡¼¥É¤ò¸«¤Ä¤±¤ë¤Èºï½ü¤¹¤ë
535  * ÆâÉô¤Çtrie_row_free¤ò¸Æ¤Ó¡¢¥­¡¼¤ò´Þ¤à¥Ç¡¼¥¿Éôʬ¤òfree¤¹¤ë
536  *
537  * ¥Ç¡¼¥¿¤È¥Î¡¼¥É¤òºï½ü¤¹¤ë¡£
538  * ºï½üÂоݤΥǡ¼¥¿¤Ïºï½üÂоݤΥΡ¼¥É¤Ë³ÊǼ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï
539  * ¸Â¤é¤Ê¤¤¤³¤È¤ËÃí°Õ¡£
540  * 1. ºï½üÂоݤÎÍÕ¤ò»ý¤Ä¥Î¡¼¥É¤Ëºï½üÂоݤÎÍÕ¤¬´Þ¤Þ¤ì¤Æ¤¤¤ë¤È¤­
541  *  ºï½üÂоݤΥΡ¼¥É¤Ï¡¢»Ò¤Ø¤Î»Þ¤Î¤¦¤Á¡¢À¸¤­¤Î¤³¤ë»Þ¤ò¿Æ¤ËÅϤ·¤Æ»à¤Ì
542  * 2. ºï½üÂоݤÎÍÕ¤ò»ý¤Ä¥Î¡¼¥É¤ÎÁÄÀè¤Ëºï½üÂоݤÎÍÕ¤¬´Þ¤Þ¤ì¤Æ¤¤¤ë¤È¤­
543  *  1. ¤Ë²Ã¤¨¤Æ¡¢ºï½üÂоݤÎÍÕ¤ò¤â¤Ä¥Î¡¼¥É¤ò»¦¤·¤Æ¡¢Âå¤ï¤ê¤Ëºï½ü
544  *  ÂоݤΥΡ¼¥É¤òºï½üÂоݤÎÍÕ¤ò¤â¤Ä¥Î¡¼¥É¤Î°ÌÃ֤˰ÜÆ°¤µ¤»À¸¤«¤¹
545  */
546 static void
547 trie_remove(struct trie_root *root, xstr *key, 
548             int *nr_used, int *nr_sused)
549 {
550   struct trie_node *p;
551   struct trie_node *q;
552   struct trie_node **pp = NULL; /* gcc ¤Î warning ²óÈò */
553   struct trie_node **qq;
554   p = &root->root;
555   qq = &p->l;
556   q = *qq;
557   while (p->bit < q->bit) {
558     pp = qq;
559     p = q;
560     qq = trie_key_nth_bit(key,p->bit) ? &p->r : &p->l;
561     q = *qq;
562   }
563   if (trie_key_cmp(&q->row.key, key) != 0) {
564     return ;
565   }
566   if (p != q) {
567     /* case 2. */
568     struct trie_node *r;
569     struct trie_node *s;
570     r = &root->root;
571     s = r->l;
572     while (s != q) {
573       r = s;
574       s = trie_key_nth_bit(key, r->bit) ? r->r : r->l;
575     }
576     *pp = (p->r == q) ? p->l : p->r;
577     p->l = q->l;
578     p->r = q->r;
579     p->bit = q->bit;
580     if (trie_key_nth_bit(key, r->bit)) {
581       r->r = p;
582     } else {
583       r->l = p;
584     }
585     p = q;
586   } else {
587     *pp = (p->r == q) ? p->l : p->r;
588   }
589   p->lru_prev->lru_next = p->lru_next;
590   p->lru_next->lru_prev = p->lru_prev;
591   if (p->dirty == LRU_USED) {
592     (*nr_used)--;
593   } else if (p->dirty == LRU_SUSED) {
594     (*nr_sused)--;
595   }
596   trie_row_free(&p->row);
597   anthy_sfree(root->node_ator, p);
598 }
599
600 /* head°Ê³°¤Î¥Î¡¼¥É¤¬¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤¹ */
601 static struct trie_node *
602 trie_first (struct trie_root *root)
603 {
604   return root->root.lru_next == &root->root ?
605     NULL : root->root.lru_next;
606 }
607
608 /* ¼¡¤Î¥Î¡¼¥É¤¬¤Ê¤±¤ì¤Ð 0 ¤òÊÖ¤¹ */
609 static struct trie_node *
610 trie_next (struct trie_root *root,
611            struct trie_node *cur)
612 {
613   return cur->lru_next == &root->root ? 0 : cur->lru_next;
614 }
615
616 /*
617  * head°Ê³°Á´¤Æ¤Î¥Î¡¼¥É¤òºï½ü¤¹¤ë
618  * ÆâÉô¤Çtrie_row_free¤ò¸Æ¤Ó¡¢¥­¡¼¤ò´Þ¤à¥Ç¡¼¥¿Éôʬ¤òfree¤¹¤ë
619  */
620 static void 
621 trie_remove_all (struct trie_root *root,
622                  int *nr_used, int *nr_sused)
623 {
624   struct trie_node* p;
625   for (p = root->root.lru_next; p != &root->root; p = p->lru_next) {
626     trie_row_free(&p->row);
627   }
628   anthy_free_allocator(root->node_ator);
629   init_trie_root(root);
630   *nr_used = 0;
631   *nr_sused = 0;
632 }
633
634 /*
635  * LRU ¥ê¥¹¥È¤ÎÀèƬ¤«¤é count ÈÖÌܤޤǤò»Ä¤·¤Æ»Ä¤ê¤ò²òÊü¤¹¤ë
636  */
637 static void
638 trie_remove_old (struct trie_root *root, int count, 
639                  int *nr_used, int *nr_sused)
640 {
641   struct trie_node *p;
642   struct trie_node *q;
643
644   if (*nr_used > count) {
645     for (p = root->root.lru_next; count; count--, p = p->lru_next)
646       ;
647     /* p ¤«¤é head ¤Þ¤Ç¤ò¾Ã¤¹ */
648     for ( ; p != &root->root; p = q) {
649       q = p->lru_next;
650       trie_remove(root, &p->row.key, nr_used, nr_sused);
651     }
652   } else if (*nr_used + *nr_sused > count) {
653     for (p = root->root.lru_next; p->dirty == LRU_USED; p = p->lru_next)
654       ; 
655     /*
656      * p ¤«¤é root ¤Þ¤Ç  sused    -> dirty := 0
657      *                   ¤½¤ì°Ê³° -> ¾Ã¤¹
658      */
659     for ( ; p != &root->root; p = q) {
660       q = p->lru_next;
661       if (p->dirty == LRU_SUSED) {
662         p->dirty = 0;
663       } else {
664         trie_remove(root, &p->row.key, nr_used, nr_sused);
665       }
666     }
667     *nr_sused = 0;
668   }
669 }      
670
671 static void
672 trie_mark_used (struct trie_root *root, struct trie_node *n,
673                 int *nr_used, int *nr_sused)
674 {
675   switch(n->dirty) {
676   case LRU_USED:
677     break;
678   case LRU_SUSED:
679     (*nr_sused)--;
680     /* fall through */
681   default:
682     n->dirty = LRU_USED;
683     (*nr_used)++;
684     break;
685   }
686   n->lru_prev->lru_next = n->lru_next;
687   n->lru_next->lru_prev = n->lru_prev;
688   root->root.lru_next->lru_prev = n;
689   n->lru_next = root->root.lru_next;
690   root->root.lru_next = n;
691   n->lru_prev = &root->root;
692 }
693
694 /*
695  * ¥È¥é¥¤¤Î¼ÂÁõ¤Ï¤³¤³¤Þ¤Ç
696  */
697
698 static xstr *
699 do_get_index_xstr(struct record_stat *rec)
700 {
701   if (!rec->cur_row) {
702     return 0;
703   }
704   return &rec->cur_row->row.key;
705 }
706
707 static struct record_section*
708 do_select_section(struct record_stat *rst, const char *name, int flag)
709 {
710   struct record_section *rsc;
711
712   for (rsc = rst->section_list.next; rsc; rsc = rsc->next) {
713     if (!strcmp(name, rsc->name)) {
714       return rsc;
715     }
716   }
717
718   if (flag) {
719     rsc = malloc(sizeof(struct record_section));
720     rsc->name = strdup(name);
721     rsc->next = rst->section_list.next;
722     rst->section_list.next = rsc;
723     rsc->lru_nr_used = 0;
724     rsc->lru_nr_sused = 0;
725     init_trie_root(&rsc->cols);
726     return rsc;
727   }
728
729   return NULL;
730 }
731
732 static struct trie_node* 
733 do_select_longest_row(struct record_section *rsc, xstr *name)
734 {
735   struct trie_node *mark, *found;
736   xstr xs;
737   int i;
738
739   if ((NULL == name) || (NULL == name->str) || (name->len < 1) || (0 == name->str[0])) {
740     /* ¼­½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
741     return NULL;
742   }
743
744   mark = trie_find_longest(&rsc->cols, name);
745   xs.str = name->str;
746   for (i = (mark->row.key.len <= name->len) ? mark->row.key.len : name->len; i > 1; i--) {  /* ÉÔÀµ¤Ê¥á¥â¥ê¥¢¥¯¥»¥¹¤Î½¤Àµ */
747     /* ¥ë¡¼¥È¥Î¡¼¥É¤Ï i == 1 ¤Ç¥Þ¥Ã¥Á¤¹¤ë¤Î¤Ç½ü³°
748      * trie_key_nth_bit »²¾È
749      */
750     xs.len = i;
751     found = trie_find(&rsc->cols, &xs);
752     if (found) {
753       return found;
754     }
755   }
756   return NULL;
757 }
758
759 static struct trie_node* 
760 do_select_row(struct record_section* rsc, xstr *name,
761                  int flag, int dirty)
762 {
763   struct trie_node *node;
764
765   if (flag) {
766     node = trie_insert(&rsc->cols, name, dirty,
767                        &rsc->lru_nr_used, &rsc->lru_nr_sused);
768     if (node) {
769       node->row.nr_vals = 0;
770       node->row.vals = 0;
771     } else {
772       node = trie_find(&rsc->cols, name);
773     }
774   } else {
775     node = trie_find(&rsc->cols, name);
776   }
777   return node;
778 }
779
780 static void 
781 do_mark_row_used(struct record_section* rsc, struct trie_node* node)
782 {
783   trie_mark_used(&rsc->cols, node, &rsc->lru_nr_used, &rsc->lru_nr_sused);
784 }
785
786 static void
787 do_truncate_section(struct record_stat *s, int count)
788 {
789   if (!s->cur_section) {
790     return;
791   }
792
793   trie_remove_old(&s->cur_section->cols, count,
794                   &s->cur_section->lru_nr_used,
795                   &s->cur_section->lru_nr_sused);
796 }
797
798
799 static struct trie_node*
800 do_select_first_row(struct record_section *rsc)
801 {
802   return trie_first(&rsc->cols);
803 }
804
805 static struct trie_node*
806 do_select_next_row(struct record_section *rsc, 
807   struct trie_node* node)
808 {
809   return trie_next(&rsc->cols, node);
810 }
811
812
813 static int
814 do_get_nr_values(struct trie_node *node)
815 {
816   if (!node)
817     return 0;
818   return node->row.nr_vals;
819 }
820
821 static struct record_val *
822 get_nth_val_ent(struct trie_node *node, int n, int f)
823 {
824   struct record_row *col;
825   col = &node->row;
826   if (n < 0) {
827     return NULL;
828   }
829   if (n < do_get_nr_values(node)) {
830     return &col->vals[n];
831   }
832   if (f) {
833     int i;
834     col->vals = realloc(col->vals, sizeof(struct record_val)*(n + 1));
835     for (i = col->nr_vals; i < n+1; i++) {
836       col->vals[i].type = RT_EMPTY;
837     }
838     col->nr_vals = n + 1;
839     return &col->vals[n];
840   }
841   return NULL;
842 }
843
844 static void
845 free_val_contents(struct record_val* v)
846 {
847   switch (v->type) {
848   case RT_XSTR:
849     anthy_free_xstr_str(&v->u.str);
850     break;
851   case RT_XSTRP:
852   case RT_VAL:
853   case RT_EMPTY:
854   default:
855     break;
856   }
857 }
858
859 static void
860 do_set_nth_value(struct trie_node *node, int nth, int val)
861 {
862   struct record_val *v = get_nth_val_ent(node, nth, 1);
863   if (!v) {
864     return ;
865   }
866   free_val_contents(v);
867   v->type = RT_VAL;
868   v->u.val = val;
869 }
870
871 static int
872 do_get_nth_value(struct trie_node *node, int n)
873 {
874   struct record_val *v = get_nth_val_ent(node, n, 0);
875   if (v && v->type == RT_VAL) {
876     return v->u.val;
877   }
878   return 0;
879 }
880
881 static xstr*
882 intern_xstr (struct trie_root* xstrs, xstr* xs)
883 {
884   struct trie_node* node;
885   int dummy;
886
887   if ((NULL == xs) || (NULL == xs->str) || (xs->len < 1) || (0 == xs->str[0])) {
888     /* ¼­½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
889     return NULL;
890   }
891   node = trie_find(xstrs, xs);
892   if (!node) 
893     node = trie_insert(xstrs, xs, 0, &dummy, &dummy);
894   return &node->row.key;
895 }
896
897 static void
898 do_set_nth_xstr (struct trie_node *node, int nth, xstr *xs,
899                  struct trie_root* xstrs)
900 {
901   struct record_val *v = get_nth_val_ent(node, nth, 1);
902   if (!v){
903     return ;
904   }
905   free_val_contents(v);
906   v->type = RT_XSTRP;
907   v->u.strp = intern_xstr(xstrs, xs);
908 }
909
910 static void
911 do_truncate_row (struct trie_node* node, int n)
912 {
913   int i;
914   if (n < node->row.nr_vals) {
915     for (i = n; i < node->row.nr_vals; i++) {
916       free_val_contents(node->row.vals + i);
917     }
918     node->row.vals = realloc(node->row.vals, 
919                                 sizeof(struct record_val)* n);
920     node->row.nr_vals = n;
921   }
922 }
923
924 static void
925 do_remove_row (struct record_section* rsc,
926                   struct trie_node* node)
927 {
928   xstr* xs;
929   xs = anthy_xstr_dup(&node->row.key);
930   trie_remove(&rsc->cols, &node->row.key, 
931               &rsc->lru_nr_used, &rsc->lru_nr_sused);
932
933   anthy_free_xstr(xs);
934 }
935
936 static xstr *
937 do_get_nth_xstr(struct trie_node *node, int n)
938 {
939   struct record_val *v = get_nth_val_ent(node, n, 0);
940   if (v) {
941     if (v->type == RT_XSTR) {
942       return &v->u.str;
943     } else if (v->type == RT_XSTRP) {
944       return v->u.strp;
945     }
946   }
947   return 0;
948 }
949
950 static void
951 lock_record (struct record_stat* rs)
952 {
953   if (rs->is_anon) {
954     return ;
955   }
956   anthy_priv_dic_lock();
957 }
958
959 static void
960 unlock_record (struct record_stat* rs)
961 {
962   if (rs->is_anon) {
963     return ;
964   }
965   anthy_priv_dic_unlock();
966 }
967
968 /* ºÆÆɤ߹þ¤ß¤ÎɬÍפ¬¤¢¤ë¤«¤ò¥Á¥§¥Ã¥¯¤¹¤ë
969  * É¬Íפ¬¤¢¤ì¤ÐÊÖ¤êÃͤ¬1¤Ë¤Ê¤ë */
970 static int
971 check_base_record_uptodate(struct record_stat *rst)
972 {
973   struct stat st;
974   if (rst->is_anon) {
975     return 1;
976   }
977   anthy_check_user_dir();
978   if (stat(rst->base_fn, &st) < 0) {
979     return 0;
980   } else if (st.st_mtime != rst->base_timestamp) {
981     return 0;
982   }
983   return 1;
984 }
985
986
987 /*
988  * row format:
989  *  ROW := OPERATION SECTION KEY VALUE*
990  *  OPERATION := "ADD"    (Äɲäޤ¿¤ÏLRU¹¹¿·)
991  *               "DEL"    (ºï½ü)
992  *  SECTION := (ʸ»úÎó)
993  *  KEY     := TD
994  *  VALUE   := TD
995  *  TD      := TYPE DATA  (¶õÇò¤ò¤¢¤±¤º¤Ë½ñ¤¯)
996  *  TYPE    := "S"        (xstr)
997  *             "N"        (number)
998  *  DATA    := (·¿¤´¤È¤Ë¥·¥ê¥¢¥é¥¤¥º¤·¤¿¤â¤Î)
999  */
1000
1001 static char*
1002 read_1_token (FILE* fp, int* eol)
1003 {
1004   int c;
1005   char* s;
1006   int in_quote;
1007   int len;
1008
1009   in_quote = 0;
1010   s = NULL;
1011   len = 0;
1012   while (1) {
1013     c = fgetc(fp);
1014     switch (c) {
1015     case EOF: case '\n':
1016       goto out;
1017     case '\\':
1018       c = fgetc(fp);
1019       if (c == EOF || c == '\n') {
1020         goto out;
1021       }
1022       break;
1023     case '\"':
1024       in_quote = !in_quote;
1025       continue;
1026     case ' ': case '\t': case '\r':
1027       if (in_quote) {
1028         break;
1029       }
1030       if (s != NULL) {
1031         goto out;
1032       }
1033       break;
1034     default:
1035       break;
1036     }
1037
1038     s = (char*) realloc(s, len + 2);
1039     s[len] = c;
1040     len ++;
1041   }
1042 out:
1043   if (s) {
1044     s[len] = '\0';
1045   }
1046   *eol = (c == '\n');
1047   return s;
1048 }
1049
1050 /* journal¤«¤éADD¤Î¹Ô¤òÆɤà */
1051 static void
1052 read_add_row(FILE *fp, struct record_stat* rst,
1053              struct record_section* rsc)
1054 {
1055   int n;
1056   xstr* xs;
1057   char *token;
1058   int eol;
1059   struct trie_node* node;
1060
1061   token = read_1_token(fp, &eol);
1062   if (!token) {
1063     return ;
1064   }
1065
1066   xs = anthy_cstr_to_xstr(/* xstr ·¿¤òɽ¤¹ S ¤òÆɤ߼ΤƤë */
1067                           token + 1,
1068                           rst->encoding);
1069   node = do_select_row(rsc, xs, 1, LRU_USED);
1070   anthy_free_xstr(xs);
1071   free(token);
1072
1073   if (node->dirty & PROTECT) {
1074     /* Êݸ¤¹¤Ù¤­ row ¤Ê¤Î¤Ç¡¢º¹Ê¬¥Õ¥¡¥¤¥ë¤òÆɤ߼ΤƤë */
1075     while (!eol) {
1076       free(read_1_token(fp, &eol));
1077     }
1078     return ;
1079   }
1080
1081   n = 0;
1082   while (!eol) {
1083     token = read_1_token(fp, &eol);
1084     if (token) {
1085       switch(*token) {
1086         /* String Ê¸»úÎó */
1087       case 'S':
1088         {
1089           xstr* xs;
1090           xs = anthy_cstr_to_xstr(token + 1, rst->encoding);
1091           do_set_nth_xstr(node, n, xs, &rst->xstrs);
1092           anthy_free_xstr(xs);
1093         }
1094         break;
1095         /* Number ¿ôÃÍ */
1096       case 'N':
1097         do_set_nth_value(node, n, atoi(token + 1));
1098         break;
1099       }
1100       free(token);
1101       n++;
1102     }
1103   }
1104   do_truncate_row(node, n);
1105 }
1106
1107 /* journal¤«¤éDEL¤Î¹Ô¤òÆɤà */
1108 static void
1109 read_del_row(FILE *fp, struct record_stat* rst,
1110              struct record_section* rsc)
1111 {
1112   struct trie_node* node;
1113   char* token;
1114   xstr* xs;
1115   int eol;
1116
1117   token = read_1_token(fp, &eol);
1118   if (!token) {
1119     return ;
1120   }
1121
1122   xs = anthy_cstr_to_xstr(/* xstr ·¿¤òɽ¤¹ S ¤òÆɤßÈô¤Ð¤¹ */
1123                           token + 1,
1124                           rst->encoding);
1125   if ((node = do_select_row(rsc, xs, 0, 0)) != NULL) {
1126     do_remove_row(rsc, node);
1127   }
1128   anthy_free_xstr(xs);
1129   free(token);
1130 }
1131
1132 /** º¹Ê¬¥Õ¥¡¥¤¥ë¤«¤é1¹ÔÆɤ߹þ¤à */
1133 static void
1134 read_1_row(struct record_stat* rst, FILE* fp, char *op)
1135 {
1136   char* sec_name;
1137   struct record_section* rsc;
1138   int eol;
1139
1140   sec_name = read_1_token(fp, &eol);
1141   if (!sec_name || eol) {
1142     free(sec_name);
1143     return ;
1144   }
1145   rsc = do_select_section(rst, sec_name, 1);
1146   free(sec_name);
1147   if (!rsc) {
1148     return ;
1149   }
1150
1151   if (strcmp(op, "ADD") == 0) {
1152     read_add_row(fp, rst, rsc);
1153   } else if (strcmp(op, "DEL") == 0) {
1154     read_del_row(fp, rst, rsc);
1155   }
1156 }
1157
1158 /*
1159  * journal(º¹Ê¬)¥Õ¥¡¥¤¥ë¤òÆɤà
1160  */
1161 static void
1162 read_journal_record(struct record_stat* rs)
1163 {
1164   FILE* fp;
1165   struct stat st;
1166
1167   if (rs->is_anon) {
1168     return ;
1169   }
1170   fp = fopen(rs->journal_fn, "r");
1171   if (fp == NULL) {
1172     return;
1173   }
1174   if (fstat(fileno(fp), &st) == -1) {
1175     fclose(fp);
1176     return ;
1177   }
1178   if (st.st_size < rs->last_update) {
1179     /* ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤¬¾®¤µ¤¯¤Ê¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢
1180      * ºÇ½é¤«¤éÆɤ߹þ¤à */
1181     fseek(fp, 0, SEEK_SET);
1182   } else {
1183     fseek(fp, rs->last_update, SEEK_SET);
1184   }
1185   rs->journal_timestamp = st.st_mtime;
1186   while (!feof(fp)) {
1187     char *op;
1188     int eol;
1189     op = read_1_token(fp, &eol);
1190     if (op && !eol) {
1191       read_1_row(rs, fp, op);
1192     }
1193     free(op);
1194   }
1195   rs->last_update = ftell(fp);
1196   fclose(fp);
1197 }
1198
1199 static void
1200 write_string(FILE* fp, const char* str)
1201 {
1202   fprintf(fp, "%s", str);
1203 }
1204
1205 /* ¥À¥Ö¥ë¥¯¥ª¡¼¥È¤â¤·¤¯¤Ï¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å¤Ë¥Ð¥Ã¥¯¥¹¥é¥Ã¥·¥å¤òÉÕ¤±¤ë */
1206 static void
1207 write_quote_string(FILE* fp, const char* str)
1208 {
1209   const char* p;
1210
1211   for (p = str; *p; p++) {
1212     if (*p == '\"' || *p == '\\') {
1213       fputc('\\', fp);
1214     }
1215     fputc(*p, fp);
1216   }
1217 }
1218
1219 static void
1220 write_quote_xstr(FILE* fp, xstr* xs, int encoding)
1221 {
1222   char* buf;
1223
1224   if ((NULL == xs) || (NULL == xs->str) || (xs->len < 1) || (0 == xs->str[0])) {
1225     /* ¼­½ñ¤â¤·¤¯¤Ï³Ø½¬¥Ç¡¼¥¿¤¬²õ¤ì¤Æ¤¤¤¿»þ¤ÎÂкö */
1226     return;
1227   }
1228
1229   buf = (char*) alloca(xs->len * 6 + 2); /* EUC ¤Þ¤¿¤ÏUTF8¤ò²¾Äê */
1230   anthy_sputxstr(buf, xs, encoding);
1231   write_quote_string(fp, buf);
1232 }
1233
1234 static void
1235 write_number(FILE* fp, int x)
1236 {
1237   fprintf(fp, "%d", x);
1238 }
1239
1240 /* journal¤Ë1¹ÔÄɵ­¤¹¤ë */
1241 static void
1242 commit_add_row(struct record_stat* rst,
1243                const char* sname, struct trie_node* node)
1244 {
1245   FILE* fp;
1246   int i;
1247
1248   fp = fopen(rst->journal_fn, "a");
1249   if (fp == NULL) {
1250     return;
1251   }
1252
1253   write_string(fp, "ADD \"");
1254   write_quote_string(fp, sname);
1255   write_string(fp, "\" S\"");
1256   write_quote_xstr(fp, &node->row.key, rst->encoding);
1257   write_string(fp, "\"");
1258
1259   for (i = 0; i < node->row.nr_vals; i++) {
1260     switch (node->row.vals[i].type) {
1261     case RT_EMPTY:
1262       write_string(fp, " E");
1263       break;
1264     case RT_VAL:
1265       write_string(fp, " N");
1266       write_number(fp, node->row.vals[i].u.val);
1267       break;
1268     case RT_XSTR:
1269       write_string(fp, " S\"");
1270       write_quote_xstr(fp, &node->row.vals[i].u.str, rst->encoding);
1271       write_string(fp, "\"");
1272       break;
1273     case RT_XSTRP:
1274       write_string(fp, " S\"");
1275       write_quote_xstr(fp, node->row.vals[i].u.strp, rst->encoding);
1276       write_string(fp, "\"");
1277       break;
1278     }
1279   }
1280   write_string(fp, "\n");
1281   rst->last_update = ftell(fp);
1282   fclose(fp);
1283 }
1284
1285 /* Á´¤Æ¤Î row ¤ò²òÊü¤¹¤ë */
1286 static void
1287 clear_record(struct record_stat* rst)
1288 {
1289   struct record_section *rsc;
1290   for (rsc = rst->section_list.next; rsc; rsc = rsc->next) {
1291     trie_remove_all(&rsc->cols, &rsc->lru_nr_used, &rsc->lru_nr_sused); 
1292   }
1293   rst->cur_row = NULL;
1294 }
1295
1296 /* ´ðËÜ¥Õ¥¡¥¤¥ë¤òÆɤà */
1297 static void
1298 read_session(struct record_stat *rst)
1299 {
1300   char **tokens;
1301   int nr;
1302   int in_section = 0;
1303   while (!anthy_read_line(&tokens, &nr)) {
1304     xstr *xs;
1305     int i;
1306     int dirty = 0;
1307     struct trie_node* node;
1308
1309     if (!strcmp(tokens[0], "---") && nr > 1) {
1310       /* ¥»¥¯¥·¥ç¥ó¤ÎÀÚ¤ìÌÜ */
1311       in_section = 1;
1312       rst->cur_section = do_select_section(rst, tokens[1], 1);
1313       goto end;
1314     }
1315     if (!in_section || nr < 2) {
1316       /* ¥»¥¯¥·¥ç¥ó¤¬»Ï¤Þ¤Ã¤Æ¤Ê¤¤ or ¹Ô¤¬ÉÔ´°Á´ */
1317       goto end;
1318     }
1319     /* ¹ÔƬ¤ÎLRU¤Î¥Þ¡¼¥¯¤òÆɤà */
1320     if (tokens[0][0] == '-') {
1321       dirty = 0;
1322     } else if (tokens[0][0] == '+') {
1323       dirty = LRU_SUSED;
1324     }
1325     /* ¼¡¤Ëindex */
1326     xs = anthy_cstr_to_xstr(&tokens[0][1], rst->encoding);
1327     node = do_select_row(rst->cur_section, xs, 1, dirty);
1328     anthy_free_xstr(xs);
1329     if (!node) {
1330       goto end;
1331     }
1332     rst->cur_row = node;
1333     /**/
1334     for (i = 1; i < nr; i++) {
1335       if (tokens[i][0] == '"') {
1336         char *str;
1337         str = strdup(&tokens[i][1]);
1338         str[strlen(str) - 1] = 0;
1339         xs = anthy_cstr_to_xstr(str, rst->encoding);
1340         free(str);
1341         do_set_nth_xstr(rst->cur_row, i-1, xs, &rst->xstrs);
1342         anthy_free_xstr(xs);
1343       }else if (tokens[i][0] == '*') {
1344         /* EMPTY entry */
1345         get_nth_val_ent(rst->cur_row, i-1, 1);
1346       } else {
1347         do_set_nth_value(rst->cur_row, i-1, atoi(tokens[i]));
1348       }
1349     }
1350   end:
1351     anthy_free_line();
1352   }
1353 }
1354
1355 /* ¤¤¤Þ¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò²òÊü¤·¤¿¸å¤Ë¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤à */
1356 static void
1357 read_base_record(struct record_stat *rst)
1358 {
1359   struct stat st;
1360   if (rst->is_anon) {
1361     clear_record(rst);
1362     return ;
1363   }
1364   anthy_check_user_dir();
1365
1366   if (anthy_open_file(rst->base_fn) == -1) {
1367     return ;
1368   }
1369
1370   clear_record(rst);
1371   read_session(rst);
1372   anthy_close_file();
1373   if (stat(rst->base_fn, &st) == 0) {
1374     rst->base_timestamp = st.st_mtime;
1375   }
1376   rst->last_update = 0;
1377 }
1378
1379 static FILE *
1380 open_tmp_in_recorddir(void)
1381 {
1382   char *pn;
1383   const char *hd;
1384   const char *sid;
1385   sid = anthy_conf_get_str("SESSION-ID");
1386   hd = anthy_conf_get_str("HOME");
1387   pn = alloca(strlen(hd)+strlen(sid) + 10);
1388   sprintf(pn, "%s/.anthy/%s", hd, sid);
1389   return fopen(pn, "w");
1390 }
1391
1392 /*
1393  * °ì»þ¥Õ¥¡¥¤¥ë¤«¤ébase¥Õ¥¡¥¤¥ë¤Ørename¤¹¤ë 
1394  */
1395 static void
1396 update_file(const char *fn)
1397 {
1398   const char *hd;
1399   char *tmp_fn;
1400   const char *sid;
1401   hd = anthy_conf_get_str("HOME");
1402   sid = anthy_conf_get_str("SESSION-ID");
1403   tmp_fn = alloca(strlen(hd)+strlen(sid) + 10);
1404
1405   sprintf(tmp_fn, "%s/.anthy/%s", hd, sid);
1406   if (rename(tmp_fn, fn)){
1407     anthy_log(0, "Failed to update record file %s -> %s.\n", tmp_fn, fn);
1408   }
1409 }
1410
1411 /* ¥«¥é¥à¤òÊݸ¤¹¤ë */
1412 static void
1413 save_a_row(FILE *fp, struct record_stat* rst,
1414            struct record_row *c, int dirty)
1415 {
1416   int i;
1417   char *buf = alloca(c->key.len * 6 + 2);
1418   /* LRU¤Î¥Þ¡¼¥¯¤ò½ÐÎÏ */
1419   if (dirty == 0) {
1420     fputc('-', fp);
1421   } else {
1422     fputc('+', fp);
1423   }
1424   anthy_sputxstr(buf, &c->key, rst->encoding);
1425   /* index ¤ò½ÐÎÏ */
1426   fprintf(fp, "%s ", buf);
1427   /**/
1428   for (i = 0; i < c->nr_vals; i++) {
1429     struct record_val *val = &c->vals[i];
1430     switch (val->type) {
1431     case RT_EMPTY:
1432       fprintf(fp, "* ");
1433       break;
1434     case RT_XSTR:
1435       /* should not happen */
1436       fprintf(fp, "\"");
1437       write_quote_xstr(fp, &val->u.str, rst->encoding);
1438       fprintf(fp, "\" ");
1439       abort();
1440       break;
1441     case RT_XSTRP:
1442       fprintf(fp, "\"");
1443       write_quote_xstr(fp, val->u.strp, rst->encoding);
1444       fprintf(fp, "\" ");
1445       break;
1446     case RT_VAL:
1447       fprintf(fp, "%d ", val->u.val);
1448       break;
1449     default:
1450       anthy_log(0, "Faild to save an unkonwn record. (in record.c)\n");
1451       break;
1452     }
1453   }
1454   fprintf(fp, "\n");
1455 }
1456
1457 static void
1458 update_base_record(struct record_stat* rst)
1459 {
1460   struct record_section *sec;
1461   struct trie_node *col;
1462   FILE *fp;
1463   struct stat st;
1464
1465   /* °ì»þ¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Ærecord¤ò½ñ¤­½Ð¤¹ */
1466   anthy_check_user_dir();
1467   fp = open_tmp_in_recorddir();
1468   if (!fp) {
1469     anthy_log(0, "Failed to open temporaly session file.\n");
1470     return ;
1471   }
1472   /* ³Æ¥»¥¯¥·¥ç¥ó¤ËÂФ·¤Æ */
1473   for (sec = rst->section_list.next;
1474        sec; sec = sec->next) {
1475     if (!trie_first(&sec->cols)) {
1476       /*¤³¤Î¥»¥¯¥·¥ç¥ó¤Ï¶õ*/
1477       continue;
1478     }
1479     /* ¥»¥¯¥·¥ç¥ó¶­³¦¤Îʸ»úÎó */
1480     fprintf(fp, "--- %s\n", sec->name);
1481     /* ³Æ¥«¥é¥à¤òÊݸ¤¹¤ë */
1482     for (col = trie_first(&sec->cols); col; 
1483          col = trie_next(&sec->cols, col)) {
1484       save_a_row(fp, rst, &col->row, col->dirty);
1485     }
1486   }
1487   fclose(fp);
1488
1489   /* ËÜÍè¤Î̾Á°¤Ërename¤¹¤ë */
1490   update_file(rst->base_fn);
1491
1492   if (stat(rst->base_fn, &st) == 0) {
1493     rst->base_timestamp = st.st_mtime;
1494   }
1495   /* journal¥Õ¥¡¥¤¥ë¤ò¾Ã¤¹ */
1496   unlink(rst->journal_fn);
1497   rst->last_update = 0;
1498 }
1499
1500 static void
1501 commit_del_row(struct record_stat* rst,
1502                const char* sname, struct trie_node* node)
1503 {
1504   FILE* fp;
1505
1506   fp = fopen(rst->journal_fn, "a");
1507   if (fp == NULL) {
1508     return;
1509   }
1510   write_string(fp, "DEL \"");
1511   write_quote_string(fp, sname);
1512   write_string(fp, "\" S\"");
1513   write_quote_xstr(fp, &node->row.key, rst->encoding);
1514   write_string(fp, "\"");
1515   write_string(fp, "\n");
1516   fclose(fp);
1517 }
1518
1519 /*
1520  * sync_add: ADD ¤Î½ñ¤­¹þ¤ß
1521  * sync_del_and_del: DEL ¤Î½ñ¤­¹þ¤ß¤Èºï½ü
1522  *   ¤É¤Á¤é¤â½ñ¤­¹þ¤ß¤ÎÁ°¤Ë¡¢Â¾¤Î¥×¥í¥»¥¹¤Ë¤è¤Ã¤Æ¥Ç¥£¥¹¥¯¾å¤ËÊݸ¤µ¤ì¤¿
1523  *   ¹¹¿·¤ò¥á¥â¥ê¾å¤ËÆɤ߹þ¤à¡£
1524  *   ¤³¤Î¤È¤­¡¢¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥Õ¥é¥Ã¥·¥å¤¹¤ë²ÄǽÀ­¤â¤¢¤ë¡£¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î
1525  *   ¥Õ¥é¥Ã¥·¥å¤¬¤¢¤ë¤È¡¢ cur_row ¤ÈÁ´¤Æ¤Î xstr ¤Ï̵¸ú¤Ë¤Ê¤ë¡£
1526  *   ¤¿¤À¤·¡¢ cur_section ¤ÎÍ­¸úÀ­¤ÏÊݸ¤µ¤ì¤ë¡£
1527  */
1528 static void
1529 sync_add(struct record_stat* rst, struct record_section* rsc, 
1530          struct trie_node* node)
1531 {
1532   lock_record(rst);
1533   if (check_base_record_uptodate(rst)) {
1534     node->dirty |= PROTECT;
1535     /* º¹Ê¬¥Õ¥¡¥¤¥ë¤À¤±Æɤà */
1536     read_journal_record(rst);
1537     node->dirty &= ~PROTECT;
1538     commit_add_row(rst, rsc->name, node);
1539   } else {
1540     /* ºÆÆɤ߹þ¤ß */
1541     commit_add_row(rst, rsc->name, node);
1542     read_base_record(rst);
1543     read_journal_record(rst);
1544   }
1545   if (rst->last_update > FILE2_LIMIT) {
1546     update_base_record(rst);
1547   }
1548   unlock_record(rst);
1549 }
1550
1551 static void
1552 sync_del_and_del(struct record_stat* rst, struct record_section* rsc, 
1553                  struct trie_node* node)
1554 {
1555   lock_record(rst);
1556   commit_del_row(rst, rsc->name, node);
1557   if (!check_base_record_uptodate(rst)) {
1558     read_base_record(rst);
1559   }
1560   read_journal_record(rst);
1561   if (rst->last_update > FILE2_LIMIT) {
1562     update_base_record(rst);
1563   }
1564   unlock_record(rst);
1565 }
1566
1567
1568 /*
1569  * prediction´Ø·¸
1570  */
1571
1572 static int
1573 read_prediction_node(struct trie_node *n, struct prediction_t* predictions, int index)
1574 {
1575   int i;
1576   int nr_predictions = do_get_nr_values(n);
1577   for (i = 0; i < nr_predictions; i += 2) {
1578     time_t t = do_get_nth_value(n, i);
1579     xstr* xs = do_get_nth_xstr(n, i + 1);
1580     if (t && xs) {
1581       if (predictions) {
1582         predictions[index].timestamp = t;
1583         predictions[index].src_str = anthy_xstr_dup(&n->row.key);
1584         predictions[index].str = anthy_xstr_dup(xs);
1585       }
1586       ++index;
1587     }
1588   }
1589   return index;
1590 }
1591
1592
1593 /*
1594  * trieÃæ¤ò¤¿¤É¤ê¡¢prefix¤¬¥Þ¥Ã¥Á¤·¤¿¤éread_prediction_node¤ò
1595  * ¸Æ¤ó¤Çpredictions¤ÎÇÛÎó¤Ë·ë²Ì¤òÄɲ乤롣
1596  */
1597 static int
1598 traverse_record_for_prediction(xstr* key, struct trie_node *n,
1599                                struct prediction_t* predictions, int index)
1600 {
1601   if (n->l->bit > n->bit) {
1602     index = traverse_record_for_prediction(key, n->l, predictions, index);
1603   } else {
1604     if (n->l->row.key.len != -1) {
1605       if (anthy_xstrncmp(&n->l->row.key, key, key->len) == 0) {
1606         index = read_prediction_node(n->l, predictions, index);
1607       }
1608     }
1609   }
1610   if (n->r->bit > n->bit) {
1611     index = traverse_record_for_prediction(key, n->r, predictions, index);
1612   } else {
1613     if (n->r->row.key.len != -1) {
1614       if (anthy_xstrncmp(&n->r->row.key, key, key->len) == 0) {
1615         index = read_prediction_node(n->r, predictions, index);
1616       }
1617     }
1618   }
1619   return index;
1620 }
1621
1622 /*
1623  * key ¤Çõº÷
1624  * key ¤Îʸ»úÎóŤò±Û¤¨¤ë¤«¡¢¥Î¡¼¥É¤¬Ìµ¤¯¤Ê¤Ã¤¿¤éõº÷ÂǤÁÀÚ¤ê
1625  * trie¤Îkey¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤ë¤È¤³¤í¤Ç¤Ê¤Ê¤¯¤ÆÍÕ¤òÊÖ¤¹
1626  */
1627 static struct trie_node *
1628 trie_find_for_prediction (struct trie_root* root, xstr *key)
1629 {
1630   struct trie_node *p;
1631   struct trie_node *q;
1632
1633   p = &root->root;
1634   q = p->l;
1635
1636   while (p->bit < q->bit) {
1637     if (q->bit >= 2) {
1638       if ((q->bit - 2) / (int)(sizeof(xchar) << 3) >= key->len) {
1639         break;
1640       }
1641     }
1642     p = q;
1643     q = trie_key_nth_bit(key, p->bit) ? p->r : p->l;
1644   }
1645   return p;
1646 }
1647
1648 static int
1649 prediction_cmp(const void* lhs, const void* rhs)
1650 {
1651   struct prediction_t *lpre = (struct prediction_t*)lhs;
1652   struct prediction_t *rpre = (struct prediction_t*)rhs;
1653   return rpre->timestamp - lpre->timestamp;
1654 }
1655
1656 int
1657 anthy_traverse_record_for_prediction(xstr* key, struct prediction_t* predictions)
1658 {
1659   struct trie_node* mark;
1660   int nr_predictions;
1661   if (anthy_select_section("PREDICTION", 0)) {
1662     return 0;
1663   }
1664
1665   /* »ØÄꤵ¤ì¤¿Ê¸»úÎó¤òprefix¤Ë»ý¤Änode¤òõ¤¹ */
1666   mark = trie_find_for_prediction(&anthy_current_record->cur_section->cols, key);
1667   if (!mark) {
1668     return 0;
1669   }
1670   nr_predictions = traverse_record_for_prediction(key, mark, predictions, 0);
1671   if (predictions) {
1672     /* ¥¿¥¤¥à¥¹¥¿¥ó¥×¤Çͽ¬¸õÊä¤ò¥½¡¼¥È¤¹¤ë */
1673     qsort(predictions, nr_predictions, sizeof(struct prediction_t), prediction_cmp);
1674   }
1675   return nr_predictions;
1676 }
1677
1678 /* Wrappers begin.. */
1679 int 
1680 anthy_select_section(const char *name, int flag)
1681 {
1682   struct record_stat* rst;
1683   struct record_section* rsc;
1684
1685   rst = anthy_current_record;
1686   if (rst->row_dirty && rst->cur_section && rst->cur_row) {
1687     sync_add(rst, rst->cur_section, rst->cur_row);
1688   }
1689   rst->cur_row = NULL;
1690   rst->row_dirty = 0;
1691   rsc = do_select_section(rst, name, flag);
1692   if (!rsc) {
1693     return -1;
1694   }
1695   rst->cur_section = rsc;
1696   return 0;
1697 }
1698
1699 int
1700 anthy_select_row(xstr *name, int flag)
1701 {
1702   struct record_stat* rst;
1703   struct trie_node* node;
1704
1705   rst = anthy_current_record;
1706   if (!rst->cur_section) {
1707     return -1;
1708   }
1709   if (rst->row_dirty && rst->cur_row) {
1710     sync_add(rst, rst->cur_section, rst->cur_row);
1711     rst->row_dirty = 0;
1712   }
1713   node = do_select_row(rst->cur_section, name, flag, LRU_USED);
1714   if (!node) {
1715     return -1;
1716   }
1717   rst->cur_row = node;
1718   rst->row_dirty = flag;
1719   return 0;
1720 }
1721
1722 int
1723 anthy_select_longest_row(xstr *name)
1724 {
1725   struct record_stat* rst;
1726   struct trie_node* node;
1727
1728   rst = anthy_current_record;
1729   if (!rst->cur_section)
1730     return -1;
1731
1732   if (rst->row_dirty && rst->cur_row) {
1733     sync_add(rst, rst->cur_section, rst->cur_row);
1734     rst->row_dirty = 0;
1735   }
1736   node = do_select_longest_row(rst->cur_section, name);
1737   if (!node) {
1738     return -1;
1739   }
1740
1741   rst->cur_row = node;
1742   rst->row_dirty = 0;
1743   return 0;
1744 }
1745
1746 void
1747 anthy_truncate_section(int count)
1748 {
1749   do_truncate_section(anthy_current_record, count);
1750 }
1751
1752 void
1753 anthy_truncate_row(int nth)
1754 {
1755   struct trie_node *cur_row = anthy_current_record->cur_row;  
1756   if (!cur_row) {
1757     return ;
1758   }
1759   do_truncate_row(cur_row, nth);
1760
1761 }
1762
1763 int
1764 anthy_mark_row_used(void)
1765 {
1766   struct record_stat* rst = anthy_current_record;
1767   if (!rst->cur_row) {
1768     return -1;
1769   }
1770
1771   do_mark_row_used(rst->cur_section, rst->cur_row);
1772   sync_add(rst, rst->cur_section, rst->cur_row);
1773   rst->row_dirty = 0;
1774   return 0;
1775 }
1776
1777 void
1778 anthy_set_nth_value(int nth, int val)
1779 {
1780   struct record_stat* rst;
1781
1782   rst = anthy_current_record;
1783   if (!rst->cur_row) {
1784     return;
1785   }
1786   do_set_nth_value(rst->cur_row, nth, val);
1787   rst->row_dirty = 1;
1788 }
1789
1790 void
1791 anthy_set_nth_xstr(int nth, xstr *xs)
1792 {
1793   struct record_stat* rst = anthy_current_record;
1794   if (!rst->cur_row) {
1795     return;
1796   }
1797   do_set_nth_xstr(rst->cur_row, nth, xs, &rst->xstrs);
1798   rst->row_dirty = 1;
1799 }
1800
1801 int
1802 anthy_get_nr_values(void)
1803 {
1804   return do_get_nr_values(anthy_current_record->cur_row);
1805 }
1806
1807 int
1808 anthy_get_nth_value(int n)
1809 {
1810   return do_get_nth_value(anthy_current_record->cur_row, n);
1811 }
1812
1813 xstr *
1814 anthy_get_nth_xstr(int n)
1815 {
1816   return do_get_nth_xstr(anthy_current_record->cur_row, n);
1817 }
1818
1819 int
1820 anthy_select_first_row(void)
1821 {
1822   struct record_stat* rst;
1823   struct trie_node* node;
1824
1825   rst = anthy_current_record;
1826   if (!rst->cur_section)
1827     return -1;
1828   
1829   if (rst->row_dirty && rst->cur_row) {
1830     sync_add(rst, rst->cur_section, rst->cur_row);
1831     rst->row_dirty = 0;
1832   }
1833   node = do_select_first_row(rst->cur_section);
1834   if (!node) {
1835     return -1;
1836   }
1837   rst->cur_row = node;
1838   rst->row_dirty = 0;
1839   return 0;
1840 }
1841
1842 int
1843 anthy_select_next_row(void)
1844 {
1845   struct record_stat* rst;
1846   struct trie_node* node;
1847
1848   rst = anthy_current_record;
1849   if (!rst->cur_section || !rst->cur_row)
1850     return -1;
1851   
1852   /* sync_add() ¤Ç cur_row ¤¬Ìµ¸ú¤Ë¤Ê¤ë¤³¤È¤¬¤¢¤ë¤Î¤Ç¡¢
1853    * ¤¿¤È¤¨ row_dirty ¤Ç¤â sync_add() ¤·¤Ê¤¤
1854    */
1855   rst->row_dirty = 0;
1856   node = do_select_next_row(rst->cur_section, rst->cur_row);
1857   if (!node)
1858     return -1;
1859   rst->cur_row = node;
1860   rst->row_dirty = 0;
1861   return 0;
1862 }
1863
1864 xstr *
1865 anthy_get_index_xstr(void)
1866 {
1867   return do_get_index_xstr(anthy_current_record);
1868 }
1869 /*..Wrappers end*/
1870
1871 /*
1872  * trie_row_init ¤Ï²¿²ó¤è¤ó¤Ç¤â¤¤¤¤
1873  */
1874 static void
1875 trie_row_init(struct record_row* rc)
1876 {
1877   rc->nr_vals = 0;
1878   rc->vals = NULL;
1879 }
1880
1881 static void
1882 trie_row_free(struct record_row *rc)
1883 {
1884   int i;
1885   for (i = 0; i < rc->nr_vals; i++)
1886     free_val_contents(rc->vals + i);
1887   free(rc->vals);
1888   free(rc->key.str);
1889 }  
1890
1891 /* ¤¢¤ë¥»¥¯¥·¥ç¥ó¤Î¥Ç¡¼¥¿¤òÁ´¤Æ²òÊü¤¹¤ë */
1892 static void
1893 free_section(struct record_stat *r, struct record_section *rs)
1894 {
1895   struct record_section *s;
1896   trie_remove_all(&rs->cols, &rs->lru_nr_used, &rs->lru_nr_sused);
1897   if (r->cur_section == rs) {
1898     r->cur_row = 0;
1899     r->cur_section = 0;
1900   }
1901   for (s = &r->section_list; s && s->next; s = s->next) {
1902     if (s->next == rs) {
1903       s->next = s->next->next;
1904     }
1905   }
1906   if (rs->name){
1907     free((void *)rs->name);
1908   }
1909   free(rs);
1910 }
1911
1912 /* ¤¹¤Ù¤Æ¤Î¥Ç¡¼¥¿¤ò²òÊü¤¹¤ë */
1913 static void
1914 free_record(struct record_stat *rst)
1915 {
1916   struct record_section *rsc;
1917   for (rsc = rst->section_list.next; rsc; ){
1918     struct record_section *tmp;
1919     tmp = rsc;
1920     rsc = rsc->next;
1921     free_section(rst, tmp);
1922   }
1923   rst->section_list.next = NULL;
1924 }
1925
1926 void
1927 anthy_release_section(void)
1928 {
1929   struct record_stat* rst;
1930
1931   rst = anthy_current_record;
1932   if (!rst->cur_section) {
1933     return ;
1934   }
1935   free_section(rst, rst->cur_section);
1936   rst->cur_section = 0;
1937 }
1938
1939 void
1940 anthy_release_row(void)
1941 {
1942   struct record_stat* rst;
1943
1944   rst = anthy_current_record;
1945   if (!rst->cur_section || !rst->cur_row) {
1946     return;
1947   }
1948
1949   rst->row_dirty = 0;
1950   /* sync_del_and_del ¤Çºï½ü¤â¤¹¤ë */
1951   sync_del_and_del(rst, rst->cur_section, rst->cur_row);
1952   rst->cur_row = NULL;
1953 }
1954
1955 static void
1956 check_record_encoding(struct record_stat *rst)
1957 {
1958   FILE *fp;
1959   if (anthy_open_file(rst->base_fn) == 0) {
1960     /* EUC¤ÎÍúÎò¥Õ¥¡¥¤¥ë¤¬¤¢¤Ã¤¿ */
1961     anthy_close_file();
1962     return ;
1963   }
1964   fp = fopen(rst->journal_fn, "r");
1965   if (fp) {
1966     /* EUC¤Îº¹Ê¬¥Õ¥¡¥¤¥ë¤¬¤¢¤Ã¤¿ */
1967     fclose(fp);
1968     return ;
1969   }
1970   rst->encoding = ANTHY_UTF8_ENCODING;
1971   strcat(rst->base_fn, ENCODING_SUFFIX);
1972   strcat(rst->journal_fn, ENCODING_SUFFIX);
1973 }
1974
1975 static void
1976 record_dtor(void *p)
1977 {
1978   int dummy;
1979   struct record_stat *rst = (struct record_stat*) p;
1980   free_record(rst);
1981   if (rst->id) {
1982     free(rst->base_fn);
1983     free(rst->journal_fn);
1984   }
1985   trie_remove_all(&rst->xstrs, &dummy, &dummy);
1986 }
1987
1988 void
1989 anthy_reload_record(void)
1990 {
1991   struct stat st;
1992   struct record_stat *rst = anthy_current_record;
1993   
1994   if (stat(rst->journal_fn, &st) == 0 &&
1995       rst->journal_timestamp == st.st_mtime) {
1996     return ;
1997   }
1998
1999   lock_record(rst);
2000   read_base_record(rst);
2001   read_journal_record(rst);
2002   unlock_record(rst);
2003 }
2004
2005 void
2006 anthy_init_record(void)
2007 {
2008   record_ator = anthy_create_allocator(sizeof(struct record_stat),
2009                                        record_dtor);
2010 }
2011
2012 static void
2013 setup_filenames(const char *id, struct record_stat *rst)
2014 {
2015   const char *home = anthy_conf_get_str("HOME");
2016   int base_len = strlen(home) + strlen(id) + 10;
2017
2018   /* ´ðËÜ¥Õ¥¡¥¤¥ë */
2019   rst->base_fn = (char*) malloc(base_len +
2020                                 strlen("/.anthy/last-record1_"));
2021   sprintf(rst->base_fn, "%s/.anthy/last-record1_%s",
2022           home, id);
2023   /* º¹Ê¬¥Õ¥¡¥¤¥ë */
2024   rst->journal_fn = (char*) malloc(base_len +
2025                                    strlen("/.anthy/last-record2_"));
2026   sprintf(rst->journal_fn, "%s/.anthy/last-record2_%s",
2027           home, id);
2028 }
2029
2030 struct record_stat *
2031 anthy_create_record(const char *id)
2032 {
2033   struct record_stat *rst;
2034
2035   if (!id) {
2036     return NULL;
2037   }
2038
2039   rst = anthy_smalloc(record_ator);
2040   rst->id = id;
2041   rst->section_list.next = 0;
2042   init_trie_root(&rst->xstrs);
2043   rst->cur_section = 0;
2044   rst->cur_row = 0;
2045   rst->row_dirty = 0;
2046   rst->encoding = 0;
2047
2048   /* ¥Õ¥¡¥¤¥ë̾¤Îʸ»úÎó¤òºî¤ë */
2049   setup_filenames(id, rst);
2050
2051   rst->last_update = 0;
2052
2053   if (!strcmp(id, ANON_ID)) {
2054     rst->is_anon = 1;
2055   } else {
2056     rst->is_anon = 0;
2057     anthy_check_user_dir();
2058   }
2059
2060   /* ¥Õ¥¡¥¤¥ë¤«¤éÆɤ߹þ¤à */
2061   lock_record(rst);
2062   check_record_encoding(rst);
2063   read_base_record(rst);
2064   read_journal_record(rst);
2065   unlock_record(rst);
2066
2067   return rst;
2068 }
2069
2070 void
2071 anthy_release_record(struct record_stat *rs)
2072 {
2073   anthy_sfree(record_ator, rs);
2074 }