1 /* internal.h -- common header file for the internal CORE and SHELL APIs.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5 
6    This file is part of the m17n library.
7 
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12 
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17 
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301 USA.  */
22 
23 #ifndef _M17N_INTERNAL_H_
24 #define _M17N_INTERNAL_H_
25 
26 /** @file internal.h
27     @brief a documentation for internal.h
28 
29     longer version of internal.h description
30 */
31 
32 extern int m17n__core_initialized;
33 extern int m17n__shell_initialized;
34 extern int m17n__gui_initialized;
35 
36 extern int mdebug_hook ();
37 
38 #if ENABLE_NLS
39 #include <libintl.h>
40 #define _(String) dgettext ("m17n-lib", String)
41 #else
42 #define _(String) (String)
43 #endif
44 
45 /** Return with code RET while setting merror_code to ERR.  */
46 
47 #define MERROR(err, ret)	\
48   do {				\
49     merror_code = (err);	\
50     mdebug_hook ();		\
51     return (ret);		\
52   } while (0)
53 
54 
55 #define MERROR_GOTO(err, label)	\
56   do {				\
57     if ((err))			\
58       merror_code = (err);	\
59     mdebug_hook ();		\
60     goto label;			\
61   } while (0)
62 
63 
64 #define MWARNING(err)	\
65   do {			\
66     mdebug_hook ();	\
67     goto warning;	\
68   } while (0)
69 
70 #define MFATAL(err)	\
71   do {			\
72     mdebug_hook ();	\
73     exit (err);		\
74   } while (0)
75 
76 #define MFAILP(cond) ((cond) ? 0 : mdebug_hook ())
77 
78 #define M_CHECK_CHAR(c, ret)		\
79   if ((c) < 0 || (c) > MCHAR_MAX)	\
80     MERROR (MERROR_CHAR, (ret));	\
81   else
82 
83 
84 /** Memory allocation stuffs.  */
85 
86 /* Call a handler function for memory full situation with argument
87    ERR.  ERR must be one of enum MErrorCode.  By default, the
88    handler function just calls exit () with argument ERR.  */
89 
90 #define MEMORY_FULL(err)		\
91   do {					\
92     (*m17n_memory_full_handler) (err);	\
93     exit (err);				\
94   } while (0)
95 
96 
97 /** The macro MTABLE_MALLOC () allocates memory (by malloc) for an
98     array of SIZE objects.  The size of each object is determined by
99     the type of P.  Then, it sets P to the allocated memory.  ERR must
100     be one of enum MErrorCode.  If the allocation fails, the macro
101     MEMORY_FULL () is called with argument ERR.  */
102 
103 #define MTABLE_MALLOC(p, size, err)				\
104   do {								\
105     if (! ((p) = (void *) malloc (sizeof (*(p)) * (size))))	\
106       MEMORY_FULL (err);					\
107   } while (0)
108 
109 
110 /** The macro MTABLE_CALLOC() is like the macro MTABLE_MALLOC but use
111     calloc instead of malloc, thus the allocated memory are zero
112     cleared.  */
113 
114 #define MTABLE_CALLOC(p, size, err)				\
115   do {								\
116     if (! ((p) = (void *) calloc (sizeof (*(p)), size)))	\
117       MEMORY_FULL (err);					\
118   } while (0)
119 
120 #define MTABLE_CALLOC_SAFE(p, size)	\
121   ((p) = (void *) calloc (sizeof (*(p)), (size)))
122 
123 
124 /** The macro MTABLE_REALLOC () changes the size of memory block
125     pointed to by P to a size suitable for an array of SIZE objects.
126     The size of each object is determined by the type of P.  ERR must
127     be one of enum MErrorCode.  If the allocation fails, the macro
128     MEMORY_FULL () is called with argument ERR.  */
129 
130 #define MTABLE_REALLOC(p, size, err)					\
131   do {									\
132     if (! ((p) = (void *) realloc ((p), sizeof (*(p)) * (size))))	\
133       MEMORY_FULL (err);						\
134   } while (0)
135 
136 
137 /** The macro MTABLE_ALLOCA () allocates memory (by alloca) for an
138     array of SIZE objects.  The size of each object is determined by
139     the type of P.  Then, it sets P to the allocated memory.  ERR must
140     be one of enum MErrorCode.  If the allocation fails, the macro
141     MEMORY_FULL () is called with argument ERR.  */
142 
143 #define MTABLE_ALLOCA(p, size, err)		\
144   do {						\
145     int allocasize = sizeof (*(p)) * (size);	\
146     if (! ((p) = (void *) alloca (allocasize)))	\
147       MEMORY_FULL (err);			\
148     memset ((p), 0, allocasize);		\
149   } while (0)
150 
151 
152 /** short description of MSTRUCT_MALLOC */
153 /** The macro MSTRUCT_MALLOC () allocates memory (by malloc) for an
154     object whose size is determined by the type of P, and sets P to
155     the allocated memory.  ERR must be one of enum MErrorCode.  If
156     the allocation fails, the macro MEMORY_FULL () is called with
157     argument ERR.  */
158 
159 #define MSTRUCT_MALLOC(p, err)				\
160   do {							\
161     if (! ((p) = (void *) malloc (sizeof (*(p)))))	\
162       MEMORY_FULL (err);				\
163   } while (0)
164 
165 
166 #define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err))
167 
168 #define MSTRUCT_CALLOC_SAFE(p) MTABLE_CALLOC_SAFE ((p), 1)
169 
170 #define USE_SAFE_ALLOCA \
171   int sa_must_free = 0, sa_size = 0
172 
173 /* P must be the same in all calls to SAFE_ALLOCA and SAFE_FREE in a
174    function.  */
175 
176 #define SAFE_ALLOCA(P, SIZE)		\
177   do {					\
178     if (sa_size < (SIZE))		\
179       {					\
180 	if (sa_must_free)		\
181 	  (P) = realloc ((P), (SIZE));	\
182 	else				\
183 	  {				\
184 	    (P) = alloca ((SIZE));	\
185 	    if (! (P))			\
186 	      {				\
187 		(P) = malloc (SIZE);	\
188 		sa_must_free = 1;	\
189 	      }				\
190 	  }				\
191 	if (! (P))			\
192 	  MEMORY_FULL (1);		\
193 	sa_size = (SIZE);		\
194       }					\
195   } while (0)
196 
197 #define SAFE_FREE(P)			\
198   do {					\
199     if (sa_must_free && sa_size > 0)	\
200       {					\
201 	free ((P));			\
202 	sa_must_free = sa_size = 0;	\
203       }					\
204   } while (0)
205 
206 
207 /** Extendable array.  */
208 
209 #define MLIST_RESET(list)	\
210   ((list)->used = 0)
211 
212 
213 #define MLIST_INIT1(list, mem, increment)	\
214   do {						\
215     (list)->size = (list)->used = 0;		\
216     (list)->inc = (increment);			\
217     (list)->mem = NULL;				\
218   } while (0)
219 
220 
221 #define MLIST_APPEND1(list, mem, elt, err)			\
222   do {								\
223     if ((list)->inc <= 0)					\
224       mdebug_hook ();						\
225     if ((list)->size == (list)->used)				\
226       {								\
227 	(list)->size += (list)->inc;				\
228 	MTABLE_REALLOC ((list)->mem, (list)->size, (err));	\
229       }								\
230     (list)->mem[(list)->used++] = (elt);			\
231   } while (0)
232 
233 
234 #define MLIST_PREPEND1(list, mem, elt, err)			\
235   do {								\
236     if ((list)->inc <= 0)					\
237       mdebug_hook ();						\
238     if ((list)->size == (list)->used)				\
239       {								\
240 	(list)->size += (list)->inc;				\
241 	MTABLE_REALLOC ((list)->mem, (list)->size, (err));	\
242       }								\
243     memmove ((list)->mem + 1, (list)->mem,			\
244 	     sizeof *((list)->mem) * ((list)->used));		\
245     (list)->mem[0] = (elt);					\
246     (list)->used++;						\
247   } while (0)
248 
249 
250 #define MLIST_INSERT1(list, mem, idx, len, err)				\
251   do {									\
252     while ((list)->used + (len) > (list)->size)				\
253       {									\
254 	(list)->size += (list)->inc;					\
255 	MTABLE_REALLOC ((list)->mem, (list)->size, (err));		\
256       }									\
257     memmove ((list)->mem + ((idx) + (len)), (list)->mem + (idx),	\
258 	     (sizeof *((list)->mem)) * ((list)->used - (idx)));		\
259     (list)->used += (len);						\
260   } while (0)
261 
262 
263 #define MLIST_DELETE1(list, mem, idx, len)				\
264   do {									\
265     memmove ((list)->mem + (idx), (list)->mem + (idx) + (len),		\
266 	     (sizeof *((list)->mem)) * ((list)->used - (idx) - (len)));	\
267     (list)->used -= (len);						\
268   } while (0)
269 
270 
271 #define MLIST_COPY1(list0, list1, mem, err)			\
272   do {								\
273     (list0)->size = (list0)->used = (list1)->used;		\
274     (list0)->inc = 1;						\
275     MTABLE_MALLOC ((list0)->mem, (list0)->used, (err));		\
276     memcpy ((list0)->mem, (list1)->mem,				\
277 	    (sizeof (list0)->mem) * (list0)->used);		\
278   } while (0)
279 
280 
281 #define MLIST_FREE1(list, mem)		\
282   if ((list)->size)			\
283     {					\
284       free ((list)->mem);		\
285       (list)->mem = NULL;		\
286       (list)->size = (list)->used = 0;	\
287     }					\
288   else
289 
290 
291 
292 typedef struct
293 {
294   void (*freer) (void *);
295   int size, inc, used;
296   unsigned *counts;
297 } M17NObjectRecord;
298 
299 typedef struct
300 {
301   /**en Reference count of the object.  */
302   /**ja ���֥������Ȥλ��ȿ�.  */
303   unsigned ref_count : 16;
304 
305   unsigned ref_count_extended : 1;
306 
307   /**en A flag bit used for various perpose.  */
308   /**ja ���ޤ��ޤ���Ū���Ѥ�����ե饰�ӥå�.  */
309   unsigned flag : 15;
310 
311   union {
312     /**en If <ref_count_extended> is zero, a function to free the
313        object.  */
314     /**ja <ref_count_extended> �� 0 �ʤ�Х��֥������Ȥ��������ؿ�.  */
315     void (*freer) (void *);
316     /**en If <ref_count_extended> is nonzero, a pointer to the
317        struct M17NObjectRecord.  */
318     /**ja <ref_count_extended> �� 0 �Ǥʤ���й�¤�� M17NObjectRecord �ؤΥݥ���.  */
319     M17NObjectRecord *record;
320   } u;
321 } M17NObject;
322 
323 
324 /** Allocate a managed object OBJECT which has freer FREE_FUNC.  */
325 
326 #define M17N_OBJECT(object, free_func, err)		\
327   do {							\
328     MSTRUCT_CALLOC ((object), (err));			\
329     ((M17NObject *) (object))->ref_count = 1;		\
330     ((M17NObject *) (object))->u.freer = free_func;	\
331   } while (0)
332 
333 
334 /**en Increment the reference count of OBJECT if the count is not
335    0.  */
336 /**ja OBJECT �λ��ȿ��� 0 �Ǥʤ���� 1 ���䤹.  */
337 
338 #define M17N_OBJECT_REF(object)				\
339   do {							\
340     if (((M17NObject *) (object))->ref_count_extended)	\
341       m17n_object_ref (object);				\
342     else if (((M17NObject *) (object))->ref_count > 0)	\
343       {							\
344 	((M17NObject *) (object))->ref_count++;		\
345 	if (! ((M17NObject *) (object))->ref_count)	\
346 	  {						\
347 	    ((M17NObject *) (object))->ref_count--;	\
348 	    m17n_object_ref (object);			\
349 	  }						\
350       }							\
351   } while (0)
352 
353 
354 #define M17N_OBJECT_REF_NTIMES(object, n)				\
355   do {									\
356     int i;								\
357 									\
358     if (((M17NObject *) (object))->ref_count_extended)			\
359       for (i = 0; i < n; i++)						\
360 	m17n_object_ref (object);					\
361     else if (((M17NObject *) (object))->ref_count > 0)			\
362       {									\
363 	int orig_ref_count = ((M17NObject *) (object))->ref_count;	\
364 									\
365 	for (i = 0; i < n; i++)						\
366 	  if (! ++((M17NObject *) (object))->ref_count)			\
367 	    {								\
368 	      ((M17NObject *) (object))->ref_count = orig_ref_count;	\
369 	      for (i = 0; i < n; i++)					\
370 		m17n_object_ref (object);				\
371 	    }								\
372       }									\
373   } while (0)
374 
375 
376 /**en Decrement the reference count of OBJECT if the count is greater
377       than 0.  In that case, if the count becomes 0, free OBJECT.  */
378 /**ja OBJECT �λ��ȿ��� 0 ����礭����� 1 ���餹�����餷�� 0 �ˤʤ��
379       OBJECT ���������.  */
380 
381 #define M17N_OBJECT_UNREF(object)					\
382   do {									\
383     if (object)								\
384       {									\
385 	if (((M17NObject *) (object))->ref_count_extended		\
386 	    || mdebug__flags[MDEBUG_FINI])				\
387 	  {								\
388 	    if (m17n_object_unref (object) == 0)			\
389 	      (object) = NULL;						\
390 	  }								\
391 	else if (((M17NObject *) (object))->ref_count == 0)		\
392 	  break;							\
393 	else								\
394 	  {								\
395 	    ((M17NObject *) (object))->ref_count--;			\
396 	    if (((M17NObject *) (object))->ref_count == 0)		\
397 	      {								\
398 		if (((M17NObject *) (object))->u.freer)			\
399 		  (((M17NObject *) (object))->u.freer) (object);	\
400 		else							\
401 		  free (object);					\
402 		(object) = NULL;					\
403 	      }								\
404 	  }								\
405       }									\
406   } while (0)
407 
408 typedef struct _M17NObjectArray M17NObjectArray;
409 
410 struct _M17NObjectArray
411 {
412   char *name;
413   int count;
414   int size, inc, used;
415   void **objects;
416   M17NObjectArray *next;
417 };
418 
419 extern void mdebug__add_object_array (M17NObjectArray *array, char *name);
420 
421 #define M17N_OBJECT_ADD_ARRAY(array, name)	\
422   if (mdebug__flags[MDEBUG_FINI])		\
423     mdebug__add_object_array (&array, name);	\
424   else
425 
426 extern void mdebug__register_object (M17NObjectArray *array, void *object);
427 
428 #define M17N_OBJECT_REGISTER(array, object)	\
429   if (mdebug__flags[MDEBUG_FINI])		\
430     mdebug__register_object (&array, object);	\
431   else
432 
433 extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
434 
435 #define M17N_OBJECT_UNREGISTER(array, object)	\
436   if (mdebug__flags[MDEBUG_FINI])		\
437     mdebug__unregister_object (&array, object);	\
438   else
439 
440 
441 
442 struct MTextPlist;
443 
444 enum MTextCoverage
445   {
446     MTEXT_COVERAGE_ASCII,
447     MTEXT_COVERAGE_UNICODE,
448     MTEXT_COVERAGE_FULL
449   };
450 
451 struct MText
452 {
453   M17NObject control;
454 
455   unsigned format : 16;
456   unsigned coverage : 16;
457 
458   /**en Number of characters in the M-text */
459   /**ja M-text ���ʸ���� */
460   int nchars;
461 
462   /**en Number of bytes used to represent the characters in the M-text. */
463   /**ja M-text ���ʸ����ɽ�魯������Ѥ�����Х��ȿ� */
464   int nbytes;
465 
466   /**en Character sequence of the M-text. */
467   /**ja M-text ���ʸ���� */
468   unsigned char *data;
469 
470   /**en Number of bytes allocated for the @c data member. */
471   /**ja ���� @c data �˳�����Ƥ�줿�Х��ȿ� */
472   int allocated;
473 
474   /**en Pointer to the property list of the M-text. */
475   /**ja M-text �Υץ�ѥƥ��ꥹ�ȤؤΥݥ��� */
476   struct MTextPlist *plist;
477 
478   /**en Caches of the character position and the corresponding byte position. */
479   /**ja ʸ�����֤�����б�����Х��Ȱ��֤Υ���å��� */
480   int cache_char_pos, cache_byte_pos;
481 };
482 
483 /** short description of M_CHECK_POS */
484 /** longer description of M_CHECK_POS */
485 
486 #define M_CHECK_POS(mt, pos, ret)		\
487   do {						\
488     if ((pos) < 0 || (pos) >= (mt)->nchars)	\
489       MERROR (MERROR_RANGE, (ret));		\
490   } while (0)
491 
492 
493 /** short description of M_CHECK_POS_X */
494 /** longer description of M_CHECK_POS_X */
495 
496 #define M_CHECK_POS_X(mt, pos, ret)		\
497   do {						\
498     if ((pos) < 0 || (pos) > (mt)->nchars)	\
499       MERROR (MERROR_RANGE, (ret));		\
500   } while (0)
501 
502 
503 /** short description of M_CHECK_RANGE */
504 /** longer description of M_CHECK_RANGE */
505 
506 #define M_CHECK_RANGE(mt, from, to, ret, ret2)			\
507   do {								\
508     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)	\
509       MERROR (MERROR_RANGE, (ret));				\
510     if ((from) == (to))						\
511       return (ret2);						\
512   } while (0)
513 
514 #define M_CHECK_RANGE_X(mt, from, to, ret)			\
515   do {								\
516     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)	\
517       MERROR (MERROR_RANGE, (ret));				\
518   } while (0)
519 
520 
521 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2)	\
522   do {							\
523     int to = (pos) + (nchars);			\
524 							\
525     M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2));	\
526   } while (0)
527 
528 
529 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
530 
531 #define M_CHECK_READONLY(mt, ret)	\
532   do {					\
533     if ((mt)->allocated < 0)		\
534       MERROR (MERROR_MTEXT, (ret));	\
535   } while (0)
536 
537 #define mtext_nchars(mt) ((mt)->nchars)
538 
539 #define mtext_nbytes(mt) ((mt)->nbytes)
540 
541 #define mtext_allocated(mt) ((mt)->allocated)
542 
543 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
544 
545 
546 
547 enum MDebugFlag
548   {
549     MDEBUG_INIT,
550     MDEBUG_FINI,
551     MDEBUG_CHARSET,
552     MDEBUG_CODING,
553     MDEBUG_DATABASE,
554     MDEBUG_FONT,
555     MDEBUG_FLT,
556     MDEBUG_FONTSET,
557     MDEBUG_INPUT,
558     MDEBUG_ALL,
559     MDEBUG_MAX = MDEBUG_ALL
560   };
561 
562 extern int mdebug__flags[MDEBUG_MAX];
563 extern FILE *mdebug__output;
564 extern void mdebug__push_time ();
565 extern void mdebug__pop_time ();
566 extern void mdebug__print_time ();
567 
568 #define MDEBUG_FLAG() mdebug__flags[mdebug_flag]
569 
570 #define MDEBUG_PRINT0(FPRINTF)		\
571   do {					\
572     if (MDEBUG_FLAG ())			\
573       {					\
574 	FPRINTF;			\
575 	fflush (mdebug__output);	\
576       }					\
577   } while (0)
578 
579 #define MDEBUG_PRINT(msg) \
580   MDEBUG_PRINT0 (fprintf (mdebug__output, "%s", (msg)))
581 
582 #define MDEBUG_PRINT1(fmt, arg) \
583   MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg)))
584 
585 #define MDEBUG_PRINT2(fmt, arg1, arg2) \
586   MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2)))
587 
588 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3) \
589   MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3)))
590 
591 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)	\
592   MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4)))
593 
594 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)	\
595   MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5)))
596 
597 #define MDEBUG_DUMP(prefix, postfix, call)		\
598   do {							\
599     if (MDEBUG_FLAG ())					\
600       {							\
601 	fprintf (mdebug__output, "%s", prefix);		\
602 	call;						\
603 	fprintf (mdebug__output, "%s", postfix);	\
604 	fflush (mdebug__output);			\
605       }							\
606   } while (0)
607 
608 #define MDEBUG_PUSH_TIME()	\
609   do {				\
610     if (MDEBUG_FLAG ())		\
611       mdebug__push_time ();	\
612   } while (0)
613 
614 
615 #define MDEBUG_POP_TIME()	\
616   do {				\
617     if (MDEBUG_FLAG ())		\
618       mdebug__pop_time ();	\
619   } while (0)
620 
621 
622 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)		\
623   do {							\
624     if (MDEBUG_FLAG ())					\
625       {							\
626 	fprintf (mdebug__output, " [%s] ", tag);	\
627 	mdebug__print_time ();				\
628 	fprintf ARG_LIST;				\
629 	fprintf (mdebug__output, "\n");			\
630       }							\
631   } while (0)
632 
633 
634 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
635 
636 #define SWAP_32(c)			\
637   (((c) >> 24) | (((c) >> 8) & 0xFF00)	\
638    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
639 
640 
641 /* Initialize/finalize function.  */
642 
643 extern int msymbol__init ();
644 extern void msymbol__fini ();
645 
646 extern int mplist__init ();
647 extern void mplist__fini ();
648 
649 extern int mtext__init ();
650 extern void mtext__fini ();
651 
652 extern int mtext__prop_init ();
653 extern void mtext__prop_fini ();
654 
655 extern int mchartable__init ();
656 extern void mchartable__fini ();
657 
658 extern int mcharset__init ();
659 extern void mcharset__fini ();
660 
661 extern int mcoding__init ();
662 extern void mcoding__fini ();
663 
664 extern int mdatabase__init (void);
665 extern void mdatabase__fini (void);
666 
667 extern int mchar__init ();
668 extern void mchar__fini ();
669 
670 extern int mlang__init ();
671 extern void mlang__fini ();
672 
673 extern int mlocale__init ();
674 extern void mlocale__fini ();
675 
676 extern int minput__init ();
677 extern void minput__fini ();
678 
679 #endif /* _M17N_INTERNAL_H_ */
680 
681 /*
682   Local Variables:
683   coding: euc-japan
684   End:
685 */
686