3354e29f2fea8d1f21c423c5d9a5b52c7790aba4
[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   unsigned ref_count : 16;
249
250   unsigned ref_count_extended : 1;
251
252   /**en A flag bit used for various perpose.  */
253   unsigned flag : 15;
254
255   union {
256     /**en If <ref_count_extended> is zero, a function to free the
257        object.  */
258     void (*freer) (void *);
259     /**en If <ref_count_extended> is nonzero, a pointer to the
260        struct M17NObjectRecord.  */
261     M17NObjectRecord *record;
262   } u;
263 } M17NObject;
264
265
266 /** Allocate a managed object OBJECT which has freer FREE_FUNC.  */
267
268 #define M17N_OBJECT(object, free_func, err)             \
269   do {                                                  \
270     MSTRUCT_CALLOC ((object), (err));                   \
271     ((M17NObject *) (object))->ref_count = 1;           \
272     ((M17NObject *) (object))->u.freer = free_func;     \
273   } while (0)
274
275
276 /**en Increment the reference count of OBJECT if the count is not
277    0.  */
278
279 #define M17N_OBJECT_REF(object)                         \
280   do {                                                  \
281     if (((M17NObject *) (object))->ref_count_extended)  \
282       m17n_object_ref (object);                         \
283     else if (((M17NObject *) (object))->ref_count > 0)  \
284       {                                                 \
285         ((M17NObject *) (object))->ref_count++;         \
286         if (! ((M17NObject *) (object))->ref_count)     \
287           {                                             \
288             ((M17NObject *) (object))->ref_count--;     \
289             m17n_object_ref (object);                   \
290           }                                             \
291       }                                                 \
292   } while (0)
293
294
295 #define M17N_OBJECT_REF_NTIMES(object, n)                               \
296   do {                                                                  \
297     int i;                                                              \
298                                                                         \
299     if (((M17NObject *) (object))->ref_count_extended)                  \
300       for (i = 0; i < n; i++)                                           \
301         m17n_object_ref (object);                                       \
302     else if (((M17NObject *) (object))->ref_count > 0)                  \
303       {                                                                 \
304         int orig_ref_count = ((M17NObject *) (object))->ref_count;      \
305                                                                         \
306         for (i = 0; i < n; i++)                                         \
307           if (! ++((M17NObject *) (object))->ref_count)                 \
308             {                                                           \
309               ((M17NObject *) (object))->ref_count = orig_ref_count;    \
310               for (i = 0; i < n; i++)                                   \
311                 m17n_object_ref (object);                               \
312             }                                                           \
313       }                                                                 \
314   } while (0)
315
316
317 /**en Decrement the reference count of OBJECT if the count is greater
318     than 0.  In that case, if the count becomes 0, free OBJECT.  */
319
320 #define M17N_OBJECT_UNREF(object)                               \
321   do {                                                          \
322     if (object)                                                 \
323       {                                                         \
324         if (((M17NObject *) (object))->ref_count_extended)      \
325           m17n_object_unref (object);                           \
326         else if (((M17NObject *) (object))->ref_count == 0)     \
327           break;                                                \
328         else if (((M17NObject *) (object))->ref_count > 1)      \
329           ((M17NObject *) (object))->ref_count--;               \
330         else                                                    \
331           {                                                     \
332             if (((M17NObject *) (object))->u.freer)             \
333               (((M17NObject *) (object))->u.freer) (object);    \
334             else                                                \
335               free (object);                                    \
336             (object) = NULL;                                    \
337           }                                                     \
338       }                                                         \
339   } while (0)
340
341
342 typedef struct
343 {
344   int count;
345   int size, inc, used;
346   void **objects;
347 } M17NObjectArray;
348
349 extern void mdebug__register_object (M17NObjectArray *array, void *object);
350
351 #define M17N_OBJECT_REGISTER(array, object)     \
352   if (mdebug__flag & MDEBUG_FINI)               \
353     mdebug__register_object (&array, object);   \
354   else
355
356 extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
357
358 #define M17N_OBJECT_UNREGISTER(array, object)   \
359   if (mdebug__flag & MDEBUG_FINI)               \
360     mdebug__unregister_object (&array, object); \
361   else
362
363 extern void mdebug__report_object (char *name, M17NObjectArray *array);
364
365 \f
366
367 struct MTextPlist;
368
369 struct MText
370 {
371   M17NObject control;
372
373   enum MTextFormat format;
374
375   /**en Number of characters in the M-text */
376   /**ja M-text Ãæ¤Îʸ»ú¿ô */
377   int nchars;
378
379   /**en Number of bytes used to represent the characters in the M-text. */
380   /**ja M-text Ãæ¤Îʸ»ú¤òɽ¤ï¤¹¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¥Ð¥¤¥È¿ô */
381   int nbytes;
382
383   /**en Character sequence of the M-text. */
384   /**ja M-text Ãæ¤Îʸ»úÎó */
385   unsigned char *data;
386
387   /**en Number of bytes allocated for the @c data member. */
388   /**ja ¥á¥ó¥Ð @c data ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥Ð¥¤¥È¿ô */
389   int allocated;
390
391   /**en Pointer to the property list of the M-text. */
392   /**ja M-text ¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿ */
393   struct MTextPlist *plist;
394
395   /**en Caches of the character position and the corresponding byte position. */
396   /**ja Ê¸»ú°ÌÃÖ¤ª¤è¤ÓÂбþ¤¹¤ë¥Ð¥¤¥È°ÌÃ֤Υ­¥ã¥Ã¥·¥å */
397   int cache_char_pos, cache_byte_pos;
398 };
399
400 /** short description of M_CHECK_POS */
401 /** longer description of M_CHECK_POS */
402
403 #define M_CHECK_POS(mt, pos, ret)               \
404   do {                                          \
405     if ((pos) < 0 || (pos) >= (mt)->nchars)     \
406       MERROR (MERROR_RANGE, (ret));             \
407   } while (0)
408
409
410 /** short description of M_CHECK_POS_X */
411 /** longer description of M_CHECK_POS_X */
412
413 #define M_CHECK_POS_X(mt, pos, ret)             \
414   do {                                          \
415     if ((pos) < 0 || (pos) > (mt)->nchars)      \
416       MERROR (MERROR_RANGE, (ret));             \
417   } while (0)
418
419
420 /** short description of M_CHECK_RANGE */
421 /** longer description of M_CHECK_RANGE */
422
423 #define M_CHECK_RANGE(mt, from, to, ret, ret2)                  \
424   do {                                                          \
425     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
426       MERROR (MERROR_RANGE, (ret));                             \
427     if ((from) == (to))                                         \
428       return (ret2);                                            \
429   } while (0)
430
431 #define M_CHECK_RANGE_X(mt, from, to, ret)                      \
432   do {                                                          \
433     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
434       MERROR (MERROR_RANGE, (ret));                             \
435   } while (0)
436
437
438 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2)  \
439   do {                                                  \
440     int to = (pos) + (nchars);                  \
441                                                         \
442     M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2));   \
443   } while (0)
444
445
446 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
447
448 #define M_CHECK_READONLY(mt, ret)       \
449   do {                                  \
450     if ((mt)->allocated < 0)            \
451       MERROR (MERROR_MTEXT, (ret));     \
452   } while (0)
453
454 #define mtext_nchars(mt) ((mt)->nchars)
455
456 #define mtext_nbytes(mt) ((mt)->nbytes)
457
458 #define mtext_allocated(mt) ((mt)->allocated)
459
460 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
461
462 \f
463
464 enum MDebugMaskBit
465   {
466     MDEBUG_INIT =       0x01,
467     MDEBUG_FINI =       0x02,
468     MDEBUG_CHARSET =    0x04,
469     MDEBUG_CODING =     0x08,
470     MDEBUG_DATABASE =   0x10,
471     MDEBUG_FONT =       0x0100,
472     MDEBUG_FONT_FLT =   0x0200,
473     MDEBUG_FONT_OTF =   0x0400,
474     MDEBUG_INPUT =      0x0800,
475     MDEBUG_MAX
476   };
477
478 extern int mdebug__flag;
479 extern void mdebug__push_time ();
480 extern void mdebug__pop_time ();
481 extern void mdebug__print_time ();
482
483 #define MDEBUG_PRINT(msg)               \
484   do {                                  \
485     if (mdebug__flag & mdebug_mask)     \
486       fprintf (stderr, (msg));          \
487   } while (0)
488
489 #define MDEBUG_PRINT1(fmt, arg)         \
490   do {                                  \
491     if (mdebug__flag & mdebug_mask)     \
492       fprintf (stderr, (fmt), (arg));   \
493   } while (0)
494
495 #define MDEBUG_PRINT2(fmt, arg1, arg2)          \
496   do {                                          \
497     if (mdebug__flag & mdebug_mask)             \
498       fprintf (stderr, (fmt), (arg1), (arg2));  \
499   } while (0)
500
501 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3)            \
502   do {                                                  \
503     if (mdebug__flag & mdebug_mask)                     \
504       fprintf (stderr, (fmt), (arg1), (arg2), (arg3));  \
505   } while (0)
506
507 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)              \
508   do {                                                          \
509     if (mdebug__flag & mdebug_mask)                             \
510       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4));  \
511   } while (0)
512
513 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)                \
514   do {                                                                  \
515     if (mdebug__flag & mdebug_mask)                                     \
516       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5));  \
517   } while (0)
518
519
520 #define MDEBUG_PUSH_TIME()              \
521   do {                                  \
522     if (mdebug__flag & mdebug_mask)     \
523       mdebug__push_time ();             \
524   } while (0)
525
526
527 #define MDEBUG_POP_TIME()               \
528   do {                                  \
529     if (mdebug__flag & mdebug_mask)     \
530       mdebug__pop_time ();              \
531   } while (0)
532
533
534 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)        \
535   do {                                          \
536     if (mdebug__flag & mdebug_mask)             \
537       {                                         \
538         fprintf (stderr, " [%s] ", tag);        \
539         mdebug__print_time ();                  \
540         fprintf ARG_LIST;                       \
541         fprintf (stderr, "\n");                 \
542       }                                         \
543   } while (0)
544
545
546 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
547
548 #define SWAP_32(c)                      \
549   (((c) >> 24) | (((c) >> 8) & 0xFF00)  \
550    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
551
552
553 extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
554                                    MSymbol tag3, MSymbol tag4);
555 extern void *(*mdatabase__loader) (void *);
556
557 /* Initialize/finalize function.  */
558
559 extern int msymbol__init ();
560 extern void msymbol__fini ();
561
562 extern int mplist__init ();
563 extern void mplist__fini ();
564
565 extern int mtext__init ();
566 extern void mtext__fini ();
567
568 extern int mtext__prop_init ();
569 extern void mtext__prop_fini ();
570
571 extern int mchartable__init ();
572 extern void mchartable__fini ();
573
574 extern int mcharset__init ();
575 extern void mcharset__fini ();
576
577 extern int mcoding__init ();
578 extern void mcoding__fini ();
579
580 extern int mdatabase__init (void);
581 extern void mdatabase__fini (void);
582
583 extern int mchar__init ();
584 extern void mchar__fini ();
585
586 extern int mlang__init ();
587 extern void mlang__fini ();
588
589 extern int mlocale__init ();
590 extern void mlocale__fini ();
591
592 extern int minput__init ();
593 extern void minput__fini ();
594
595 #endif /* _M17N_INTERNAL_H_ */
596
597 /*
598   Local Variables:
599   coding: euc-japan
600   End:
601 */