1 /* internal.h -- common header file for the internal CORE and SHELL APIs. 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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., 51 Franklin Street, Fifth Floor, 21 Boston, MA 02110-1301 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 #if ENABLE_NLS 39 #include <libintl.h> 40 #define _(String) dgettext ("m17n-lib", String) 41 #else 42 #define _(String) (String) 43 #endif 44 45 /** Return with code RET while setting merror_code to ERR. */ 46 47 #define MERROR(err, ret) \ 48 do { \ 49 merror_code = (err); \ 50 mdebug_hook (); \ 51 return (ret); \ 52 } while (0) 53 54 55 #define MERROR_GOTO(err, label) \ 56 do { \ 57 if ((err)) \ 58 merror_code = (err); \ 59 mdebug_hook (); \ 60 goto label; \ 61 } while (0) 62 63 64 #define MWARNING(err) \ 65 do { \ 66 mdebug_hook (); \ 67 goto warning; \ 68 } while (0) 69 70 #define MFATAL(err) \ 71 do { \ 72 mdebug_hook (); \ 73 exit (err); \ 74 } while (0) 75 76 #define MFAILP(cond) ((cond) ? 0 : mdebug_hook ()) 77 78 #define M_CHECK_CHAR(c, ret) \ 79 if ((c) < 0 || (c) > MCHAR_MAX) \ 80 MERROR (MERROR_CHAR, (ret)); \ 81 else 82 83 84 /** Memory allocation stuffs. */ 85 86 /* Call a handler function for memory full situation with argument 87 ERR. ERR must be one of enum MErrorCode. By default, the 88 handler function just calls exit () with argument ERR. */ 89 90 #define MEMORY_FULL(err) \ 91 do { \ 92 (*m17n_memory_full_handler) (err); \ 93 exit (err); \ 94 } while (0) 95 96 97 /** The macro MTABLE_MALLOC () allocates memory (by malloc) for an 98 array of SIZE objects. The size of each object is determined by 99 the type of P. Then, it sets P to the allocated memory. ERR must 100 be one of enum MErrorCode. If the allocation fails, the macro 101 MEMORY_FULL () is called with argument ERR. */ 102 103 #define MTABLE_MALLOC(p, size, err) \ 104 do { \ 105 if (! ((p) = (void *) malloc (sizeof (*(p)) * (size)))) \ 106 MEMORY_FULL (err); \ 107 } while (0) 108 109 110 /** The macro MTABLE_CALLOC() is like the macro MTABLE_MALLOC but use 111 calloc instead of malloc, thus the allocated memory are zero 112 cleared. */ 113 114 #define MTABLE_CALLOC(p, size, err) \ 115 do { \ 116 if (! ((p) = (void *) calloc (sizeof (*(p)), size))) \ 117 MEMORY_FULL (err); \ 118 } while (0) 119 120 #define MTABLE_CALLOC_SAFE(p, size) \ 121 ((p) = (void *) calloc (sizeof (*(p)), (size))) 122 123 124 /** The macro MTABLE_REALLOC () changes the size of memory block 125 pointed to by P to a size suitable for an array of SIZE objects. 126 The size of each object is determined by the type of P. ERR must 127 be one of enum MErrorCode. If the allocation fails, the macro 128 MEMORY_FULL () is called with argument ERR. */ 129 130 #define MTABLE_REALLOC(p, size, err) \ 131 do { \ 132 if (! ((p) = (void *) realloc ((p), sizeof (*(p)) * (size)))) \ 133 MEMORY_FULL (err); \ 134 } while (0) 135 136 137 /** The macro MTABLE_ALLOCA () allocates memory (by alloca) for an 138 array of SIZE objects. The size of each object is determined by 139 the type of P. Then, it sets P to the allocated memory. ERR must 140 be one of enum MErrorCode. If the allocation fails, the macro 141 MEMORY_FULL () is called with argument ERR. */ 142 143 #define MTABLE_ALLOCA(p, size, err) \ 144 do { \ 145 int allocasize = sizeof (*(p)) * (size); \ 146 if (! ((p) = (void *) alloca (allocasize))) \ 147 MEMORY_FULL (err); \ 148 memset ((p), 0, allocasize); \ 149 } while (0) 150 151 152 /** short description of MSTRUCT_MALLOC */ 153 /** The macro MSTRUCT_MALLOC () allocates memory (by malloc) for an 154 object whose size is determined by the type of P, and sets P to 155 the allocated memory. ERR must be one of enum MErrorCode. If 156 the allocation fails, the macro MEMORY_FULL () is called with 157 argument ERR. */ 158 159 #define MSTRUCT_MALLOC(p, err) \ 160 do { \ 161 if (! ((p) = (void *) malloc (sizeof (*(p))))) \ 162 MEMORY_FULL (err); \ 163 } while (0) 164 165 166 #define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err)) 167 168 #define MSTRUCT_CALLOC_SAFE(p) MTABLE_CALLOC_SAFE ((p), 1) 169 170 #define USE_SAFE_ALLOCA \ 171 int sa_must_free = 0, sa_size = 0 172 173 /* P must be the same in all calls to SAFE_ALLOCA and SAFE_FREE in a 174 function. */ 175 176 #define SAFE_ALLOCA(P, SIZE) \ 177 do { \ 178 if (sa_size < (SIZE)) \ 179 { \ 180 if (sa_must_free) \ 181 (P) = realloc ((P), (SIZE)); \ 182 else \ 183 { \ 184 (P) = alloca ((SIZE)); \ 185 if (! (P)) \ 186 { \ 187 (P) = malloc (SIZE); \ 188 sa_must_free = 1; \ 189 } \ 190 } \ 191 if (! (P)) \ 192 MEMORY_FULL (1); \ 193 sa_size = (SIZE); \ 194 } \ 195 } while (0) 196 197 #define SAFE_FREE(P) \ 198 do { \ 199 if (sa_must_free && sa_size > 0) \ 200 { \ 201 free ((P)); \ 202 sa_must_free = sa_size = 0; \ 203 } \ 204 } while (0) 205 206 207 /** Extendable array. */ 208 209 #define MLIST_RESET(list) \ 210 ((list)->used = 0) 211 212 213 #define MLIST_INIT1(list, mem, increment) \ 214 do { \ 215 (list)->size = (list)->used = 0; \ 216 (list)->inc = (increment); \ 217 (list)->mem = NULL; \ 218 } while (0) 219 220 221 #define MLIST_APPEND1(list, mem, elt, err) \ 222 do { \ 223 if ((list)->inc <= 0) \ 224 mdebug_hook (); \ 225 if ((list)->size == (list)->used) \ 226 { \ 227 (list)->size += (list)->inc; \ 228 MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ 229 } \ 230 (list)->mem[(list)->used++] = (elt); \ 231 } while (0) 232 233 234 #define MLIST_PREPEND1(list, mem, elt, err) \ 235 do { \ 236 if ((list)->inc <= 0) \ 237 mdebug_hook (); \ 238 if ((list)->size == (list)->used) \ 239 { \ 240 (list)->size += (list)->inc; \ 241 MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ 242 } \ 243 memmove ((list)->mem + 1, (list)->mem, \ 244 sizeof *((list)->mem) * ((list)->used)); \ 245 (list)->mem[0] = (elt); \ 246 (list)->used++; \ 247 } while (0) 248 249 250 #define MLIST_INSERT1(list, mem, idx, len, err) \ 251 do { \ 252 while ((list)->used + (len) > (list)->size) \ 253 { \ 254 (list)->size += (list)->inc; \ 255 MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ 256 } \ 257 memmove ((list)->mem + ((idx) + (len)), (list)->mem + (idx), \ 258 (sizeof *((list)->mem)) * ((list)->used - (idx))); \ 259 (list)->used += (len); \ 260 } while (0) 261 262 263 #define MLIST_DELETE1(list, mem, idx, len) \ 264 do { \ 265 memmove ((list)->mem + (idx), (list)->mem + (idx) + (len), \ 266 (sizeof *((list)->mem)) * ((list)->used - (idx) - (len))); \ 267 (list)->used -= (len); \ 268 } while (0) 269 270 271 #define MLIST_COPY1(list0, list1, mem, err) \ 272 do { \ 273 (list0)->size = (list0)->used = (list1)->used; \ 274 (list0)->inc = 1; \ 275 MTABLE_MALLOC ((list0)->mem, (list0)->used, (err)); \ 276 memcpy ((list0)->mem, (list1)->mem, \ 277 (sizeof (list0)->mem) * (list0)->used); \ 278 } while (0) 279 280 281 #define MLIST_FREE1(list, mem) \ 282 if ((list)->size) \ 283 { \ 284 free ((list)->mem); \ 285 (list)->mem = NULL; \ 286 (list)->size = (list)->used = 0; \ 287 } \ 288 else 289 290 291 292 typedef struct 293 { 294 void (*freer) (void *); 295 int size, inc, used; 296 unsigned *counts; 297 } M17NObjectRecord; 298 299 typedef struct 300 { 301 /**en Reference count of the object. */ 302 /**ja ���֥������Ȥλ��ȿ�. */ 303 unsigned ref_count : 16; 304 305 unsigned ref_count_extended : 1; 306 307 /**en A flag bit used for various perpose. */ 308 /**ja ���ޤ��ޤ���Ū���Ѥ�����ե饰�ӥå�. */ 309 unsigned flag : 15; 310 311 union { 312 /**en If <ref_count_extended> is zero, a function to free the 313 object. */ 314 /**ja <ref_count_extended> �� 0 �ʤ�Х��֥������Ȥ��������ؿ�. */ 315 void (*freer) (void *); 316 /**en If <ref_count_extended> is nonzero, a pointer to the 317 struct M17NObjectRecord. */ 318 /**ja <ref_count_extended> �� 0 �Ǥʤ���й�¤�� M17NObjectRecord �ؤΥݥ���. */ 319 M17NObjectRecord *record; 320 } u; 321 } M17NObject; 322 323 324 /** Allocate a managed object OBJECT which has freer FREE_FUNC. */ 325 326 #define M17N_OBJECT(object, free_func, err) \ 327 do { \ 328 MSTRUCT_CALLOC ((object), (err)); \ 329 ((M17NObject *) (object))->ref_count = 1; \ 330 ((M17NObject *) (object))->u.freer = free_func; \ 331 } while (0) 332 333 334 /**en Increment the reference count of OBJECT if the count is not 335 0. */ 336 /**ja OBJECT �λ��ȿ��� 0 �Ǥʤ���� 1 ���䤹. */ 337 338 #define M17N_OBJECT_REF(object) \ 339 do { \ 340 if (((M17NObject *) (object))->ref_count_extended) \ 341 m17n_object_ref (object); \ 342 else if (((M17NObject *) (object))->ref_count > 0) \ 343 { \ 344 ((M17NObject *) (object))->ref_count++; \ 345 if (! ((M17NObject *) (object))->ref_count) \ 346 { \ 347 ((M17NObject *) (object))->ref_count--; \ 348 m17n_object_ref (object); \ 349 } \ 350 } \ 351 } while (0) 352 353 354 #define M17N_OBJECT_REF_NTIMES(object, n) \ 355 do { \ 356 int i; \ 357 \ 358 if (((M17NObject *) (object))->ref_count_extended) \ 359 for (i = 0; i < n; i++) \ 360 m17n_object_ref (object); \ 361 else if (((M17NObject *) (object))->ref_count > 0) \ 362 { \ 363 int orig_ref_count = ((M17NObject *) (object))->ref_count; \ 364 \ 365 for (i = 0; i < n; i++) \ 366 if (! ++((M17NObject *) (object))->ref_count) \ 367 { \ 368 ((M17NObject *) (object))->ref_count = orig_ref_count; \ 369 for (i = 0; i < n; i++) \ 370 m17n_object_ref (object); \ 371 } \ 372 } \ 373 } while (0) 374 375 376 /**en Decrement the reference count of OBJECT if the count is greater 377 than 0. In that case, if the count becomes 0, free OBJECT. */ 378 /**ja OBJECT �λ��ȿ��� 0 ����礭����� 1 ���餹�����餷�� 0 �ˤʤ�� 379 OBJECT ���������. */ 380 381 #define M17N_OBJECT_UNREF(object) \ 382 do { \ 383 if (object) \ 384 { \ 385 if (((M17NObject *) (object))->ref_count_extended \ 386 || mdebug__flags[MDEBUG_FINI]) \ 387 { \ 388 if (m17n_object_unref (object) == 0) \ 389 (object) = NULL; \ 390 } \ 391 else if (((M17NObject *) (object))->ref_count == 0) \ 392 break; \ 393 else \ 394 { \ 395 ((M17NObject *) (object))->ref_count--; \ 396 if (((M17NObject *) (object))->ref_count == 0) \ 397 { \ 398 if (((M17NObject *) (object))->u.freer) \ 399 (((M17NObject *) (object))->u.freer) (object); \ 400 else \ 401 free (object); \ 402 (object) = NULL; \ 403 } \ 404 } \ 405 } \ 406 } while (0) 407 408 typedef struct _M17NObjectArray M17NObjectArray; 409 410 struct _M17NObjectArray 411 { 412 char *name; 413 int count; 414 int size, inc, used; 415 void **objects; 416 M17NObjectArray *next; 417 }; 418 419 extern void mdebug__add_object_array (M17NObjectArray *array, char *name); 420 421 #define M17N_OBJECT_ADD_ARRAY(array, name) \ 422 if (mdebug__flags[MDEBUG_FINI]) \ 423 mdebug__add_object_array (&array, name); \ 424 else 425 426 extern void mdebug__register_object (M17NObjectArray *array, void *object); 427 428 #define M17N_OBJECT_REGISTER(array, object) \ 429 if (mdebug__flags[MDEBUG_FINI]) \ 430 mdebug__register_object (&array, object); \ 431 else 432 433 extern void mdebug__unregister_object (M17NObjectArray *array, void *object); 434 435 #define M17N_OBJECT_UNREGISTER(array, object) \ 436 if (mdebug__flags[MDEBUG_FINI]) \ 437 mdebug__unregister_object (&array, object); \ 438 else 439 440 441 442 struct MTextPlist; 443 444 enum MTextCoverage 445 { 446 MTEXT_COVERAGE_ASCII, 447 MTEXT_COVERAGE_UNICODE, 448 MTEXT_COVERAGE_FULL 449 }; 450 451 struct MText 452 { 453 M17NObject control; 454 455 unsigned format : 16; 456 unsigned coverage : 16; 457 458 /**en Number of characters in the M-text */ 459 /**ja M-text ���ʸ���� */ 460 int nchars; 461 462 /**en Number of bytes used to represent the characters in the M-text. */ 463 /**ja M-text ���ʸ����ɽ�魯������Ѥ�����Х��ȿ� */ 464 int nbytes; 465 466 /**en Character sequence of the M-text. */ 467 /**ja M-text ���ʸ���� */ 468 unsigned char *data; 469 470 /**en Number of bytes allocated for the @c data member. */ 471 /**ja ���� @c data �˳�����Ƥ�줿�Х��ȿ� */ 472 int allocated; 473 474 /**en Pointer to the property list of the M-text. */ 475 /**ja M-text �Υץ�ѥƥ��ꥹ�ȤؤΥݥ��� */ 476 struct MTextPlist *plist; 477 478 /**en Caches of the character position and the corresponding byte position. */ 479 /**ja ʸ�����֤�����б�����Х��Ȱ��֤Υ���å��� */ 480 int cache_char_pos, cache_byte_pos; 481 }; 482 483 /** short description of M_CHECK_POS */ 484 /** longer description of M_CHECK_POS */ 485 486 #define M_CHECK_POS(mt, pos, ret) \ 487 do { \ 488 if ((pos) < 0 || (pos) >= (mt)->nchars) \ 489 MERROR (MERROR_RANGE, (ret)); \ 490 } while (0) 491 492 493 /** short description of M_CHECK_POS_X */ 494 /** longer description of M_CHECK_POS_X */ 495 496 #define M_CHECK_POS_X(mt, pos, ret) \ 497 do { \ 498 if ((pos) < 0 || (pos) > (mt)->nchars) \ 499 MERROR (MERROR_RANGE, (ret)); \ 500 } while (0) 501 502 503 /** short description of M_CHECK_RANGE */ 504 /** longer description of M_CHECK_RANGE */ 505 506 #define M_CHECK_RANGE(mt, from, to, ret, ret2) \ 507 do { \ 508 if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars) \ 509 MERROR (MERROR_RANGE, (ret)); \ 510 if ((from) == (to)) \ 511 return (ret2); \ 512 } while (0) 513 514 #define M_CHECK_RANGE_X(mt, from, to, ret) \ 515 do { \ 516 if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars) \ 517 MERROR (MERROR_RANGE, (ret)); \ 518 } while (0) 519 520 521 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2) \ 522 do { \ 523 int to = (pos) + (nchars); \ 524 \ 525 M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2)); \ 526 } while (0) 527 528 529 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0) 530 531 #define M_CHECK_READONLY(mt, ret) \ 532 do { \ 533 if ((mt)->allocated < 0) \ 534 MERROR (MERROR_MTEXT, (ret)); \ 535 } while (0) 536 537 #define mtext_nchars(mt) ((mt)->nchars) 538 539 #define mtext_nbytes(mt) ((mt)->nbytes) 540 541 #define mtext_allocated(mt) ((mt)->allocated) 542 543 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars)) 544 545 546 547 enum MDebugFlag 548 { 549 MDEBUG_INIT, 550 MDEBUG_FINI, 551 MDEBUG_CHARSET, 552 MDEBUG_CODING, 553 MDEBUG_DATABASE, 554 MDEBUG_FONT, 555 MDEBUG_FLT, 556 MDEBUG_FONTSET, 557 MDEBUG_INPUT, 558 MDEBUG_ALL, 559 MDEBUG_MAX = MDEBUG_ALL 560 }; 561 562 extern int mdebug__flags[MDEBUG_MAX]; 563 extern FILE *mdebug__output; 564 extern void mdebug__push_time (); 565 extern void mdebug__pop_time (); 566 extern void mdebug__print_time (); 567 568 #define MDEBUG_FLAG() mdebug__flags[mdebug_flag] 569 570 #define MDEBUG_PRINT0(FPRINTF) \ 571 do { \ 572 if (MDEBUG_FLAG ()) \ 573 { \ 574 FPRINTF; \ 575 fflush (mdebug__output); \ 576 } \ 577 } while (0) 578 579 #define MDEBUG_PRINT(msg) \ 580 MDEBUG_PRINT0 (fprintf (mdebug__output, "%s", (msg))) 581 582 #define MDEBUG_PRINT1(fmt, arg) \ 583 MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg))) 584 585 #define MDEBUG_PRINT2(fmt, arg1, arg2) \ 586 MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2))) 587 588 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3) \ 589 MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3))) 590 591 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4) \ 592 MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4))) 593 594 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5) \ 595 MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5))) 596 597 #define MDEBUG_DUMP(prefix, postfix, call) \ 598 do { \ 599 if (MDEBUG_FLAG ()) \ 600 { \ 601 fprintf (mdebug__output, "%s", prefix); \ 602 call; \ 603 fprintf (mdebug__output, "%s", postfix); \ 604 fflush (mdebug__output); \ 605 } \ 606 } while (0) 607 608 #define MDEBUG_PUSH_TIME() \ 609 do { \ 610 if (MDEBUG_FLAG ()) \ 611 mdebug__push_time (); \ 612 } while (0) 613 614 615 #define MDEBUG_POP_TIME() \ 616 do { \ 617 if (MDEBUG_FLAG ()) \ 618 mdebug__pop_time (); \ 619 } while (0) 620 621 622 #define MDEBUG_PRINT_TIME(tag, ARG_LIST) \ 623 do { \ 624 if (MDEBUG_FLAG ()) \ 625 { \ 626 fprintf (mdebug__output, " [%s] ", tag); \ 627 mdebug__print_time (); \ 628 fprintf ARG_LIST; \ 629 fprintf (mdebug__output, "\n"); \ 630 } \ 631 } while (0) 632 633 634 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8)) 635 636 #define SWAP_32(c) \ 637 (((c) >> 24) | (((c) >> 8) & 0xFF00) \ 638 | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24)) 639 640 641 /* Initialize/finalize function. */ 642 643 extern int msymbol__init (); 644 extern void msymbol__fini (); 645 646 extern int mplist__init (); 647 extern void mplist__fini (); 648 649 extern int mtext__init (); 650 extern void mtext__fini (); 651 652 extern int mtext__prop_init (); 653 extern void mtext__prop_fini (); 654 655 extern int mchartable__init (); 656 extern void mchartable__fini (); 657 658 extern int mcharset__init (); 659 extern void mcharset__fini (); 660 661 extern int mcoding__init (); 662 extern void mcoding__fini (); 663 664 extern int mdatabase__init (void); 665 extern void mdatabase__fini (void); 666 667 extern int mchar__init (); 668 extern void mchar__fini (); 669 670 extern int mlang__init (); 671 extern void mlang__fini (); 672 673 extern int mlocale__init (); 674 extern void mlocale__fini (); 675 676 extern int minput__init (); 677 extern void minput__fini (); 678 679 #endif /* _M17N_INTERNAL_H_ */ 680 681 /* 682 Local Variables: 683 coding: euc-japan 684 End: 685 */ 686