1 /*
2  * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
3  * This file is part of FreeWnn.
4  *
5  * Copyright Kyoto University Research Institute for Mathematical Sciences
6  *                 1987, 1988, 1989, 1990, 1991, 1992
7  * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
8  * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
9  * Copyright FreeWnn Project 1999, 2000, 2002, 2003
10  *
11  * Maintainer:  FreeWnn Project   <freewnn@tomo.gr.jp>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 static char rcs_id[] = "$Id: b_index.c,v 1.8 2003/06/07 02:23:58 hiroo Exp $";
28 
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32 
33 #include <stdio.h>
34 #if STDC_HEADERS
35 #  include <stdlib.h>
36 #else
37 #  if HAVE_MALLOC_H
38 #    include <malloc.h>
39 #  endif
40 #endif /* STDC_HEADERS */
41 
42 #include "commonhd.h"
43 #include "de_header.h"
44 #include "jdata.h"
45 
46 #ifdef CONVERT_by_STROKE
47 /*******  Create B_dic index  *************************************/
48 static int delete_b_node (struct JT *jt, w_char *yomi, int level, int p_node);
49 static int creat_b_node (struct JT *jt, w_char *yomi, int level, int p_node);
50 static int bnode_alloc (struct JT *jt);
51 static int bnode_free (struct JT *jt, int k);
52 
53 static int free_bnode = -1;     /* Initially no free b_node */
54 static int b_cnt;               /* Current member of b_node in b_nodes area */
55                                 /* Note,  b_cnt < jt->bufsize_bnode */
56 
57 /*----------------------------------------------------------------+
58   SYNOPSYS: Create b_index for b_dic.
59   RETURN VALUE: success: b_cnt (current b_node); failure: -1
60  +----------------------------------------------------------------*/
61 int
create_b_index(struct JT * jt)62 create_b_index (struct JT *jt)
63 {
64   int i;
65   int serial;
66   w_char *yomi;                 /* The inputed character string */
67 
68   /* Make Space of b_nodes */
69   jt->bind = (struct b_node *) malloc (2 * jt->bufsize_ri1[0] * sizeof (struct b_node));
70 
71   /*  If the bind size is determined in atod, we use the
72      following statement instead of the above
73    */
74   if (jt->bind == NULL)
75     {
76       log_err ("error in creating head of b_index.");
77       return (-1);
78     }
79   /* Set the first one be a  dummy b_node */
80   jt->bind[0].pter_next = -1;
81   jt->bind[0].pter_son = -1;
82   jt->bind[0].pter = -1;
83 
84 /* Delete the following line when the bufsize of bnode is set at atod step */
85   jt->bufsize_bnode = 2 * jt->bufsize_ri1[0];
86 
87   b_cnt = 0;
88 
89         /** For each tuple in ri1[0] create b_nodes */
90   for (i = 0; i < jt->maxri1[0]; i++)
91     {
92       serial = (jt->ri1[0] + i)->pter;
93       yomi = KANJI_str (jt->ri2[serial].kanjipter + jt->kanji, 0);
94       b_index_add (jt, yomi, serial);
95     }
96   return (b_cnt);
97 }
98 
99 /*----------------------------------------------------------------+
100   SYNOPSYS: Create a b_node for each character in a tuple.
101   RETURN VALUE:	success: 0;  failure: -1
102  +----------------------------------------------------------------*/
103 int
b_index_add(struct JT * jt,w_char * yomi,int serial)104 b_index_add (struct JT *jt, w_char *yomi, int serial)
105 {
106   int k;
107   int p_node;                   /* Current b_node in No.  */
108 
109   p_node = 0;
110   for (k = 0; k < Strlen (yomi); k++)
111     {
112       if ((p_node = creat_b_node (jt, yomi, k, p_node)) == -1)
113         {
114           log_err ("error in creating b_index.");
115           return (-1);
116         }
117     }
118   jt->bind[p_node].pter = serial;
119   return (0);
120 }
121 
122 /*----------------------------------------------------------------+
123   SYNOPSYS:
124  +----------------------------------------------------------------*/
125 void
b_index_delete(struct JT * jt,int serial)126 b_index_delete (struct JT *jt, int serial)
127 {
128   w_char *yomi;
129   yomi = KANJI_str (jt->ri2[serial].kanjipter + jt->kanji, 0);
130   delete_b_node (jt, yomi, 0, 0);
131 }
132 
133 /*----------------------------------------------------------------+
134   SYNOPSYS:
135   RETURN VALUE:	0  Having no son
136  		1  Having some sons
137  +----------------------------------------------------------------*/
138 static int
delete_b_node(struct JT * jt,w_char * yomi,int level,int p_node)139 delete_b_node (struct JT *jt, w_char *yomi, int level, int p_node)
140 {
141   int tmp_node;
142   int buf_node1, buf_node2;
143   w_char *yo_kanji = NULL;
144 
145   if (p_node == -1)
146     return (0);
147 
148   buf_node1 = jt->bind[p_node].pter_son;        /*Initialize two tmp nodes */
149   buf_node2 = jt->bind[p_node].pter_son;
150 
151   /* search if the node exists already */
152   while (buf_node2 != -1)
153     {
154       tmp_node = buf_node2;
155       while (jt->bind[tmp_node].pter == -1)
156         {
157           tmp_node = jt->bind[tmp_node].pter_son;
158         }
159       yo_kanji = KANJI_str (jt->ri2[jt->bind[tmp_node].pter].kanjipter + jt->kanji, 0);
160       if (yomi[level] > yo_kanji[level])
161         {
162           buf_node1 = buf_node2;
163           buf_node2 = jt->bind[buf_node2].pter_next;
164         }
165       else
166         break;
167     }
168   if (yo_kanji == NULL || yomi[level] != yo_kanji[level])
169     {
170       /* Error case */
171       log_err ("error on b_index.");
172       return (-1);
173     }
174 
175   if (level == (Strlen (yomi) - 1))
176     {
177       jt->bind[buf_node2].pter = -1;    /* HERE HERE */
178       if (jt->bind[buf_node2].pter_son != -1)   /* having son */
179         return (1);
180     }
181   if (level < (Strlen (yomi) - 1))
182     {
183       if ((delete_b_node (jt, yomi, level + 1, buf_node2) != 0) || (jt->bind[buf_node2].pter != -1))
184         return (1);
185     }
186   /* 0 case: (bnode_free) below */
187   if (buf_node1 == buf_node2)
188     {                           /* only one b_node in this level */
189       bnode_free (jt, buf_node2);
190       return (0);
191     }
192   else
193     {
194       jt->bind[buf_node1].pter_next = jt->bind[buf_node2].pter_next;
195       bnode_free (jt, buf_node2);
196       return (1);
197     }
198 }
199 
200 /*----------------------------------------------------------------+
201   SYNOPSIS: Create a son of the parent node p_node, when it does
202  	 not exist.
203   PARAMETERS:	jt: Header of the current dic.
204 		yomi: Cureent character in this level.
205 		level: Level number.
206 		p_node: cureent b_node.
207   RETURN VALUE:	new or existent node number whether created or existed.
208 		failure: -1
209  +----------------------------------------------------------------*/
210 static int
creat_b_node(struct JT * jt,w_char * yomi,int level,int p_node)211 creat_b_node (struct JT *jt, w_char *yomi, int level, int p_node)
212 {
213   int new_node;
214   int buf_node1, buf_node2;
215   int tmp_node;
216   w_char *yo_kanji = NULL;
217 
218   buf_node1 = jt->bind[p_node].pter_son;        /*Initialize two tmp nodes */
219   buf_node2 = jt->bind[p_node].pter_son;
220 
221   /* search if the node exists already */
222   while (buf_node2 != -1)
223     {
224       tmp_node = buf_node2;
225       while (jt->bind[tmp_node].pter == -1)
226         {
227           tmp_node = jt->bind[tmp_node].pter_son;
228         }
229       yo_kanji = KANJI_str (jt->ri2[jt->bind[tmp_node].pter].kanjipter + jt->kanji, 0);
230 
231       if (yomi[level] > yo_kanji[level])
232         {
233           buf_node1 = buf_node2;
234           buf_node2 = jt->bind[buf_node2].pter_next;
235         }
236       else
237         break;
238     }
239 
240   if (buf_node1 == -1)
241     {                           /* the cur is the first */
242       if (buf_node2 == -1)
243         {
244           if ((new_node = bnode_alloc (jt)) == -1)
245             {
246               log_err ("error in reallocing area of b_index.");
247               return (-1);
248             }
249           jt->bind[p_node].pter_son = new_node;
250 
251           jt->bind[new_node].pter_next = -1;
252           jt->bind[new_node].pter_son = -1;
253           jt->bind[new_node].pter = -1;
254         }
255       else
256         return (-1);            /* Error case.  Impossible case  */
257       return (new_node);
258 
259     }
260   else if (buf_node2 == -1)
261     {                           /* insert to last */
262       new_node = bnode_alloc (jt);
263       jt->bind[buf_node1].pter_next = new_node;
264 
265       jt->bind[new_node].pter_next = -1;
266       jt->bind[new_node].pter_son = -1;
267       jt->bind[new_node].pter = -1;
268       return (new_node);
269 
270     }
271   else if (yo_kanji == NULL)
272     {
273       return (-1);
274     }
275   else if (yomi[level] == yo_kanji[level])      /* exist already */
276     return (buf_node2);
277 
278   /* insert  in before tnp_node2 */
279   else if (yomi[level] < yo_kanji[level])
280     {
281       new_node = bnode_alloc (jt);
282       jt->bind[new_node].pter_next = buf_node2;
283       jt->bind[new_node].pter_son = -1;
284       jt->bind[new_node].pter = -1;
285 
286 
287       if (buf_node1 == buf_node2)       /*insert to first */
288         jt->bind[p_node].pter_son = new_node;
289       else
290         jt->bind[buf_node1].pter_next = new_node;       /*to middle */
291       return (new_node);
292     }
293   else
294     return (-1);
295 }
296 
297 
298 /*----------------------------------------------------------------+
299   SYNOPSYS: Get a b_node from free_bnode list if there is any.
300 	Otherwise get a b_node sequencially by doing b_cnt++.
301 	When b_cnt is greater than bufsize of b_node, rallocation
302 	will be performed.
303   RETURN VALUE:
304  +----------------------------------------------------------------*/
305 static int
bnode_alloc(struct JT * jt)306 bnode_alloc (struct JT *jt)
307 {
308   int i;
309 
310   if (free_bnode != -1)
311     {                           /* Use free b_nodes */
312       i = free_bnode;
313       free_bnode = jt->bind[free_bnode].pter_next;
314       return (i);
315     }
316   if (b_cnt++ >= jt->bufsize_bnode)     /* Use new  b_nodes */
317     if (rd_realloc_bind (jt) == NULL)	/* realloc jt->bind */
318       return (-1);
319   return (jt->bufsize_bnode = b_cnt);   /* Not re-alloc */
320 }
321 
322 /*----------------------------------------------------------------+
323   SYNOPSIS: Free b_node[k] from jt.
324  +----------------------------------------------------------------*/
325 static int
bnode_free(struct JT * jt,int k)326 bnode_free (struct JT *jt, int k)
327 {
328   if (k <= 0 || k > jt->max_bnode)
329     {
330       log_err ("error: bnode_free()");
331       return (-1);
332     }
333   jt->bind[k].pter = -1;        /* Initial this node   */
334   jt->bind[k].pter_son = -1;
335   jt->bind[k].pter_next = -1;
336 
337   if (k < jt->max_bnode)
338     {
339       jt->bind[k].pter_next = free_bnode;
340       free_bnode = k;
341     }
342   else
343     jt->max_bnode = --b_cnt;    /* case of k==b_cnt */
344   return (0);
345 }
346 #endif /* CONVERT_by_STROKE */
347