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