*** empty log message ***
[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           }                                                     \
337       }                                                         \
338   } while (0)
339
340
341 typedef struct
342 {
343   int count;
344   int size, inc, used;
345   void **objects;
346 } M17NObjectArray;
347
348 extern void mdebug__register_object (M17NObjectArray *array, void *object);
349
350 #define M17N_OBJECT_REGISTER(array, object)     \
351   if (mdebug__flag & MDEBUG_FINI)               \
352     mdebug__register_object (&array, object);   \
353   else
354
355 extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
356
357 #define M17N_OBJECT_UNREGISTER(array, object)   \
358   if (mdebug__flag & MDEBUG_FINI)               \
359     mdebug__unregister_object (&array, object); \
360   else
361
362 extern void mdebug__report_object (char *name, M17NObjectArray *array);
363
364 \f
365
366 struct MTextPlist;
367
368 struct MText
369 {
370   M17NObject control;
371
372   enum MTextFormat format;
373
374   /**en Number of characters in the M-text */
375   /**ja M-text Ãæ¤Îʸ»ú¿ô */
376   int nchars;
377
378   /**en Number of bytes used to represent the characters in the M-text. */
379   /**ja M-text Ãæ¤Îʸ»ú¤òɽ¤ï¤¹¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¥Ð¥¤¥È¿ô */
380   int nbytes;
381
382   /**en Character sequence of the M-text. */
383   /**ja M-text Ãæ¤Îʸ»úÎó */
384   unsigned char *data;
385
386   /**en Number of bytes allocated for the @c data member. */
387   /**ja ¥á¥ó¥Ð @c data ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥Ð¥¤¥È¿ô */
388   int allocated;
389
390   /**en Pointer to the property list of the M-text. */
391   /**ja M-text ¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿ */
392   struct MTextPlist *plist;
393
394   /**en Caches of the character position and the corresponding byte position. */
395   /**ja Ê¸»ú°ÌÃÖ¤ª¤è¤ÓÂбþ¤¹¤ë¥Ð¥¤¥È°ÌÃ֤Υ­¥ã¥Ã¥·¥å */
396   int cache_char_pos, cache_byte_pos;
397 };
398
399 /** short description of M_CHECK_POS */
400 /** longer description of M_CHECK_POS */
401
402 #define M_CHECK_POS(mt, pos, ret)               \
403   do {                                          \
404     if ((pos) < 0 || (pos) >= (mt)->nchars)     \
405       MERROR (MERROR_RANGE, (ret));             \
406   } while (0)
407
408
409 /** short description of M_CHECK_POS_X */
410 /** longer description of M_CHECK_POS_X */
411
412 #define M_CHECK_POS_X(mt, pos, ret)             \
413   do {                                          \
414     if ((pos) < 0 || (pos) > (mt)->nchars)      \
415       MERROR (MERROR_RANGE, (ret));             \
416   } while (0)
417
418
419 /** short description of M_CHECK_RANGE */
420 /** longer description of M_CHECK_RANGE */
421
422 #define M_CHECK_RANGE(mt, from, to, ret, ret2)                  \
423   do {                                                          \
424     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
425       MERROR (MERROR_RANGE, (ret));                             \
426     if ((from) == (to))                                         \
427       return (ret2);                                            \
428   } while (0)
429
430 #define M_CHECK_RANGE_X(mt, from, to, ret)                      \
431   do {                                                          \
432     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
433       MERROR (MERROR_RANGE, (ret));                             \
434   } while (0)
435
436
437 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2)  \
438   do {                                                  \
439     int to = (pos) + (nchars);                  \
440                                                         \
441     M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2));   \
442   } while (0)
443
444
445 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
446
447 #define M_CHECK_READONLY(mt, ret)       \
448   do {                                  \
449     if ((mt)->allocated < 0)            \
450       MERROR (MERROR_MTEXT, (ret));     \
451   } while (0)
452
453 #define mtext_nchars(mt) ((mt)->nchars)
454
455 #define mtext_nbytes(mt) ((mt)->nbytes)
456
457 #define mtext_allocated(mt) ((mt)->allocated)
458
459 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
460
461 \f
462
463 enum MDebugMaskBit
464   {
465     MDEBUG_INIT =       0x01,
466     MDEBUG_FINI =       0x02,
467     MDEBUG_CHARSET =    0x04,
468     MDEBUG_CODING =     0x08,
469     MDEBUG_DATABASE =   0x10,
470     MDEBUG_FONT =       0x0100,
471     MDEBUG_FONT_FLT =   0x0200,
472     MDEBUG_FONT_OTF =   0x0400,
473     MDEBUG_INPUT =      0x0800,
474     MDEBUG_MAX
475   };
476
477 extern int mdebug__flag;
478 extern void mdebug__push_time ();
479 extern void mdebug__pop_time ();
480 extern void mdebug__print_time ();
481
482 #define MDEBUG_PRINT(msg)               \
483   do {                                  \
484     if (mdebug__flag & mdebug_mask)     \
485       fprintf (stderr, (msg));          \
486   } while (0)
487
488 #define MDEBUG_PRINT1(fmt, arg)         \
489   do {                                  \
490     if (mdebug__flag & mdebug_mask)     \
491       fprintf (stderr, (fmt), (arg));   \
492   } while (0)
493
494 #define MDEBUG_PRINT2(fmt, arg1, arg2)          \
495   do {                                          \
496     if (mdebug__flag & mdebug_mask)             \
497       fprintf (stderr, (fmt), (arg1), (arg2));  \
498   } while (0)
499
500 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3)            \
501   do {                                                  \
502     if (mdebug__flag & mdebug_mask)                     \
503       fprintf (stderr, (fmt), (arg1), (arg2), (arg3));  \
504   } while (0)
505
506 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)              \
507   do {                                                          \
508     if (mdebug__flag & mdebug_mask)                             \
509       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4));  \
510   } while (0)
511
512 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)                \
513   do {                                                                  \
514     if (mdebug__flag & mdebug_mask)                                     \
515       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5));  \
516   } while (0)
517
518
519 #define MDEBUG_PUSH_TIME()              \
520   do {                                  \
521     if (mdebug__flag & mdebug_mask)     \
522       mdebug__push_time ();             \
523   } while (0)
524
525
526 #define MDEBUG_POP_TIME()               \
527   do {                                  \
528     if (mdebug__flag & mdebug_mask)     \
529       mdebug__pop_time ();              \
530   } while (0)
531
532
533 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)        \
534   do {                                          \
535     if (mdebug__flag & mdebug_mask)             \
536       {                                         \
537         fprintf (stderr, " [%s] ", tag);        \
538         mdebug__print_time ();                  \
539         fprintf ARG_LIST;                       \
540         fprintf (stderr, "\n");                 \
541       }                                         \
542   } while (0)
543
544
545 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
546
547 #define SWAP_32(c)                      \
548   (((c) >> 24) | (((c) >> 8) & 0xFF00)  \
549    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
550
551
552 extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
553                                    MSymbol tag3, MSymbol tag4);
554 extern void *(*mdatabase__loader) (void *);
555
556 /* Initialize/finalize function.  */
557
558 extern int msymbol__init ();
559 extern void msymbol__fini ();
560
561 extern int mplist__init ();
562 extern void mplist__fini ();
563
564 extern int mtext__init ();
565 extern void mtext__fini ();
566
567 extern int mtext__prop_init ();
568 extern void mtext__prop_fini ();
569
570 extern int mchartable__init ();
571 extern void mchartable__fini ();
572
573 extern int mcharset__init ();
574 extern void mcharset__fini ();
575
576 extern int mcoding__init ();
577 extern void mcoding__fini ();
578
579 extern int mdatabase__init (void);
580 extern void mdatabase__fini (void);
581
582 extern int mchar__init ();
583 extern void mchar__fini ();
584
585 extern int mlang__init ();
586 extern void mlang__fini ();
587
588 extern int mlocale__init ();
589 extern void mlocale__fini ();
590
591 extern int minput__init ();
592 extern void minput__fini ();
593
594 #endif /* _M17N_INTERNAL_H_ */
595
596 /*
597   Local Variables:
598   coding: euc-japan
599   End:
600 */