(libm17n_core_la_LIBADD): Add THAI_WORDSEG_LD_FLAGS,
[m17n/m17n-lib.git] / src / internal.h
1 /* internal.h -- common header file for the internal CORE and SHELL APIs.
2    Copyright (C) 2003, 2004                             
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., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, 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 /** Return with code RET while setting merror_code to ERR.  */
39
40 #define MERROR(err, ret)        \
41   do {                          \
42     merror_code = (err);        \
43     mdebug_hook ();             \
44     return (ret);               \
45   } while (0)
46
47
48 #define MERROR_GOTO(err, label) \
49   do {                          \
50     if ((err))                  \
51       merror_code = (err);      \
52     mdebug_hook ();             \
53     goto label;                 \
54   } while (0)
55
56
57 #define MWARNING(err)   \
58   do {                  \
59     mdebug_hook ();     \
60     goto warning;       \
61   } while (0)
62
63
64 #define M_CHECK_CHAR(c, ret)            \
65   if ((c) < 0 || (c) > MCHAR_MAX)       \
66     MERROR (MERROR_CHAR, (ret));        \
67   else
68
69 \f
70 /** Memory allocation stuffs.  */
71
72 /* Call a handler function for memory full situation with argument
73    ERR.  ERR must be one of enum MErrorCode.  By default, the
74    handler function just calls exit () with argument ERR.  */
75
76 #define MEMORY_FULL(err)                \
77   do {                                  \
78     (*m17n_memory_full_handler) (err);  \
79     exit (err);                         \
80   } while (0)
81
82
83 /** The macro MTABLE_MALLOC () allocates memory (by malloc) for an
84     array of SIZE objects.  The size of each object is determined by
85     the type of P.  Then, it sets P to the allocated memory.  ERR must
86     be one of enum MErrorCode.  If the allocation fails, the macro
87     MEMORY_FULL () is called with argument ERR.  */
88
89 #define MTABLE_MALLOC(p, size, err)             \
90   do {                                          \
91     int bytes = sizeof (*(p)) * (size);         \
92     if (! ((p) = (void *) malloc (bytes)))      \
93       MEMORY_FULL (err);                        \
94   } while (0)
95
96
97 /** The macro MTABLE_CALLOC() is like the macro MTABLE_MALLOC but use
98     calloc instead of malloc, thus the allocated memory are zero
99     cleared.  */
100
101 #define MTABLE_CALLOC(p, size, err)                             \
102   do {                                                          \
103     if (! ((p) = (void *) calloc (sizeof (*(p)), size)))        \
104       MEMORY_FULL (err);                                        \
105   } while (0)
106
107
108 /** The macro MTABLE_REALLOC () changes the size of memory block
109     pointed to by P to a size suitable for an array of SIZE objects.
110     The size of each object is determined by the type of P.  ERR must
111     be one of enum MErrorCode.  If the allocation fails, the macro
112     MEMORY_FULL () is called with argument ERR.  */
113
114 #define MTABLE_REALLOC(p, size, err)                                    \
115   do {                                                                  \
116     if (! ((p) = (void *) realloc ((p), sizeof (*(p)) * (size))))       \
117       MEMORY_FULL (err);                                                \
118   } while (0)
119
120
121 /** The macro MTABLE_ALLOCA () allocates memory (by alloca) for an
122     array of SIZE objects.  The size of each object is determined by
123     the type of P.  Then, it sets P to the allocated memory.  ERR must
124     be one of enum MErrorCode.  If the allocation fails, the macro
125     MEMORY_FULL () is called with argument ERR.  */
126
127 #define MTABLE_ALLOCA(p, size, err)             \
128   do {                                          \
129     int bytes = sizeof (*(p)) * (size);         \
130     if (! ((p) = (void *) alloca (bytes)))      \
131       MEMORY_FULL (err);                        \
132     memset ((p), 0, bytes);                     \
133   } while (0)
134
135
136 /** short description of MSTRUCT_MALLOC */
137 /** The macro MSTRUCT_MALLOC () allocates memory (by malloc) for an
138     object whose size is determined by the type of P, and sets P to
139     the allocated memory.  ERR must be one of enum MErrorCode.  If
140     the allocation fails, the macro MEMORY_FULL () is called with
141     argument ERR.  */
142
143 #define MSTRUCT_MALLOC(p, err)                          \
144   do {                                                  \
145     if (! ((p) = (void *) malloc (sizeof (*(p)))))      \
146       MEMORY_FULL (err);                                \
147   } while (0)
148
149
150 #define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err))
151
152 \f
153 /** Extendable array.  */
154
155 #define MLIST_RESET(list)       \
156   ((list)->used = 0)
157
158
159 #define MLIST_INIT1(list, mem, increment)       \
160   do {                                          \
161     (list)->size = (list)->used = 0;            \
162     (list)->inc = (increment);                  \
163     (list)->mem = NULL;                         \
164   } while (0)
165
166
167 #define MLIST_APPEND1(list, mem, elt, err)                      \
168   do {                                                          \
169     if ((list)->inc <= 0)                                       \
170       mdebug_hook ();                                           \
171     if ((list)->size == (list)->used)                           \
172       {                                                         \
173         (list)->size += (list)->inc;                            \
174         MTABLE_REALLOC ((list)->mem, (list)->size, (err));      \
175       }                                                         \
176     (list)->mem[(list)->used++] = (elt);                        \
177   } while (0)
178
179
180 #define MLIST_PREPEND1(list, mem, elt, err)                     \
181   do {                                                          \
182     if ((list)->inc <= 0)                                       \
183       mdebug_hook ();                                           \
184     if ((list)->size == (list)->used)                           \
185       {                                                         \
186         (list)->size += (list)->inc;                            \
187         MTABLE_REALLOC ((list)->mem, (list)->size, (err));      \
188       }                                                         \
189     memmove ((list)->mem + 1, (list)->mem,                      \
190              sizeof *((list)->mem) * ((list)->used));           \
191     (list)->mem[0] = (elt);                                     \
192     (list)->used++;                                             \
193   } while (0)
194
195
196 #define MLIST_INSERT1(list, mem, idx, len, err)                         \
197   do {                                                                  \
198     while ((list)->used + (len) > (list)->size)                         \
199       {                                                                 \
200         (list)->size += (list)->inc;                                    \
201         MTABLE_REALLOC ((list)->mem, (list)->size, (err));              \
202       }                                                                 \
203     memmove ((list)->mem + ((idx) + (len)), (list)->mem + (idx),        \
204              (sizeof *((list)->mem)) * ((list)->used - (idx)));         \
205     (list)->used += (len);                                              \
206   } while (0)
207
208
209 #define MLIST_DELETE1(list, mem, idx, len)                              \
210   do {                                                                  \
211     memmove ((list)->mem + (idx), (list)->mem + (idx) + (len),          \
212              (sizeof *((list)->mem)) * ((list)->used - (idx) - (len))); \
213     (list)->used -= (len);                                              \
214   } while (0)
215
216
217 #define MLIST_COPY1(list0, list1, mem, err)                     \
218   do {                                                          \
219     (list0)->size = (list0)->used = (list1)->used;              \
220     (list0)->inc = 1;                                           \
221     MTABLE_MALLOC ((list0)->mem, (list0)->used, (err));         \
222     memcpy ((list0)->mem, (list1)->mem,                         \
223             (sizeof (list0)->mem) * (list0)->used);             \
224   } while (0)
225
226
227 #define MLIST_FREE1(list, mem)          \
228   if ((list)->size)                     \
229     {                                   \
230       free ((list)->mem);               \
231       (list)->mem = NULL;               \
232       (list)->size = (list)->used = 0;  \
233     }                                   \
234   else
235
236 \f
237
238 typedef struct
239 {
240   void (*freer) (void *);
241   int size, inc, used;
242   unsigned *counts;
243 } M17NObjectRecord;
244
245 typedef struct
246 {
247   /**en Reference count of the object.  */
248   /**ja ¥ª¥Ö¥¸¥§¥¯¥È¤Î»²¾È¿ô.  */
249   unsigned ref_count : 16;
250
251   unsigned ref_count_extended : 1;
252
253   /**en A flag bit used for various perpose.  */
254   /**ja ¤µ¤Þ¤¶¤Þ¤ÊÌÜŪ¤ËÍѤ¤¤é¤ì¤ë¥Õ¥é¥°¥Ó¥Ã¥È.  */
255   unsigned flag : 15;
256
257   union {
258     /**en If <ref_count_extended> is zero, a function to free the
259        object.  */
260     /**ja <ref_count_extended> ¤¬ 0 ¤Ê¤é¤Ð¥ª¥Ö¥¸¥§¥¯¥È¤ò²òÊü¤¹¤ë´Ø¿ô.  */
261     void (*freer) (void *);
262     /**en If <ref_count_extended> is nonzero, a pointer to the
263        struct M17NObjectRecord.  */
264     /**ja <ref_count_extended> ¤¬ 0 ¤Ç¤Ê¤±¤ì¤Ð¹½Â¤ÂΠM17NObjectRecord ¤Ø¤Î¥Ý¥¤¥ó¥¿.  */
265     M17NObjectRecord *record;
266   } u;
267 } M17NObject;
268
269
270 /** Allocate a managed object OBJECT which has freer FREE_FUNC.  */
271
272 #define M17N_OBJECT(object, free_func, err)             \
273   do {                                                  \
274     MSTRUCT_CALLOC ((object), (err));                   \
275     ((M17NObject *) (object))->ref_count = 1;           \
276     ((M17NObject *) (object))->u.freer = free_func;     \
277   } while (0)
278
279
280 /**en Increment the reference count of OBJECT if the count is not
281    0.  */
282 /**ja OBJECT ¤Î»²¾È¿ô¤¬ 0 ¤Ç¤Ê¤±¤ì¤Ð 1 Áý¤ä¤¹.  */
283
284 #define M17N_OBJECT_REF(object)                         \
285   do {                                                  \
286     if (((M17NObject *) (object))->ref_count_extended)  \
287       m17n_object_ref (object);                         \
288     else if (((M17NObject *) (object))->ref_count > 0)  \
289       {                                                 \
290         ((M17NObject *) (object))->ref_count++;         \
291         if (! ((M17NObject *) (object))->ref_count)     \
292           {                                             \
293             ((M17NObject *) (object))->ref_count--;     \
294             m17n_object_ref (object);                   \
295           }                                             \
296       }                                                 \
297   } while (0)
298
299
300 #define M17N_OBJECT_REF_NTIMES(object, n)                               \
301   do {                                                                  \
302     int i;                                                              \
303                                                                         \
304     if (((M17NObject *) (object))->ref_count_extended)                  \
305       for (i = 0; i < n; i++)                                           \
306         m17n_object_ref (object);                                       \
307     else if (((M17NObject *) (object))->ref_count > 0)                  \
308       {                                                                 \
309         int orig_ref_count = ((M17NObject *) (object))->ref_count;      \
310                                                                         \
311         for (i = 0; i < n; i++)                                         \
312           if (! ++((M17NObject *) (object))->ref_count)                 \
313             {                                                           \
314               ((M17NObject *) (object))->ref_count = orig_ref_count;    \
315               for (i = 0; i < n; i++)                                   \
316                 m17n_object_ref (object);                               \
317             }                                                           \
318       }                                                                 \
319   } while (0)
320
321
322 /**en Decrement the reference count of OBJECT if the count is greater
323       than 0.  In that case, if the count becomes 0, free OBJECT.  */
324 /**ja OBJECT ¤Î»²¾È¿ô¤¬ 0 ¤è¤êÂ礭¤±¤ì¤Ð 1 ¸º¤é¤¹¡£¸º¤é¤·¤Æ 0 ¤Ë¤Ê¤ì¤Ð
325       OBJECT ¤ò²òÊü¤¹¤ë.  */
326
327 #define M17N_OBJECT_UNREF(object)                               \
328   do {                                                          \
329     if (object)                                                 \
330       {                                                         \
331         if (((M17NObject *) (object))->ref_count_extended)      \
332           m17n_object_unref (object);                           \
333         else if (((M17NObject *) (object))->ref_count == 0)     \
334           break;                                                \
335         else if (((M17NObject *) (object))->ref_count > 1)      \
336           ((M17NObject *) (object))->ref_count--;               \
337         else                                                    \
338           {                                                     \
339             if (((M17NObject *) (object))->u.freer)             \
340               (((M17NObject *) (object))->u.freer) (object);    \
341             else                                                \
342               free (object);                                    \
343             (object) = NULL;                                    \
344           }                                                     \
345       }                                                         \
346   } while (0)
347
348
349 typedef struct
350 {
351   int count;
352   int size, inc, used;
353   void **objects;
354 } M17NObjectArray;
355
356 extern void mdebug__register_object (M17NObjectArray *array, void *object);
357
358 #define M17N_OBJECT_REGISTER(array, object)     \
359   if (mdebug__flag & MDEBUG_FINI)               \
360     mdebug__register_object (&array, object);   \
361   else
362
363 extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
364
365 #define M17N_OBJECT_UNREGISTER(array, object)   \
366   if (mdebug__flag & MDEBUG_FINI)               \
367     mdebug__unregister_object (&array, object); \
368   else
369
370 extern void mdebug__report_object (char *name, M17NObjectArray *array);
371
372 \f
373
374 struct MTextPlist;
375
376 struct MText
377 {
378   M17NObject control;
379
380   enum MTextFormat format;
381
382   /**en Number of characters in the M-text */
383   /**ja M-text Ãæ¤Îʸ»ú¿ô */
384   int nchars;
385
386   /**en Number of bytes used to represent the characters in the M-text. */
387   /**ja M-text Ãæ¤Îʸ»ú¤òɽ¤ï¤¹¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¥Ð¥¤¥È¿ô */
388   int nbytes;
389
390   /**en Character sequence of the M-text. */
391   /**ja M-text Ãæ¤Îʸ»úÎó */
392   unsigned char *data;
393
394   /**en Number of bytes allocated for the @c data member. */
395   /**ja ¥á¥ó¥Ð @c data ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥Ð¥¤¥È¿ô */
396   int allocated;
397
398   /**en Pointer to the property list of the M-text. */
399   /**ja M-text ¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿ */
400   struct MTextPlist *plist;
401
402   /**en Caches of the character position and the corresponding byte position. */
403   /**ja Ê¸»ú°ÌÃÖ¤ª¤è¤ÓÂбþ¤¹¤ë¥Ð¥¤¥È°ÌÃ֤Υ­¥ã¥Ã¥·¥å */
404   int cache_char_pos, cache_byte_pos;
405 };
406
407 /** short description of M_CHECK_POS */
408 /** longer description of M_CHECK_POS */
409
410 #define M_CHECK_POS(mt, pos, ret)               \
411   do {                                          \
412     if ((pos) < 0 || (pos) >= (mt)->nchars)     \
413       MERROR (MERROR_RANGE, (ret));             \
414   } while (0)
415
416
417 /** short description of M_CHECK_POS_X */
418 /** longer description of M_CHECK_POS_X */
419
420 #define M_CHECK_POS_X(mt, pos, ret)             \
421   do {                                          \
422     if ((pos) < 0 || (pos) > (mt)->nchars)      \
423       MERROR (MERROR_RANGE, (ret));             \
424   } while (0)
425
426
427 /** short description of M_CHECK_RANGE */
428 /** longer description of M_CHECK_RANGE */
429
430 #define M_CHECK_RANGE(mt, from, to, ret, ret2)                  \
431   do {                                                          \
432     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
433       MERROR (MERROR_RANGE, (ret));                             \
434     if ((from) == (to))                                         \
435       return (ret2);                                            \
436   } while (0)
437
438 #define M_CHECK_RANGE_X(mt, from, to, ret)                      \
439   do {                                                          \
440     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
441       MERROR (MERROR_RANGE, (ret));                             \
442   } while (0)
443
444
445 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2)  \
446   do {                                                  \
447     int to = (pos) + (nchars);                  \
448                                                         \
449     M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2));   \
450   } while (0)
451
452
453 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
454
455 #define M_CHECK_READONLY(mt, ret)       \
456   do {                                  \
457     if ((mt)->allocated < 0)            \
458       MERROR (MERROR_MTEXT, (ret));     \
459   } while (0)
460
461 #define mtext_nchars(mt) ((mt)->nchars)
462
463 #define mtext_nbytes(mt) ((mt)->nbytes)
464
465 #define mtext_allocated(mt) ((mt)->allocated)
466
467 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
468
469 \f
470
471 enum MDebugMaskBit
472   {
473     MDEBUG_INIT =       0x01,
474     MDEBUG_FINI =       0x02,
475     MDEBUG_CHARSET =    0x04,
476     MDEBUG_CODING =     0x08,
477     MDEBUG_DATABASE =   0x10,
478     MDEBUG_FONT =       0x0100,
479     MDEBUG_FONT_FLT =   0x0200,
480     MDEBUG_FONT_OTF =   0x0400,
481     MDEBUG_INPUT =      0x0800,
482     MDEBUG_MAX
483   };
484
485 extern int mdebug__flag;
486 extern void mdebug__push_time ();
487 extern void mdebug__pop_time ();
488 extern void mdebug__print_time ();
489
490 #define MDEBUG_PRINT(msg)               \
491   do {                                  \
492     if (mdebug__flag & mdebug_mask)     \
493       fprintf (stderr, (msg));          \
494   } while (0)
495
496 #define MDEBUG_PRINT1(fmt, arg)         \
497   do {                                  \
498     if (mdebug__flag & mdebug_mask)     \
499       fprintf (stderr, (fmt), (arg));   \
500   } while (0)
501
502 #define MDEBUG_PRINT2(fmt, arg1, arg2)          \
503   do {                                          \
504     if (mdebug__flag & mdebug_mask)             \
505       fprintf (stderr, (fmt), (arg1), (arg2));  \
506   } while (0)
507
508 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3)            \
509   do {                                                  \
510     if (mdebug__flag & mdebug_mask)                     \
511       fprintf (stderr, (fmt), (arg1), (arg2), (arg3));  \
512   } while (0)
513
514 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)              \
515   do {                                                          \
516     if (mdebug__flag & mdebug_mask)                             \
517       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4));  \
518   } while (0)
519
520 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)                \
521   do {                                                                  \
522     if (mdebug__flag & mdebug_mask)                                     \
523       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5));  \
524   } while (0)
525
526
527 #define MDEBUG_PUSH_TIME()              \
528   do {                                  \
529     if (mdebug__flag & mdebug_mask)     \
530       mdebug__push_time ();             \
531   } while (0)
532
533
534 #define MDEBUG_POP_TIME()               \
535   do {                                  \
536     if (mdebug__flag & mdebug_mask)     \
537       mdebug__pop_time ();              \
538   } while (0)
539
540
541 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)        \
542   do {                                          \
543     if (mdebug__flag & mdebug_mask)             \
544       {                                         \
545         fprintf (stderr, " [%s] ", tag);        \
546         mdebug__print_time ();                  \
547         fprintf ARG_LIST;                       \
548         fprintf (stderr, "\n");                 \
549       }                                         \
550   } while (0)
551
552
553 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
554
555 #define SWAP_32(c)                      \
556   (((c) >> 24) | (((c) >> 8) & 0xFF00)  \
557    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
558
559
560 extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
561                                    MSymbol tag3, MSymbol tag4);
562 extern void *(*mdatabase__loader) (void *);
563
564 /* Initialize/finalize function.  */
565
566 extern int msymbol__init ();
567 extern void msymbol__fini ();
568
569 extern int mplist__init ();
570 extern void mplist__fini ();
571
572 extern int mtext__init ();
573 extern void mtext__fini ();
574
575 extern int mtext__prop_init ();
576 extern void mtext__prop_fini ();
577
578 extern int mchartable__init ();
579 extern void mchartable__fini ();
580
581 extern int mcharset__init ();
582 extern void mcharset__fini ();
583
584 extern int mcoding__init ();
585 extern void mcoding__fini ();
586
587 extern int mdatabase__init (void);
588 extern void mdatabase__fini (void);
589
590 extern int mchar__init ();
591 extern void mchar__fini ();
592
593 extern int mlang__init ();
594 extern void mlang__fini ();
595
596 extern int mlocale__init ();
597 extern void mlocale__fini ();
598
599 extern int minput__init ();
600 extern void minput__fini ();
601
602 #endif /* _M17N_INTERNAL_H_ */
603
604 /*
605   Local Variables:
606   coding: euc-japan
607   End:
608 */