OSDN Git Service

* crtstuff.c, integrate.h, tree-scalar-evolution.h,
[pf3gnuchains/gcc-fork.git] / gcc / crtstuff.c
1 /* Specialized bits of code needed to support construction and
2    destruction of file-scope objects in C++ code.
3    Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5    Contributed by Ron Guilmette (rfg@monkeys.com).
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 In addition to the permissions in the GNU General Public License, the
15 Free Software Foundation gives you unlimited permission to link the
16 compiled version of this file into combinations with other programs,
17 and to distribute those combinations without any restriction coming
18 from the use of this file.  (The General Public License restrictions
19 do apply in other respects; for example, they cover modification of
20 the file, and distribution when not linked into a combine
21 executable.)
22
23 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
24 WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
26 for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with GCC; see the file COPYING.  If not, write to the Free
30 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
31 02111-1307, USA.  */
32
33 /* This file is a bit like libgcc2.c in that it is compiled
34    multiple times and yields multiple .o files.
35
36    This file is useful on target machines where the object file format
37    supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE).  On
38    such systems, this file allows us to avoid running collect (or any
39    other such slow and painful kludge).  Additionally, if the target
40    system supports a .init section, this file allows us to support the
41    linking of C++ code with a non-C++ main program.
42
43    Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
44    this file *will* make use of the .init section.  If that symbol is
45    not defined however, then the .init section will not be used.
46
47    Currently, only ELF and COFF are supported.  It is likely however that
48    ROSE could also be supported, if someone was willing to do the work to
49    make whatever (small?) adaptations are needed.  (Some work may be
50    needed on the ROSE assembler and linker also.)
51
52    This file must be compiled with gcc.  */
53
54 #include "tconfig.h"
55 #include "tsystem.h"
56 #include "coretypes.h"
57 #include "tm.h"
58 #include "unwind-dw2-fde.h"
59
60 #ifndef FORCE_CODE_SECTION_ALIGN
61 # define FORCE_CODE_SECTION_ALIGN
62 #endif
63
64 #ifndef CRT_CALL_STATIC_FUNCTION
65 # define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)     \
66 static void __attribute__((__used__))                   \
67 call_ ## FUNC (void)                                    \
68 {                                                       \
69   asm (SECTION_OP);                                     \
70   FUNC ();                                              \
71   FORCE_CODE_SECTION_ALIGN                              \
72   asm (TEXT_SECTION_ASM_OP);                            \
73 }
74 #endif
75
76 #if defined(OBJECT_FORMAT_ELF) && defined(HAVE_LD_EH_FRAME_HDR) \
77     && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
78     && defined(__GLIBC__) && __GLIBC__ >= 2
79 #include <link.h>
80 # if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
81      || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
82 #  define USE_PT_GNU_EH_FRAME
83 # endif
84 #endif
85 #if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
86 # define USE_EH_FRAME_REGISTRY
87 #endif
88 #if defined(EH_FRAME_SECTION_NAME) && EH_TABLES_CAN_BE_READ_ONLY
89 # define EH_FRAME_SECTION_CONST const
90 #else
91 # define EH_FRAME_SECTION_CONST
92 #endif
93
94 /* We do not want to add the weak attribute to the declarations of these
95    routines in unwind-dw2-fde.h because that will cause the definition of
96    these symbols to be weak as well.
97
98    This exposes a core issue, how to handle creating weak references vs
99    how to create weak definitions.  Either we have to have the definition
100    of TARGET_WEAK_ATTRIBUTE be conditional in the shared header files or
101    have a second declaration if we want a function's references to be weak,
102    but not its definition.
103
104    Making TARGET_WEAK_ATTRIBUTE conditional seems like a good solution until
105    one thinks about scaling to larger problems -- i.e., the condition under
106    which TARGET_WEAK_ATTRIBUTE is active will eventually get far too
107    complicated.
108
109    So, we take an approach similar to #pragma weak -- we have a second
110    declaration for functions that we want to have weak references.
111
112    Neither way is particularly good.  */
113    
114 /* References to __register_frame_info and __deregister_frame_info should
115    be weak in this file if at all possible.  */
116 extern void __register_frame_info (const void *, struct object *)
117                                   TARGET_ATTRIBUTE_WEAK;
118 extern void __register_frame_info_bases (const void *, struct object *,
119                                          void *, void *)
120                                   TARGET_ATTRIBUTE_WEAK;
121 extern void *__deregister_frame_info (const void *)
122                                      TARGET_ATTRIBUTE_WEAK;
123 extern void *__deregister_frame_info_bases (const void *)
124                                      TARGET_ATTRIBUTE_WEAK;
125 extern void __do_global_ctors_1 (void);
126
127 /* Likewise for _Jv_RegisterClasses.  */
128 extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
129
130 #ifdef OBJECT_FORMAT_ELF
131
132 /*  Declare a pointer to void function type.  */
133 typedef void (*func_ptr) (void);
134 #define STATIC static
135
136 #else  /* OBJECT_FORMAT_ELF */
137
138 #include "gbl-ctors.h"
139
140 #define STATIC
141
142 #endif /* OBJECT_FORMAT_ELF */
143
144 #ifdef CRT_BEGIN
145
146 /* NOTE:  In order to be able to support SVR4 shared libraries, we arrange
147    to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
148    __DTOR_END__ } per root executable and also one set of these symbols
149    per shared library.  So in any given whole process image, we may have
150    multiple definitions of each of these symbols.  In order to prevent
151    these definitions from conflicting with one another, and in order to
152    ensure that the proper lists are used for the initialization/finalization
153    of each individual shared library (respectively), we give these symbols
154    only internal (i.e. `static') linkage, and we also make it a point to
155    refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
156    symbol in crtbegin.o, where they are defined.  */
157
158 /* The -1 is a flag to __do_global_[cd]tors indicating that this table
159    does not start with a count of elements.  */
160 #ifdef CTOR_LIST_BEGIN
161 CTOR_LIST_BEGIN;
162 #elif defined(CTORS_SECTION_ASM_OP)
163 /* Hack: force cc1 to switch to .data section early, so that assembling
164    __CTOR_LIST__ does not undo our behind-the-back change to .ctors.  */
165 static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
166 asm (CTORS_SECTION_ASM_OP);
167 STATIC func_ptr __CTOR_LIST__[1]
168   __attribute__ ((__unused__, aligned(sizeof(func_ptr))))
169   = { (func_ptr) (-1) };
170 #else
171 STATIC func_ptr __CTOR_LIST__[1]
172   __attribute__ ((__unused__, section(".ctors"), aligned(sizeof(func_ptr))))
173   = { (func_ptr) (-1) };
174 #endif /* __CTOR_LIST__ alternatives */
175
176 #ifdef DTOR_LIST_BEGIN
177 DTOR_LIST_BEGIN;
178 #elif defined(DTORS_SECTION_ASM_OP)
179 asm (DTORS_SECTION_ASM_OP);
180 STATIC func_ptr __DTOR_LIST__[1]
181   __attribute__ ((aligned(sizeof(func_ptr))))
182   = { (func_ptr) (-1) };
183 #else
184 STATIC func_ptr __DTOR_LIST__[1]
185   __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
186   = { (func_ptr) (-1) };
187 #endif /* __DTOR_LIST__ alternatives */
188
189 #ifdef USE_EH_FRAME_REGISTRY
190 /* Stick a label at the beginning of the frame unwind info so we can register
191    and deregister it with the exception handling library code.  */
192 STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
193      __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
194      = { };
195 #endif /* USE_EH_FRAME_REGISTRY */
196
197 #ifdef JCR_SECTION_NAME
198 /* Stick a label at the beginning of the java class registration info
199    so we can register them properly.  */
200 STATIC void *__JCR_LIST__[]
201   __attribute__ ((unused, section(JCR_SECTION_NAME), aligned(sizeof(void*))))
202   = { };
203 #endif /* JCR_SECTION_NAME */
204
205 #if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP)
206
207 #ifdef OBJECT_FORMAT_ELF
208
209 /* Declare the __dso_handle variable.  It should have a unique value
210    in every shared-object; in a main program its value is zero.  The
211    object should in any case be protected.  This means the instance
212    in one DSO or the main program is not used in another object.  The
213    dynamic linker takes care of this.  */
214
215 #ifdef HAVE_GAS_HIDDEN
216 extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
217 #endif
218 #ifdef CRTSTUFFS_O
219 void *__dso_handle = &__dso_handle;
220 #else
221 void *__dso_handle = 0;
222 #endif
223
224 /* The __cxa_finalize function may not be available so we use only a
225    weak declaration.  */
226 extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK;
227
228 /* Run all the global destructors on exit from the program.  */
229  
230 /* Some systems place the number of pointers in the first word of the
231    table.  On SVR4 however, that word is -1.  In all cases, the table is
232    null-terminated.  On SVR4, we start from the beginning of the list and
233    invoke each per-compilation-unit destructor routine in order
234    until we find that null.
235
236    Note that this function MUST be static.  There will be one of these
237    functions in each root executable and one in each shared library, but
238    although they all have the same code, each one is unique in that it
239    refers to one particular associated `__DTOR_LIST__' which belongs to the
240    same particular root executable or shared library file.
241
242    On some systems, this routine is run more than once from the .fini,
243    when exit is called recursively, so we arrange to remember where in
244    the list we left off processing, and we resume at that point,
245    should we be re-invoked.  */
246
247 static void __attribute__((used))
248 __do_global_dtors_aux (void)
249 {
250 #ifndef FINI_ARRAY_SECTION_ASM_OP
251   static func_ptr *p = __DTOR_LIST__ + 1;
252   func_ptr f;
253 #endif /* !defined(FINI_ARRAY_SECTION_ASM_OP)  */
254   static _Bool completed;
255
256   if (__builtin_expect (completed, 0))
257     return;
258
259 #ifdef CRTSTUFFS_O
260   if (__cxa_finalize)
261     __cxa_finalize (__dso_handle);
262 #endif
263
264 #ifdef FINI_ARRAY_SECTION_ASM_OP
265   /* If we are using .fini_array then destructors will be run via that
266      mechanism.  */
267 #else /* !defined (FINI_ARRAY_SECTION_ASM_OP) */
268   while ((f = *p))
269     {
270       p++;
271       f ();
272     }
273 #endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */
274
275 #ifdef USE_EH_FRAME_REGISTRY
276 #ifdef CRT_GET_RFIB_DATA
277   /* If we used the new __register_frame_info_bases interface,
278      make sure that we deregister from the same place.  */
279   if (__deregister_frame_info_bases)
280     __deregister_frame_info_bases (__EH_FRAME_BEGIN__);
281 #else
282   if (__deregister_frame_info)
283     __deregister_frame_info (__EH_FRAME_BEGIN__);
284 #endif
285 #endif
286
287   completed = 1;
288 }
289
290 /* Stick a call to __do_global_dtors_aux into the .fini section.  */
291 #ifdef FINI_SECTION_ASM_OP
292 CRT_CALL_STATIC_FUNCTION (FINI_SECTION_ASM_OP, __do_global_dtors_aux)
293 #else /* !defined(FINI_SECTION_ASM_OP) */
294 static func_ptr __do_global_dtors_aux_fini_array_entry[]
295   __attribute__ ((__unused__, section(".fini_array")))
296   = { __do_global_dtors_aux };
297 #endif /* !defined(FINI_SECTION_ASM_OP) */
298
299 #if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
300 /* Stick a call to __register_frame_info into the .init section.  For some
301    reason calls with no arguments work more reliably in .init, so stick the
302    call in another function.  */
303
304 static void __attribute__((used))
305 frame_dummy (void)
306 {
307 #ifdef USE_EH_FRAME_REGISTRY
308   static struct object object;
309 #ifdef CRT_GET_RFIB_DATA
310   void *tbase, *dbase;
311   tbase = 0;
312   CRT_GET_RFIB_DATA (dbase);
313   if (__register_frame_info_bases)
314     __register_frame_info_bases (__EH_FRAME_BEGIN__, &object, tbase, dbase);
315 #else
316   if (__register_frame_info)
317     __register_frame_info (__EH_FRAME_BEGIN__, &object);
318 #endif /* CRT_GET_RFIB_DATA */
319 #endif /* USE_EH_FRAME_REGISTRY */
320 #ifdef JCR_SECTION_NAME
321   if (__JCR_LIST__[0])
322     {
323       void (*register_classes) (void *) = _Jv_RegisterClasses;
324       __asm ("" : "+r" (register_classes));
325       if (register_classes)
326         register_classes (__JCR_LIST__);
327     }
328 #endif /* JCR_SECTION_NAME */
329 }
330
331 #ifdef INIT_SECTION_ASM_OP
332 CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
333 #else /* defined(INIT_SECTION_ASM_OP) */
334 static func_ptr __frame_dummy_init_array_entry[]
335   __attribute__ ((__unused__, section(".init_array")))
336   = { frame_dummy };
337 #endif /* !defined(INIT_SECTION_ASM_OP) */
338 #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
339
340 #else  /* OBJECT_FORMAT_ELF */
341
342 /* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
343    and once in crtend.o).  It must be declared static to avoid a link
344    error.  Here, we define __do_global_ctors as an externally callable
345    function.  It is externally callable so that __main can invoke it when
346    INVOKE__main is defined.  This has the additional effect of forcing cc1
347    to switch to the .text section.  */
348
349 static void __do_global_ctors_aux (void);
350 void
351 __do_global_ctors (void)
352 {
353 #ifdef INVOKE__main
354   /* If __main won't actually call __do_global_ctors then it doesn't matter
355      what's inside the function.  The inside of __do_global_ctors_aux is
356      called automatically in that case.  And the Alliant fx2800 linker
357      crashes on this reference.  So prevent the crash.  */
358   __do_global_ctors_aux ();
359 #endif
360 }
361
362 asm (INIT_SECTION_ASM_OP);      /* cc1 doesn't know that we are switching! */
363
364 /* A routine to invoke all of the global constructors upon entry to the
365    program.  We put this into the .init section (for systems that have
366    such a thing) so that we can properly perform the construction of
367    file-scope static-storage C++ objects within shared libraries.  */
368
369 static void __attribute__((used))
370 __do_global_ctors_aux (void)    /* prologue goes in .init section */
371 {
372   FORCE_CODE_SECTION_ALIGN      /* explicit align before switch to .text */
373   asm (TEXT_SECTION_ASM_OP);    /* don't put epilogue and body in .init */
374   DO_GLOBAL_CTORS_BODY;
375   atexit (__do_global_dtors);
376 }
377
378 #endif /* OBJECT_FORMAT_ELF */
379
380 #elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
381
382 extern void __do_global_dtors (void);
383
384 /* This case is used by the Irix 6 port, which supports named sections but
385    not an SVR4-style .fini section.  __do_global_dtors can be non-static
386    in this case because we protect it with -hidden_symbol.  */
387
388 void
389 __do_global_dtors (void)
390 {
391   func_ptr *p, f;
392   for (p = __DTOR_LIST__ + 1; (f = *p); p++)
393     f ();
394
395 #ifdef USE_EH_FRAME_REGISTRY
396   if (__deregister_frame_info)
397     __deregister_frame_info (__EH_FRAME_BEGIN__);
398 #endif
399 }
400
401 #if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
402 /* A helper function for __do_global_ctors, which is in crtend.o.  Here
403    in crtbegin.o, we can reference a couple of symbols not visible there.
404    Plus, since we're before libgcc.a, we have no problems referencing
405    functions from there.  */
406 void
407 __do_global_ctors_1(void)
408 {
409 #ifdef USE_EH_FRAME_REGISTRY
410   static struct object object;
411   if (__register_frame_info)
412     __register_frame_info (__EH_FRAME_BEGIN__, &object);
413 #endif
414 #ifdef JCR_SECTION_NAME
415   if (__JCR_LIST__[0])
416     {
417       void (*register_classes) (void *) = _Jv_RegisterClasses;
418       __asm ("" : "+r" (register_classes));
419       if (register_classes)
420         register_classes (__JCR_LIST__);
421     }
422 #endif
423 }
424 #endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
425
426 #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
427 #error "What are you doing with crtstuff.c, then?"
428 #endif
429
430 #elif defined(CRT_END) /* ! CRT_BEGIN */
431
432 /* Put a word containing zero at the end of each of our two lists of function
433    addresses.  Note that the words defined here go into the .ctors and .dtors
434    sections of the crtend.o file, and since that file is always linked in
435    last, these words naturally end up at the very ends of the two lists
436    contained in these two sections.  */
437
438 #ifdef CTOR_LIST_END
439 CTOR_LIST_END;
440 #elif defined(CTORS_SECTION_ASM_OP)
441 /* Hack: force cc1 to switch to .data section early, so that assembling
442    __CTOR_LIST__ does not undo our behind-the-back change to .ctors.  */
443 static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
444 asm (CTORS_SECTION_ASM_OP);
445 STATIC func_ptr __CTOR_END__[1]
446   __attribute__((aligned(sizeof(func_ptr))))
447   = { (func_ptr) 0 };
448 #else
449 STATIC func_ptr __CTOR_END__[1]
450   __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
451   = { (func_ptr) 0 };
452 #endif
453
454 #ifdef DTOR_LIST_END
455 DTOR_LIST_END;
456 #elif defined(DTORS_SECTION_ASM_OP)
457 asm (DTORS_SECTION_ASM_OP);
458 STATIC func_ptr __DTOR_END__[1]
459   __attribute__ ((unused, aligned(sizeof(func_ptr))))
460   = { (func_ptr) 0 };
461 #else
462 STATIC func_ptr __DTOR_END__[1]
463   __attribute__((unused, section(".dtors"), aligned(sizeof(func_ptr))))
464   = { (func_ptr) 0 };
465 #endif
466
467 #ifdef EH_FRAME_SECTION_NAME
468 /* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
469    this would be the 'length' field in a real FDE.  */
470 # if __INT_MAX__ == 2147483647
471 typedef int int32;
472 # elif __LONG_MAX__ == 2147483647
473 typedef long int32;
474 # elif __SHRT_MAX__ == 2147483647
475 typedef short int32;
476 # else
477 #  error "Missing a 4 byte integer"
478 # endif
479 STATIC EH_FRAME_SECTION_CONST int32 __FRAME_END__[]
480      __attribute__ ((unused, section(EH_FRAME_SECTION_NAME),
481                      aligned(sizeof(int32))))
482      = { 0 };
483 #endif /* EH_FRAME_SECTION_NAME */
484
485 #ifdef JCR_SECTION_NAME
486 /* Null terminate the .jcr section array.  */
487 STATIC void *__JCR_END__[1] 
488    __attribute__ ((unused, section(JCR_SECTION_NAME),
489                    aligned(sizeof(void *))))
490    = { 0 };
491 #endif /* JCR_SECTION_NAME */
492
493 #ifdef INIT_ARRAY_SECTION_ASM_OP
494
495 /* If we are using .init_array, there is nothing to do.  */
496
497 #elif defined(INIT_SECTION_ASM_OP)
498
499 #ifdef OBJECT_FORMAT_ELF
500 static void __attribute__((used))
501 __do_global_ctors_aux (void)
502 {
503   func_ptr *p;
504   for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
505     (*p) ();
506 }
507
508 /* Stick a call to __do_global_ctors_aux into the .init section.  */
509 CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_ctors_aux)
510 #else  /* OBJECT_FORMAT_ELF */
511
512 /* Stick the real initialization code, followed by a normal sort of
513    function epilogue at the very end of the .init section for this
514    entire root executable file or for this entire shared library file.
515
516    Note that we use some tricks here to get *just* the body and just
517    a function epilogue (but no function prologue) into the .init
518    section of the crtend.o file.  Specifically, we switch to the .text
519    section, start to define a function, and then we switch to the .init
520    section just before the body code.
521
522    Earlier on, we put the corresponding function prologue into the .init
523    section of the crtbegin.o file (which will be linked in first).
524
525    Note that we want to invoke all constructors for C++ file-scope static-
526    storage objects AFTER any other possible initialization actions which
527    may be performed by the code in the .init section contributions made by
528    other libraries, etc.  That's because those other initializations may
529    include setup operations for very primitive things (e.g. initializing
530    the state of the floating-point coprocessor, etc.) which should be done
531    before we start to execute any of the user's code.  */
532
533 static void
534 __do_global_ctors_aux (void)    /* prologue goes in .text section */
535 {
536   asm (INIT_SECTION_ASM_OP);
537   DO_GLOBAL_CTORS_BODY;
538   atexit (__do_global_dtors);
539 }                               /* epilogue and body go in .init section */
540
541 FORCE_CODE_SECTION_ALIGN
542 asm (TEXT_SECTION_ASM_OP);
543
544 #endif /* OBJECT_FORMAT_ELF */
545
546 #elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
547
548 extern void __do_global_ctors (void);
549
550 /* This case is used by the Irix 6 port, which supports named sections but
551    not an SVR4-style .init section.  __do_global_ctors can be non-static
552    in this case because we protect it with -hidden_symbol.  */
553 void
554 __do_global_ctors (void)
555 {
556   func_ptr *p;
557 #if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
558   __do_global_ctors_1();
559 #endif
560   for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
561     (*p) ();
562 }
563
564 #else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
565 #error "What are you doing with crtstuff.c, then?"
566 #endif
567
568 #else /* ! CRT_BEGIN && ! CRT_END */
569 #error "One of CRT_BEGIN or CRT_END must be defined."
570 #endif