Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
1
gmodule/AUTHORS
Normal file
1
gmodule/AUTHORS
Normal file
|
|
@ -0,0 +1 @@
|
|||
Tim Janik <timj@gtk.org>
|
||||
502
gmodule/COPYING
Normal file
502
gmodule/COPYING
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library 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 library 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 library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
182
gmodule/gmodule-ar.c
Normal file
182
gmodule/gmodule-ar.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998, 2000 Tim Janik
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
/* because we are compatible with archive format only since AIX 4.3 */
|
||||
|
||||
#define __AR_BIG__
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <ar.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* --- functions --- */
|
||||
static gchar*
|
||||
fetch_dlerror (gboolean replace_null)
|
||||
{
|
||||
gchar *msg = dlerror ();
|
||||
|
||||
/* make sure we always return an error message != NULL, if
|
||||
* expected to do so. */
|
||||
|
||||
if (!msg && replace_null)
|
||||
return "unknown dl-error";
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
static gchar* _g_module_get_member(const gchar* file_name)
|
||||
{
|
||||
gchar* member = NULL;
|
||||
struct fl_hdr file_header;
|
||||
struct ar_hdr ar_header;
|
||||
long first_member;
|
||||
long name_len;
|
||||
int fd;
|
||||
|
||||
fd = open(file_name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
if (read(fd, (void*)&file_header, FL_HSZ) != FL_HSZ)
|
||||
goto exit;
|
||||
|
||||
if (strncmp(file_header.fl_magic, AIAMAGBIG, SAIAMAG) != 0)
|
||||
goto exit;
|
||||
|
||||
/* read first archive file member header */
|
||||
|
||||
first_member = atol(file_header.fl_fstmoff);
|
||||
|
||||
if (lseek(fd, first_member, SEEK_SET) != first_member)
|
||||
goto exit;
|
||||
|
||||
if (read(fd, (void*)&ar_header, AR_HSZ - 2) != AR_HSZ - 2)
|
||||
goto exit;
|
||||
|
||||
/* read member name */
|
||||
|
||||
name_len = atol(ar_header.ar_namlen);
|
||||
|
||||
member = g_malloc(name_len+1);
|
||||
if (!member)
|
||||
goto exit;
|
||||
|
||||
if (read(fd, (void*)member, name_len) != name_len)
|
||||
{
|
||||
g_free(member);
|
||||
member = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
member[name_len] = 0;
|
||||
|
||||
exit:
|
||||
close(fd);
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_open (const gchar *file_name,
|
||||
gboolean bind_lazy,
|
||||
gboolean bind_local,
|
||||
GError **error)
|
||||
{
|
||||
gpointer handle;
|
||||
gchar* member;
|
||||
gchar* full_name;
|
||||
|
||||
/* extract name of first member of archive */
|
||||
|
||||
member = _g_module_get_member (file_name);
|
||||
if (member != NULL)
|
||||
{
|
||||
full_name = g_strconcat (file_name, "(", member, ")", NULL);
|
||||
g_free (member);
|
||||
}
|
||||
else
|
||||
full_name = g_strdup (file_name);
|
||||
|
||||
handle = dlopen (full_name,
|
||||
(bind_local ? RTLD_LOCAL : RTLD_GLOBAL) | RTLD_MEMBER | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
|
||||
|
||||
g_free (full_name);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
const gchar *message = fetch_dlerror (TRUE);
|
||||
|
||||
g_module_set_error (message);
|
||||
g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED, message);
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_self (void)
|
||||
{
|
||||
gpointer handle;
|
||||
|
||||
handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (!handle)
|
||||
g_module_set_error (fetch_dlerror (TRUE));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void
|
||||
_g_module_close (gpointer handle)
|
||||
{
|
||||
if (dlclose (handle) != 0)
|
||||
g_module_set_error (fetch_dlerror (TRUE));
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_symbol (gpointer handle,
|
||||
const gchar *symbol_name)
|
||||
{
|
||||
gpointer p;
|
||||
|
||||
p = dlsym (handle, symbol_name);
|
||||
if (!p)
|
||||
g_module_set_error (fetch_dlerror (FALSE));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name)
|
||||
{
|
||||
if (directory && *directory) {
|
||||
if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strconcat (directory, "/", module_name, NULL);
|
||||
else
|
||||
return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
|
||||
} else if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strdup (module_name);
|
||||
else
|
||||
return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
|
||||
}
|
||||
225
gmodule/gmodule-dl.c
Normal file
225
gmodule/gmodule-dl.c
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998, 2000 Tim Janik
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <glib.h>
|
||||
|
||||
/* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systems? */
|
||||
|
||||
|
||||
/* dlerror() is not implemented on all systems
|
||||
*/
|
||||
#ifndef G_MODULE_HAVE_DLERROR
|
||||
# ifdef __NetBSD__
|
||||
# define dlerror() g_strerror (errno)
|
||||
# else /* !__NetBSD__ */
|
||||
/* could we rely on errno's state here? */
|
||||
# define dlerror() "unknown dl-error"
|
||||
# endif /* !__NetBSD__ */
|
||||
#endif /* G_MODULE_HAVE_DLERROR */
|
||||
|
||||
/* some flags are missing on some systems, so we provide
|
||||
* harmless defaults.
|
||||
* The Perl sources say, RTLD_LAZY needs to be defined as (1),
|
||||
* at least for Solaris 1.
|
||||
*
|
||||
* Mandatory:
|
||||
* RTLD_LAZY - resolve undefined symbols as code from the dynamic library
|
||||
* is executed.
|
||||
* RTLD_NOW - resolve all undefined symbols before dlopen returns, and fail
|
||||
* if this cannot be done.
|
||||
* Optionally:
|
||||
* RTLD_GLOBAL - the external symbols defined in the library will be made
|
||||
* available to subsequently loaded libraries.
|
||||
*/
|
||||
#ifndef HAVE_RTLD_LAZY
|
||||
#define RTLD_LAZY 1
|
||||
#endif /* RTLD_LAZY */
|
||||
#ifndef HAVE_RTLD_NOW
|
||||
#define RTLD_NOW 0
|
||||
#endif /* RTLD_NOW */
|
||||
/* some systems (OSF1 V5.0) have broken RTLD_GLOBAL linkage */
|
||||
#ifdef G_MODULE_BROKEN_RTLD_GLOBAL
|
||||
#undef RTLD_GLOBAL
|
||||
#undef HAVE_RTLD_GLOBAL
|
||||
#endif /* G_MODULE_BROKEN_RTLD_GLOBAL */
|
||||
#ifndef HAVE_RTLD_GLOBAL
|
||||
#define RTLD_GLOBAL 0
|
||||
#endif /* RTLD_GLOBAL */
|
||||
|
||||
|
||||
/* According to POSIX.1-2001, dlerror() is not necessarily thread-safe
|
||||
* (see https://pubs.opengroup.org/onlinepubs/009695399/), and so must be
|
||||
* called within the same locked section as the dlopen()/dlsym() call which
|
||||
* may have caused an error.
|
||||
*
|
||||
* However, some libc implementations, such as glibc, implement dlerror() using
|
||||
* thread-local storage, so are thread-safe. As of early 2021:
|
||||
* - glibc is thread-safe: https://github.com/bminor/glibc/blob/HEAD/dlfcn/libc_dlerror_result.c
|
||||
* - uclibc-ng is not thread-safe: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/ldso/libdl/libdl.c?id=132decd2a043d0ccf799f42bf89f3ae0c11e95d5#n1075
|
||||
* - Other libc implementations have not been checked, and no problems have
|
||||
* been reported with them in 10 years, so default to assuming that they
|
||||
* don’t need additional thread-safety from GLib
|
||||
*/
|
||||
#if defined(__UCLIBC__)
|
||||
G_LOCK_DEFINE_STATIC (errors);
|
||||
#else
|
||||
#define DLERROR_IS_THREADSAFE 1
|
||||
#endif
|
||||
|
||||
static void
|
||||
lock_dlerror (void)
|
||||
{
|
||||
#ifndef DLERROR_IS_THREADSAFE
|
||||
G_LOCK (errors);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_dlerror (void)
|
||||
{
|
||||
#ifndef DLERROR_IS_THREADSAFE
|
||||
G_UNLOCK (errors);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This should be called with lock_dlerror() held */
|
||||
static const gchar *
|
||||
fetch_dlerror (gboolean replace_null)
|
||||
{
|
||||
const gchar *msg = dlerror ();
|
||||
|
||||
/* make sure we always return an error message != NULL, if
|
||||
* expected to do so. */
|
||||
|
||||
if (!msg && replace_null)
|
||||
return "unknown dl-error";
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_open (const gchar *file_name,
|
||||
gboolean bind_lazy,
|
||||
gboolean bind_local,
|
||||
GError **error)
|
||||
{
|
||||
gpointer handle;
|
||||
|
||||
lock_dlerror ();
|
||||
handle = dlopen (file_name,
|
||||
(bind_local ? 0 : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
|
||||
if (!handle)
|
||||
{
|
||||
const gchar *message = fetch_dlerror (TRUE);
|
||||
|
||||
g_module_set_error (message);
|
||||
g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED, message);
|
||||
}
|
||||
|
||||
unlock_dlerror ();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_self (void)
|
||||
{
|
||||
gpointer handle;
|
||||
|
||||
/* to query symbols from the program itself, special link options
|
||||
* are required on some systems.
|
||||
*/
|
||||
|
||||
/* On Android 32 bit (i.e. not __LP64__), dlopen(NULL)
|
||||
* does not work reliable and generally no symbols are found
|
||||
* at all. RTLD_DEFAULT works though.
|
||||
* On Android 64 bit, dlopen(NULL) seems to work but dlsym(handle)
|
||||
* always returns 'undefined symbol'. Only if RTLD_DEFAULT or
|
||||
* NULL is given, dlsym returns an appropriate pointer.
|
||||
*/
|
||||
lock_dlerror ();
|
||||
#if defined(__BIONIC__)
|
||||
handle = RTLD_DEFAULT;
|
||||
#else
|
||||
handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
|
||||
#endif
|
||||
if (!handle)
|
||||
g_module_set_error (fetch_dlerror (TRUE));
|
||||
unlock_dlerror ();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void
|
||||
_g_module_close (gpointer handle)
|
||||
{
|
||||
#if defined(__BIONIC__)
|
||||
if (handle != RTLD_DEFAULT)
|
||||
#endif
|
||||
{
|
||||
lock_dlerror ();
|
||||
if (dlclose (handle) != 0)
|
||||
g_module_set_error (fetch_dlerror (TRUE));
|
||||
unlock_dlerror ();
|
||||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_symbol (gpointer handle,
|
||||
const gchar *symbol_name)
|
||||
{
|
||||
gpointer p;
|
||||
const gchar *msg;
|
||||
|
||||
lock_dlerror ();
|
||||
fetch_dlerror (FALSE);
|
||||
p = dlsym (handle, symbol_name);
|
||||
msg = fetch_dlerror (FALSE);
|
||||
if (msg)
|
||||
g_module_set_error (msg);
|
||||
unlock_dlerror ();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name)
|
||||
{
|
||||
if (directory && *directory) {
|
||||
if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strconcat (directory, "/", module_name, NULL);
|
||||
else
|
||||
return g_strconcat (directory, "/lib", module_name, "." G_MODULE_SUFFIX, NULL);
|
||||
} else if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strdup (module_name);
|
||||
else
|
||||
return g_strconcat ("lib", module_name, "." G_MODULE_SUFFIX, NULL);
|
||||
}
|
||||
237
gmodule/gmodule-win32.c
Normal file
237
gmodule/gmodule-win32.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998, 2000 Tim Janik
|
||||
*
|
||||
* Win32 GMODULE implementation
|
||||
* Copyright (C) 1998 Tor Lillqvist
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <tlhelp32.h>
|
||||
|
||||
#ifdef G_WITH_CYGWIN
|
||||
#include <sys/cygwin.h>
|
||||
#endif
|
||||
|
||||
static void G_GNUC_PRINTF (2, 3)
|
||||
set_error (GError **error,
|
||||
const gchar *format,
|
||||
...)
|
||||
{
|
||||
gchar *win32_error;
|
||||
gchar *detail;
|
||||
gchar *message;
|
||||
va_list args;
|
||||
|
||||
win32_error = g_win32_error_message (GetLastError ());
|
||||
|
||||
va_start (args, format);
|
||||
detail = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
message = g_strconcat (detail, win32_error, NULL);
|
||||
|
||||
g_module_set_error (message);
|
||||
g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED, message);
|
||||
|
||||
g_free (message);
|
||||
g_free (detail);
|
||||
g_free (win32_error);
|
||||
}
|
||||
|
||||
/* --- functions --- */
|
||||
static gpointer
|
||||
_g_module_open (const gchar *file_name,
|
||||
gboolean bind_lazy,
|
||||
gboolean bind_local,
|
||||
GError **error)
|
||||
{
|
||||
HINSTANCE handle;
|
||||
wchar_t *wfilename;
|
||||
DWORD old_mode;
|
||||
BOOL success;
|
||||
#ifdef G_WITH_CYGWIN
|
||||
gchar tmp[MAX_PATH];
|
||||
|
||||
cygwin_conv_to_win32_path(file_name, tmp);
|
||||
file_name = tmp;
|
||||
#endif
|
||||
wfilename = g_utf8_to_utf16 (file_name, -1, NULL, NULL, NULL);
|
||||
|
||||
/* suppress error dialog */
|
||||
success = SetThreadErrorMode (SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS, &old_mode);
|
||||
if (!success)
|
||||
set_error (error, "");
|
||||
|
||||
/* When building for UWP, load app asset DLLs instead of filesystem DLLs.
|
||||
* Needs MSVC, Windows 8 and newer, and is only usable from apps. */
|
||||
#if _WIN32_WINNT >= 0x0602 && defined(G_WINAPI_ONLY_APP)
|
||||
handle = LoadPackagedLibrary (wfilename, 0);
|
||||
#else
|
||||
handle = LoadLibraryW (wfilename);
|
||||
#endif
|
||||
|
||||
if (success)
|
||||
SetThreadErrorMode (old_mode, NULL);
|
||||
g_free (wfilename);
|
||||
|
||||
if (!handle)
|
||||
set_error (error, "'%s': ", file_name);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static gint dummy;
|
||||
static gpointer null_module_handle = &dummy;
|
||||
|
||||
static gpointer
|
||||
_g_module_self (void)
|
||||
{
|
||||
return null_module_handle;
|
||||
}
|
||||
|
||||
static void
|
||||
_g_module_close (gpointer handle)
|
||||
{
|
||||
if (handle != null_module_handle)
|
||||
if (!FreeLibrary (handle))
|
||||
set_error (NULL, "");
|
||||
}
|
||||
|
||||
static gpointer
|
||||
find_in_any_module_using_toolhelp (const gchar *symbol_name)
|
||||
{
|
||||
HANDLE snapshot;
|
||||
MODULEENTRY32 me32;
|
||||
|
||||
gpointer p = NULL;
|
||||
|
||||
/* Under UWP, Module32Next and Module32First are not available since we're
|
||||
* not allowed to search in the address space of arbitrary loaded DLLs */
|
||||
#if !defined(G_WINAPI_ONLY_APP)
|
||||
/* https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot#remarks
|
||||
* If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds. */
|
||||
while (TRUE)
|
||||
{
|
||||
snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
|
||||
if (snapshot == INVALID_HANDLE_VALUE && GetLastError () == ERROR_BAD_LENGTH)
|
||||
{
|
||||
g_thread_yield ();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (snapshot == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
me32.dwSize = sizeof (me32);
|
||||
p = NULL;
|
||||
if (Module32First (snapshot, &me32))
|
||||
{
|
||||
do {
|
||||
if ((p = GetProcAddress (me32.hModule, symbol_name)) != NULL)
|
||||
break;
|
||||
} while (Module32Next (snapshot, &me32));
|
||||
}
|
||||
|
||||
CloseHandle (snapshot);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
find_in_any_module (const gchar *symbol_name)
|
||||
{
|
||||
gpointer result;
|
||||
|
||||
if ((result = find_in_any_module_using_toolhelp (symbol_name)) == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
_g_module_symbol (gpointer handle,
|
||||
const gchar *symbol_name)
|
||||
{
|
||||
gpointer p;
|
||||
|
||||
if (handle == null_module_handle)
|
||||
{
|
||||
if ((p = GetProcAddress (GetModuleHandle (NULL), symbol_name)) == NULL)
|
||||
p = find_in_any_module (symbol_name);
|
||||
}
|
||||
else
|
||||
p = GetProcAddress (handle, symbol_name);
|
||||
|
||||
if (!p)
|
||||
set_error (NULL, "");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name)
|
||||
{
|
||||
gint k;
|
||||
|
||||
k = strlen (module_name);
|
||||
|
||||
if (directory && *directory)
|
||||
if (k > 4 && g_ascii_strcasecmp (module_name + k - 4, ".dll") == 0)
|
||||
return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, NULL);
|
||||
#ifdef G_WITH_CYGWIN
|
||||
else if (strncmp (module_name, "lib", 3) == 0 || strncmp (module_name, "cyg", 3) == 0)
|
||||
return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, ".dll", NULL);
|
||||
else
|
||||
return g_strconcat (directory, G_DIR_SEPARATOR_S, "cyg", module_name, ".dll", NULL);
|
||||
#else
|
||||
else if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, ".dll", NULL);
|
||||
else
|
||||
return g_strconcat (directory, G_DIR_SEPARATOR_S, "lib", module_name, ".dll", NULL);
|
||||
#endif
|
||||
else if (k > 4 && g_ascii_strcasecmp (module_name + k - 4, ".dll") == 0)
|
||||
return g_strdup (module_name);
|
||||
#ifdef G_WITH_CYGWIN
|
||||
else if (strncmp (module_name, "lib", 3) == 0 || strncmp (module_name, "cyg", 3) == 0)
|
||||
return g_strconcat (module_name, ".dll", NULL);
|
||||
else
|
||||
return g_strconcat ("cyg", module_name, ".dll", NULL);
|
||||
#else
|
||||
else if (strncmp (module_name, "lib", 3) == 0)
|
||||
return g_strconcat (module_name, ".dll", NULL);
|
||||
else
|
||||
return g_strconcat ("lib", module_name, ".dll", NULL);
|
||||
#endif
|
||||
}
|
||||
910
gmodule/gmodule.c
Normal file
910
gmodule/gmodule.c
Normal file
|
|
@ -0,0 +1,910 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MT safe
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "glib.h"
|
||||
#include "gmodule.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef G_OS_UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef G_OS_WIN32
|
||||
#include <io.h> /* For open() and close() prototypes. */
|
||||
#endif
|
||||
|
||||
#include "gmoduleconf.h"
|
||||
#include "gstdio.h"
|
||||
|
||||
/**
|
||||
* SECTION:modules
|
||||
* @title: Dynamic Loading of Modules
|
||||
* @short_description: portable method for dynamically loading 'plug-ins'
|
||||
*
|
||||
* These functions provide a portable way to dynamically load object files
|
||||
* (commonly known as 'plug-ins'). The current implementation supports all
|
||||
* systems that provide an implementation of dlopen() (e.g. Linux/Sun), as
|
||||
* well as Windows platforms via DLLs.
|
||||
*
|
||||
* A program which wants to use these functions must be linked to the
|
||||
* libraries output by the command `pkg-config --libs gmodule-2.0`.
|
||||
*
|
||||
* To use them you must first determine whether dynamic loading
|
||||
* is supported on the platform by calling g_module_supported().
|
||||
* If it is, you can open a module with g_module_open(),
|
||||
* find the module's symbols (e.g. function names) with g_module_symbol(),
|
||||
* and later close the module with g_module_close().
|
||||
* g_module_name() will return the file name of a currently opened module.
|
||||
*
|
||||
* If any of the above functions fail, the error status can be found with
|
||||
* g_module_error().
|
||||
*
|
||||
* The #GModule implementation features reference counting for opened modules,
|
||||
* and supports hook functions within a module which are called when the
|
||||
* module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload).
|
||||
*
|
||||
* If your module introduces static data to common subsystems in the running
|
||||
* program, e.g. through calling
|
||||
* `g_quark_from_static_string ("my-module-stuff")`,
|
||||
* it must ensure that it is never unloaded, by calling g_module_make_resident().
|
||||
*
|
||||
* Example: Calling a function defined in a GModule
|
||||
* |[<!-- language="C" -->
|
||||
* // the function signature for 'say_hello'
|
||||
* typedef void (* SayHelloFunc) (const char *message);
|
||||
*
|
||||
* gboolean
|
||||
* just_say_hello (const char *filename, GError **error)
|
||||
* {
|
||||
* SayHelloFunc say_hello;
|
||||
* GModule *module;
|
||||
*
|
||||
* module = g_module_open (filename, G_MODULE_BIND_LAZY);
|
||||
* if (!module)
|
||||
* {
|
||||
* g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
|
||||
* "%s", g_module_error ());
|
||||
* return FALSE;
|
||||
* }
|
||||
*
|
||||
* if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))
|
||||
* {
|
||||
* g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
|
||||
* "%s: %s", filename, g_module_error ());
|
||||
* if (!g_module_close (module))
|
||||
* g_warning ("%s: %s", filename, g_module_error ());
|
||||
* return FALSE;
|
||||
* }
|
||||
*
|
||||
* if (say_hello == NULL)
|
||||
* {
|
||||
* g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
|
||||
* "symbol say_hello is NULL");
|
||||
* if (!g_module_close (module))
|
||||
* g_warning ("%s: %s", filename, g_module_error ());
|
||||
* return FALSE;
|
||||
* }
|
||||
*
|
||||
* // call our function in the module
|
||||
* say_hello ("Hello world!");
|
||||
*
|
||||
* if (!g_module_close (module))
|
||||
* g_warning ("%s: %s", filename, g_module_error ());
|
||||
* return TRUE;
|
||||
* }
|
||||
* ]|
|
||||
*/
|
||||
|
||||
/**
|
||||
* GModule:
|
||||
*
|
||||
* The #GModule struct is an opaque data structure to represent a
|
||||
* [dynamically-loaded module][glib-Dynamic-Loading-of-Modules].
|
||||
* It should only be accessed via the following functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GModuleCheckInit:
|
||||
* @module: the #GModule corresponding to the module which has just been loaded
|
||||
*
|
||||
* Specifies the type of the module initialization function.
|
||||
* If a module contains a function named g_module_check_init() it is called
|
||||
* automatically when the module is loaded. It is passed the #GModule structure
|
||||
* and should return %NULL on success or a string describing the initialization
|
||||
* error.
|
||||
*
|
||||
* Returns: %NULL on success, or a string describing the initialization error
|
||||
*/
|
||||
|
||||
/**
|
||||
* GModuleUnload:
|
||||
* @module: the #GModule about to be unloaded
|
||||
*
|
||||
* Specifies the type of the module function called when it is unloaded.
|
||||
* If a module contains a function named g_module_unload() it is called
|
||||
* automatically when the module is unloaded.
|
||||
* It is passed the #GModule structure.
|
||||
*/
|
||||
|
||||
/**
|
||||
* G_MODULE_SUFFIX:
|
||||
*
|
||||
* Expands to the proper shared library suffix for the current platform
|
||||
* without the leading dot. For most Unices and Linux this is "so", and
|
||||
* for Windows this is "dll".
|
||||
*/
|
||||
|
||||
/**
|
||||
* G_MODULE_EXPORT:
|
||||
*
|
||||
* Used to declare functions exported by libraries or modules.
|
||||
*
|
||||
* When compiling for Windows, it marks the symbol as `dllexport`.
|
||||
*
|
||||
* When compiling for Linux and Unices, it marks the symbol as having `default`
|
||||
* visibility. This is no-op unless the code is being compiled with a
|
||||
* non-default
|
||||
* [visibility flag](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility-1260)
|
||||
* such as `hidden`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* G_MODULE_IMPORT:
|
||||
*
|
||||
* Used to declare functions imported from modules.
|
||||
*/
|
||||
|
||||
/* We maintain a list of modules, so we can reference count them.
|
||||
* That's needed because some platforms don't support references counts on
|
||||
* modules. Also, the module for the program itself is kept separately for
|
||||
* faster access and because it has special semantics.
|
||||
*/
|
||||
|
||||
|
||||
/* --- structures --- */
|
||||
struct _GModule
|
||||
{
|
||||
gchar *file_name;
|
||||
gpointer handle;
|
||||
guint ref_count : 31;
|
||||
guint is_resident : 1;
|
||||
GModuleUnload unload;
|
||||
GModule *next;
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
static gpointer _g_module_open (const gchar *file_name,
|
||||
gboolean bind_lazy,
|
||||
gboolean bind_local,
|
||||
GError **error);
|
||||
static void _g_module_close (gpointer handle);
|
||||
static gpointer _g_module_self (void);
|
||||
static gpointer _g_module_symbol (gpointer handle,
|
||||
const gchar *symbol_name);
|
||||
static gchar* _g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name);
|
||||
static inline void g_module_set_error (const gchar *error);
|
||||
static inline GModule* g_module_find_by_handle (gpointer handle);
|
||||
static inline GModule* g_module_find_by_name (const gchar *name);
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
static GModule *modules = NULL;
|
||||
static GModule *main_module = NULL;
|
||||
static GPrivate module_error_private = G_PRIVATE_INIT (g_free);
|
||||
static gboolean module_debug_initialized = FALSE;
|
||||
static guint module_debug_flags = 0;
|
||||
|
||||
|
||||
/* --- inline functions --- */
|
||||
static inline GModule*
|
||||
g_module_find_by_handle (gpointer handle)
|
||||
{
|
||||
GModule *module;
|
||||
GModule *retval = NULL;
|
||||
|
||||
if (main_module && main_module->handle == handle)
|
||||
retval = main_module;
|
||||
else
|
||||
for (module = modules; module; module = module->next)
|
||||
if (handle == module->handle)
|
||||
{
|
||||
retval = module;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline GModule*
|
||||
g_module_find_by_name (const gchar *name)
|
||||
{
|
||||
GModule *module;
|
||||
GModule *retval = NULL;
|
||||
|
||||
for (module = modules; module; module = module->next)
|
||||
if (strcmp (name, module->file_name) == 0)
|
||||
{
|
||||
retval = module;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void
|
||||
g_module_set_error_unduped (gchar *error)
|
||||
{
|
||||
g_private_replace (&module_error_private, error);
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
g_module_set_error (const gchar *error)
|
||||
{
|
||||
g_module_set_error_unduped (g_strdup (error));
|
||||
}
|
||||
|
||||
|
||||
/* --- include platform specific code --- */
|
||||
#define SUPPORT_OR_RETURN(rv) { g_module_set_error (NULL); }
|
||||
#if (G_MODULE_IMPL == G_MODULE_IMPL_DL)
|
||||
#include "gmodule-dl.c"
|
||||
#elif (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
|
||||
#include "gmodule-win32.c"
|
||||
#elif (G_MODULE_IMPL == G_MODULE_IMPL_AR)
|
||||
#include "gmodule-ar.c"
|
||||
#else
|
||||
#undef SUPPORT_OR_RETURN
|
||||
#define SUPPORT_OR_RETURN(rv) { g_module_set_error ("dynamic modules are " \
|
||||
"not supported by this system"); return rv; }
|
||||
static gpointer
|
||||
_g_module_open (const gchar *file_name,
|
||||
gboolean bind_lazy,
|
||||
gboolean bind_local,
|
||||
GError **error)
|
||||
{
|
||||
g_module_set_error (NULL);
|
||||
return NULL;
|
||||
}
|
||||
static void
|
||||
_g_module_close (gpointer handle)
|
||||
{
|
||||
}
|
||||
static gpointer
|
||||
_g_module_self (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static gpointer
|
||||
_g_module_symbol (gpointer handle,
|
||||
const gchar *symbol_name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static gchar*
|
||||
_g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* no implementation */
|
||||
|
||||
/**
|
||||
* G_MODULE_ERROR:
|
||||
*
|
||||
* The error domain of the #GModule API.
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
G_DEFINE_QUARK (g-module-error-quark, g_module_error)
|
||||
|
||||
/* --- functions --- */
|
||||
|
||||
/**
|
||||
* g_module_supported:
|
||||
*
|
||||
* Checks if modules are supported on the current platform.
|
||||
*
|
||||
* Returns: %TRUE if modules are supported
|
||||
*/
|
||||
gboolean
|
||||
g_module_supported (void)
|
||||
{
|
||||
SUPPORT_OR_RETURN (FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
parse_libtool_archive (const gchar* libtool_name)
|
||||
{
|
||||
const guint TOKEN_DLNAME = G_TOKEN_LAST + 1;
|
||||
const guint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
|
||||
const guint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
|
||||
gchar *lt_dlname = NULL;
|
||||
gboolean lt_installed = TRUE;
|
||||
gchar *lt_libdir = NULL;
|
||||
gchar *name;
|
||||
GTokenType token;
|
||||
GScanner *scanner;
|
||||
|
||||
int fd = g_open (libtool_name, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
gchar *display_libtool_name = g_filename_display_name (libtool_name);
|
||||
g_module_set_error_unduped (g_strdup_printf ("failed to open libtool archive \"%s\"", display_libtool_name));
|
||||
g_free (display_libtool_name);
|
||||
return NULL;
|
||||
}
|
||||
/* search libtool's dlname specification */
|
||||
scanner = g_scanner_new (NULL);
|
||||
g_scanner_input_file (scanner, fd);
|
||||
scanner->config->symbol_2_token = TRUE;
|
||||
g_scanner_scope_add_symbol (scanner, 0, "dlname",
|
||||
GUINT_TO_POINTER (TOKEN_DLNAME));
|
||||
g_scanner_scope_add_symbol (scanner, 0, "installed",
|
||||
GUINT_TO_POINTER (TOKEN_INSTALLED));
|
||||
g_scanner_scope_add_symbol (scanner, 0, "libdir",
|
||||
GUINT_TO_POINTER (TOKEN_LIBDIR));
|
||||
while (!g_scanner_eof (scanner))
|
||||
{
|
||||
token = g_scanner_get_next_token (scanner);
|
||||
if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED ||
|
||||
token == TOKEN_LIBDIR)
|
||||
{
|
||||
if (g_scanner_get_next_token (scanner) != '=' ||
|
||||
g_scanner_get_next_token (scanner) !=
|
||||
(token == TOKEN_INSTALLED ?
|
||||
G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
|
||||
{
|
||||
gchar *display_libtool_name = g_filename_display_name (libtool_name);
|
||||
g_module_set_error_unduped (g_strdup_printf ("unable to parse libtool archive \"%s\"", display_libtool_name));
|
||||
g_free (display_libtool_name);
|
||||
|
||||
g_free (lt_dlname);
|
||||
g_free (lt_libdir);
|
||||
g_scanner_destroy (scanner);
|
||||
close (fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (token == TOKEN_DLNAME)
|
||||
{
|
||||
g_free (lt_dlname);
|
||||
lt_dlname = g_strdup (scanner->value.v_string);
|
||||
}
|
||||
else if (token == TOKEN_INSTALLED)
|
||||
lt_installed =
|
||||
strcmp (scanner->value.v_identifier, "yes") == 0;
|
||||
else /* token == TOKEN_LIBDIR */
|
||||
{
|
||||
g_free (lt_libdir);
|
||||
lt_libdir = g_strdup (scanner->value.v_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!lt_installed)
|
||||
{
|
||||
gchar *dir = g_path_get_dirname (libtool_name);
|
||||
g_free (lt_libdir);
|
||||
lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL);
|
||||
g_free (dir);
|
||||
}
|
||||
|
||||
name = g_strconcat (lt_libdir, G_DIR_SEPARATOR_S, lt_dlname, NULL);
|
||||
|
||||
g_free (lt_dlname);
|
||||
g_free (lt_libdir);
|
||||
g_scanner_destroy (scanner);
|
||||
close (fd);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
G_MODULE_DEBUG_RESIDENT_MODULES = 1 << 0,
|
||||
G_MODULE_DEBUG_BIND_NOW_MODULES = 1 << 1
|
||||
};
|
||||
|
||||
static void
|
||||
_g_module_debug_init (void)
|
||||
{
|
||||
const GDebugKey keys[] = {
|
||||
{ "resident-modules", G_MODULE_DEBUG_RESIDENT_MODULES },
|
||||
{ "bind-now-modules", G_MODULE_DEBUG_BIND_NOW_MODULES }
|
||||
};
|
||||
const gchar *env;
|
||||
|
||||
env = g_getenv ("G_DEBUG");
|
||||
|
||||
module_debug_flags =
|
||||
!env ? 0 : g_parse_debug_string (env, keys, G_N_ELEMENTS (keys));
|
||||
|
||||
module_debug_initialized = TRUE;
|
||||
}
|
||||
|
||||
static GRecMutex g_module_global_lock;
|
||||
|
||||
/**
|
||||
* g_module_open_full:
|
||||
* @file_name: (nullable): the name of the file containing the module, or %NULL
|
||||
* to obtain a #GModule representing the main program itself
|
||||
* @flags: the flags used for opening the module. This can be the
|
||||
* logical OR of any of the #GModuleFlags
|
||||
* @error: #GError.
|
||||
*
|
||||
* Opens a module. If the module has already been opened,
|
||||
* its reference count is incremented.
|
||||
*
|
||||
* First of all g_module_open_full() tries to open @file_name as a module.
|
||||
* If that fails and @file_name has the ".la"-suffix (and is a libtool
|
||||
* archive) it tries to open the corresponding module. If that fails
|
||||
* and it doesn't have the proper module suffix for the platform
|
||||
* (%G_MODULE_SUFFIX), this suffix will be appended and the corresponding
|
||||
* module will be opened. If that fails and @file_name doesn't have the
|
||||
* ".la"-suffix, this suffix is appended and g_module_open_full() tries to open
|
||||
* the corresponding module. If eventually that fails as well, %NULL is
|
||||
* returned.
|
||||
*
|
||||
* Returns: a #GModule on success, or %NULL on failure
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
GModule*
|
||||
g_module_open_full (const gchar *file_name,
|
||||
GModuleFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
GModule *module;
|
||||
gpointer handle = NULL;
|
||||
gchar *name = NULL;
|
||||
|
||||
SUPPORT_OR_RETURN (NULL);
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
g_rec_mutex_lock (&g_module_global_lock);
|
||||
|
||||
if (G_UNLIKELY (!module_debug_initialized))
|
||||
_g_module_debug_init ();
|
||||
|
||||
if (module_debug_flags & G_MODULE_DEBUG_BIND_NOW_MODULES)
|
||||
flags &= ~G_MODULE_BIND_LAZY;
|
||||
|
||||
if (!file_name)
|
||||
{
|
||||
if (!main_module)
|
||||
{
|
||||
handle = _g_module_self ();
|
||||
/* On Android 64 bit, RTLD_DEFAULT is (void *)0x0
|
||||
* so it always fails to create main_module if file_name is NULL */
|
||||
#if !defined(__BIONIC__) || !defined(__LP64__)
|
||||
if (handle)
|
||||
#endif
|
||||
{
|
||||
main_module = g_new (GModule, 1);
|
||||
main_module->file_name = NULL;
|
||||
main_module->handle = handle;
|
||||
main_module->ref_count = 1;
|
||||
main_module->is_resident = TRUE;
|
||||
main_module->unload = NULL;
|
||||
main_module->next = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
main_module->ref_count++;
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return main_module;
|
||||
}
|
||||
|
||||
/* we first search the module list by name */
|
||||
module = g_module_find_by_name (file_name);
|
||||
if (module)
|
||||
{
|
||||
module->ref_count++;
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return module;
|
||||
}
|
||||
|
||||
/* check whether we have a readable file right away */
|
||||
if (g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
|
||||
name = g_strdup (file_name);
|
||||
/* try completing file name with standard library suffix */
|
||||
if (!name)
|
||||
{
|
||||
name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
|
||||
if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
g_free (name);
|
||||
name = NULL;
|
||||
}
|
||||
}
|
||||
/* try completing by appending libtool suffix */
|
||||
if (!name)
|
||||
{
|
||||
name = g_strconcat (file_name, ".la", NULL);
|
||||
if (!g_file_test (name, G_FILE_TEST_IS_REGULAR))
|
||||
{
|
||||
g_free (name);
|
||||
name = NULL;
|
||||
}
|
||||
}
|
||||
/* we can't access() the file, lets hope the platform backends finds
|
||||
* it via library paths
|
||||
*/
|
||||
if (!name)
|
||||
{
|
||||
gchar *dot = strrchr (file_name, '.');
|
||||
gchar *slash = strrchr (file_name, G_DIR_SEPARATOR);
|
||||
|
||||
/* make sure the name has a suffix */
|
||||
if (!dot || dot < slash)
|
||||
name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
|
||||
else
|
||||
name = g_strdup (file_name);
|
||||
}
|
||||
|
||||
/* ok, try loading the module */
|
||||
g_assert (name != NULL);
|
||||
|
||||
/* if it's a libtool archive, figure library file to load */
|
||||
if (g_str_has_suffix (name, ".la")) /* libtool archive? */
|
||||
{
|
||||
gchar *real_name = parse_libtool_archive (name);
|
||||
|
||||
/* real_name might be NULL, but then module error is already set */
|
||||
if (real_name)
|
||||
{
|
||||
g_free (name);
|
||||
name = real_name;
|
||||
}
|
||||
}
|
||||
|
||||
handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0,
|
||||
(flags & G_MODULE_BIND_LOCAL) != 0, error);
|
||||
g_free (name);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
gchar *saved_error;
|
||||
GModuleCheckInit check_init;
|
||||
const gchar *check_failed = NULL;
|
||||
|
||||
/* search the module list by handle, since file names are not unique */
|
||||
module = g_module_find_by_handle (handle);
|
||||
if (module)
|
||||
{
|
||||
_g_module_close (module->handle);
|
||||
module->ref_count++;
|
||||
g_module_set_error (NULL);
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return module;
|
||||
}
|
||||
|
||||
saved_error = g_strdup (g_module_error ());
|
||||
g_module_set_error (NULL);
|
||||
|
||||
module = g_new (GModule, 1);
|
||||
module->file_name = g_strdup (file_name);
|
||||
module->handle = handle;
|
||||
module->ref_count = 1;
|
||||
module->is_resident = FALSE;
|
||||
module->unload = NULL;
|
||||
module->next = modules;
|
||||
modules = module;
|
||||
|
||||
/* check initialization */
|
||||
if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init) && check_init != NULL)
|
||||
check_failed = check_init (module);
|
||||
|
||||
/* we don't call unload() if the initialization check failed. */
|
||||
if (!check_failed)
|
||||
g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
|
||||
|
||||
if (check_failed)
|
||||
{
|
||||
gchar *temp_error;
|
||||
|
||||
temp_error = g_strconcat ("GModule (", file_name, ") ",
|
||||
"initialization check failed: ",
|
||||
check_failed, NULL);
|
||||
g_module_close (module);
|
||||
module = NULL;
|
||||
g_module_set_error (temp_error);
|
||||
g_set_error_literal (error, G_MODULE_ERROR, G_MODULE_ERROR_CHECK_FAILED, temp_error);
|
||||
g_free (temp_error);
|
||||
}
|
||||
else
|
||||
g_module_set_error (saved_error);
|
||||
|
||||
g_free (saved_error);
|
||||
}
|
||||
|
||||
if (module != NULL &&
|
||||
(module_debug_flags & G_MODULE_DEBUG_RESIDENT_MODULES))
|
||||
g_module_make_resident (module);
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_open:
|
||||
* @file_name: (nullable): the name of the file containing the module, or %NULL
|
||||
* to obtain a #GModule representing the main program itself
|
||||
* @flags: the flags used for opening the module. This can be the
|
||||
* logical OR of any of the #GModuleFlags.
|
||||
*
|
||||
* A thin wrapper function around g_module_open_full()
|
||||
*
|
||||
* Returns: a #GModule on success, or %NULL on failure
|
||||
*/
|
||||
GModule *
|
||||
g_module_open (const gchar *file_name,
|
||||
GModuleFlags flags)
|
||||
{
|
||||
return g_module_open_full (file_name, flags, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_close:
|
||||
* @module: a #GModule to close
|
||||
*
|
||||
* Closes a module.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
g_module_close (GModule *module)
|
||||
{
|
||||
SUPPORT_OR_RETURN (FALSE);
|
||||
|
||||
g_return_val_if_fail (module != NULL, FALSE);
|
||||
g_return_val_if_fail (module->ref_count > 0, FALSE);
|
||||
|
||||
g_rec_mutex_lock (&g_module_global_lock);
|
||||
|
||||
module->ref_count--;
|
||||
|
||||
if (!module->ref_count && !module->is_resident && module->unload)
|
||||
{
|
||||
GModuleUnload unload;
|
||||
|
||||
unload = module->unload;
|
||||
module->unload = NULL;
|
||||
unload (module);
|
||||
}
|
||||
|
||||
if (!module->ref_count && !module->is_resident)
|
||||
{
|
||||
GModule *last;
|
||||
GModule *node;
|
||||
|
||||
last = NULL;
|
||||
|
||||
node = modules;
|
||||
while (node)
|
||||
{
|
||||
if (node == module)
|
||||
{
|
||||
if (last)
|
||||
last->next = node->next;
|
||||
else
|
||||
modules = node->next;
|
||||
break;
|
||||
}
|
||||
last = node;
|
||||
node = last->next;
|
||||
}
|
||||
module->next = NULL;
|
||||
|
||||
_g_module_close (module->handle);
|
||||
g_free (module->file_name);
|
||||
g_free (module);
|
||||
}
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return g_module_error() == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_make_resident:
|
||||
* @module: a #GModule to make permanently resident
|
||||
*
|
||||
* Ensures that a module will never be unloaded.
|
||||
* Any future g_module_close() calls on the module will be ignored.
|
||||
*/
|
||||
void
|
||||
g_module_make_resident (GModule *module)
|
||||
{
|
||||
g_return_if_fail (module != NULL);
|
||||
|
||||
module->is_resident = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_error:
|
||||
*
|
||||
* Gets a string describing the last module error.
|
||||
*
|
||||
* Returns: a string describing the last module error
|
||||
*/
|
||||
const gchar *
|
||||
g_module_error (void)
|
||||
{
|
||||
return g_private_get (&module_error_private);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_symbol:
|
||||
* @module: a #GModule
|
||||
* @symbol_name: the name of the symbol to find
|
||||
* @symbol: (out): returns the pointer to the symbol value
|
||||
*
|
||||
* Gets a symbol pointer from a module, such as one exported
|
||||
* by %G_MODULE_EXPORT. Note that a valid symbol can be %NULL.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
g_module_symbol (GModule *module,
|
||||
const gchar *symbol_name,
|
||||
gpointer *symbol)
|
||||
{
|
||||
const gchar *module_error;
|
||||
|
||||
if (symbol)
|
||||
*symbol = NULL;
|
||||
SUPPORT_OR_RETURN (FALSE);
|
||||
|
||||
g_return_val_if_fail (module != NULL, FALSE);
|
||||
g_return_val_if_fail (symbol_name != NULL, FALSE);
|
||||
g_return_val_if_fail (symbol != NULL, FALSE);
|
||||
|
||||
g_rec_mutex_lock (&g_module_global_lock);
|
||||
|
||||
#ifdef G_MODULE_NEED_USCORE
|
||||
{
|
||||
gchar *name;
|
||||
|
||||
name = g_strconcat ("_", symbol_name, NULL);
|
||||
*symbol = _g_module_symbol (module->handle, name);
|
||||
g_free (name);
|
||||
}
|
||||
#else /* !G_MODULE_NEED_USCORE */
|
||||
*symbol = _g_module_symbol (module->handle, symbol_name);
|
||||
#endif /* !G_MODULE_NEED_USCORE */
|
||||
|
||||
module_error = g_module_error ();
|
||||
if (module_error)
|
||||
{
|
||||
gchar *error;
|
||||
|
||||
error = g_strconcat ("'", symbol_name, "': ", module_error, NULL);
|
||||
g_module_set_error (error);
|
||||
g_free (error);
|
||||
*symbol = NULL;
|
||||
}
|
||||
|
||||
g_rec_mutex_unlock (&g_module_global_lock);
|
||||
return !module_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_name:
|
||||
* @module: a #GModule
|
||||
*
|
||||
* Returns the filename that the module was opened with.
|
||||
*
|
||||
* If @module refers to the application itself, "main" is returned.
|
||||
*
|
||||
* Returns: (transfer none): the filename of the module
|
||||
*/
|
||||
const gchar *
|
||||
g_module_name (GModule *module)
|
||||
{
|
||||
g_return_val_if_fail (module != NULL, NULL);
|
||||
|
||||
if (module == main_module)
|
||||
return "main";
|
||||
|
||||
return module->file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_module_build_path:
|
||||
* @directory: (nullable): the directory where the module is. This can be
|
||||
* %NULL or the empty string to indicate that the standard platform-specific
|
||||
* directories will be used, though that is not recommended
|
||||
* @module_name: the name of the module
|
||||
*
|
||||
* A portable way to build the filename of a module. The platform-specific
|
||||
* prefix and suffix are added to the filename, if needed, and the result
|
||||
* is added to the directory, using the correct separator character.
|
||||
*
|
||||
* The directory should specify the directory where the module can be found.
|
||||
* It can be %NULL or an empty string to indicate that the module is in a
|
||||
* standard platform-specific directory, though this is not recommended
|
||||
* since the wrong module may be found.
|
||||
*
|
||||
* For example, calling g_module_build_path() on a Linux system with a
|
||||
* @directory of `/lib` and a @module_name of "mylibrary" will return
|
||||
* `/lib/libmylibrary.so`. On a Windows system, using `\Windows` as the
|
||||
* directory it will return `\Windows\mylibrary.dll`.
|
||||
*
|
||||
* Returns: the complete path of the module, including the standard library
|
||||
* prefix and suffix. This should be freed when no longer needed
|
||||
*/
|
||||
gchar *
|
||||
g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name)
|
||||
{
|
||||
g_return_val_if_fail (module_name != NULL, NULL);
|
||||
|
||||
return _g_module_build_path (directory, module_name);
|
||||
}
|
||||
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* Binary compatibility versions. Not for newly compiled code. */
|
||||
|
||||
_GLIB_EXTERN GModule * g_module_open_utf8 (const gchar *file_name,
|
||||
GModuleFlags flags);
|
||||
|
||||
_GLIB_EXTERN const gchar *g_module_name_utf8 (GModule *module);
|
||||
|
||||
GModule*
|
||||
g_module_open_utf8 (const gchar *file_name,
|
||||
GModuleFlags flags)
|
||||
{
|
||||
return g_module_open (file_name, flags);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
g_module_name_utf8 (GModule *module)
|
||||
{
|
||||
return g_module_name (module);
|
||||
}
|
||||
|
||||
#endif
|
||||
142
gmodule/gmodule.h
Normal file
142
gmodule/gmodule.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GMODULE_H__
|
||||
#define __GMODULE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* exporting and importing functions, this is special cased
|
||||
* to feature Windows dll stubs.
|
||||
*/
|
||||
#define G_MODULE_IMPORT extern
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
# define G_MODULE_EXPORT __declspec(dllexport)
|
||||
#elif __GNUC__ >= 4
|
||||
# define G_MODULE_EXPORT __attribute__((visibility("default")))
|
||||
#else /* !G_PLATFORM_WIN32 && __GNUC__ < 4 */
|
||||
# define G_MODULE_EXPORT
|
||||
#endif /* !G_PLATFORM_WIN32 */
|
||||
|
||||
/**
|
||||
* GModuleFlags:
|
||||
* @G_MODULE_BIND_LAZY: specifies that symbols are only resolved when
|
||||
* needed. The default action is to bind all symbols when the module
|
||||
* is loaded.
|
||||
* @G_MODULE_BIND_LOCAL: specifies that symbols in the module should
|
||||
* not be added to the global name space. The default action on most
|
||||
* platforms is to place symbols in the module in the global name space,
|
||||
* which may cause conflicts with existing symbols.
|
||||
* @G_MODULE_BIND_MASK: mask for all flags.
|
||||
*
|
||||
* Flags passed to g_module_open().
|
||||
* Note that these flags are not supported on all platforms.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_MODULE_BIND_LAZY = 1 << 0,
|
||||
G_MODULE_BIND_LOCAL = 1 << 1,
|
||||
G_MODULE_BIND_MASK = 0x03
|
||||
} GModuleFlags;
|
||||
|
||||
typedef struct _GModule GModule;
|
||||
typedef const gchar* (*GModuleCheckInit) (GModule *module);
|
||||
typedef void (*GModuleUnload) (GModule *module);
|
||||
|
||||
#define G_MODULE_ERROR g_module_error_quark () GLIB_AVAILABLE_MACRO_IN_2_70
|
||||
GLIB_AVAILABLE_IN_2_70
|
||||
GQuark g_module_error_quark (void);
|
||||
|
||||
/**
|
||||
* GModuleError:
|
||||
* @G_MODULE_ERROR_FAILED: there was an error loading or opening a module file
|
||||
* @G_MODULE_ERROR_CHECK_FAILED: a module returned an error from its `g_module_check_init()` function
|
||||
*
|
||||
* Errors returned by g_module_open_full().
|
||||
*
|
||||
* Since: 2.70
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
G_MODULE_ERROR_FAILED,
|
||||
G_MODULE_ERROR_CHECK_FAILED,
|
||||
} GModuleError
|
||||
GLIB_AVAILABLE_ENUMERATOR_IN_2_70;
|
||||
|
||||
/* return TRUE if dynamic module loading is supported */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_module_supported (void) G_GNUC_CONST;
|
||||
|
||||
/* open a module 'file_name' and return handle, which is NULL on error */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GModule* g_module_open (const gchar *file_name,
|
||||
GModuleFlags flags);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_70
|
||||
GModule *g_module_open_full (const gchar *file_name,
|
||||
GModuleFlags flags,
|
||||
GError **error);
|
||||
|
||||
/* close a previously opened module, returns TRUE on success */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_module_close (GModule *module);
|
||||
|
||||
/* make a module resident so g_module_close on it will be ignored */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_module_make_resident (GModule *module);
|
||||
|
||||
/* query the last module error as a string */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
const gchar * g_module_error (void);
|
||||
|
||||
/* retrieve a symbol pointer from 'module', returns TRUE on success */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_module_symbol (GModule *module,
|
||||
const gchar *symbol_name,
|
||||
gpointer *symbol);
|
||||
|
||||
/* retrieve the file name from an existing module */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
const gchar * g_module_name (GModule *module);
|
||||
|
||||
/* Build the actual file name containing a module. 'directory' is the
|
||||
* directory where the module file is supposed to be, or NULL or empty
|
||||
* in which case it should either be in the current directory or, on
|
||||
* some operating systems, in some standard place, for instance on the
|
||||
* PATH. Hence, to be absolutely sure to get the correct module,
|
||||
* always pass in a directory. The file name consists of the directory,
|
||||
* if supplied, and 'module_name' suitably decorated according to
|
||||
* the operating system's conventions (for instance lib*.so or *.dll).
|
||||
*
|
||||
* No checks are made that the file exists, or is of correct type.
|
||||
*/
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gchar* g_module_build_path (const gchar *directory,
|
||||
const gchar *module_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GMODULE_H__ */
|
||||
30
gmodule/gmodule.rc.in
Normal file
30
gmodule/gmodule.rc.in
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <winver.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0
|
||||
PRODUCTVERSION @GLIB_MAJOR_VERSION@,@GLIB_MINOR_VERSION@,@GLIB_MICRO_VERSION@,0
|
||||
FILEFLAGSMASK 0
|
||||
FILEFLAGS 0
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "The GLib developer community"
|
||||
VALUE "FileDescription", "GModule"
|
||||
VALUE "FileVersion", "@GLIB_VERSION@.0"
|
||||
VALUE "InternalName", "libgmodule-2.0-@LT_CURRENT_MINUS_AGE@"
|
||||
VALUE "LegalCopyright", "Copyright 1998-2011 Tim Janik and others."
|
||||
VALUE "OriginalFilename", "libgmodule-2.0-@LT_CURRENT_MINUS_AGE@.dll"
|
||||
VALUE "ProductName", "GLib"
|
||||
VALUE "ProductVersion", "@GLIB_VERSION@"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
48
gmodule/gmoduleconf.h.in
Normal file
48
gmodule/gmoduleconf.h.in
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* GMODULE - GLIB wrapper code for dynamic module loading
|
||||
* Copyright (C) 1998 Tim Janik
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __G_MODULE_CONF_H__
|
||||
#define __G_MODULE_CONF_H__
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#define G_MODULE_IMPL_NONE 0
|
||||
#define G_MODULE_IMPL_DL 1
|
||||
#define G_MODULE_IMPL_WIN32 3
|
||||
#define G_MODULE_IMPL_AR 7
|
||||
|
||||
#define G_MODULE_IMPL @G_MODULE_IMPL@
|
||||
#undef G_MODULE_HAVE_DLERROR
|
||||
#if (@G_MODULE_HAVE_DLERROR@)
|
||||
#define G_MODULE_HAVE_DLERROR
|
||||
#endif
|
||||
#if (@G_MODULE_NEED_USCORE@)
|
||||
#define G_MODULE_NEED_USCORE
|
||||
#endif
|
||||
#if (@G_MODULE_BROKEN_RTLD_GLOBAL@)
|
||||
#define G_MODULE_BROKEN_RTLD_GLOBAL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __G_MODULE_CONF_H__ */
|
||||
137
gmodule/meson.build
Normal file
137
gmodule/meson.build
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
gmoduleconf_conf = configuration_data()
|
||||
|
||||
g_module_need_uscore = 0
|
||||
g_module_broken_rtld_global = 0
|
||||
g_module_have_dlerror = 0
|
||||
|
||||
g_module_impl = ''
|
||||
|
||||
# On Windows force native WIN32 shared lib loader
|
||||
if host_system == 'windows'
|
||||
g_module_impl = 'G_MODULE_IMPL_WIN32'
|
||||
# Force native AIX library loader
|
||||
# dlopen() filepath must be of the form /path/libname.a(libname.so)
|
||||
elif host_system == 'aix'
|
||||
g_module_impl = 'G_MODULE_IMPL_AR'
|
||||
elif have_dlopen_dlsym
|
||||
g_module_impl = 'G_MODULE_IMPL_DL'
|
||||
endif
|
||||
|
||||
# additional checks for G_MODULE_IMPL_DL
|
||||
if g_module_impl == 'G_MODULE_IMPL_DL'
|
||||
# FIXME: check for OSF1/5.0 RTLD_GLOBAL brokenness (is this still relevant?)
|
||||
|
||||
# Check whether we need preceding underscores
|
||||
if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl'
|
||||
message('Building for MSVC: assuming that symbols are prefixed with underscore')
|
||||
g_module_need_uscore = 1
|
||||
elif meson.has_exe_wrapper()
|
||||
# FIXME: communicate result via stdout instead of return value, so non-0 return is not printed in bold red
|
||||
rres = cc.run(dlopen_dlsym_test_code,
|
||||
dependencies : libdl_dep,
|
||||
name : 'dlsym() preceding underscores')
|
||||
if host_system == 'windows' or (rres.compiled() and rres.returncode() == 0)
|
||||
g_module_need_uscore = 1
|
||||
endif
|
||||
else
|
||||
message('Cross-compiling: assuming that symbols aren\'t prefixed with underscore')
|
||||
g_module_need_uscore = 0
|
||||
endif
|
||||
|
||||
if cc.has_function('dlerror', dependencies : libdl_dep)
|
||||
g_module_have_dlerror = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# Done, have we got an implementation?
|
||||
if g_module_impl == ''
|
||||
g_module_impl = '0'
|
||||
message('WARNING: No suitable GModule implementation found!')
|
||||
endif
|
||||
|
||||
gmoduleconf_conf.set('G_MODULE_IMPL', g_module_impl)
|
||||
gmoduleconf_conf.set('G_MODULE_SUPPORTED', g_module_impl != '0')
|
||||
gmoduleconf_conf.set('G_MODULE_HAVE_DLERROR', g_module_have_dlerror)
|
||||
gmoduleconf_conf.set('G_MODULE_NEED_USCORE', g_module_need_uscore)
|
||||
gmoduleconf_conf.set('G_MODULE_BROKEN_RTLD_GLOBAL', g_module_broken_rtld_global)
|
||||
|
||||
gmoduleconf_h = configure_file(input : 'gmoduleconf.h.in',
|
||||
output : 'gmoduleconf.h',
|
||||
configuration : gmoduleconf_conf)
|
||||
|
||||
# Expose as variable to be used by gobject-introspection
|
||||
# when it includes GLib as a subproject
|
||||
gmodule_h = files('gmodule.h')
|
||||
gmodule_c = files('gmodule.c')
|
||||
|
||||
install_headers([gmodule_h], subdir : 'glib-2.0')
|
||||
|
||||
gmodule_sources = [gmodule_c]
|
||||
if host_system == 'windows'
|
||||
gmodule_win_rc = configure_file(
|
||||
input: 'gmodule.rc.in',
|
||||
output: 'gmodule.rc',
|
||||
configuration: glibconfig_conf,
|
||||
)
|
||||
gmodule_win_res = windows.compile_resources(gmodule_win_rc)
|
||||
gmodule_sources += [gmodule_win_res]
|
||||
endif
|
||||
|
||||
libgmodule = library('gmodule-2.0',
|
||||
sources : gmodule_sources,
|
||||
version : library_version,
|
||||
soversion : soversion,
|
||||
darwin_versions : darwin_versions,
|
||||
install : true,
|
||||
include_directories : [configinc, gmoduleinc],
|
||||
dependencies : [libdl_dep, libglib_dep],
|
||||
c_args : ['-DG_LOG_DOMAIN="GModule"'] + glib_hidden_visibility_args,
|
||||
link_args : [glib_link_flags],
|
||||
)
|
||||
|
||||
supported_var = 'gmodule_supported=@0@'.format(g_module_impl != '0')
|
||||
|
||||
pkg.generate(libgmodule,
|
||||
libraries : [thread_dep],
|
||||
requires : ['glib-2.0'],
|
||||
version : glib_version,
|
||||
variables : [supported_var],
|
||||
install_dir : glib_pkgconfigreldir,
|
||||
filebase : 'gmodule-no-export-2.0',
|
||||
name : 'GModule',
|
||||
description : 'Dynamic module loader for GLib',
|
||||
)
|
||||
|
||||
pkg.generate(libraries : [libgmodule, export_dynamic_ldflags],
|
||||
requires : ['glib-2.0'],
|
||||
version : glib_version,
|
||||
variables : [supported_var],
|
||||
install_dir : glib_pkgconfigreldir,
|
||||
filebase : 'gmodule-export-2.0',
|
||||
name : 'GModule',
|
||||
description : 'Dynamic module loader for GLib',
|
||||
)
|
||||
|
||||
pkg.generate(libraries : [libgmodule, export_dynamic_ldflags],
|
||||
requires : ['glib-2.0'],
|
||||
version : glib_version,
|
||||
variables : [supported_var],
|
||||
install_dir : glib_pkgconfigreldir,
|
||||
filebase : 'gmodule-2.0',
|
||||
name : 'GModule',
|
||||
description : 'Dynamic module loader for GLib',
|
||||
)
|
||||
|
||||
libgmodule_dep = declare_dependency(link_with : libgmodule,
|
||||
include_directories : [gmoduleinc],
|
||||
dependencies : [libglib_dep])
|
||||
|
||||
if meson.version().version_compare('>=0.54.0')
|
||||
meson.override_dependency('gmodule-no-export-2.0', libgmodule_dep)
|
||||
meson.override_dependency('gmodule-export-2.0', libgmodule_dep)
|
||||
meson.override_dependency('gmodule-2.0', libgmodule_dep)
|
||||
endif
|
||||
|
||||
if build_tests
|
||||
subdir('tests')
|
||||
endif
|
||||
26
gmodule/tests/cxx.cpp
Normal file
26
gmodule/tests/cxx.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (C) 2001 Sebastian Wilhelmi <wilhelmi@google.com>
|
||||
*
|
||||
* This library 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 library 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 library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* A trivial C++ program to be compiled in C++ mode, which
|
||||
* smoketests that the GModule headers are valid C++ headers. */
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
47
gmodule/tests/meson.build
Normal file
47
gmodule/tests/meson.build
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
if have_cxx
|
||||
gmodule_tests = {
|
||||
'cxx' : {
|
||||
'source' : ['cxx.cpp'],
|
||||
},
|
||||
}
|
||||
endif
|
||||
|
||||
test_env = environment()
|
||||
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
|
||||
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
|
||||
test_env.set('G_DEBUG', 'gc-friendly')
|
||||
test_env.set('MALLOC_CHECK_', '2')
|
||||
test_env.set('MALLOC_PERTURB_', '@0@'.format(random_number % 256))
|
||||
|
||||
test_deps = [libm, thread_dep, libglib_dep, libgmodule_dep]
|
||||
test_cargs = ['-DG_LOG_DOMAIN="GModule"', '-UG_DISABLE_ASSERT']
|
||||
|
||||
foreach test_name, extra_args : gmodule_tests
|
||||
source = extra_args.get('source', test_name + '.c')
|
||||
install = installed_tests_enabled and extra_args.get('install', true)
|
||||
|
||||
if install
|
||||
test_conf = configuration_data()
|
||||
test_conf.set('installed_tests_dir', installed_tests_execdir)
|
||||
test_conf.set('program', test_name)
|
||||
test_conf.set('env', '')
|
||||
configure_file(
|
||||
input: installed_tests_template_tap,
|
||||
output: test_name + '.test',
|
||||
install_dir: installed_tests_metadir,
|
||||
configuration: test_conf
|
||||
)
|
||||
endif
|
||||
|
||||
exe = executable(test_name, source,
|
||||
c_args : test_cargs + extra_args.get('c_args', []),
|
||||
link_args : extra_args.get('link_args', []),
|
||||
dependencies : test_deps + extra_args.get('dependencies', []),
|
||||
install_dir: installed_tests_execdir,
|
||||
install: install,
|
||||
)
|
||||
|
||||
suite = ['gmodule'] + extra_args.get('suite', [])
|
||||
timeout = suite.contains('slow') ? test_timeout_slow : test_timeout
|
||||
test(test_name, exe, env : test_env, timeout : timeout, suite : suite)
|
||||
endforeach
|
||||
Loading…
Add table
Add a link
Reference in a new issue