From 2ae8e3fac91e25f3ecf318471ee401b52e28cfeb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 18 Feb 2025 12:01:59 +0100 Subject: [PATCH] at-init: New module. * lib/at-init.h: New file. * lib/at-init.c: New file. * modules/at-init: New file. --- ChangeLog | 7 +++ lib/at-init.c | 33 ++++++++++++ lib/at-init.h | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ modules/at-init | 22 ++++++++ 4 files changed, 203 insertions(+) create mode 100644 lib/at-init.c create mode 100644 lib/at-init.h create mode 100644 modules/at-init diff --git a/ChangeLog b/ChangeLog index fb902df384..ed82d50346 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2025-02-18 Bruno Haible + + at-init: New module. + * lib/at-init.h: New file. + * lib/at-init.c: New file. + * modules/at-init: New file. + 2025-02-17 Paul Eggert fts: expose fts_debug diff --git a/lib/at-init.c b/lib/at-init.c new file mode 100644 index 0000000000..2e9e8702a4 --- /dev/null +++ b/lib/at-init.c @@ -0,0 +1,33 @@ +/* Computed initializations before the program starts. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "at-init.h" + +#if defined _MSC_VER + +void +gl_at_init_dummy (_GL_UNUSED const void *p) +{ +} + +#endif + +/* This declaration is solely to ensure that after preprocessing + this file is never empty. */ +typedef int dummy; diff --git a/lib/at-init.h b/lib/at-init.h new file mode 100644 index 0000000000..95ec026ca3 --- /dev/null +++ b/lib/at-init.h @@ -0,0 +1,141 @@ +/* Computed initializations before the program starts. + Copyright (C) 2025 Free Software Foundation, Inc. + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#ifndef _GL_AT_INIT_H +#define _GL_AT_INIT_H + + +/* AT_INIT (function); + registers a function to be executed when the program is initialized, i.e. + even before the main() function is entered. + + AT_FINI (function); + registers a function to be executed when the program is about to exit. + Similar to 'atexit (function)' or 'at_quick_exit (function)'. + + The function must have an empty argument list and return 'void'. + + An initialization function must not depend on the result of other + initialization functions. The order in which the initialization functions + are executed is unspecified. + + These macro invocations must *precede* the definition of the function. + (This is necessary for clang.) + + These macros apply to executables. They are not supported in shared + libraries. + + Note: It would be easy to achieve the same functionality by using a small + C++ compilation unit. But it's better to stay with C all the way. */ + +/* This is implemented for each compiler separately. Basically, the idea is + to look how the corresponding C++ compiler implements static initializations + of C++ variables with a non-POD type, and do the same thing in C through a + mix of pragmas and asms. */ +/* For clang on native Windows (which defines both __clang__ and _MSC_VER): + - Both definitions of AT_INIT work. + - Only the .CRT$XCU based definition of AT_FINI works; the __destructor__ + based definition of AT_FINI does not work. */ +#if defined __GNUC__ || (defined __clang__ && !defined _MSC_VER) +/* GCC and compatible compilers */ + +/* Documentation: + */ + +# define AT_INIT(function) \ + static void __attribute__ ((__constructor__)) function (void) +# define AT_FINI(function) \ + static void __attribute__ ((__destructor__)) function (void) + +#elif defined _MSC_VER +/* MSVC */ + +/* Taken from glib-2.83 gconstructor.h. + Documentation: + + See also . */ + +/* Avoid an error in the pragma below. */ +# undef read + +# ifdef _WIN64 +# define GL_MSVC_SYMBOL_PREFIX "" +# else +# define GL_MSVC_SYMBOL_PREFIX "_" +# endif + +# define AT_INIT(function) GL_MSVC_CTOR (function, GL_MSVC_SYMBOL_PREFIX) +# define AT_FINI(function) GL_MSVC_DTOR (function, GL_MSVC_SYMBOL_PREFIX) + +# define GL_MSVC_CTOR(function,_sym_prefix) \ + static void function(void); \ + extern int (* _array ## function)(void); \ + int function ## _wrapper(void); \ + int function ## _wrapper(void) { function(); gl_at_init_dummy (_array ## function); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # function "_wrapper")) \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) int (* _array ## function)(void) = function ## _wrapper + +# define GL_MSVC_DTOR(function,_sym_prefix) \ + static void function(void); \ + extern int (* _array ## function)(void); \ + int function ## _constructor(void); \ + int function ## _constructor(void) { atexit (function); gl_at_init_dummy (_array ## function); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # function "_constructor")) \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) int (* _array ## function)(void) = function ## _constructor + +extern void gl_at_init_dummy (const void *); + +#elif defined __SUNPRO_C +/* Sun C */ + +/* Needs also: #pragma init(function) */ +# define AT_INIT(function) \ + static void function (void) + +/* Needs also: #pragma fini(function) */ +# define AT_FINI(function) \ + static void function (void) + +#elif defined __xlC__ +/* AIX xlc */ + +/* Needs also: #pragma init(function) + and a C++ linker. See + */ +# define AT_INIT(function) \ + static void function (void) + +/* Needs also: #pragma fini(function) + and a C++ linker. See + */ +# define AT_FINI(function) \ + static void function (void) + +#else +/* Another compiler */ + +/* This is just a dummy. It will not work. */ +# define AT_INIT(function) \ + static void function (void) +# define AT_FINI(function) \ + static void function (void) + +#endif + +#endif /* _GL_AT_INIT_H */ diff --git a/modules/at-init b/modules/at-init new file mode 100644 index 0000000000..95296ea39c --- /dev/null +++ b/modules/at-init @@ -0,0 +1,22 @@ +Description: +Computed initializations before the program starts + +Files: +lib/at-init.h +lib/at-init.c + +Depends-on: + +configure.ac: + +Makefile.am: +lib_SOURCES += at-init.c + +Include: +"at-init.h" + +License: +LGPLv2+ + +Maintainer: +all -- 2.39.5