New upstream version 2.47
This commit is contained in:
parent
062d493759
commit
72ebc9cbe9
10
Changes
10
Changes
|
@ -1,5 +1,15 @@
|
|||
Revision history for Perl extension XML::Parser.
|
||||
|
||||
2.47 2023-12-28 (by Todd Rinaldo)
|
||||
- #84 use $fh instead of $foo
|
||||
- #85 Fix typo in documentation
|
||||
- #89 Devel::CheckLib to from 0.99 -> 1.14
|
||||
- Devel::CheckLibn 1.16
|
||||
- #91 POD fix for verbatim text
|
||||
- #97 Add a LICENSE file
|
||||
- #94 Don't ship Expat/Makefile
|
||||
- Various github workflow improvements. Windows is still not working.
|
||||
|
||||
2.46 2019-09-24 (by Todd Rinaldo)
|
||||
- use foreach not for for loops
|
||||
- produce README.md so travis will show up on github
|
||||
|
|
|
@ -7,7 +7,7 @@ use strict;
|
|||
use XSLoader;
|
||||
use Carp;
|
||||
|
||||
our $VERSION = '2.46';
|
||||
our $VERSION = '2.47';
|
||||
|
||||
our ( %Encoding_Table, @Encoding_Path, $have_File_Spec );
|
||||
|
||||
|
@ -1147,7 +1147,7 @@ The element declaration handlers are passed objects of this class as the
|
|||
content model of the element declaration. They also represent content
|
||||
particles, components of a content model.
|
||||
|
||||
When referred to as a string, these objects are automagicly converted to a
|
||||
When referred to as a string, these objects are automagically converted to a
|
||||
string representation of the model (or content particle).
|
||||
|
||||
=over 4
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
The Artistic License 2.0
|
||||
|
||||
Copyright (c) 1998-2000 Larry Wall and Clark Cooper
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
This license establishes the terms under which a given free software
|
||||
Package may be copied, modified, distributed, and/or redistributed.
|
||||
The intent is that the Copyright Holder maintains some artistic
|
||||
control over the development of that Package while still keeping the
|
||||
Package available as open source and free software.
|
||||
|
||||
You are always permitted to make arrangements wholly outside of this
|
||||
license directly with the Copyright Holder of a given Package. If the
|
||||
terms of this license do not permit the full use that you propose to
|
||||
make of the Package, you should contact the Copyright Holder and seek
|
||||
a different licensing arrangement.
|
||||
|
||||
Definitions
|
||||
|
||||
"Copyright Holder" means the individual(s) or organization(s)
|
||||
named in the copyright notice for the entire Package.
|
||||
|
||||
"Contributor" means any party that has contributed code or other
|
||||
material to the Package, in accordance with the Copyright Holder's
|
||||
procedures.
|
||||
|
||||
"You" and "your" means any person who would like to copy,
|
||||
distribute, or modify the Package.
|
||||
|
||||
"Package" means the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection and/or of
|
||||
those files. A given Package may consist of either the Standard
|
||||
Version, or a Modified Version.
|
||||
|
||||
"Distribute" means providing a copy of the Package or making it
|
||||
accessible to anyone else, or in the case of a company or
|
||||
organization, to others outside of your company or organization.
|
||||
|
||||
"Distributor Fee" means any fee that you charge for Distributing
|
||||
this Package or providing support for this Package to another
|
||||
party. It does not mean licensing fees.
|
||||
|
||||
"Standard Version" refers to the Package if it has not been
|
||||
modified, or has been modified only in ways explicitly requested
|
||||
by the Copyright Holder.
|
||||
|
||||
"Modified Version" means the Package, if it has been changed, and
|
||||
such changes were not explicitly requested by the Copyright
|
||||
Holder.
|
||||
|
||||
"Original License" means this Artistic License as Distributed with
|
||||
the Standard Version of the Package, in its current version or as
|
||||
it may be modified by The Perl Foundation in the future.
|
||||
|
||||
"Source" form means the source code, documentation source, and
|
||||
configuration files for the Package.
|
||||
|
||||
"Compiled" form means the compiled bytecode, object code, binary,
|
||||
or any other form resulting from mechanical transformation or
|
||||
translation of the Source form.
|
||||
|
||||
|
||||
Permission for Use and Modification Without Distribution
|
||||
|
||||
(1) You are permitted to use the Standard Version and create and use
|
||||
Modified Versions for any purpose without restriction, provided that
|
||||
you do not Distribute the Modified Version.
|
||||
|
||||
|
||||
Permissions for Redistribution of the Standard Version
|
||||
|
||||
(2) You may Distribute verbatim copies of the Source form of the
|
||||
Standard Version of this Package in any medium without restriction,
|
||||
either gratis or for a Distributor Fee, provided that you duplicate
|
||||
all of the original copyright notices and associated disclaimers. At
|
||||
your discretion, such verbatim copies may or may not include a
|
||||
Compiled form of the Package.
|
||||
|
||||
(3) You may apply any bug fixes, portability changes, and other
|
||||
modifications made available from the Copyright Holder. The resulting
|
||||
Package will still be considered the Standard Version, and as such
|
||||
will be subject to the Original License.
|
||||
|
||||
|
||||
Distribution of Modified Versions of the Package as Source
|
||||
|
||||
(4) You may Distribute your Modified Version as Source (either gratis
|
||||
or for a Distributor Fee, and with or without a Compiled form of the
|
||||
Modified Version) provided that you clearly document how it differs
|
||||
from the Standard Version, including, but not limited to, documenting
|
||||
any non-standard features, executables, or modules, and provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
(a) make the Modified Version available to the Copyright Holder
|
||||
of the Standard Version, under the Original License, so that the
|
||||
Copyright Holder may include your modifications in the Standard
|
||||
Version.
|
||||
|
||||
(b) ensure that installation of your Modified Version does not
|
||||
prevent the user installing or running the Standard Version. In
|
||||
addition, the Modified Version must bear a name that is different
|
||||
from the name of the Standard Version.
|
||||
|
||||
(c) allow anyone who receives a copy of the Modified Version to
|
||||
make the Source form of the Modified Version available to others
|
||||
under
|
||||
|
||||
(i) the Original License or
|
||||
|
||||
(ii) a license that permits the licensee to freely copy,
|
||||
modify and redistribute the Modified Version using the same
|
||||
licensing terms that apply to the copy that the licensee
|
||||
received, and requires that the Source form of the Modified
|
||||
Version, and of any works derived from it, be made freely
|
||||
available in that license fees are prohibited but Distributor
|
||||
Fees are allowed.
|
||||
|
||||
|
||||
Distribution of Compiled Forms of the Standard Version
|
||||
or Modified Versions without the Source
|
||||
|
||||
(5) You may Distribute Compiled forms of the Standard Version without
|
||||
the Source, provided that you include complete instructions on how to
|
||||
get the Source of the Standard Version. Such instructions must be
|
||||
valid at the time of your distribution. If these instructions, at any
|
||||
time while you are carrying out such distribution, become invalid, you
|
||||
must provide new instructions on demand or cease further distribution.
|
||||
If you provide valid instructions or cease distribution within thirty
|
||||
days after you become aware that the instructions are invalid, then
|
||||
you do not forfeit any of your rights under this license.
|
||||
|
||||
(6) You may Distribute a Modified Version in Compiled form without
|
||||
the Source, provided that you comply with Section 4 with respect to
|
||||
the Source of the Modified Version.
|
||||
|
||||
|
||||
Aggregating or Linking the Package
|
||||
|
||||
(7) You may aggregate the Package (either the Standard Version or
|
||||
Modified Version) with other packages and Distribute the resulting
|
||||
aggregation provided that you do not charge a licensing fee for the
|
||||
Package. Distributor Fees are permitted, and licensing fees for other
|
||||
components in the aggregation are permitted. The terms of this license
|
||||
apply to the use and Distribution of the Standard or Modified Versions
|
||||
as included in the aggregation.
|
||||
|
||||
(8) You are permitted to link Modified and Standard Versions with
|
||||
other works, to embed the Package in a larger work of your own, or to
|
||||
build stand-alone binary or bytecode versions of applications that
|
||||
include the Package, and Distribute the result without restriction,
|
||||
provided the result does not expose a direct interface to the Package.
|
||||
|
||||
|
||||
Items That are Not Considered Part of a Modified Version
|
||||
|
||||
(9) Works (including, but not limited to, modules and scripts) that
|
||||
merely extend or make use of the Package, do not, by themselves, cause
|
||||
the Package to be a Modified Version. In addition, such works are not
|
||||
considered parts of the Package itself, and are not subject to the
|
||||
terms of this license.
|
||||
|
||||
|
||||
General Provisions
|
||||
|
||||
(10) Any use, modification, and distribution of the Standard or
|
||||
Modified Versions is governed by this Artistic License. By using,
|
||||
modifying or distributing the Package, you accept this license. Do not
|
||||
use, modify, or distribute the Package, if you do not accept this
|
||||
license.
|
||||
|
||||
(11) If your Modified Version has been derived from a Modified
|
||||
Version made by someone other than you, you are nevertheless required
|
||||
to ensure that your Modified Version complies with the requirements of
|
||||
this license.
|
||||
|
||||
(12) This license does not grant you the right to use any trademark,
|
||||
service mark, tradename, or logo of the Copyright Holder.
|
||||
|
||||
(13) This license includes the non-exclusive, worldwide,
|
||||
free-of-charge patent license to make, have made, use, offer to sell,
|
||||
sell, import and otherwise transfer the Package with respect to any
|
||||
patent claims licensable by the Copyright Holder that are necessarily
|
||||
infringed by the Package. If you institute patent litigation
|
||||
(including a cross-claim or counterclaim) against any party alleging
|
||||
that the Package constitutes direct or contributory patent
|
||||
infringement, then this Artistic License to you shall terminate on the
|
||||
date that such litigation is filed.
|
||||
|
||||
(14) Disclaimer of Warranty:
|
||||
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
|
||||
IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
|
||||
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
25
MANIFEST
25
MANIFEST
|
@ -1,18 +1,19 @@
|
|||
inc/Devel/CheckLib.pm
|
||||
Changes Change log
|
||||
Expat/encoding.h Header file; describes *.enc structure
|
||||
Expat/Expat.pm XML::Parser::Expat module
|
||||
Expat/Expat.xs Extension library
|
||||
Expat/Makefile.PL perl MakeMaker script for XML::Parser::Expat
|
||||
Expat/encoding.h Header file; describes *.enc structure
|
||||
Expat/typemap XS typemap
|
||||
MANIFEST This file
|
||||
inc/Devel/CheckLib.pm
|
||||
LICENSE
|
||||
Makefile.PL perl MakeMaker script for XML::Parser
|
||||
MANIFEST This file
|
||||
MANIFEST.SKIP
|
||||
Parser.pm XML::Parser module
|
||||
Parser/LWPExternEnt.pl LWP based external entity handler
|
||||
Parser/Encodings/Japanese_Encodings.msg Message about Japanese encodings.
|
||||
Parser/Encodings/README Info about encoding maps
|
||||
Parser/Encodings/big5.enc Big5 binary encoding map
|
||||
Parser/Encodings/euc-kr.enc EUC-KR binary encoding map
|
||||
Parser/Encodings/ibm866.enc
|
||||
Parser/Encodings/iso-8859-15.enc ISO-8859-15 binary encoding map
|
||||
Parser/Encodings/iso-8859-2.enc ISO-8859-2 binary encoding map
|
||||
Parser/Encodings/iso-8859-3.enc ISO-8859-3 binary encoding map
|
||||
Parser/Encodings/iso-8859-4.enc ISO-8859-4 binary encoding map
|
||||
|
@ -20,7 +21,9 @@ Parser/Encodings/iso-8859-5.enc ISO-8859-5 binary encoding map
|
|||
Parser/Encodings/iso-8859-7.enc ISO-8859-7 binary encoding map
|
||||
Parser/Encodings/iso-8859-8.enc ISO-8859-8 binary encoding map
|
||||
Parser/Encodings/iso-8859-9.enc ISO-8859-9 binary encoding map
|
||||
Parser/Encodings/iso-8859-15.enc ISO-8859-15 binary encoding map
|
||||
Parser/Encodings/Japanese_Encodings.msg Message about Japanese encodings.
|
||||
Parser/Encodings/koi8-r.enc
|
||||
Parser/Encodings/README Info about encoding maps
|
||||
Parser/Encodings/windows-1250.enc cp1250-WinLatin2 binary encoding map
|
||||
Parser/Encodings/windows-1251.enc cp1251-Russian binary encoding map
|
||||
Parser/Encodings/windows-1252.enc cp1252-WinLatin1 binary encoding map
|
||||
|
@ -31,14 +34,14 @@ Parser/Encodings/x-sjis-cp932.enc x-sjis-cp932 encoding map
|
|||
Parser/Encodings/x-sjis-jdk117.enc x-sjis-jdk117 encoding map
|
||||
Parser/Encodings/x-sjis-jisx0221.enc x-sjis-jisx0221 encoding map
|
||||
Parser/Encodings/x-sjis-unicode.enc x-sjis-unicode encoding map
|
||||
Parser/Encodings/ibm866.enc
|
||||
Parser/Encodings/koi8-r.enc
|
||||
Parser/LWPExternEnt.pl LWP based external entity handler
|
||||
Parser/Style/Debug.pm Debug style parser
|
||||
Parser/Style/Objects.pm Objects style parser
|
||||
Parser/Style/Stream.pm Stream style parser
|
||||
Parser/Style/Subs.pm Subs style parser
|
||||
Parser/Style/Tree.pm Tree style parser
|
||||
README Short explanation
|
||||
README.md
|
||||
samples/canonical A utility to generate canonical XML
|
||||
samples/canontst.xml An xml document to demonstrate canonical
|
||||
samples/ctest.dtd An external DTD used by canontst.xml
|
||||
|
@ -51,12 +54,12 @@ t/cdata.t Test script
|
|||
t/decl.t Test script
|
||||
t/defaulted.t Test script
|
||||
t/encoding.t Test script
|
||||
t/ext.ent External entity for parament.t test
|
||||
t/ext2.ent External entity for parament.t test
|
||||
t/external_ent.t Test script
|
||||
t/file.t Test script
|
||||
t/file_open_scalar.t Test script
|
||||
t/finish.t Test script
|
||||
t/ext.ent External entity for parament.t test
|
||||
t/ext2.ent External entity for parament.t test
|
||||
t/foo.dtd External DTD for parament.t test
|
||||
t/namespaces.t Test script
|
||||
t/parament.t Test script
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
\.gitignore
|
||||
\.perltidyrc
|
||||
\.travis.yml
|
||||
cpanfile
|
||||
\.git/
|
||||
^MANIFEST.bak
|
||||
^MYMETA
|
||||
/MYMETA
|
||||
^Makefile$
|
||||
\.github/
|
||||
^Expat/Makefile$
|
|
@ -4,7 +4,7 @@
|
|||
"Clark Cooper (coopercc@netheaven.com)"
|
||||
],
|
||||
"dynamic_config" : 1,
|
||||
"generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010",
|
||||
"generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010",
|
||||
"license" : [
|
||||
"perl_5"
|
||||
],
|
||||
|
@ -33,7 +33,7 @@
|
|||
"runtime" : {
|
||||
"requires" : {
|
||||
"LWP::UserAgent" : "0",
|
||||
"perl" : "5.00405"
|
||||
"perl" : "5.004050"
|
||||
}
|
||||
},
|
||||
"test" : {
|
||||
|
@ -52,6 +52,6 @@
|
|||
"url" : "http://github.com/toddr/XML-Parser"
|
||||
}
|
||||
},
|
||||
"version" : "2.46",
|
||||
"x_serialization_backend" : "JSON::PP version 2.97001"
|
||||
"version" : "2.47",
|
||||
"x_serialization_backend" : "JSON::PP version 4.07"
|
||||
}
|
||||
|
|
6
META.yml
6
META.yml
|
@ -9,7 +9,7 @@ build_requires:
|
|||
configure_requires:
|
||||
ExtUtils::MakeMaker: '0'
|
||||
dynamic_config: 1
|
||||
generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010'
|
||||
generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 2.150010'
|
||||
license: perl
|
||||
meta-spec:
|
||||
url: http://module-build.sourceforge.net/META-spec-v1.4.html
|
||||
|
@ -21,9 +21,9 @@ no_index:
|
|||
- inc
|
||||
requires:
|
||||
LWP::UserAgent: '0'
|
||||
perl: '5.00405'
|
||||
perl: '5.004050'
|
||||
resources:
|
||||
bugtracker: https://github.com/toddr/XML-Parser/issues
|
||||
repository: http://github.com/toddr/XML-Parser
|
||||
version: '2.46'
|
||||
version: '2.47'
|
||||
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
|
||||
|
|
|
@ -16,7 +16,7 @@ use Carp;
|
|||
|
||||
BEGIN {
|
||||
require XML::Parser::Expat;
|
||||
$VERSION = '2.46';
|
||||
$VERSION = '2.47';
|
||||
die "Parser.pm and Expat.pm versions don't match"
|
||||
unless $VERSION eq $XML::Parser::Expat::VERSION;
|
||||
}
|
||||
|
@ -346,8 +346,8 @@ XML::Parser - A perl module for parsing XML documents
|
|||
Default => \&other);
|
||||
|
||||
open(my $fh, 'xmlgenerator |');
|
||||
$p3->parse($foo, ProtocolEncoding => 'ISO-8859-1');
|
||||
close($foo);
|
||||
$p3->parse($fh, ProtocolEncoding => 'ISO-8859-1');
|
||||
close($fh);
|
||||
|
||||
$p3->parsefile('junk.xml', ErrorContext => 3);
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ So for example the result of parsing:
|
|||
<foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
|
||||
|
||||
would be:
|
||||
|
||||
Tag Content
|
||||
==================================================================
|
||||
[foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]],
|
||||
|
|
4
README
4
README
|
@ -21,8 +21,8 @@ SYNOPSIS
|
|||
Default => \&other);
|
||||
|
||||
open(my $fh, 'xmlgenerator |');
|
||||
$p3->parse($foo, ProtocolEncoding => 'ISO-8859-1');
|
||||
close($foo);
|
||||
$p3->parse($fh, ProtocolEncoding => 'ISO-8859-1');
|
||||
close($fh);
|
||||
|
||||
$p3->parsefile('junk.xml', ErrorContext => 3);
|
||||
|
||||
|
|
|
@ -0,0 +1,491 @@
|
|||
[](https://travis-ci.org/toddr/XML-Parser)
|
||||
# NAME
|
||||
|
||||
XML::Parser - A perl module for parsing XML documents
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
use XML::Parser;
|
||||
|
||||
$p1 = XML::Parser->new(Style => 'Debug');
|
||||
$p1->parsefile('REC-xml-19980210.xml');
|
||||
$p1->parse('<foo id="me">Hello World</foo>');
|
||||
|
||||
# Alternative
|
||||
$p2 = XML::Parser->new(Handlers => {Start => \&handle_start,
|
||||
End => \&handle_end,
|
||||
Char => \&handle_char});
|
||||
$p2->parse($socket);
|
||||
|
||||
# Another alternative
|
||||
$p3 = XML::Parser->new(ErrorContext => 2);
|
||||
|
||||
$p3->setHandlers(Char => \&text,
|
||||
Default => \&other);
|
||||
|
||||
open(my $fh, 'xmlgenerator |');
|
||||
$p3->parse($fh, ProtocolEncoding => 'ISO-8859-1');
|
||||
close($fh);
|
||||
|
||||
$p3->parsefile('junk.xml', ErrorContext => 3);
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
This module provides ways to parse XML documents. It is built on top of
|
||||
[XML::Parser::Expat](https://metacpan.org/pod/XML::Parser::Expat), which is a lower level interface to James Clark's
|
||||
expat library. Each call to one of the parsing methods creates a new
|
||||
instance of XML::Parser::Expat which is then used to parse the document.
|
||||
Expat options may be provided when the XML::Parser object is created.
|
||||
These options are then passed on to the Expat object on each parse call.
|
||||
They can also be given as extra arguments to the parse methods, in which
|
||||
case they override options given at XML::Parser creation time.
|
||||
|
||||
The behavior of the parser is controlled either by `["STYLES"](#styles)` and/or
|
||||
`["HANDLERS"](#handlers)` options, or by ["setHandlers"](#sethandlers) method. These all provide
|
||||
mechanisms for XML::Parser to set the handlers needed by XML::Parser::Expat.
|
||||
If neither `Style` nor `Handlers` are specified, then parsing just
|
||||
checks the document for being well-formed.
|
||||
|
||||
When underlying handlers get called, they receive as their first parameter
|
||||
the _Expat_ object, not the Parser object.
|
||||
|
||||
# METHODS
|
||||
|
||||
- new
|
||||
|
||||
This is a class method, the constructor for XML::Parser. Options are passed
|
||||
as keyword value pairs. Recognized options are:
|
||||
|
||||
- Style
|
||||
|
||||
This option provides an easy way to create a given style of parser. The
|
||||
built in styles are: ["Debug"](#debug), ["Subs"](#subs), ["Tree"](#tree), ["Objects"](#objects),
|
||||
and ["Stream"](#stream). These are all defined in separate packages under
|
||||
`XML::Parser::Style::*`, and you can find further documentation for
|
||||
each style both below, and in those packages.
|
||||
|
||||
Custom styles can be provided by giving a full package name containing
|
||||
at least one '::'. This package should then have subs defined for each
|
||||
handler it wishes to have installed. See ["STYLES"](#styles) below
|
||||
for a discussion of each built in style.
|
||||
|
||||
- Handlers
|
||||
|
||||
When provided, this option should be an anonymous hash containing as
|
||||
keys the type of handler and as values a sub reference to handle that
|
||||
type of event. All the handlers get passed as their 1st parameter the
|
||||
instance of expat that is parsing the document. Further details on
|
||||
handlers can be found in ["HANDLERS"](#handlers). Any handler set here
|
||||
overrides the corresponding handler set with the Style option.
|
||||
|
||||
- Pkg
|
||||
|
||||
Some styles will refer to subs defined in this package. If not provided,
|
||||
it defaults to the package which called the constructor.
|
||||
|
||||
- ErrorContext
|
||||
|
||||
This is an Expat option. When this option is defined, errors are reported
|
||||
in context. The value should be the number of lines to show on either side
|
||||
of the line in which the error occurred.
|
||||
|
||||
- ProtocolEncoding
|
||||
|
||||
This is an Expat option. This sets the protocol encoding name. It defaults
|
||||
to none. The built-in encodings are: `UTF-8`, `ISO-8859-1`, `UTF-16`, and
|
||||
`US-ASCII`. Other encodings may be used if they have encoding maps in one
|
||||
of the directories in the @Encoding\_Path list. Check ["ENCODINGS"](#encodings) for
|
||||
more information on encoding maps. Setting the protocol encoding overrides
|
||||
any encoding in the XML declaration.
|
||||
|
||||
- Namespaces
|
||||
|
||||
This is an Expat option. If this is set to a true value, then namespace
|
||||
processing is done during the parse. See ["Namespaces" in XML::Parser::Expat](https://metacpan.org/pod/XML::Parser::Expat#Namespaces)
|
||||
for further discussion of namespace processing.
|
||||
|
||||
- NoExpand
|
||||
|
||||
This is an Expat option. Normally, the parser will try to expand references
|
||||
to entities defined in the internal subset. If this option is set to a true
|
||||
value, and a default handler is also set, then the default handler will be
|
||||
called when an entity reference is seen in text. This has no effect if a
|
||||
default handler has not been registered, and it has no effect on the expansion
|
||||
of entity references inside attribute values.
|
||||
|
||||
- Stream\_Delimiter
|
||||
|
||||
This is an Expat option. It takes a string value. When this string is found
|
||||
alone on a line while parsing from a stream, then the parse is ended as if it
|
||||
saw an end of file. The intended use is with a stream of xml documents in a
|
||||
MIME multipart format. The string should not contain a trailing newline.
|
||||
|
||||
- ParseParamEnt
|
||||
|
||||
This is an Expat option. Unless standalone is set to "yes" in the XML
|
||||
declaration, setting this to a true value allows the external DTD to be read,
|
||||
and parameter entities to be parsed and expanded.
|
||||
|
||||
- NoLWP
|
||||
|
||||
This option has no effect if the ExternEnt or ExternEntFin handlers are
|
||||
directly set. Otherwise, if true, it forces the use of a file based external
|
||||
entity handler.
|
||||
|
||||
- Non\_Expat\_Options
|
||||
|
||||
If provided, this should be an anonymous hash whose keys are options that
|
||||
shouldn't be passed to Expat. This should only be of concern to those
|
||||
subclassing XML::Parser.
|
||||
|
||||
- setHandlers(TYPE, HANDLER \[, TYPE, HANDLER \[...\]\])
|
||||
|
||||
This method registers handlers for various parser events. It overrides any
|
||||
previous handlers registered through the Style or Handler options or through
|
||||
earlier calls to setHandlers. By providing a false or undefined value as
|
||||
the handler, the existing handler can be unset.
|
||||
|
||||
This method returns a list of type, handler pairs corresponding to the
|
||||
input. The handlers returned are the ones that were in effect prior to
|
||||
the call.
|
||||
|
||||
See a description of the handler types in ["HANDLERS"](#handlers).
|
||||
|
||||
- parse(SOURCE \[, OPT => OPT\_VALUE \[...\]\])
|
||||
|
||||
The SOURCE parameter should either be a string containing the whole XML
|
||||
document, or it should be an open IO::Handle. Constructor options to
|
||||
XML::Parser::Expat given as keyword-value pairs may follow the SOURCE
|
||||
parameter. These override, for this call, any options or attributes passed
|
||||
through from the XML::Parser instance.
|
||||
|
||||
A die call is thrown if a parse error occurs. Otherwise it will return 1
|
||||
or whatever is returned from the **Final** handler, if one is installed.
|
||||
In other words, what parse may return depends on the style.
|
||||
|
||||
- parsestring
|
||||
|
||||
This is just an alias for parse for backwards compatibility.
|
||||
|
||||
- parsefile(FILE \[, OPT => OPT\_VALUE \[...\]\])
|
||||
|
||||
Open FILE for reading, then call parse with the open handle. The file
|
||||
is closed no matter how parse returns. Returns what parse returns.
|
||||
|
||||
- parse\_start(\[ OPT => OPT\_VALUE \[...\]\])
|
||||
|
||||
Create and return a new instance of XML::Parser::ExpatNB. Constructor
|
||||
options may be provided. If an init handler has been provided, it is
|
||||
called before returning the ExpatNB object. Documents are parsed by
|
||||
making incremental calls to the parse\_more method of this object, which
|
||||
takes a string. A single call to the parse\_done method of this object,
|
||||
which takes no arguments, indicates that the document is finished.
|
||||
|
||||
If there is a final handler installed, it is executed by the parse\_done
|
||||
method before returning and the parse\_done method returns whatever is
|
||||
returned by the final handler.
|
||||
|
||||
# HANDLERS
|
||||
|
||||
Expat is an event based parser. As the parser recognizes parts of the
|
||||
document (say the start or end tag for an XML element), then any handlers
|
||||
registered for that type of an event are called with suitable parameters.
|
||||
All handlers receive an instance of XML::Parser::Expat as their first
|
||||
argument. See ["METHODS" in XML::Parser::Expat](https://metacpan.org/pod/XML::Parser::Expat#METHODS) for a discussion of the
|
||||
methods that can be called on this object.
|
||||
|
||||
## Init (Expat)
|
||||
|
||||
This is called just before the parsing of the document starts.
|
||||
|
||||
## Final (Expat)
|
||||
|
||||
This is called just after parsing has finished, but only if no errors
|
||||
occurred during the parse. Parse returns what this returns.
|
||||
|
||||
## Start (Expat, Element \[, Attr, Val \[,...\]\])
|
||||
|
||||
This event is generated when an XML start tag is recognized. Element is the
|
||||
name of the XML element type that is opened with the start tag. The Attr &
|
||||
Val pairs are generated for each attribute in the start tag.
|
||||
|
||||
## End (Expat, Element)
|
||||
|
||||
This event is generated when an XML end tag is recognized. Note that
|
||||
an XML empty tag (<foo/>) generates both a start and an end event.
|
||||
|
||||
## Char (Expat, String)
|
||||
|
||||
This event is generated when non-markup is recognized. The non-markup
|
||||
sequence of characters is in String. A single non-markup sequence of
|
||||
characters may generate multiple calls to this handler. Whatever the
|
||||
encoding of the string in the original document, this is given to the
|
||||
handler in UTF-8.
|
||||
|
||||
## Proc (Expat, Target, Data)
|
||||
|
||||
This event is generated when a processing instruction is recognized.
|
||||
|
||||
## Comment (Expat, Data)
|
||||
|
||||
This event is generated when a comment is recognized.
|
||||
|
||||
## CdataStart (Expat)
|
||||
|
||||
This is called at the start of a CDATA section.
|
||||
|
||||
## CdataEnd (Expat)
|
||||
|
||||
This is called at the end of a CDATA section.
|
||||
|
||||
## Default (Expat, String)
|
||||
|
||||
This is called for any characters that don't have a registered handler.
|
||||
This includes both characters that are part of markup for which no
|
||||
events are generated (markup declarations) and characters that
|
||||
could generate events, but for which no handler has been registered.
|
||||
|
||||
Whatever the encoding in the original document, the string is returned to
|
||||
the handler in UTF-8.
|
||||
|
||||
## Unparsed (Expat, Entity, Base, Sysid, Pubid, Notation)
|
||||
|
||||
This is called for a declaration of an unparsed entity. Entity is the name
|
||||
of the entity. Base is the base to be used for resolving a relative URI.
|
||||
Sysid is the system id. Pubid is the public id. Notation is the notation
|
||||
name. Base and Pubid may be undefined.
|
||||
|
||||
## Notation (Expat, Notation, Base, Sysid, Pubid)
|
||||
|
||||
This is called for a declaration of notation. Notation is the notation name.
|
||||
Base is the base to be used for resolving a relative URI. Sysid is the system
|
||||
id. Pubid is the public id. Base, Sysid, and Pubid may all be undefined.
|
||||
|
||||
## ExternEnt (Expat, Base, Sysid, Pubid)
|
||||
|
||||
This is called when an external entity is referenced. Base is the base to be
|
||||
used for resolving a relative URI. Sysid is the system id. Pubid is the public
|
||||
id. Base, and Pubid may be undefined.
|
||||
|
||||
This handler should either return a string, which represents the contents of
|
||||
the external entity, or return an open filehandle that can be read to obtain
|
||||
the contents of the external entity, or return undef, which indicates the
|
||||
external entity couldn't be found and will generate a parse error.
|
||||
|
||||
If an open filehandle is returned, it must be returned as either a glob
|
||||
(\*FOO) or as a reference to a glob (e.g. an instance of IO::Handle).
|
||||
|
||||
A default handler is installed for this event. The default handler is
|
||||
XML::Parser::lwp\_ext\_ent\_handler unless the NoLWP option was provided with
|
||||
a true value, otherwise XML::Parser::file\_ext\_ent\_handler is the default
|
||||
handler for external entities. Even without the NoLWP option, if the
|
||||
URI or LWP modules are missing, the file based handler ends up being used
|
||||
after giving a warning on the first external entity reference.
|
||||
|
||||
The LWP external entity handler will use proxies defined in the environment
|
||||
(http\_proxy, ftp\_proxy, etc.).
|
||||
|
||||
Please note that the LWP external entity handler reads the entire
|
||||
entity into a string and returns it, where as the file handler opens a
|
||||
filehandle.
|
||||
|
||||
Also note that the file external entity handler will likely choke on
|
||||
absolute URIs or file names that don't fit the conventions of the local
|
||||
operating system.
|
||||
|
||||
The expat base method can be used to set a basename for
|
||||
relative pathnames. If no basename is given, or if the basename is itself
|
||||
a relative name, then it is relative to the current working directory.
|
||||
|
||||
## ExternEntFin (Expat)
|
||||
|
||||
This is called after parsing an external entity. It's not called unless
|
||||
an ExternEnt handler is also set. There is a default handler installed
|
||||
that pairs with the default ExternEnt handler.
|
||||
|
||||
If you're going to install your own ExternEnt handler, then you should
|
||||
set (or unset) this handler too.
|
||||
|
||||
## Entity (Expat, Name, Val, Sysid, Pubid, Ndata, IsParam)
|
||||
|
||||
This is called when an entity is declared. For internal entities, the Val
|
||||
parameter will contain the value and the remaining three parameters will be
|
||||
undefined. For external entities, the Val parameter will be undefined, the
|
||||
Sysid parameter will have the system id, the Pubid parameter will have the
|
||||
public id if it was provided (it will be undefined otherwise), the Ndata
|
||||
parameter will contain the notation for unparsed entities. If this is a
|
||||
parameter entity declaration, then the IsParam parameter is true.
|
||||
|
||||
Note that this handler and the Unparsed handler above overlap. If both are
|
||||
set, then this handler will not be called for unparsed entities.
|
||||
|
||||
## Element (Expat, Name, Model)
|
||||
|
||||
The element handler is called when an element declaration is found. Name
|
||||
is the element name, and Model is the content model as an XML::Parser::Content
|
||||
object. See ["XML::Parser::ContentModel Methods" in XML::Parser::Expat](https://metacpan.org/pod/XML::Parser::Expat#XML::Parser::ContentModel-Methods)
|
||||
for methods available for this class.
|
||||
|
||||
## Attlist (Expat, Elname, Attname, Type, Default, Fixed)
|
||||
|
||||
This handler is called for each attribute in an ATTLIST declaration.
|
||||
So an ATTLIST declaration that has multiple attributes will generate multiple
|
||||
calls to this handler. The Elname parameter is the name of the element with
|
||||
which the attribute is being associated. The Attname parameter is the name
|
||||
of the attribute. Type is the attribute type, given as a string. Default is
|
||||
the default value, which will either be "#REQUIRED", "#IMPLIED" or a quoted
|
||||
string (i.e. the returned string will begin and end with a quote character).
|
||||
If Fixed is true, then this is a fixed attribute.
|
||||
|
||||
## Doctype (Expat, Name, Sysid, Pubid, Internal)
|
||||
|
||||
This handler is called for DOCTYPE declarations. Name is the document type
|
||||
name. Sysid is the system id of the document type, if it was provided,
|
||||
otherwise it's undefined. Pubid is the public id of the document type,
|
||||
which will be undefined if no public id was given. Internal is the internal
|
||||
subset, given as a string. If there was no internal subset, it will be
|
||||
undefined. Internal will contain all whitespace, comments, processing
|
||||
instructions, and declarations seen in the internal subset. The declarations
|
||||
will be there whether or not they have been processed by another handler
|
||||
(except for unparsed entities processed by the Unparsed handler). However,
|
||||
comments and processing instructions will not appear if they've been processed
|
||||
by their respective handlers.
|
||||
|
||||
## \* DoctypeFin (Parser)
|
||||
|
||||
This handler is called after parsing of the DOCTYPE declaration has finished,
|
||||
including any internal or external DTD declarations.
|
||||
|
||||
## XMLDecl (Expat, Version, Encoding, Standalone)
|
||||
|
||||
This handler is called for xml declarations. Version is a string containing
|
||||
the version. Encoding is either undefined or contains an encoding string.
|
||||
Standalone will be either true, false, or undefined if the standalone attribute
|
||||
is yes, no, or not made respectively.
|
||||
|
||||
# STYLES
|
||||
|
||||
## Debug
|
||||
|
||||
This just prints out the document in outline form. Nothing special is
|
||||
returned by parse.
|
||||
|
||||
## Subs
|
||||
|
||||
Each time an element starts, a sub by that name in the package specified
|
||||
by the Pkg option is called with the same parameters that the Start
|
||||
handler gets called with.
|
||||
|
||||
Each time an element ends, a sub with that name appended with an underscore
|
||||
("\_"), is called with the same parameters that the End handler gets called
|
||||
with.
|
||||
|
||||
Nothing special is returned by parse.
|
||||
|
||||
## Tree
|
||||
|
||||
Parse will return a parse tree for the document. Each node in the tree
|
||||
takes the form of a tag, content pair. Text nodes are represented with
|
||||
a pseudo-tag of "0" and the string that is their content. For elements,
|
||||
the content is an array reference. The first item in the array is a
|
||||
(possibly empty) hash reference containing attributes. The remainder of
|
||||
the array is a sequence of tag-content pairs representing the content
|
||||
of the element.
|
||||
|
||||
So for example the result of parsing:
|
||||
|
||||
<foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
|
||||
|
||||
would be:
|
||||
|
||||
Tag Content
|
||||
==================================================================
|
||||
[foo, [{}, head, [{id => "a"}, 0, "Hello ", em, [{}, 0, "there"]],
|
||||
bar, [ {}, 0, "Howdy", ref, [{}]],
|
||||
0, "do"
|
||||
]
|
||||
]
|
||||
|
||||
The root document "foo", has 3 children: a "head" element, a "bar"
|
||||
element and the text "do". After the empty attribute hash, these are
|
||||
represented in it's contents by 3 tag-content pairs.
|
||||
|
||||
## Objects
|
||||
|
||||
This is similar to the Tree style, except that a hash object is created for
|
||||
each element. The corresponding object will be in the class whose name
|
||||
is created by appending "::" and the element name to the package set with
|
||||
the Pkg option. Non-markup text will be in the ::Characters class. The
|
||||
contents of the corresponding object will be in an anonymous array that
|
||||
is the value of the Kids property for that object.
|
||||
|
||||
## Stream
|
||||
|
||||
This style also uses the Pkg package. If none of the subs that this
|
||||
style looks for is there, then the effect of parsing with this style is
|
||||
to print a canonical copy of the document without comments or declarations.
|
||||
All the subs receive as their 1st parameter the Expat instance for the
|
||||
document they're parsing.
|
||||
|
||||
It looks for the following routines:
|
||||
|
||||
- StartDocument
|
||||
|
||||
Called at the start of the parse .
|
||||
|
||||
- StartTag
|
||||
|
||||
Called for every start tag with a second parameter of the element type. The $\_
|
||||
variable will contain a copy of the tag and the %\_ variable will contain
|
||||
attribute values supplied for that element.
|
||||
|
||||
- EndTag
|
||||
|
||||
Called for every end tag with a second parameter of the element type. The $\_
|
||||
variable will contain a copy of the end tag.
|
||||
|
||||
- Text
|
||||
|
||||
Called just before start or end tags with accumulated non-markup text in
|
||||
the $\_ variable.
|
||||
|
||||
- PI
|
||||
|
||||
Called for processing instructions. The $\_ variable will contain a copy of
|
||||
the PI and the target and data are sent as 2nd and 3rd parameters
|
||||
respectively.
|
||||
|
||||
- EndDocument
|
||||
|
||||
Called at conclusion of the parse.
|
||||
|
||||
# ENCODINGS
|
||||
|
||||
XML documents may be encoded in character sets other than Unicode as
|
||||
long as they may be mapped into the Unicode character set. Expat has
|
||||
further restrictions on encodings. Read the xmlparse.h header file in
|
||||
the expat distribution to see details on these restrictions.
|
||||
|
||||
Expat has built-in encodings for: `UTF-8`, `ISO-8859-1`, `UTF-16`, and
|
||||
`US-ASCII`. Encodings are set either through the XML declaration
|
||||
encoding attribute or through the ProtocolEncoding option to XML::Parser
|
||||
or XML::Parser::Expat.
|
||||
|
||||
For encodings other than the built-ins, expat calls the function
|
||||
load\_encoding in the Expat package with the encoding name. This function
|
||||
looks for a file in the path list @XML::Parser::Expat::Encoding\_Path, that
|
||||
matches the lower-cased name with a '.enc' extension. The first one it
|
||||
finds, it loads.
|
||||
|
||||
If you wish to build your own encoding maps, check out the XML::Encoding
|
||||
module from CPAN.
|
||||
|
||||
# AUTHORS
|
||||
|
||||
Larry Wall <`larry@wall.org`> wrote version 1.0.
|
||||
|
||||
Clark Cooper <`coopercc@netheaven.com`> picked up support, changed the API
|
||||
for this version (2.x), provided documentation,
|
||||
and added some standard package features.
|
||||
|
||||
Matt Sergeant <`matt@sergeant.org`> is now maintaining XML::Parser
|
|
@ -5,9 +5,9 @@ package Devel::CheckLib;
|
|||
use 5.00405; #postfix foreach
|
||||
use strict;
|
||||
use vars qw($VERSION @ISA @EXPORT);
|
||||
$VERSION = '0.99';
|
||||
$VERSION = '1.16';
|
||||
use Config qw(%Config);
|
||||
use Text::ParseWords 'quotewords';
|
||||
use Text::ParseWords qw(quotewords shellwords);
|
||||
|
||||
use File::Spec;
|
||||
use File::Temp;
|
||||
|
@ -54,7 +54,7 @@ and link to the libraries.
|
|||
|
||||
It works by trying to compile some code - which defaults to this:
|
||||
|
||||
int main(void) { return 0; }
|
||||
int main(int argc, char *argv[]) { return 0; }
|
||||
|
||||
and linking it to the specified libraries. If something pops out the end
|
||||
which looks executable, it gets executed, and if main() returns 0 we know
|
||||
|
@ -109,7 +109,7 @@ representing additional paths to search for libraries.
|
|||
|
||||
=item LIBS
|
||||
|
||||
a C<ExtUtils::MakeMaker>-style space-seperated list of
|
||||
a C<ExtUtils::MakeMaker>-style space-separated list of
|
||||
libraries (each preceded by '-l') and directories (preceded by '-L').
|
||||
|
||||
This can also be supplied on the command-line.
|
||||
|
@ -137,11 +137,32 @@ representing additional paths to search for headers.
|
|||
|
||||
=item INC
|
||||
|
||||
a C<ExtUtils::MakeMaker>-style space-seperated list of
|
||||
a C<ExtUtils::MakeMaker>-style space-separated list of
|
||||
incpaths, each preceded by '-I'.
|
||||
|
||||
This can also be supplied on the command-line.
|
||||
|
||||
=item ccflags
|
||||
|
||||
Extra flags to pass to the compiler.
|
||||
|
||||
=item ldflags
|
||||
|
||||
Extra flags to pass to the linker.
|
||||
|
||||
=item analyze_binary
|
||||
|
||||
a callback function that will be invoked in order to perform custom
|
||||
analysis of the generated binary. The callback arguments are the
|
||||
library name and the path to the binary just compiled.
|
||||
|
||||
It is possible to use this callback, for instance, to inspect the
|
||||
binary for further dependencies.
|
||||
|
||||
=item not_execute
|
||||
|
||||
Do not try to execute generated binary. Only check that compilation has not failed.
|
||||
|
||||
=back
|
||||
|
||||
=head2 check_lib_or_exit
|
||||
|
@ -166,7 +187,7 @@ returning false instead of dieing, or true otherwise.
|
|||
|
||||
sub check_lib_or_exit {
|
||||
eval 'assert_lib(@_)';
|
||||
if ($@) {
|
||||
if($@) {
|
||||
warn $@;
|
||||
exit;
|
||||
}
|
||||
|
@ -177,26 +198,150 @@ sub check_lib {
|
|||
return $@ ? 0 : 1;
|
||||
}
|
||||
|
||||
# borrowed from Text::ParseWords
|
||||
sub _parse_line {
|
||||
my($delimiter, $keep, $line) = @_;
|
||||
my($word, @pieces);
|
||||
|
||||
no warnings 'uninitialized'; # we will be testing undef strings
|
||||
|
||||
while (length($line)) {
|
||||
# This pattern is optimised to be stack conservative on older perls.
|
||||
# Do not refactor without being careful and testing it on very long strings.
|
||||
# See Perl bug #42980 for an example of a stack busting input.
|
||||
$line =~ s/^
|
||||
(?:
|
||||
# double quoted string
|
||||
(") # $quote
|
||||
((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted
|
||||
| # --OR--
|
||||
# singe quoted string
|
||||
(') # $quote
|
||||
((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted
|
||||
| # --OR--
|
||||
# unquoted string
|
||||
( # $unquoted
|
||||
(?:\\.|[^\\"'])*?
|
||||
)
|
||||
# followed by
|
||||
( # $delim
|
||||
\Z(?!\n) # EOL
|
||||
| # --OR--
|
||||
(?-x:$delimiter) # delimiter
|
||||
| # --OR--
|
||||
(?!^)(?=["']) # a quote
|
||||
)
|
||||
)//xs or return; # extended layout
|
||||
my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6);
|
||||
|
||||
return() unless( defined($quote) || length($unquoted) || length($delim));
|
||||
|
||||
if ($keep) {
|
||||
$quoted = "$quote$quoted$quote";
|
||||
}
|
||||
else {
|
||||
$unquoted =~ s/\\(.)/$1/sg;
|
||||
if (defined $quote) {
|
||||
$quoted =~ s/\\(.)/$1/sg if ($quote eq '"');
|
||||
}
|
||||
}
|
||||
$word .= substr($line, 0, 0); # leave results tainted
|
||||
$word .= defined $quote ? $quoted : $unquoted;
|
||||
|
||||
if (length($delim)) {
|
||||
push(@pieces, $word);
|
||||
push(@pieces, $delim) if ($keep eq 'delimiters');
|
||||
undef $word;
|
||||
}
|
||||
if (!length($line)) {
|
||||
push(@pieces, $word);
|
||||
}
|
||||
}
|
||||
return(@pieces);
|
||||
}
|
||||
|
||||
sub _parsewords {
|
||||
return shellwords @_ if $^O ne 'MSWin32';
|
||||
# for Win32, take off "" but leave \
|
||||
map { my $s=$_; $s =~ s/^"(.*)"$/$1/; $s } grep defined && length, quotewords '\s+', 1, @_;
|
||||
}
|
||||
|
||||
sub _compile_cmd {
|
||||
my ($Config_cc, $cc, $cfile, $exefile, $incpaths, $ld, $Config_libs, $lib, $libpaths) = @_;
|
||||
my @sys_cmd = @$cc;
|
||||
if ( $Config_cc eq 'cl' ) { # Microsoft compiler
|
||||
# this is horribly sensitive to the order of arguments
|
||||
push @sys_cmd,
|
||||
$cfile,
|
||||
(defined $lib ? "${lib}.lib" : ()),
|
||||
"/Fe$exefile",
|
||||
(map '/I'.$_, @$incpaths),
|
||||
"/link",
|
||||
@$ld,
|
||||
_parsewords($Config_libs),
|
||||
(defined $lib ? map '/libpath:'.$_, @$libpaths : ()),
|
||||
;
|
||||
} elsif($Config_cc =~ /bcc32(\.exe)?/) { # Borland
|
||||
push @sys_cmd,
|
||||
@$ld,
|
||||
(map "-I$_", @$incpaths),
|
||||
"-o$exefile",
|
||||
(defined $lib ? ((map "-L$_", @$libpaths), "-l$lib") : ()),
|
||||
$cfile,
|
||||
;
|
||||
} else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
|
||||
push @sys_cmd,
|
||||
(map "-I$_", @$incpaths),
|
||||
$cfile,
|
||||
(!defined $lib ? () : (
|
||||
(map "-L$_", @$libpaths),
|
||||
($^O eq 'darwin' ? (map { "-Wl,-rpath,$_" } @$libpaths) : ()),
|
||||
"-l$lib",
|
||||
)),
|
||||
@$ld,
|
||||
"-o", $exefile,
|
||||
;
|
||||
}
|
||||
@sys_cmd;
|
||||
}
|
||||
|
||||
sub _make_cfile {
|
||||
my ($use_headers, $function, $debug) = @_;
|
||||
my $code = '';
|
||||
$code .= qq{#include <$_>\n} for @$use_headers;
|
||||
$code .= "int main(int argc, char *argv[]) { ".($function || 'return 0;')." }\n";
|
||||
if ($debug) {
|
||||
(my $c = $code) =~ s:^:# :gm;
|
||||
warn "# Code:\n$c\n";
|
||||
}
|
||||
my ($ch, $cfile) = File::Temp::tempfile(
|
||||
'assertlibXXXXXXXX', SUFFIX => '.c'
|
||||
);
|
||||
print $ch $code;
|
||||
close $ch;
|
||||
(my $ofile = $cfile) =~ s/\.c$/$Config{_o}/;
|
||||
($cfile, $ofile);
|
||||
}
|
||||
|
||||
sub assert_lib {
|
||||
my %args = @_;
|
||||
my ( @libs, @libpaths, @headers, @incpaths );
|
||||
$args{$_} = [$args{$_}]
|
||||
for grep $args{$_} && !ref($args{$_}), qw(lib libpath header incpath);
|
||||
my @libs = @{$args{lib} || []};
|
||||
my @libpaths = @{$args{libpath} || []};
|
||||
my @headers = @{$args{header} || []};
|
||||
my @incpaths = @{$args{incpath} || []};
|
||||
my $analyze_binary = $args{analyze_binary};
|
||||
my $execute = !$args{not_execute};
|
||||
|
||||
# FIXME: these four just SCREAM "refactor" at me
|
||||
@libs = ( ref( $args{lib} ) ? @{ $args{lib} } : $args{lib} )
|
||||
if $args{lib};
|
||||
@libpaths = ( ref( $args{libpath} ) ? @{ $args{libpath} } : $args{libpath} )
|
||||
if $args{libpath};
|
||||
@headers = ( ref( $args{header} ) ? @{ $args{header} } : $args{header} )
|
||||
if $args{header};
|
||||
@incpaths = ( ref( $args{incpath} ) ? @{ $args{incpath} } : $args{incpath} )
|
||||
if $args{incpath};
|
||||
my @argv = @ARGV;
|
||||
push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||'');
|
||||
|
||||
# work-a-like for Makefile.PL's LIBS and INC arguments
|
||||
# if given as command-line argument, append to %args
|
||||
for my $arg (@ARGV) {
|
||||
for my $arg (@argv) {
|
||||
for my $mm_attr_key (qw(LIBS INC)) {
|
||||
if ( my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x ) {
|
||||
|
||||
if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
|
||||
# it is tempting to put some \s* into the expression, but the
|
||||
# MM command-line parser only accepts LIBS etc. followed by =,
|
||||
# so we should not be any more lenient with whitespace than that
|
||||
|
@ -205,187 +350,149 @@ sub assert_lib {
|
|||
}
|
||||
}
|
||||
|
||||
# using special form of split to trim whitespace
|
||||
if ( defined( $args{LIBS} ) ) {
|
||||
foreach my $arg ( split( ' ', $args{LIBS} ) ) {
|
||||
die("LIBS argument badly-formed: $arg\n") unless ( $arg =~ /^-[lLR]/ );
|
||||
push @{ $arg =~ /^-l/ ? \@libs : \@libpaths }, substr( $arg, 2 );
|
||||
if(defined($args{LIBS})) {
|
||||
foreach my $arg (_parsewords($args{LIBS})) {
|
||||
die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/);
|
||||
push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2);
|
||||
}
|
||||
}
|
||||
if ( defined( $args{INC} ) ) {
|
||||
foreach my $arg ( split( ' ', $args{INC} ) ) {
|
||||
die("INC argument badly-formed: $arg\n") unless ( $arg =~ /^-I/ );
|
||||
push @incpaths, substr( $arg, 2 );
|
||||
if(defined($args{INC})) {
|
||||
foreach my $arg (_parsewords($args{INC})) {
|
||||
die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
|
||||
push @incpaths, substr($arg, 2);
|
||||
}
|
||||
}
|
||||
|
||||
my ( $cc, $ld ) = _findcc();
|
||||
my ($cc, $ld) = _findcc($args{debug}, $args{ccflags}, $args{ldflags});
|
||||
my @missing;
|
||||
my @wrongresult;
|
||||
my @wronganalysis;
|
||||
my @use_headers;
|
||||
|
||||
# first figure out which headers we can't find ...
|
||||
for my $header (@headers) {
|
||||
push @use_headers, $header;
|
||||
my ( $ch, $cfile ) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' );
|
||||
my $ofile = $cfile;
|
||||
$ofile =~ s/\.c$/$Config{_o}/;
|
||||
print $ch qq{#include <$_>\n} for @use_headers;
|
||||
print $ch qq{int main(void) { return 0; }\n};
|
||||
close($ch);
|
||||
my $exefile = File::Temp::mktemp('assertlibXXXXXXXX') . $Config{_exe};
|
||||
my @sys_cmd;
|
||||
|
||||
# FIXME: re-factor - almost identical code later when linking
|
||||
if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
|
||||
require Win32;
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
$cfile,
|
||||
"/Fe$exefile",
|
||||
( map { '/I' . Win32::GetShortPathName($_) } @incpaths ),
|
||||
"/link",
|
||||
@$ld
|
||||
);
|
||||
}
|
||||
elsif ( $Config{cc} =~ /bcc32(\.exe)?/ ) { # Borland
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
@$ld,
|
||||
( map { "-I$_" } @incpaths ),
|
||||
"-o$exefile",
|
||||
$cfile
|
||||
);
|
||||
}
|
||||
else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
@$ld,
|
||||
$cfile,
|
||||
( map { "-I$_" } @incpaths ),
|
||||
"-o", "$exefile"
|
||||
);
|
||||
}
|
||||
my ($cfile, $ofile) = _make_cfile(\@use_headers, '', $args{debug});
|
||||
my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
|
||||
my @sys_cmd = _compile_cmd($Config{cc}, $cc, $cfile, $exefile, \@incpaths, $ld, $Config{libs});
|
||||
warn "# @sys_cmd\n" if $args{debug};
|
||||
my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
|
||||
push @missing, $header if $rv != 0 || !-x $exefile;
|
||||
push @missing, $header if $rv != 0 || ! -f $exefile;
|
||||
_cleanup_exe($exefile);
|
||||
unlink $ofile if -e $ofile;
|
||||
unlink $cfile;
|
||||
}
|
||||
|
||||
# now do each library in turn with headers
|
||||
my ( $ch, $cfile ) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' );
|
||||
my $ofile = $cfile;
|
||||
$ofile =~ s/\.c$/$Config{_o}/;
|
||||
print $ch qq{#include <$_>\n} foreach (@headers);
|
||||
print $ch "int main(void) { " . ( $args{function} || 'return 0;' ) . " }\n";
|
||||
close($ch);
|
||||
for my $lib (@libs) {
|
||||
my $exefile = File::Temp::mktemp('assertlibXXXXXXXX') . $Config{_exe};
|
||||
my @sys_cmd;
|
||||
if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
|
||||
require Win32;
|
||||
my @libpath = map { q{/libpath:} . Win32::GetShortPathName($_) } @libpaths;
|
||||
|
||||
# this is horribly sensitive to the order of arguments
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
$cfile,
|
||||
"${lib}.lib",
|
||||
"/Fe$exefile",
|
||||
( map { '/I' . Win32::GetShortPathName($_) } @incpaths ),
|
||||
"/link",
|
||||
@$ld,
|
||||
( map { '/libpath:' . Win32::GetShortPathName($_) } @libpaths ),
|
||||
);
|
||||
}
|
||||
elsif ( $Config{cc} eq 'CC/DECC' ) { # VMS
|
||||
}
|
||||
elsif ( $Config{cc} =~ /bcc32(\.exe)?/ ) { # Borland
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
@$ld,
|
||||
"-o$exefile",
|
||||
( map { "-I$_" } @incpaths ),
|
||||
( map { "-L$_" } @libpaths ),
|
||||
"-l$lib",
|
||||
$cfile
|
||||
);
|
||||
}
|
||||
else { # Unix-ish
|
||||
# gcc, Sun, AIX (gcc, cc)
|
||||
@sys_cmd = (
|
||||
@$cc,
|
||||
@$ld,
|
||||
$cfile,
|
||||
"-o", "$exefile",
|
||||
( map { "-I$_" } @incpaths ),
|
||||
( map { "-L$_" } @libpaths ),
|
||||
"-l$lib",
|
||||
);
|
||||
}
|
||||
my ($cfile, $ofile) = _make_cfile(\@use_headers, @args{qw(function debug)});
|
||||
for my $lib ( @libs ) {
|
||||
last if $Config{cc} eq 'CC/DECC'; # VMS
|
||||
my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
|
||||
my @sys_cmd = _compile_cmd($Config{cc}, $cc, $cfile, $exefile, \@incpaths, $ld, $Config{libs}, $lib, \@libpaths);
|
||||
warn "# @sys_cmd\n" if $args{debug};
|
||||
local $ENV{LD_RUN_PATH} = join(":", grep $_, @libpaths, $ENV{LD_RUN_PATH}) unless $^O eq 'MSWin32' or $^O eq 'darwin';
|
||||
local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32';
|
||||
my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
|
||||
push @missing, $lib if $rv != 0 || !-x $exefile;
|
||||
if ($rv != 0 || ! -f $exefile) {
|
||||
push @missing, $lib;
|
||||
}
|
||||
else {
|
||||
chmod 0755, $exefile;
|
||||
my $absexefile = File::Spec->rel2abs($exefile);
|
||||
$absexefile = '"' . $absexefile . '"' if $absexefile =~ m/\s/;
|
||||
push @wrongresult, $lib if $rv == 0 && -x $exefile && system($absexefile) != 0;
|
||||
unlink $ofile if -e $ofile;
|
||||
$absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/;
|
||||
warn "# Execute($execute): $absexefile\n" if $args{debug};
|
||||
if ($execute) {
|
||||
my $retval = system($absexefile);
|
||||
warn "# return value: $retval\n" if $args{debug};
|
||||
push @wrongresult, $lib if $retval != 0;
|
||||
}
|
||||
push @wronganalysis, $lib
|
||||
if $analyze_binary and !$analyze_binary->($lib, $exefile);
|
||||
}
|
||||
_cleanup_exe($exefile);
|
||||
}
|
||||
unlink $cfile;
|
||||
|
||||
my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
|
||||
my $miss_string = join( q{, }, map qq{'$_'}, @missing );
|
||||
die("Can't link/include C library $miss_string, aborting.\n") if @missing;
|
||||
my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult );
|
||||
my $wrong_string = join( q{, }, map qq{'$_'}, @wrongresult);
|
||||
die("wrong result: $wrong_string\n") if @wrongresult;
|
||||
my $analysis_string = join(q{, }, map qq{'$_'}, @wronganalysis );
|
||||
die("wrong analysis: $analysis_string") if @wronganalysis;
|
||||
}
|
||||
|
||||
sub _cleanup_exe {
|
||||
my ($exefile) = @_;
|
||||
my $ofile = $exefile;
|
||||
$ofile =~ s/$Config{_exe}$/$Config{_o}/;
|
||||
unlink $exefile if -f $exefile;
|
||||
unlink $ofile if -f $ofile;
|
||||
unlink "$exefile\.manifest" if -f "$exefile\.manifest";
|
||||
# List of files to remove
|
||||
my @rmfiles;
|
||||
push @rmfiles, $exefile, $ofile, "$exefile\.manifest";
|
||||
if ( $Config{cc} eq 'cl' ) {
|
||||
|
||||
# MSVC also creates foo.ilk and foo.pdb
|
||||
my $ilkfile = $exefile;
|
||||
$ilkfile =~ s/$Config{_exe}$/.ilk/;
|
||||
my $pdbfile = $exefile;
|
||||
$pdbfile =~ s/$Config{_exe}$/.pdb/;
|
||||
unlink $ilkfile if -f $ilkfile;
|
||||
unlink $pdbfile if -f $pdbfile;
|
||||
push @rmfiles, $ilkfile, $pdbfile;
|
||||
}
|
||||
return;
|
||||
foreach (grep -f, @rmfiles) {
|
||||
unlink $_ or warn "Could not remove $_: $!";
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
# return ($cc, $ld)
|
||||
# where $cc is an array ref of compiler name, compiler flags
|
||||
# where $ld is an array ref of linker flags
|
||||
sub _findcc {
|
||||
|
||||
my ($debug, $user_ccflags, $user_ldflags) = @_;
|
||||
# Need to use $keep=1 to work with MSWin32 backslashes and quotes
|
||||
my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile
|
||||
$Config_ccflags =~ s:-O\S*::; # stop GCC optimising away test code
|
||||
my @Config_ldflags = ();
|
||||
for my $config_val ( @Config{qw(ldflags perllibs)} ) {
|
||||
for my $config_val ( @Config{qw(ldflags)} ){
|
||||
push @Config_ldflags, $config_val if ( $config_val =~ /\S/ );
|
||||
}
|
||||
my @ccflags = grep { length } quotewords( '\s+', 1, $Config_ccflags || '' );
|
||||
my @ldflags = grep { length } quotewords( '\s+', 1, @Config_ldflags );
|
||||
my @paths = split( /$Config{path_sep}/, $ENV{PATH} );
|
||||
my @cc = split( /\s+/, $Config{cc} );
|
||||
return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
|
||||
foreach my $path (@paths) {
|
||||
my $compiler = File::Spec->catfile( $path, $cc[0] ) . $Config{_exe};
|
||||
return ( [ $compiler, @cc[ 1 .. $#cc ], @ccflags ], \@ldflags )
|
||||
if -x $compiler;
|
||||
my @ccflags = grep { length } _parsewords($Config_ccflags||'', $user_ccflags||'');
|
||||
my @ldflags = grep { length && $_ !~ m/^-Wl/ } _parsewords(@Config_ldflags, $user_ldflags||'');
|
||||
my @paths = split(/$Config{path_sep}/, $ENV{PATH});
|
||||
my @cc = _parsewords($Config{cc});
|
||||
if (check_compiler ($cc[0], $debug)) {
|
||||
return ( [ @cc, @ccflags ], \@ldflags );
|
||||
}
|
||||
die("Couldn't find your C compiler\n");
|
||||
# Find the extension for executables.
|
||||
my $exe = $Config{_exe};
|
||||
if ($^O eq 'cygwin') {
|
||||
$exe = '';
|
||||
}
|
||||
foreach my $path (@paths) {
|
||||
# Look for "$path/$cc[0].exe"
|
||||
my $compiler = File::Spec->catfile($path, $cc[0]) . $exe;
|
||||
if (check_compiler ($compiler, $debug)) {
|
||||
return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
|
||||
}
|
||||
next if ! $exe;
|
||||
# Look for "$path/$cc[0]" without the .exe, if necessary.
|
||||
$compiler = File::Spec->catfile($path, $cc[0]);
|
||||
if (check_compiler ($compiler, $debug)) {
|
||||
return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
|
||||
}
|
||||
}
|
||||
die("Couldn't find your C compiler.\n");
|
||||
}
|
||||
|
||||
sub check_compiler
|
||||
{
|
||||
my ($compiler, $debug) = @_;
|
||||
if (-f $compiler && -x $compiler) {
|
||||
warn "# Compiler seems to be $compiler\n" if $debug;
|
||||
return 1;
|
||||
}
|
||||
warn "# Compiler was not $compiler\n" if $debug;
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
# code substantially borrowed from IPC::Run3
|
||||
sub _quiet_system {
|
||||
my (@cmd) = @_;
|
||||
|
@ -422,7 +529,7 @@ sub _quiet_system {
|
|||
You must have a C compiler installed. We check for C<$Config{cc}>,
|
||||
both literally as it is in Config.pm and also in the $PATH.
|
||||
|
||||
It has been tested with varying degrees on rigourousness on:
|
||||
It has been tested with varying degrees of rigorousness on:
|
||||
|
||||
=over
|
||||
|
||||
|
|
Loading…
Reference in New Issue