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