1 /* # skkinput (Simple Kana-Kanji Input)
2  *
3  * This file is part of skkinput.
4  * Copyright (C) 2002
5  * Takashi SAKAMOTO (PXG01715@nifty.ne.jp)
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with skkinput; see the file COPYING.  If not, write to
19  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include "local.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <sys/time.h>
27 #include "lispmgrp.h"
28 #include "cstring.h"
29 
30 static	Boolean	lispMgr_initialize 				(TLispManager*) ;
31 static	Boolean	lispMgr_collectOtherGarbage		(TLispManager*, TLispEntity**) ;
32 static	Boolean	lispMgr_markEntityRecursively	(TLispManager*, TLispEntity*) ;
33 static	Boolean	lispMgr_registerEntityToList    (TLispManager*, TLispEntity**, TLispEntity*) ;
34 
35 /*	inline functions */
36 inline	Boolean
lispMgr_markedEntityp(register TLispManager * pLispMgr,register TLispEntity * pEntity)37 lispMgr_markedEntityp (
38 	register TLispManager*	pLispMgr,
39 	register TLispEntity*	pEntity)
40 {
41 	assert (pLispMgr != NULL) ;
42 	assert (pEntity  != NULL) ;
43 
44 	return	(pEntity->m_iMarker == pLispMgr->m_iMarker)? True : False ;
45 }
46 
47 inline	Boolean
lispMgr_markEntity(register TLispManager * pLispMgr,register TLispEntity * pEntity)48 lispMgr_markEntity (
49 	register TLispManager*	pLispMgr,
50 	register TLispEntity*	pEntity)
51 {
52 	assert (pLispMgr != NULL) ;
53 	assert (pEntity  != NULL) ;
54 
55 	pEntity->m_iMarker	= pLispMgr->m_iMarker ;
56 	return	True ;
57 }
58 
59 /*	Ʊ̾/Ʊ�����Ǥ��äƤ� eq ��Ƚ��� nil ���֤� entity ��Ĥʤ���*/
60 static inline	Boolean
lispMgr_registerEntityToList(register TLispManager * pLispMgr,register TLispEntity ** ppEntTop,register TLispEntity * pEntity)61 lispMgr_registerEntityToList (
62 	register TLispManager*	pLispMgr,
63 	register TLispEntity**	ppEntTop,
64 	register TLispEntity*	pEntity)
65 {
66 	assert (pLispMgr != NULL) ;
67 	assert (ppEntTop != NULL) ;
68 	assert (pEntity  != NULL) ;
69 
70 	pEntity->m_pRight			= *ppEntTop ;
71 	pEntity->m_pLeft			= NULL ;
72 	if (*ppEntTop != NULL)
73 		(*ppEntTop)->m_pLeft	= pEntity ;
74 	*ppEntTop	= pEntity ;
75 	return	True ;
76 }
77 
78 static inline	Boolean
lispMgr_unregisterEntityFromList(register TLispManager * pLispMgr,register TLispEntity ** ppEntTop,register TLispEntity * pEntity)79 lispMgr_unregisterEntityFromList (
80 	register TLispManager*	pLispMgr,
81 	register TLispEntity**	ppEntTop,
82 	register TLispEntity*	pEntity)
83 {
84 	assert (pLispMgr != NULL) ;
85 	assert (pEntity  != NULL) ;
86 
87 	if (pEntity->m_pLeft != NULL) {
88 		pEntity->m_pLeft->m_pRight	= pEntity->m_pRight ;
89 	} else {
90 		assert (pEntity == *ppEntTop) ;
91 		*ppEntTop	= pEntity->m_pRight ;
92 	}
93 	if (pEntity->m_pRight != NULL)
94 		pEntity->m_pRight->m_pLeft	= pEntity->m_pLeft ;
95 
96 	pEntity->m_pRight			= NULL ;
97 	pEntity->m_pLeft			= NULL ;
98 
99 	return	True ;
100 }
101 
102 /*	global functions */
103 Boolean
TLispMgr_Create(register TLispManager ** const ppLispMgr)104 TLispMgr_Create (
105 	register TLispManager** const	ppLispMgr)
106 {
107 	register TLispManager*	pLispMgr ;
108 	register int			i ;
109 
110 	assert (ppLispMgr != NULL) ;
111 
112 	pLispMgr	= MALLOC (sizeof (TLispManager)) ;
113 	if (pLispMgr == NULL)
114 		return	False ;
115 
116 	for (i = 0 ; i < NELEMENTS (pLispMgr->m_apSymbolListTop) ; i ++)
117 		pLispMgr->m_apSymbolListTop [i]		= NULL ;
118 	for (i = 0 ; i < NELEMENTS (pLispMgr->m_apIntegerListTop) ; i ++)
119 		pLispMgr->m_apIntegerListTop [i]	= NULL ;
120 	for (i = 0 ; i < NELEMENTS (pLispMgr->m_apSubrListTop) ; i ++)
121 		pLispMgr->m_apSubrListTop [i]		= NULL ;
122 	pLispMgr->m_pEntListNamedMutex	= NULL ;
123 	pLispMgr->m_pEntListNoNameMutex	= NULL ;
124 	pLispMgr->m_pEntMiscListTop		= NULL ;
125 	pLispMgr->m_pEntVoid			= NULL ;
126 	pLispMgr->m_pEntEmpty			= NULL ;
127 	for (i = 0 ; i < LISPMGR_SIZE_RESERVED ; i ++)
128 		pLispMgr->m_apEntReserved [i]	= NULL ;
129 
130 	if (TFAILED (TVarbuffer_Initialize (&pLispMgr->m_vbufLocalSymbol, sizeof (TLispEntity*))))
131 		goto	error ;
132 	if (TFAILED (lispMgr_initialize (pLispMgr)))
133 		goto	error ;
134 	*ppLispMgr			= pLispMgr ;
135 	return	True ;
136 
137   error:
138 	FREE (pLispMgr) ;
139 	return	False ;
140 }
141 
142 Boolean
TLispMgr_Destroy(register TLispManager * pLispMgr)143 TLispMgr_Destroy (
144 	register TLispManager*	pLispMgr)
145 {
146 	/*	�˴��λ���...*/
147 	return	False ;
148 }
149 
150 /*	���Ȥ���Ƥ��ʤ� ENTITY ��������롣*/
151 Boolean
lispMgr_CollectGarbage(register TLispManager * pLispMgr)152 lispMgr_CollectGarbage (
153 	register TLispManager*	pLispMgr)
154 {
155 	register TLispEntity*	pEntity ;
156 #if defined (DEBUG) || 0
157 	struct timeval	start, end ;
158 	long			lEllapsed ;
159 	gettimeofday (&start, NULL) ;
160 #endif
161 
162 	pLispMgr->m_iMarker	++ ;
163 
164 	/*	ENTITY �λ��ȥ���������֤˸��ơ�ï����⻲�Ȥ���Ƥ��ʤ�¸�ߤ�
165 	 *	�������롣
166 	 *	��������Vector �� Conscell �ˤ�äƻ��Ȥ���Ƥ�����ϻ��ȥ�����
167 	 *	�����äƤ��ʤ��Τ���դ��뤳�ȡ�
168 	 *	���äơ�Vector �� Conscell ��õ���ƻ�����˥ޡ������Ƥ������Ȥ�
169 	 *	ɬ�פȤʤ롣
170 	 */
171 	pEntity	= pLispMgr->m_pEntMiscListTop ;
172 	while (pEntity != NULL) {
173 		if (pEntity->m_lReferCount > 0)
174 			lispMgr_markEntityRecursively (pLispMgr, pEntity) ;
175 		pEntity	= pEntity->m_pRight ;
176 	}
177 
178 	lispMgr_CollectIntegerGarbage (pLispMgr) ;
179 	/*	̾���դ� MUTEX �� GC ���оݤˤϷ褷�Ƥʤ�ʤ��������顢̾���դ�
180 	 *	MUTEX ��ɤ�ɤ���������ȡ��꥽��������������ġ���դ��뤳
181 	 *	�ȡ�*/
182 	lispMgr_collectOtherGarbage (pLispMgr, &pLispMgr->m_pEntListNoNameMutex) ;
183 	lispMgr_collectOtherGarbage (pLispMgr, &pLispMgr->m_pEntMiscListTop) ;
184 
185 #if defined (DEBUG) && defined (WIN32)
186 	fprintf (stderr, "GarbageCollect ... %ld ms\n", GetTickCount () - dwStart) ;
187 #endif
188 #if defined (DEBUG) || 0
189 	gettimeofday (&end, NULL) ;
190 	lEllapsed	= (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000 ;
191 	fprintf (stderr, "GC (%ld msec)\n", lEllapsed) ;
192 #endif
193 	return	True ;
194 }
195 
196 Boolean
lispMgr_UnregisterMisc(register TLispManager * pLispMgr,register TLispEntity * pEntity)197 lispMgr_UnregisterMisc (
198 	register TLispManager*	pLispMgr,
199 	register TLispEntity*	pEntity)
200 {
201 	assert (pLispMgr != NULL) ;
202 	assert (pEntity  != NULL) ;
203 	assert (0 < pEntity->m_iType && pEntity->m_iType < MAX_LISPENTITY_TYPE &&
204 			pEntity->m_iType != LISPENTITY_INTEGER) ;
205 
206 	return	lispMgr_unregisterEntityFromList (pLispMgr, &pLispMgr->m_pEntMiscListTop, pEntity) ;
207 }
208 
209 Boolean
lispMgr_initialize(register TLispManager * pLispMgr)210 lispMgr_initialize (
211 	register TLispManager*	pLispMgr)
212 {
213 	/*	�졹����ľ���ʤ��ƺѤ�褦����Ͽ���Ƥ�����*/
214 	static const char*	apReservedSymbols [LISPMGR_SIZE_RESERVED]	= {
215 		"nil",					"t",					"-",
216 		"lambda",				"macro",				"&optional",
217 		"&rest",				"keymap",				"error",
218 		"exit",					"quit",					"quit-flag",
219 		"inhibit-quit",			"features",				"interactive",
220 		"this-command",			"last-command",			"unread-command-events",
221 		"pre-command-hook",		"post-command-hook",	"last-command-char",
222 		"last-command-event",	"unread-command-char",	"global-map",
223 		"minibuffer-local-map",	"minor-mode-map-alist",	"wrong-type-argument",
224 		"buffer-file-name",		"mode-line-format",		"load-path",
225 		"kill-ring",			"kill-region",			"kill-ring-yank-pointer",
226 		"yank",
227 
228 		"coding-system-for-read",	"coding-system-for-write",	"euc-japan",
229 		"euc-jp",				"shift-jis",			"japanese-shift-jis",
230 		"sjis",					"junet",				"iso-2022-jp",
231 		"iso-2022-jp-2",		"ctext",				"x-ctext",
232 		"compound-text",
233 
234 		/*	for skk */
235 		"skk-server-host",		"skk-server-list",		"skk-portnum",
236 		"skk-process-okuri-early",	"j-henkan-key",		"j-search-key",
237 		"j-okuri-ari",			"j-henkan-okurigana",	"j-henkan-okuri-strictly",
238 
239 		/* for skk10 */
240 		"skk-servers-list",
241 	} ;
242 	/*	default �� buffer-local-symbol �Ȥ����Ѱդ���륷��ܥ롣
243 	 */
244 	static int	rnDefaultBufferSymbols []	= {
245 		LISPMGR_INDEX_BUFFER_FILE_NAME,
246 	} ;
247 	register const char**	pPtr ;
248 	register int			i ;
249 	TLispEntity*			pEntity ;
250 	TLispEntity*			pEntVoid ;
251 	TLispEntity*			pEntEmpty ;
252 
253 	pPtr	= apReservedSymbols ;
254 	for (i = 0 ; i < NELEMENTS (apReservedSymbols) ; i ++) {
255 		if (TFAILED (lispMgr_InternSymbolA (pLispMgr, *pPtr, strlen (*pPtr), &pEntity)))
256 			return	False ;
257 		lispEntity_AddRef (pLispMgr, pEntity) ;
258 		pLispMgr->m_apEntReserved [i]	= pEntity ;
259 		pPtr	++ ;
260 	}
261 	if (TFAILED (lispMgr_CreateSymbolA (pLispMgr, "void", 4, &pEntVoid)))
262 		return	False ;
263 	pEntVoid->m_iType		= LISPENTITY_VOID ;
264 	pLispMgr->m_pEntVoid	= pEntVoid ;
265 	lispEntity_AddRef (pLispMgr, pEntVoid) ;
266 	if (TFAILED (lispMgr_CreateSymbolA (pLispMgr, "empty", 4, &pEntEmpty)))
267 		return	False ;
268 	pEntEmpty->m_iType		= LISPENTITY_EMPTY ;
269 	pLispMgr->m_pEntEmpty	= pEntEmpty ;
270 
271 	/*	default �� buffer-local �ˤʤ� symbol ����Ͽ���Ƥ��������ߤΤȤ���
272 	 *		buffer-file-name,
273 	 *	�������ꤷ�Ƥ��롣
274 	 */
275 	for (i = 0 ; i < NELEMENTS (rnDefaultBufferSymbols) ; i ++) {
276 		pEntity	= pLispMgr->m_apEntReserved [rnDefaultBufferSymbols [i]] ;
277 		lispMgr_AddSymbolToLocalSymbols (pLispMgr, pEntity) ;
278 	}
279 	return	True ;
280 }
281 
282 Boolean
lispMgr_collectOtherGarbage(register TLispManager * pLispMgr,register TLispEntity ** ppEntTop)283 lispMgr_collectOtherGarbage (
284 	register TLispManager*	pLispMgr,
285 	register TLispEntity**	ppEntTop)
286 {
287 	register TLispEntity*	pNextEntity ;
288 	register TLispEntity*	pEntity ;
289 
290 	assert (pLispMgr != NULL) ;
291 
292 	pEntity	= *ppEntTop ;
293 	while (pEntity != NULL) {
294 		pNextEntity	= pEntity->m_pRight ;
295 		if (pEntity->m_lReferCount == 0 &&
296 			pEntity->m_iMarker != pLispMgr->m_iMarker) {
297 			lispMgr_unregisterEntityFromList (pLispMgr, ppEntTop, pEntity) ;
298 			lispMgr_DestroyEntity (pLispMgr, pEntity) ;
299 		} else {
300 			pEntity->m_iMarker	= pLispMgr->m_iMarker ;
301 		}
302 		pEntity	= pNextEntity ;
303 	}
304 	return	True ;
305 }
306 
307 
308 Boolean
lispMgr_markEntityRecursively(register TLispManager * pLispMgr,register TLispEntity * pEntity)309 lispMgr_markEntityRecursively (
310 	register TLispManager*	pLispMgr,
311 	register TLispEntity*	pEntity)
312 {
313 	lispMgr_markEntity (pLispMgr, pEntity) ;
314 
315 	switch (pEntity->m_iType) {
316 	case	LISPENTITY_CONSCELL:
317 	{
318 		TLispEntity*	pCar ;
319 		TLispEntity*	pCdr ;
320 
321 		lispEntity_GetCar (pLispMgr, pEntity, &pCar) ;
322 		lispEntity_GetCdr (pLispMgr, pEntity, &pCdr) ;
323 		if (TFAILED (lispMgr_markedEntityp (pLispMgr, pCar)))
324 			lispMgr_markEntityRecursively (pLispMgr, pCar) ;
325 		if (TFAILED (lispMgr_markedEntityp (pLispMgr, pCdr)))
326 			lispMgr_markEntityRecursively (pLispMgr, pCdr) ;
327 		break ;
328 	}
329 
330 	case	LISPENTITY_VECTOR:
331 	{
332 		TLispEntity**	ppElement ;
333 		int				nElement ;
334 
335 		lispEntity_GetVectorValue (pLispMgr, pEntity, &ppElement, &nElement) ;
336 		while (nElement > 0) {
337 			if (TFAILED (lispMgr_markedEntityp (pLispMgr, *ppElement)))
338 				lispMgr_markEntityRecursively (pLispMgr, *ppElement) ;
339 			ppElement	++ ;
340 			nElement	-- ;
341 		}
342 		break ;
343 	}
344 
345 	default:
346 		break ;
347 	}
348 	return	True ;
349 }
350 
351 #if defined (DEBUG)
352 void
lispMgr_CheckEntity(register TLispManager * pLispMgr,register TLispEntity * pEntity)353 lispMgr_CheckEntity (
354 	register TLispManager*	pLispMgr,
355 	register TLispEntity*	pEntity)
356 {
357 	register TLispEntity*	pNode ;
358 
359 	assert (pLispMgr != NULL) ;
360 	assert (pEntity  != NULL) ;
361 
362 	fprintf (stderr, " Searching: Entity(%p),Count(%ld),Type(%d) ...",
363 			 pEntity, pEntity->m_lReferCount, pEntity->m_iType) ;
364 
365 	switch (pEntity->m_iType) {
366 	case	LISPENTITY_INTEGER:
367 	case	LISPENTITY_SYMBOL:
368 		fprintf (stderr, "not check\n") ;
369 		break ;
370 
371 	default:
372 		pNode	= pLispMgr->m_pEntMiscListTop ;
373 		while (pNode != NULL) {
374 			if (pNode == pEntity) {
375 				fprintf (stderr, "hit\n") ;
376 				//lispMgr_CheckMark (pLispMgr, pEntity) ;
377 				return ;
378 			}
379 			pNode	= pNode->m_pRight ;
380 		}
381 		fprintf (stderr, "miss\n") ;
382 		break ;
383 	}
384 	return ;
385 }
386 
387 void
lispMgr_CheckMark(register TLispManager * pLispMgr,register TLispEntity * pEntity)388 lispMgr_CheckMark (
389 	register TLispManager*	pLispMgr,
390 	register TLispEntity*	pEntity)
391 {
392 	register TLispEntity*	pNode ;
393 
394 	if (pEntity->m_iType != 2)
395 		return ;
396 
397 	fprintf (stderr, "Target(%p): Mark = %d -> ",
398 			 pEntity, pEntity->m_iMarker) ;
399 	pLispMgr->m_iMarker	++ ;
400 	pNode	= pLispMgr->m_pEntMiscListTop ;
401 	while (pNode != NULL) {
402 		if (pNode->m_lReferCount > 0)
403 			lispMgr_markEntityRecursively (pLispMgr, pNode) ;
404 		pNode	= pNode->m_pRight ;
405 	}
406 	fprintf (stderr, "%d/%d\n",
407 			 pEntity->m_iMarker, pLispMgr->m_iMarker) ;
408 	return ;
409 }
410 #endif
411 
412