Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.5
      4  *
      5  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /**
     27  * \file imports.h
     28  * Standard C library function wrappers.
     29  *
     30  * This file provides wrappers for all the standard C library functions
     31  * like malloc(), free(), printf(), getenv(), etc.
     32  */
     33 
     34 
     35 #ifndef IMPORTS_H
     36 #define IMPORTS_H
     37 
     38 
     39 #include "compiler.h"
     40 #include "glheader.h"
     41 #include "errors.h"
     42 
     43 #ifdef __cplusplus
     44 extern "C" {
     45 #endif
     46 
     47 
     48 /**********************************************************************/
     49 /** Memory macros */
     50 /*@{*/
     51 
     52 /** Allocate \p BYTES bytes */
     53 #define MALLOC(BYTES)      malloc(BYTES)
     54 /** Allocate and zero \p BYTES bytes */
     55 #define CALLOC(BYTES)      calloc(1, BYTES)
     56 /** Allocate a structure of type \p T */
     57 #define MALLOC_STRUCT(T)   (struct T *) malloc(sizeof(struct T))
     58 /** Allocate and zero a structure of type \p T */
     59 #define CALLOC_STRUCT(T)   (struct T *) calloc(1, sizeof(struct T))
     60 /** Free memory */
     61 #define FREE(PTR)          free(PTR)
     62 
     63 /*@}*/
     64 
     65 
     66 /*
     67  * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers
     68  * as offsets into buffer stores.  Since the vertex array pointer and
     69  * buffer store pointer are both pointers and we need to add them, we use
     70  * this macro.
     71  * Both pointers/offsets are expressed in bytes.
     72  */
     73 #define ADD_POINTERS(A, B)  ( (GLubyte *) (A) + (uintptr_t) (B) )
     74 
     75 
     76 /**
     77  * Sometimes we treat GLfloats as GLints.  On x86 systems, moving a float
     78  * as a int (thereby using integer registers instead of FP registers) is
     79  * a performance win.  Typically, this can be done with ordinary casts.
     80  * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0)
     81  * these casts generate warnings.
     82  * The following union typedef is used to solve that.
     83  */
     84 typedef union { GLfloat f; GLint i; GLuint u; } fi_type;
     85 
     86 
     87 
     88 /**********************************************************************
     89  * Math macros
     90  */
     91 
     92 #define MAX_GLUSHORT	0xffff
     93 #define MAX_GLUINT	0xffffffff
     94 
     95 /* Degrees to radians conversion: */
     96 #define DEG2RAD (M_PI/180.0)
     97 
     98 
     99 /***
    100  *** SQRTF: single-precision square root
    101  ***/
    102 #define SQRTF(X)  (float) sqrt((float) (X))
    103 
    104 
    105 /***
    106  *** INV_SQRTF: single-precision inverse square root
    107  ***/
    108 #define INV_SQRTF(X) (1.0F / SQRTF(X))
    109 
    110 
    111 /**
    112  * \name Work-arounds for platforms that lack C99 math functions
    113  */
    114 /*@{*/
    115 #if (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 600)) && !defined(_ISOC99_SOURCE) \
    116    && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)) \
    117    && (!defined(_MSC_VER) || (_MSC_VER < 1400))
    118 #define acosf(f) ((float) acos(f))
    119 #define asinf(f) ((float) asin(f))
    120 #define atan2f(x,y) ((float) atan2(x,y))
    121 #define atanf(f) ((float) atan(f))
    122 #define ceilf(f) ((float) ceil(f))
    123 #define cosf(f) ((float) cos(f))
    124 #define coshf(f) ((float) cosh(f))
    125 #define expf(f) ((float) exp(f))
    126 #define exp2f(f) ((float) exp2(f))
    127 #define floorf(f) ((float) floor(f))
    128 #define logf(f) ((float) log(f))
    129 
    130 #ifdef ANDROID
    131 #define log2f(f) (logf(f) * (float) (1.0 / M_LN2))
    132 #else
    133 #define log2f(f) ((float) log2(f))
    134 #endif
    135 
    136 #define powf(x,y) ((float) pow(x,y))
    137 #define sinf(f) ((float) sin(f))
    138 #define sinhf(f) ((float) sinh(f))
    139 #define sqrtf(f) ((float) sqrt(f))
    140 #define tanf(f) ((float) tan(f))
    141 #define tanhf(f) ((float) tanh(f))
    142 #define acoshf(f) ((float) acosh(f))
    143 #define asinhf(f) ((float) asinh(f))
    144 #define atanhf(f) ((float) atanh(f))
    145 #endif
    146 
    147 #if defined(_MSC_VER)
    148 static inline float truncf(float x) { return x < 0.0f ? ceilf(x) : floorf(x); }
    149 static inline float exp2f(float x) { return powf(2.0f, x); }
    150 static inline float log2f(float x) { return logf(x) * 1.442695041f; }
    151 static inline float asinhf(float x) { return logf(x + sqrtf(x * x + 1.0f)); }
    152 static inline float acoshf(float x) { return logf(x + sqrtf(x * x - 1.0f)); }
    153 static inline float atanhf(float x) { return (logf(1.0f + x) - logf(1.0f - x)) / 2.0f; }
    154 static inline int isblank(int ch) { return ch == ' ' || ch == '\t'; }
    155 #define strtoll(p, e, b) _strtoi64(p, e, b)
    156 #endif
    157 /*@}*/
    158 
    159 /***
    160  *** LOG2: Log base 2 of float
    161  ***/
    162 #ifdef USE_IEEE
    163 #if 0
    164 /* This is pretty fast, but not accurate enough (only 2 fractional bits).
    165  * Based on code from http://www.stereopsis.com/log2.html
    166  */
    167 static inline GLfloat LOG2(GLfloat x)
    168 {
    169    const GLfloat y = x * x * x * x;
    170    const GLuint ix = *((GLuint *) &y);
    171    const GLuint exp = (ix >> 23) & 0xFF;
    172    const GLint log2 = ((GLint) exp) - 127;
    173    return (GLfloat) log2 * (1.0 / 4.0);  /* 4, because of x^4 above */
    174 }
    175 #endif
    176 /* Pretty fast, and accurate.
    177  * Based on code from http://www.flipcode.com/totd/
    178  */
    179 static inline GLfloat LOG2(GLfloat val)
    180 {
    181    fi_type num;
    182    GLint log_2;
    183    num.f = val;
    184    log_2 = ((num.i >> 23) & 255) - 128;
    185    num.i &= ~(255 << 23);
    186    num.i += 127 << 23;
    187    num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3;
    188    return num.f + log_2;
    189 }
    190 #else
    191 /*
    192  * NOTE: log_base_2(x) = log(x) / log(2)
    193  * NOTE: 1.442695 = 1/log(2).
    194  */
    195 #define LOG2(x)  ((GLfloat) (log(x) * 1.442695F))
    196 #endif
    197 
    198 
    199 /***
    200  *** IS_INF_OR_NAN: test if float is infinite or NaN
    201  ***/
    202 #ifdef USE_IEEE
    203 static inline int IS_INF_OR_NAN( float x )
    204 {
    205    fi_type tmp;
    206    tmp.f = x;
    207    return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31);
    208 }
    209 #elif defined(isfinite)
    210 #define IS_INF_OR_NAN(x)        (!isfinite(x))
    211 #elif defined(finite)
    212 #define IS_INF_OR_NAN(x)        (!finite(x))
    213 #elif defined(__VMS)
    214 #define IS_INF_OR_NAN(x)        (!finite(x))
    215 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    216 #define IS_INF_OR_NAN(x)        (!isfinite(x))
    217 #else
    218 #define IS_INF_OR_NAN(x)        (!finite(x))
    219 #endif
    220 
    221 
    222 /***
    223  *** IS_NEGATIVE: test if float is negative
    224  ***/
    225 #if defined(USE_IEEE)
    226 static inline int GET_FLOAT_BITS( float x )
    227 {
    228    fi_type fi;
    229    fi.f = x;
    230    return fi.i;
    231 }
    232 #define IS_NEGATIVE(x) (GET_FLOAT_BITS(x) < 0)
    233 #else
    234 #define IS_NEGATIVE(x) (x < 0.0F)
    235 #endif
    236 
    237 
    238 /***
    239  *** DIFFERENT_SIGNS: test if two floats have opposite signs
    240  ***/
    241 #if defined(USE_IEEE)
    242 #define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
    243 #else
    244 /* Could just use (x*y<0) except for the flatshading requirements.
    245  * Maybe there's a better way?
    246  */
    247 #define DIFFERENT_SIGNS(x,y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
    248 #endif
    249 
    250 
    251 /***
    252  *** CEILF: ceiling of float
    253  *** FLOORF: floor of float
    254  *** FABSF: absolute value of float
    255  *** LOGF: the natural logarithm (base e) of the value
    256  *** EXPF: raise e to the value
    257  *** LDEXPF: multiply value by an integral power of two
    258  *** FREXPF: extract mantissa and exponent from value
    259  ***/
    260 #if defined(__gnu_linux__)
    261 /* C99 functions */
    262 #define CEILF(x)   ceilf(x)
    263 #define FLOORF(x)  floorf(x)
    264 #define FABSF(x)   fabsf(x)
    265 #define LOGF(x)    logf(x)
    266 #define EXPF(x)    expf(x)
    267 #define LDEXPF(x,y)  ldexpf(x,y)
    268 #define FREXPF(x,y)  frexpf(x,y)
    269 #else
    270 #define CEILF(x)   ((GLfloat) ceil(x))
    271 #define FLOORF(x)  ((GLfloat) floor(x))
    272 #define FABSF(x)   ((GLfloat) fabs(x))
    273 #define LOGF(x)    ((GLfloat) log(x))
    274 #define EXPF(x)    ((GLfloat) exp(x))
    275 #define LDEXPF(x,y)  ((GLfloat) ldexp(x,y))
    276 #define FREXPF(x,y)  ((GLfloat) frexp(x,y))
    277 #endif
    278 
    279 
    280 /**
    281  * Convert float to int by rounding to nearest integer, away from zero.
    282  */
    283 static inline int IROUND(float f)
    284 {
    285    return (int) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F));
    286 }
    287 
    288 
    289 /**
    290  * Convert float to int64 by rounding to nearest integer.
    291  */
    292 static inline GLint64 IROUND64(float f)
    293 {
    294    return (GLint64) ((f >= 0.0F) ? (f + 0.5F) : (f - 0.5F));
    295 }
    296 
    297 
    298 /**
    299  * Convert positive float to int by rounding to nearest integer.
    300  */
    301 static inline int IROUND_POS(float f)
    302 {
    303    assert(f >= 0.0F);
    304    return (int) (f + 0.5F);
    305 }
    306 
    307 
    308 /**
    309  * Convert float to int using a fast method.  The rounding mode may vary.
    310  * XXX We could use an x86-64/SSE2 version here.
    311  */
    312 #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
    313 static inline int F_TO_I(float f)
    314 {
    315    int r;
    316    __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
    317    return r;
    318 }
    319 #elif defined(USE_X86_ASM) && defined(_MSC_VER)
    320 static inline int F_TO_I(float f)
    321 {
    322    int r;
    323    _asm {
    324 	 fld f
    325 	 fistp r
    326 	}
    327    return r;
    328 }
    329 #elif defined(__WATCOMC__) && defined(__386__)
    330 long F_TO_I(float f);
    331 #pragma aux iround =                    \
    332 	"push   eax"                        \
    333 	"fistp  dword ptr [esp]"            \
    334 	"pop    eax"                        \
    335 	parm [8087]                         \
    336 	value [eax]                         \
    337 	modify exact [eax];
    338 #else
    339 #define F_TO_I(f)  IROUND(f)
    340 #endif
    341 
    342 
    343 /***
    344  *** IFLOOR: return (as an integer) floor of float
    345  ***/
    346 #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
    347 /*
    348  * IEEE floor for computers that round to nearest or even.
    349  * 'f' must be between -4194304 and 4194303.
    350  * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1",
    351  * but uses some IEEE specific tricks for better speed.
    352  * Contributed by Josh Vanderhoof
    353  */
    354 static inline int ifloor(float f)
    355 {
    356    int ai, bi;
    357    double af, bf;
    358    af = (3 << 22) + 0.5 + (double)f;
    359    bf = (3 << 22) + 0.5 - (double)f;
    360    /* GCC generates an extra fstp/fld without this. */
    361    __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
    362    __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
    363    return (ai - bi) >> 1;
    364 }
    365 #define IFLOOR(x)  ifloor(x)
    366 #elif defined(USE_IEEE)
    367 static inline int ifloor(float f)
    368 {
    369    int ai, bi;
    370    double af, bf;
    371    fi_type u;
    372 
    373    af = (3 << 22) + 0.5 + (double)f;
    374    bf = (3 << 22) + 0.5 - (double)f;
    375    u.f = (float) af;  ai = u.i;
    376    u.f = (float) bf;  bi = u.i;
    377    return (ai - bi) >> 1;
    378 }
    379 #define IFLOOR(x)  ifloor(x)
    380 #else
    381 static inline int ifloor(float f)
    382 {
    383    int i = IROUND(f);
    384    return (i > f) ? i - 1 : i;
    385 }
    386 #define IFLOOR(x)  ifloor(x)
    387 #endif
    388 
    389 
    390 /***
    391  *** ICEIL: return (as an integer) ceiling of float
    392  ***/
    393 #if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
    394 /*
    395  * IEEE ceil for computers that round to nearest or even.
    396  * 'f' must be between -4194304 and 4194303.
    397  * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1",
    398  * but uses some IEEE specific tricks for better speed.
    399  * Contributed by Josh Vanderhoof
    400  */
    401 static inline int iceil(float f)
    402 {
    403    int ai, bi;
    404    double af, bf;
    405    af = (3 << 22) + 0.5 + (double)f;
    406    bf = (3 << 22) + 0.5 - (double)f;
    407    /* GCC generates an extra fstp/fld without this. */
    408    __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st");
    409    __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st");
    410    return (ai - bi + 1) >> 1;
    411 }
    412 #define ICEIL(x)  iceil(x)
    413 #elif defined(USE_IEEE)
    414 static inline int iceil(float f)
    415 {
    416    int ai, bi;
    417    double af, bf;
    418    fi_type u;
    419    af = (3 << 22) + 0.5 + (double)f;
    420    bf = (3 << 22) + 0.5 - (double)f;
    421    u.f = (float) af; ai = u.i;
    422    u.f = (float) bf; bi = u.i;
    423    return (ai - bi + 1) >> 1;
    424 }
    425 #define ICEIL(x)  iceil(x)
    426 #else
    427 static inline int iceil(float f)
    428 {
    429    int i = IROUND(f);
    430    return (i < f) ? i + 1 : i;
    431 }
    432 #define ICEIL(x)  iceil(x)
    433 #endif
    434 
    435 
    436 /**
    437  * Is x a power of two?
    438  */
    439 static inline int
    440 _mesa_is_pow_two(int x)
    441 {
    442    return !(x & (x - 1));
    443 }
    444 
    445 /**
    446  * Round given integer to next higer power of two
    447  * If X is zero result is undefined.
    448  *
    449  * Source for the fallback implementation is
    450  * Sean Eron Anderson's webpage "Bit Twiddling Hacks"
    451  * http://graphics.stanford.edu/~seander/bithacks.html
    452  *
    453  * When using builtin function have to do some work
    454  * for case when passed values 1 to prevent hiting
    455  * undefined result from __builtin_clz. Undefined
    456  * results would be different depending on optimization
    457  * level used for build.
    458  */
    459 static inline int32_t
    460 _mesa_next_pow_two_32(uint32_t x)
    461 {
    462 #if defined(__GNUC__) && \
    463 	((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
    464 	uint32_t y = (x != 1);
    465 	return (1 + y) << ((__builtin_clz(x - y) ^ 31) );
    466 #else
    467 	x--;
    468 	x |= x >> 1;
    469 	x |= x >> 2;
    470 	x |= x >> 4;
    471 	x |= x >> 8;
    472 	x |= x >> 16;
    473 	x++;
    474 	return x;
    475 #endif
    476 }
    477 
    478 static inline int64_t
    479 _mesa_next_pow_two_64(uint64_t x)
    480 {
    481 #if defined(__GNUC__) && \
    482 	((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
    483 	uint64_t y = (x != 1);
    484 	if (sizeof(x) == sizeof(long))
    485 		return (1 + y) << ((__builtin_clzl(x - y) ^ 63));
    486 	else
    487 		return (1 + y) << ((__builtin_clzll(x - y) ^ 63));
    488 #else
    489 	x--;
    490 	x |= x >> 1;
    491 	x |= x >> 2;
    492 	x |= x >> 4;
    493 	x |= x >> 8;
    494 	x |= x >> 16;
    495 	x |= x >> 32;
    496 	x++;
    497 	return x;
    498 #endif
    499 }
    500 
    501 
    502 /*
    503  * Returns the floor form of binary logarithm for a 32-bit integer.
    504  */
    505 static inline GLuint
    506 _mesa_logbase2(GLuint n)
    507 {
    508 #if defined(__GNUC__) && \
    509    ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
    510    return (31 - __builtin_clz(n | 1));
    511 #else
    512    GLuint pos = 0;
    513    if (n >= 1<<16) { n >>= 16; pos += 16; }
    514    if (n >= 1<< 8) { n >>=  8; pos +=  8; }
    515    if (n >= 1<< 4) { n >>=  4; pos +=  4; }
    516    if (n >= 1<< 2) { n >>=  2; pos +=  2; }
    517    if (n >= 1<< 1) {           pos +=  1; }
    518    return pos;
    519 #endif
    520 }
    521 
    522 
    523 /**
    524  * Return 1 if this is a little endian machine, 0 if big endian.
    525  */
    526 static inline GLboolean
    527 _mesa_little_endian(void)
    528 {
    529    const GLuint ui = 1; /* intentionally not static */
    530    return *((const GLubyte *) &ui);
    531 }
    532 
    533 
    534 
    535 /**********************************************************************
    536  * Functions
    537  */
    538 
    539 extern void *
    540 _mesa_align_malloc( size_t bytes, unsigned long alignment );
    541 
    542 extern void *
    543 _mesa_align_calloc( size_t bytes, unsigned long alignment );
    544 
    545 extern void
    546 _mesa_align_free( void *ptr );
    547 
    548 extern void *
    549 _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
    550                     unsigned long alignment);
    551 
    552 extern void *
    553 _mesa_exec_malloc( GLuint size );
    554 
    555 extern void
    556 _mesa_exec_free( void *addr );
    557 
    558 extern void *
    559 _mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize );
    560 
    561 
    562 #ifndef FFS_DEFINED
    563 #define FFS_DEFINED 1
    564 #ifdef __GNUC__
    565 
    566 #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(ANDROID) || defined(__APPLE__)
    567 #define ffs __builtin_ffs
    568 #define ffsll __builtin_ffsll
    569 #endif
    570 
    571 #else
    572 
    573 extern int ffs(int i);
    574 extern int ffsll(long long int i);
    575 
    576 #endif /*__ GNUC__ */
    577 #endif /* FFS_DEFINED */
    578 
    579 
    580 #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
    581 #define _mesa_bitcount(i) __builtin_popcount(i)
    582 #define _mesa_bitcount_64(i) __builtin_popcountll(i)
    583 #else
    584 extern unsigned int
    585 _mesa_bitcount(unsigned int n);
    586 extern unsigned int
    587 _mesa_bitcount_64(uint64_t n);
    588 #endif
    589 
    590 /**
    591  * Find the last (most significant) bit set in a word.
    592  *
    593  * Essentially ffs() in the reverse direction.
    594  */
    595 static inline unsigned int
    596 _mesa_fls(unsigned int n)
    597 {
    598 #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304)
    599    return n == 0 ? 0 : 32 - __builtin_clz(n);
    600 #else
    601    unsigned int v = 1;
    602 
    603    if (n == 0)
    604       return 0;
    605 
    606    while (n >>= 1)
    607        v++;
    608 
    609    return v;
    610 #endif
    611 }
    612 
    613 extern GLhalfARB
    614 _mesa_float_to_half(float f);
    615 
    616 extern float
    617 _mesa_half_to_float(GLhalfARB h);
    618 
    619 
    620 extern void *
    621 _mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
    622                int (*compar)(const void *, const void *) );
    623 
    624 extern char *
    625 _mesa_getenv( const char *var );
    626 
    627 extern char *
    628 _mesa_strdup( const char *s );
    629 
    630 extern float
    631 _mesa_strtof( const char *s, char **end );
    632 
    633 extern unsigned int
    634 _mesa_str_checksum(const char *str);
    635 
    636 extern int
    637 _mesa_snprintf( char *str, size_t size, const char *fmt, ... ) PRINTFLIKE(3, 4);
    638 
    639 extern int
    640 _mesa_vsnprintf(char *str, size_t size, const char *fmt, va_list arg);
    641 
    642 
    643 #if defined(_MSC_VER) && !defined(snprintf)
    644 #define snprintf _snprintf
    645 #endif
    646 
    647 
    648 #ifdef __cplusplus
    649 }
    650 #endif
    651 
    652 
    653 #endif /* IMPORTS_H */
    654