(mface_put_prop): If the new value is the same as the
[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 MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
442
443 #define M_CHECK_READONLY(mt, ret)       \
444   do {                                  \
445     if ((mt)->allocated < 0)            \
446       MERROR (MERROR_MTEXT, (ret));     \
447   } while (0)
448
449 #define mtext_nchars(mt) ((mt)->nchars)
450
451 #define mtext_nbytes(mt) ((mt)->nbytes)
452
453 #define mtext_allocated(mt) ((mt)->allocated)
454
455 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
456
457 \f
458
459 enum MDebugMaskBit
460   {
461     MDEBUG_INIT =       0x01,
462     MDEBUG_FINI =       0x02,
463     MDEBUG_CHARSET =    0x04,
464     MDEBUG_CODING =     0x08,
465     MDEBUG_DATABASE =   0x10,
466     MDEBUG_FONT =       0x0100,
467     MDEBUG_FONT_FLT =   0x0200,
468     MDEBUG_FONT_OTF =   0x0400,
469     MDEBUG_INPUT =      0x0800,
470     MDEBUG_MAX
471   };
472
473 extern int mdebug__flag;
474 extern void mdebug__push_time ();
475 extern void mdebug__pop_time ();
476 extern void mdebug__print_time ();
477
478 #define MDEBUG_PRINT(msg)               \
479   do {                                  \
480     if (mdebug__flag & mdebug_mask)     \
481       fprintf (stderr, (msg));          \
482   } while (0)
483
484 #define MDEBUG_PRINT1(fmt, arg)         \
485   do {                                  \
486     if (mdebug__flag & mdebug_mask)     \
487       fprintf (stderr, (fmt), (arg));   \
488   } while (0)
489
490 #define MDEBUG_PRINT2(fmt, arg1, arg2)          \
491   do {                                          \
492     if (mdebug__flag & mdebug_mask)             \
493       fprintf (stderr, (fmt), (arg1), (arg2));  \
494   } while (0)
495
496 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3)            \
497   do {                                                  \
498     if (mdebug__flag & mdebug_mask)                     \
499       fprintf (stderr, (fmt), (arg1), (arg2), (arg3));  \
500   } while (0)
501
502 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)              \
503   do {                                                          \
504     if (mdebug__flag & mdebug_mask)                             \
505       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4));  \
506   } while (0)
507
508 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)                \
509   do {                                                                  \
510     if (mdebug__flag & mdebug_mask)                                     \
511       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5));  \
512   } while (0)
513
514
515 #define MDEBUG_PUSH_TIME()              \
516   do {                                  \
517     if (mdebug__flag & mdebug_mask)     \
518       mdebug__push_time ();             \
519   } while (0)
520
521
522 #define MDEBUG_POP_TIME()               \
523   do {                                  \
524     if (mdebug__flag & mdebug_mask)     \
525       mdebug__pop_time ();              \
526   } while (0)
527
528
529 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)        \
530   do {                                          \
531     if (mdebug__flag & mdebug_mask)             \
532       {                                         \
533         fprintf (stderr, " [%s] ", tag);        \
534         mdebug__print_time ();                  \
535         fprintf ARG_LIST;                       \
536         fprintf (stderr, "\n");                 \
537       }                                         \
538   } while (0)
539
540
541 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
542
543 #define SWAP_32(c)                      \
544   (((c) >> 24) | (((c) >> 8) & 0xFF00)  \
545    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
546
547
548 extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
549                                    MSymbol tag3, MSymbol tag4);
550 extern void *(*mdatabase__loader) (void *);
551
552 /* Initialize/finalize function.  */
553
554 extern int msymbol__init ();
555 extern void msymbol__fini ();
556
557 extern int mplist__init ();
558 extern void mplist__fini ();
559
560 extern int mtext__init ();
561 extern void mtext__fini ();
562
563 extern int mtext__prop_init ();
564 extern void mtext__prop_fini ();
565
566 extern int mchartable__init ();
567 extern void mchartable__fini ();
568
569 extern int mcharset__init ();
570 extern void mcharset__fini ();
571
572 extern int mcoding__init ();
573 extern void mcoding__fini ();
574
575 extern int mdatabase__init (void);
576 extern void mdatabase__fini (void);
577
578 extern int mchar__init ();
579 extern void mchar__fini ();
580
581 extern int mlang__init ();
582 extern void mlang__fini ();
583
584 extern int mlocale__init ();
585 extern void mlocale__fini ();
586
587 extern int minput__init ();
588 extern void minput__fini ();
589
590 #endif /* _M17N_INTERNAL_H_ */
591
592 /*
593   Local Variables:
594   coding: euc-japan
595   End:
596 */