|
Packit |
910689 |
#!/usr/bin/perl
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# Configure.pm. Version 1.00 Copyright (C) 1995, Kenneth Albanowski
|
|
Packit |
910689 |
#
|
|
Packit |
910689 |
# You are welcome to use this code in your own perl modules, I just
|
|
Packit |
910689 |
# request that you don't distribute modified copies without making it clear
|
|
Packit |
910689 |
# that you have changed something. If you have a change you think is worth
|
|
Packit |
910689 |
# merging into the original, please contact me at kjahds@kjahds.com or
|
|
Packit |
910689 |
# CIS:70705,126
|
|
Packit |
910689 |
#
|
|
Packit |
910689 |
# $Id: Configure.pm,v 2.21 2004/03/02 20:28:11 jonathan Exp $
|
|
Packit |
910689 |
#
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# Todo: clean up redudant code in CPP, Compile, Link, and Execute
|
|
Packit |
910689 |
#
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# for when no_index is not enough
|
|
Packit |
910689 |
package
|
|
Packit |
910689 |
Configure;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
use strict;
|
|
Packit |
910689 |
use vars qw(@EXPORT @ISA);
|
|
Packit |
910689 |
|
|
Packit |
910689 |
use Carp;
|
|
Packit |
910689 |
require Exporter;
|
|
Packit |
910689 |
@ISA = qw(Exporter);
|
|
Packit |
910689 |
|
|
Packit |
910689 |
@EXPORT = qw( CPP
|
|
Packit |
910689 |
Compile
|
|
Packit |
910689 |
Link
|
|
Packit |
910689 |
Execute
|
|
Packit |
910689 |
FindHeader
|
|
Packit |
910689 |
FindLib
|
|
Packit |
910689 |
Apply
|
|
Packit |
910689 |
ApplyHeaders
|
|
Packit |
910689 |
ApplyLibs
|
|
Packit |
910689 |
ApplyHeadersAndLibs
|
|
Packit |
910689 |
ApplyHeadersAndLibsAndExecute
|
|
Packit |
910689 |
CheckHeader
|
|
Packit |
910689 |
CheckStructure
|
|
Packit |
910689 |
CheckField
|
|
Packit |
910689 |
CheckHSymbol
|
|
Packit |
910689 |
CheckSymbol
|
|
Packit |
910689 |
CheckLSymbol
|
|
Packit |
910689 |
GetSymbol
|
|
Packit |
910689 |
GetTextSymbol
|
|
Packit |
910689 |
GetNumericSymbol
|
|
Packit |
910689 |
GetConstants);
|
|
Packit |
910689 |
|
|
Packit |
910689 |
use Config;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my ($C_usrinc, $C_libpth, $C_cppstdin, $C_cppflags, $C_cppminus,
|
|
Packit |
910689 |
$C_ccflags,$C_ldflags,$C_cc,$C_libs) =
|
|
Packit |
910689 |
@Config{qw( usrinc libpth cppstdin cppflags cppminus
|
|
Packit |
910689 |
ccflags ldflags cc libs)};
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $Verbose = 0;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head1 NAME
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Configure.pm - provide auto-configuration utilities
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head1 SUMMARY
|
|
Packit |
910689 |
|
|
Packit |
910689 |
This perl module provides tools to figure out what is present in the C
|
|
Packit |
910689 |
compilation environment. This is intended mostly for perl extensions to use
|
|
Packit |
910689 |
to configure themselves. There are a number of functions, with widely varying
|
|
Packit |
910689 |
levels of specificity, so here is a summary of what the functions can do:
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckHeader: Look for headers.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckStructure: Look for a structure.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckField: Look for a field in a structure.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckHSymbol: Look for a symbol in a header.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckLSymbol: Look for a symbol in a library.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CheckSymbol: Look for a symbol in a header and library.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
GetTextSymbol: Get the contents of a symbol as text.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
GetNumericSymbol: Get the contents of a symbol as a number.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply: Try compiling code with a set of headers and libs.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
ApplyHeaders: Try compiling code with a set of headers.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
ApplyLibraries: Try linking code with a set of libraries.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
ApplyHeadersAndLibaries: You get the idea.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
ApplyHeadersAndLibariesAnExecute: You get the idea.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
CPP: Feed some code through the C preproccessor.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Compile: Try to compile some C code.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Link: Try to compile & link some C code.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Execute: Try to compile, link, & execute some C code.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head1 FUNCTIONS
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# Here we go into the actual functions
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CPP
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes one or more arguments. The first is a string containing a C program.
|
|
Packit |
910689 |
Embedded newlines are legal, the text simply being stuffed into a temporary
|
|
Packit |
910689 |
file. The result is then fed to the C preproccessor (that preproccessor being
|
|
Packit |
910689 |
previously determined by perl's Configure script.) Any additional arguments
|
|
Packit |
910689 |
provided are passed to the preprocessing command.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context, the return value is either undef, if something went wrong,
|
|
Packit |
910689 |
or the text returned by the preprocessor. In an array context, two values are
|
|
Packit |
910689 |
returned: the numeric exit status and the output of the preproccessor.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CPP { # Feed code to preproccessor, returning error value and output
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my($code,@options) = @_;
|
|
Packit |
910689 |
my($options) = join(" ",@options);
|
|
Packit |
910689 |
my($file) = "tmp$$";
|
|
Packit |
910689 |
my($in,$out) = ($file.".c",$file.".o");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
open(F,">$in");
|
|
Packit |
910689 |
print F $code;
|
|
Packit |
910689 |
close(F);
|
|
Packit |
910689 |
|
|
Packit |
910689 |
print "Preprocessing |$code|\n" if $Verbose;
|
|
Packit |
910689 |
my($result) = scalar(`$C_cppstdin $C_cppflags $C_cppminus $options < $in 2>/dev/null`);
|
|
Packit |
910689 |
print "Executing '$C_cppstdin $C_cppflags $C_cppminus $options < $in 2>/dev/null'\n" if $Verbose;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my($error) = $?;
|
|
Packit |
910689 |
print "Returned |$result|\n" if $Verbose;
|
|
Packit |
910689 |
unlink($in,$out);
|
|
Packit |
910689 |
return ($error ? undef : $result) unless wantarray;
|
|
Packit |
910689 |
($error,$result);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 Compile
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes one or more arguments. The first is a string containing a C program.
|
|
Packit |
910689 |
Embedded newlines are legal, the text simply being stuffed into a temporary
|
|
Packit |
910689 |
file. The result is then fed to the C compiler (that compiler being
|
|
Packit |
910689 |
previously determined by perl's Configure script.) Any additional arguments
|
|
Packit |
910689 |
provided are passed to the compiler command.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context, either 0 or 1 will be returned, with 1 indicating a
|
|
Packit |
910689 |
successful compilation. In an array context, three values are returned: the
|
|
Packit |
910689 |
numeric exit status of the compiler, a string consisting of the output
|
|
Packit |
910689 |
generated by the compiler, and a numeric value that is false if a ".o" file
|
|
Packit |
910689 |
wasn't produced by the compiler, error status or no.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub Compile { # Feed code to compiler. On error, return status and text
|
|
Packit |
910689 |
my($code,@options) = @_;
|
|
Packit |
910689 |
my($options)=join(" ",@options);
|
|
Packit |
910689 |
my($file) = "tmp$$";
|
|
Packit |
910689 |
my($in,$out) = ($file.".c",$file.".o");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
open(F,">$in");
|
|
Packit |
910689 |
print F $code;
|
|
Packit |
910689 |
close(F);
|
|
Packit |
910689 |
print "Compiling |$code|\n" if $Verbose;
|
|
Packit |
910689 |
my($result) = scalar(`$C_cc $C_ccflags -c $in $C_ldflags $C_libs $options 2>&1`);
|
|
Packit |
910689 |
print "Executing '$C_cc $C_ccflags -c $in $C_ldflags $C_libs $options 2>&1'\n" if $Verbose;
|
|
Packit |
910689 |
my($error) = $?;
|
|
Packit |
910689 |
my($error2) = ! -e $out;
|
|
Packit |
910689 |
unlink($in,$out);
|
|
Packit |
910689 |
return (($error || $error2) ? 0 : 1) unless wantarray;
|
|
Packit |
910689 |
($error,$result,$error2);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 Link
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes one or more arguments. The first is a string containing a C program.
|
|
Packit |
910689 |
Embedded newlines are legal, the text simply being stuffed into a temporary
|
|
Packit |
910689 |
file. The result is then fed to the C compiler and linker (that compiler and
|
|
Packit |
910689 |
linker being previously determined by perl's Configure script.) Any
|
|
Packit |
910689 |
additional arguments provided are passed to the compilation/link command.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context, either 0 or 1 is returned, with 1 indicating a
|
|
Packit |
910689 |
successful compilation. In an array context, two values are returned: the
|
|
Packit |
910689 |
numeric exit status of the compiler/linker, and a string consisting of the
|
|
Packit |
910689 |
output generated by the compiler/linker.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Note that this command I<only> compiles and links the C code. It does not
|
|
Packit |
910689 |
attempt to execute it.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub Link { # Feed code to compiler and linker. On error, return status and text
|
|
Packit |
910689 |
my($code,@options) = @_;
|
|
Packit |
910689 |
my($options) = join(" ",@options);
|
|
Packit |
910689 |
my($file) = "tmp$$";
|
|
Packit |
910689 |
my($in,$out) = $file.".c",$file.".o";
|
|
Packit |
910689 |
|
|
Packit |
910689 |
open(F,">$in");
|
|
Packit |
910689 |
print F $code;
|
|
Packit |
910689 |
close(F);
|
|
Packit |
910689 |
print "Linking |$code|\n" if $Verbose;
|
|
Packit |
910689 |
my($result) = scalar(`$C_cc $C_ccflags -o $file $in $C_ldflags $C_libs $options 2>&1`);
|
|
Packit |
910689 |
print "Executing '$C_cc $C_ccflags -o $file $in $C_ldflags $C_libs $options 2>&1'\n" if $Verbose;
|
|
Packit |
910689 |
my($error)=$?;
|
|
Packit |
910689 |
print "Error linking: $error, |$result|\n" if $Verbose;
|
|
Packit |
910689 |
unlink($in,$out,$file);
|
|
Packit |
910689 |
return (($error || $result ne "")?0:1) unless wantarray;
|
|
Packit |
910689 |
($error,$result);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 Execute
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes one or more arguments. The first is a string containing a C program.
|
|
Packit |
910689 |
Embedded newlines are legal, the text simply being stuffed into a temporary
|
|
Packit |
910689 |
file. The result is then fed to the C compiler and linker (that compiler and
|
|
Packit |
910689 |
linker being previously determined by perl's metaconfig script.) and then
|
|
Packit |
910689 |
executed. Any additional arguments provided are passed to the
|
|
Packit |
910689 |
compilation/link command. (There is no way to feed arguments to the program
|
|
Packit |
910689 |
being executed.)
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context, the return value is either undef, indicating the
|
|
Packit |
910689 |
compilation or link failed, or that the executed program returned a nonzero
|
|
Packit |
910689 |
status. Otherwise, the return value is the text output by the program.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In an array context, an array consisting of three values is returned: the
|
|
Packit |
910689 |
first value is 0 or 1, 1 if the compile/link succeeded. The second value either
|
|
Packit |
910689 |
the exist status of the compiler or program, and the third is the output text.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub Execute { #Compile, link, and execute.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my($code,@options) = @_;
|
|
Packit |
910689 |
my($options)=join(" ",@options);
|
|
Packit |
910689 |
my($file) = "tmp$$";
|
|
Packit |
910689 |
my($in,$out) = $file.".c",$file.".o";
|
|
Packit |
910689 |
|
|
Packit |
910689 |
open(F,">$in");
|
|
Packit |
910689 |
print F $code;
|
|
Packit |
910689 |
close(F);
|
|
Packit |
910689 |
print "Executing |$code|\n" if $Verbose;
|
|
Packit |
910689 |
my($result) = scalar(`$C_cc $C_ccflags -o $file $in $C_ldflags $C_libs $options 2>&1`);
|
|
Packit |
910689 |
print "Executing '$C_cc $C_ccflags -o $file $in $C_ldflags $C_libs $options 2>&1'\n" if $Verbose;
|
|
Packit |
910689 |
my($error) = $?;
|
|
Packit |
910689 |
unlink($in,$out);
|
|
Packit |
910689 |
if(!$error) {
|
|
Packit |
910689 |
my($result2) = scalar(`./$file`);
|
|
Packit |
910689 |
$error = $?;
|
|
Packit |
910689 |
unlink($file);
|
|
Packit |
910689 |
return ($error?undef:$result2) unless wantarray;
|
|
Packit |
910689 |
print "Executed successfully, status $error, link $result, exec |$result2|\n" if $Verbose;
|
|
Packit |
910689 |
(1,$error,$result2);
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
print "Link failed, status $error, message |$result|\n" if $Verbose;
|
|
Packit |
910689 |
return undef unless wantarray;
|
|
Packit |
910689 |
(0,$error,$result);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 FindHeader
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes an unlimited number of arguments, consisting of both header names in
|
|
Packit |
910689 |
the form "header.h", or directory specifications such as "-I/usr/include/bsd".
|
|
Packit |
910689 |
For each supplied header, FindHeader will attempt to find the complete path.
|
|
Packit |
910689 |
The return value is an array consisting of all the headers that were located.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub FindHeader { #For each supplied header name, find full path
|
|
Packit |
910689 |
my(@headers) = grep(!/^-I/,@_);
|
|
Packit |
910689 |
my(@I) = grep(/^-I/,@_);
|
|
Packit |
910689 |
my($h);
|
|
Packit |
910689 |
for $h (@headers) {
|
|
Packit |
910689 |
print "Searching for $h... " if $Verbose;
|
|
Packit |
910689 |
if($h eq "") {$h=undef; next}
|
|
Packit |
910689 |
if( -f $h) {next}
|
|
Packit |
910689 |
if( -f $Config{"usrinc"}."/".$h) {
|
|
Packit |
910689 |
$h = $Config{"usrinc"}."/".$h;
|
|
Packit |
910689 |
print "Found as $h.\n" if $Verbose;
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
my $text;
|
|
Packit |
910689 |
if($text = CPP("#include <$h>",join(" ",@I))) {
|
|
Packit |
910689 |
grepcpp:
|
|
Packit |
910689 |
for (split(/\s+/,(grep(/^\s*#.*$h/,split(/\n/,$text)))[0])) {
|
|
Packit |
910689 |
if(/$h/) {
|
|
Packit |
910689 |
s/^\"(.*)\"$/$1/;
|
|
Packit |
910689 |
s/^\'(.*)\'$/$1/;
|
|
Packit |
910689 |
$h = $_;
|
|
Packit |
910689 |
print "Found as $h.\n" if $Verbose;
|
|
Packit |
910689 |
last grepcpp;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
$h = undef; # remove header from resulting list
|
|
Packit |
910689 |
print "Not found.\n" if $Verbose;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
grep($_,@headers);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 FindLib
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes an unlimited number of arguments, consisting of both library names in
|
|
Packit |
910689 |
the form "-llibname", "/usr/lib/libxyz.a" or "dld", or directory
|
|
Packit |
910689 |
specifications such as "-L/usr/lib/foo". For each supplied library, FindLib
|
|
Packit |
910689 |
will attempt to find the complete path. The return value is an array
|
|
Packit |
910689 |
consisting of the full paths to all of the libraries that were located.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub FindLib { #For each supplied library name, find full path
|
|
Packit |
910689 |
my(@libs) = grep(!/^-L/,@_);
|
|
Packit |
910689 |
my(@L) = (grep(/^-L/,@_),split(" ",$Config{"libpth"}));
|
|
Packit |
910689 |
grep(s/^-L//,@L);
|
|
Packit |
910689 |
my($l);
|
|
Packit |
910689 |
my($so) = $Config{"so"};
|
|
Packit |
910689 |
my($found);
|
|
Packit |
910689 |
#print "Libaries I am searching for: ",join(",",@libs),"\n";
|
|
Packit |
910689 |
#print "Directories: ",join(",",@L),"\n";
|
|
Packit |
910689 |
my $lib;
|
|
Packit |
910689 |
for $lib (@libs) {
|
|
Packit |
910689 |
print "Searching for $lib... " if $Verbose;
|
|
Packit |
910689 |
$found=0;
|
|
Packit |
910689 |
$lib =~ s/^-l//;
|
|
Packit |
910689 |
if($lib eq "") {$lib=undef; next}
|
|
Packit |
910689 |
next if -f $lib;
|
|
Packit |
910689 |
my $path;
|
|
Packit |
910689 |
for $path (@L) {
|
|
Packit |
910689 |
my ( $fullname, @fullname );
|
|
Packit |
910689 |
print "Searching $path for $lib...\n" if $Verbose;
|
|
Packit |
910689 |
if (@fullname=<${path}/lib${lib}.${so}.[0-9]*>){
|
|
Packit |
910689 |
$fullname=$fullname[-1]; #ATTN: 10 looses against 9!
|
|
Packit |
910689 |
} elsif (-f ($fullname="$path/lib$lib.$so")){
|
|
Packit |
910689 |
} elsif (-f ($fullname="$path/lib${lib}_s.a")
|
|
Packit |
910689 |
&& ($lib .= "_s") ){ # we must explicitly ask for _s version
|
|
Packit |
910689 |
} elsif (-f ($fullname="$path/lib$lib.a")){
|
|
Packit |
910689 |
} elsif (-f ($fullname="$path/Slib$lib.a")){
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
warn "$lib not found in $path\n" if $Verbose;
|
|
Packit |
910689 |
next;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
warn "'-l$lib' found at $fullname\n" if $Verbose;
|
|
Packit |
910689 |
$lib = $fullname;
|
|
Packit |
910689 |
$found=1;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
if(!$found) {
|
|
Packit |
910689 |
$lib = undef; # Remove lib if not found
|
|
Packit |
910689 |
print "Not found.\n" if $Verbose;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
grep($_,@libs);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply takes a chunk of code, a series of libraries and headers, and attempts
|
|
Packit |
910689 |
to apply them, in series, to a given perl command. In a scalar context, the
|
|
Packit |
910689 |
return value of the first set of headers and libraries that produces a
|
|
Packit |
910689 |
non-zero return value from the command is returned. In an array context, the
|
|
Packit |
910689 |
header and library set it returned.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
This is best explained by some examples:
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply(\&Compile,"main(){}","sgtty.h","");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context either C<undef> or C<1>. In an array context,
|
|
Packit |
910689 |
this returns C<()> or C<("sgtty.h","")>.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply(\&Link,"main(){int i=COLOR_PAIRS;}","curses.h","-lcurses",
|
|
Packit |
910689 |
"ncurses.h","-lncurses","ncurses/ncurses.h","-lncurses");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
In a scalar context, this returns either C<undef>, C<1>. In an array context,
|
|
Packit |
910689 |
this returns C<("curses.h","-lcurses")>, C<("ncurses.h","-lncurses")>,
|
|
Packit |
910689 |
C<("ncurses/ncurses.h","-lncurses")>, or C<()>.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
If we had instead said
|
|
Packit |
910689 |
C<Apply(\&Execute,'main(){printf("%d",(int)COLOR_PAIRS)',...)> then in a scalar
|
|
Packit |
910689 |
context either C<undef> or the value of COLOR_PAIRS would be returned.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Note that you can also supply multiple headers and/or libraries at one time,
|
|
Packit |
910689 |
like this:
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply(\&Compile,"main(){fcntl(0,F_GETFD);}","fcntl.h","",
|
|
Packit |
910689 |
"ioctl.h fcntl.h","","sys/ioctl.h fcntl.h"","");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
So if fcntl needs ioctl or sys/ioctl loaded first, this will catch it. In an
|
|
Packit |
910689 |
array context, C<()>, C<("fcntl.h","")>, C<("ioctl.h fcntl.h","")>, or
|
|
Packit |
910689 |
C<("sys/ioctl.h fcntl.h","")> could be returned.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
You can also use nested arrays to get exactly the same effect. The returned
|
|
Packit |
910689 |
array will always consist of a string, though, with elements separated by
|
|
Packit |
910689 |
spaces.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Apply(\&Compile,"main(){fcntl(0,F_GETFD);}",["fcntl.h"],"",
|
|
Packit |
910689 |
["ioctl.h","fcntl.h"],"",["sys/ioctl.h","fcntl.h"],"");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Note that there are many functions that provide simpler ways of doing these
|
|
Packit |
910689 |
things, from GetNumericSymbol to get the value of a symbol, to ApplyHeaders
|
|
Packit |
910689 |
which doesn't ask for libraries.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub Apply { #
|
|
Packit |
910689 |
my($cmd,$code,@lookup) = @_;
|
|
Packit |
910689 |
my(@l,@h,$i,$ret);
|
|
Packit |
910689 |
for ($i=0;$i<@lookup;$i+=2) {
|
|
Packit |
910689 |
if( ref($lookup[$i]) eq "ARRAY" ) {
|
|
Packit |
910689 |
@h = @{$lookup[$i]};
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
@h = split(/\s+/,$lookup[$i]);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
if( ref($lookup[$i+1]) eq "ARRAY" ) {
|
|
Packit |
910689 |
@l = @{$lookup[$i+1]};
|
|
Packit |
910689 |
} else {
|
|
Packit |
910689 |
@l = split(/\s+/,$lookup[$i+1]);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if ($ret=&{$cmd == \&Link && !@l?\&Compile:$cmd}(
|
|
Packit |
910689 |
join("",map($_?"#include <$_>\n":"",grep(!/^-I/,@h))).
|
|
Packit |
910689 |
$code,grep(/^-I/,@h),@l)) {
|
|
Packit |
910689 |
print "Ret=|$ret|\n" if $Verbose;
|
|
Packit |
910689 |
return $ret unless wantarray;
|
|
Packit |
910689 |
return (join(" ",@h),join(" ",@l));
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
return 0 unless wantarray;
|
|
Packit |
910689 |
();
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 ApplyHeadersAndLibs
|
|
Packit |
910689 |
|
|
Packit |
910689 |
This function takes the same sort of arguments as Apply, it just sends them
|
|
Packit |
910689 |
directly to Link.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub ApplyHeadersAndLibs { #
|
|
Packit |
910689 |
my($code,@lookup) = @_;
|
|
Packit |
910689 |
Apply \&Link,$code,@lookup;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 ApplyHeadersAndLibsAndExecute
|
|
Packit |
910689 |
|
|
Packit |
910689 |
This function is similar to Apply and ApplyHeadersAndLibs, but it always
|
|
Packit |
910689 |
uses Execute.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub ApplyHeadersAndLibsAndExecute { #
|
|
Packit |
910689 |
my($code,@lookup) = @_;
|
|
Packit |
910689 |
Apply \&Execute,$code,@lookup;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 ApplyHeaders
|
|
Packit |
910689 |
|
|
Packit |
910689 |
If you are only checking headers, and don't need to look at libs, then
|
|
Packit |
910689 |
you will probably want to use ApplyHeaders. The return value is the same
|
|
Packit |
910689 |
in a scalar context, but in an array context the returned array will only
|
|
Packit |
910689 |
consists of the headers, spread out.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub ApplyHeaders {
|
|
Packit |
910689 |
my($code,@headers) = @_;
|
|
Packit |
910689 |
return scalar(ApplyHeadersAndLibs $code, map(($_,""),@headers))
|
|
Packit |
910689 |
unless wantarray;
|
|
Packit |
910689 |
split(/\s+/,(ApplyHeadersAndLibs $code, map(($_,""),@headers))[0]);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 ApplyLibs
|
|
Packit |
910689 |
|
|
Packit |
910689 |
If you are only checking libraries, and don't need to look at headers, then
|
|
Packit |
910689 |
you will probably want to use ApplyLibs. The return value is the same
|
|
Packit |
910689 |
in a scalar context, but in an array context the returned array will only
|
|
Packit |
910689 |
consists of the libraries, spread out.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub ApplyLibs {
|
|
Packit |
910689 |
my($code,@libs) = @_;
|
|
Packit |
910689 |
return scalar(ApplyHeadersAndLibs $code, map(("",$_),@libs))
|
|
Packit |
910689 |
unless wantarray;
|
|
Packit |
910689 |
split(/\s+/,(ApplyHeadersAndLibs $code, map(("",$_),@libs))[0]);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckHeader
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes an unlimited number of arguments, consiting of headers in the
|
|
Packit |
910689 |
Apply style. The first set that is fully accepted
|
|
Packit |
910689 |
by the compiler is returned.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckHeader { #Find a header (or set of headers) that exists
|
|
Packit |
910689 |
ApplyHeaders("main(){}",@_);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckStructure
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a structure, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of header groups. The first group that defines that structure
|
|
Packit |
910689 |
properly will be returned. B<undef> will be returned if nothing succeeds.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckStructure { # Check existance of a structure.
|
|
Packit |
910689 |
my($structname,@headers) = @_;
|
|
Packit |
910689 |
ApplyHeaders("main(){ struct $structname s;}",@headers);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckField
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a structure, the name of a field, and an unlimited number
|
|
Packit |
910689 |
of further arguments consisting of header groups. The first group that
|
|
Packit |
910689 |
defines a structure that contains the field will be returned. B<undef> will
|
|
Packit |
910689 |
be returned if nothing succeeds.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckField { # Check for the existance of specified field in structure
|
|
Packit |
910689 |
my($structname,$fieldname,@headers) = @_;
|
|
Packit |
910689 |
ApplyHeaders("main(){ struct $structname s1; struct $structname s2;
|
|
Packit |
910689 |
s1.$fieldname = s2.$fieldname; }",@headers);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckLSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of library groups. The first group of libraries that defines
|
|
Packit |
910689 |
that symbol will be returned. B<undef> will be returned if nothing succeeds.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckLSymbol { # Check for linkable symbol
|
|
Packit |
910689 |
my($symbol,@libs) = @_;
|
|
Packit |
910689 |
ApplyLibs("main() { void * f = (void *)($symbol); }",@libs);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of header and library groups, in the Apply format. The first
|
|
Packit |
910689 |
group of headers and libraries that defines that symbol will be returned.
|
|
Packit |
910689 |
B<undef> will be returned if nothing succeeds.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckSymbol { # Check for linkable/header symbol
|
|
Packit |
910689 |
my($symbol,@lookup) = @_;
|
|
Packit |
910689 |
ApplyHeadersAndLibs("main() { void * f = (void *)($symbol); }",@lookup);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckHSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of header groups. The first group of headers that defines
|
|
Packit |
910689 |
that symbol will be returned. B<undef> will be returned if nothing succeeds.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckHSymbol { # Check for header symbol
|
|
Packit |
910689 |
my($symbol,@headers) = @_;
|
|
Packit |
910689 |
ApplyHeaders("main() { void * f = (void *)($symbol); }",@headers);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 CheckHPrototype (unexported)
|
|
Packit |
910689 |
|
|
Packit |
910689 |
An experimental routine that takes a name of a function, a nested array
|
|
Packit |
910689 |
consisting of the prototype, and then the normal header groups. It attempts
|
|
Packit |
910689 |
to deduce whether the given prototype matches what the header supplies.
|
|
Packit |
910689 |
Basically, it doesn't work. Or maybe it does. I wouldn't reccomend it,
|
|
Packit |
910689 |
though.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub CheckHPrototype { # Check for header prototype.
|
|
Packit |
910689 |
# Note: This function is extremely picky about "const int" versus "int",
|
|
Packit |
910689 |
# and depends on having an extremely snotty compiler. Anything but GCC
|
|
Packit |
910689 |
# may fail, and even GCC may not work properly. In any case, if the
|
|
Packit |
910689 |
# names function doesn't exist, this call will _succeed_. Caveat Utilitor.
|
|
Packit |
910689 |
my($function,$proto,@headers) = @_;
|
|
Packit |
910689 |
my(@proto) = @{$proto};
|
|
Packit |
910689 |
ApplyHeaders("main() { extern ".$proto[0]." $function(".
|
|
Packit |
910689 |
join(",",@proto[1..$#proto])."); }",@headers);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 GetSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, a printf command, a cast, and an unlimited
|
|
Packit |
910689 |
number of further arguments consisting of header and library groups, in the
|
|
Packit |
910689 |
Apply. The first group of headers and libraries that defines that symbol
|
|
Packit |
910689 |
will be used to get the contents of the symbol in the format, and return it.
|
|
Packit |
910689 |
B<undef> will be returned if nothing defines that symbol.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Example:
|
|
Packit |
910689 |
|
|
Packit |
910689 |
GetSymbol("__LINE__","ld","long","","");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub GetSymbol { # Check for linkable/header symbol
|
|
Packit |
910689 |
my($symbol,$printf,$cast,@lookup) = @_,"","";
|
|
Packit |
910689 |
scalar(ApplyHeadersAndLibsAndExecute(
|
|
Packit |
910689 |
"main(){ printf(\"\%$printf\",($cast)($symbol));exit(0);}",@lookup));
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 GetTextSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of header and library groups, in the ApplyHeadersAndLibs format.
|
|
Packit |
910689 |
The first group of headers and libraries that defines that symbol will be
|
|
Packit |
910689 |
used to get the contents of the symbol in text format, and return it.
|
|
Packit |
910689 |
B<undef> will be returned if nothing defines that symbol.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Note that the symbol I<must> actually be text, either a char* or a constant
|
|
Packit |
910689 |
string. Otherwise, the results are undefined.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub GetTextSymbol { # Check for linkable/header symbol
|
|
Packit |
910689 |
my($symbol,@lookup) = @_,"","";
|
|
Packit |
910689 |
my($result) = GetSymbol($symbol,"s","char*",@lookup);
|
|
Packit |
910689 |
$result .= "" if defined($result);
|
|
Packit |
910689 |
$result;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 GetNumericSymbol
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes the name of a symbol, and an unlimited number of further arguments
|
|
Packit |
910689 |
consisting of header and library groups, in the ApplyHeadersAndLibs format.
|
|
Packit |
910689 |
The first group of headers and libraries that defines that symbol will be
|
|
Packit |
910689 |
used to get the contents of the symbol in numeric format, and return it.
|
|
Packit |
910689 |
B<undef> will be returned if nothing defines that symbol.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Note that the symbol I<must> actually be numeric, in a format compatible
|
|
Packit |
910689 |
with a float. Otherwise, the results are undefined.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub GetNumericSymbol { # Check for linkable/header symbol
|
|
Packit |
910689 |
my($symbol,@lookup) = @_,"","";
|
|
Packit |
910689 |
my($result) = GetSymbol($symbol,"f","float",@lookup);
|
|
Packit |
910689 |
$result += 0 if defined($result);
|
|
Packit |
910689 |
$result;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 GetConstants
|
|
Packit |
910689 |
|
|
Packit |
910689 |
Takes a list of header names (possibly including -I directives) and attempts
|
|
Packit |
910689 |
to grep the specified files for constants, a constant being something #defined
|
|
Packit |
910689 |
with a name that matches /[A-Z0-9_]+/. Returns the list of names.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
sub GetConstants { # Try to grep constants out of a header
|
|
Packit |
910689 |
my(@headers) = @_;
|
|
Packit |
910689 |
@headers = FindHeader(@headers);
|
|
Packit |
910689 |
my %seen;
|
|
Packit |
910689 |
my(%results);
|
|
Packit |
910689 |
map($seen{$_}=1,@headers);
|
|
Packit |
910689 |
while(@headers) {
|
|
Packit |
910689 |
$_=shift(@headers);
|
|
Packit |
910689 |
next if !defined($_);
|
|
Packit |
910689 |
open(SEARCHHEADER,"<$_");
|
|
Packit |
910689 |
while(<SEARCHHEADER>) {
|
|
Packit |
910689 |
if(/^\s*#\s*define\s+([A-Z_][A-Za-z0-9_]+)\s+/) {
|
|
Packit |
910689 |
$results{$1} = 1;
|
|
Packit |
910689 |
} elsif(/^\s*#\s*include\s+[<"]?([^">]+)[>"]?/) {
|
|
Packit |
910689 |
my(@include) = FindHeader($1);
|
|
Packit |
910689 |
@include = grep(!$seen{$_},map(defined($_)?$_:(),@include));
|
|
Packit |
910689 |
push(@headers,@include);
|
|
Packit |
910689 |
map($seen{$_}=1,@include);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
close(SEARCHHEADER);
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
keys %results;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=head2 DeducePrototype (unexported)
|
|
Packit |
910689 |
|
|
Packit |
910689 |
This one is B<really> experimental. The idea is to figure out some basic
|
|
Packit |
910689 |
characteristics of the compiler, and then attempt to "feel out" the prototype
|
|
Packit |
910689 |
of a function. Eventually, it may work. It is guaranteed to be very slow,
|
|
Packit |
910689 |
and it may simply not be capable of working on some systems.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
=cut
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $firstdeduce = 1;
|
|
Packit |
910689 |
sub DeducePrototype {
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my (@types, $checkreturn, $checknilargs, $checkniletcargs, $checkreturnnil);
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if($firstdeduce) {
|
|
Packit |
910689 |
$firstdeduce=0;
|
|
Packit |
910689 |
my $checknumber=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b);
|
|
Packit |
910689 |
extern int func(int a,int b,int c);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
$checkreturn=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b);
|
|
Packit |
910689 |
extern long func(int a,int b);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checketc= !Compile("
|
|
Packit |
910689 |
extern int func(int a,int b);
|
|
Packit |
910689 |
extern long func(int a,...);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checknumberetc=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b);
|
|
Packit |
910689 |
extern int func(int a,int b,...);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checketcnumber=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b,int c,...);
|
|
Packit |
910689 |
extern int func(int a,int b,...);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checkargtypes=!Compile("
|
|
Packit |
910689 |
extern int func(int a);
|
|
Packit |
910689 |
extern int func(long a);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checkargsnil=!Compile("
|
|
Packit |
910689 |
extern int func();
|
|
Packit |
910689 |
extern int func(int a,int b,int c);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
$checknilargs=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b,int c);
|
|
Packit |
910689 |
extern int func();
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
my $checkargsniletc=!Compile("
|
|
Packit |
910689 |
extern int func(...);
|
|
Packit |
910689 |
extern int func(int a,int b,int c);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
$checkniletcargs=!Compile("
|
|
Packit |
910689 |
extern int func(int a,int b,int c);
|
|
Packit |
910689 |
extern int func(...);
|
|
Packit |
910689 |
main(){}");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $checkconst=!Compile("
|
|
Packit |
910689 |
extern int func(const int * a);
|
|
Packit |
910689 |
extern int func(int * a);
|
|
Packit |
910689 |
main(){ }");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $checksign=!Compile("
|
|
Packit |
910689 |
extern int func(int a);
|
|
Packit |
910689 |
extern int func(unsigned int a);
|
|
Packit |
910689 |
main(){ }");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
$checkreturnnil=!Compile("
|
|
Packit |
910689 |
extern func(int a);
|
|
Packit |
910689 |
extern void func(int a);
|
|
Packit |
910689 |
main(){ }");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
@types = sort grep(Compile("main(){$_ a;}"),
|
|
Packit |
910689 |
"void","int","long int","unsigned int","unsigned long int","long long int",
|
|
Packit |
910689 |
"long long","unsigned long long",
|
|
Packit |
910689 |
"unsigned long long int","float","long float",
|
|
Packit |
910689 |
"double","long double",
|
|
Packit |
910689 |
"char","unsigned char","short int","unsigned short int");
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if(Compile("main(){flurfie a;}")) { @types = (); }
|
|
Packit |
910689 |
|
|
Packit |
910689 |
$Verbose=0;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# Attempt to remove duplicate types (if any) from type list
|
|
Packit |
910689 |
my ( $i, $j );
|
|
Packit |
910689 |
if($checkargtypes) {
|
|
Packit |
910689 |
for ($i=0;$i<=$#types;$i++) {
|
|
Packit |
910689 |
for ($j=$i+1;$j<=$#types;$j++) {
|
|
Packit |
910689 |
next if $j==$i;
|
|
Packit |
910689 |
if(Compile("
|
|
Packit |
910689 |
extern void func($types[$i]);
|
|
Packit |
910689 |
extern void func($types[$j]);
|
|
Packit |
910689 |
main(){}")) {
|
|
Packit |
910689 |
print "Removing type $types[$j] because it equals $types[$i]\n";
|
|
Packit |
910689 |
splice(@types,$j,1);
|
|
Packit |
910689 |
$j--;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
} elsif($checkreturn) {
|
|
Packit |
910689 |
for ($i=0;$i<=$#types;$i++) {
|
|
Packit |
910689 |
for ($j=$i+1;$j<=$#types;$j++) {
|
|
Packit |
910689 |
next if $j==$i;
|
|
Packit |
910689 |
if(Compile("
|
|
Packit |
910689 |
$types[$i] func(void);
|
|
Packit |
910689 |
extern $types[$j] func(void);
|
|
Packit |
910689 |
main(){}")) {
|
|
Packit |
910689 |
print "Removing type $types[$j] because it equals $types[$i]\n";
|
|
Packit |
910689 |
splice(@types,$j,1);
|
|
Packit |
910689 |
$j--;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
$Verbose=1;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
print "Detect differing numbers of arguments: $checknumber\n";
|
|
Packit |
910689 |
print "Detect differing return types: $checkreturn\n";
|
|
Packit |
910689 |
print "Detect differing argument types if one is ...: $checketc\n";
|
|
Packit |
910689 |
print "Detect differing numbers of arguments if ... is involved: $checknumberetc\n";
|
|
Packit |
910689 |
print "Detect differing numbers of arguments if ... is involved #2: $checketcnumber\n";
|
|
Packit |
910689 |
print "Detect differing argument types: $checkargtypes\n";
|
|
Packit |
910689 |
print "Detect differing argument types if first has no defined args: $checkargsnil\n";
|
|
Packit |
910689 |
print "Detect differing argument types if second has no defined args: $checknilargs\n";
|
|
Packit |
910689 |
print "Detect differing argument types if first has only ...: $checkargsniletc\n";
|
|
Packit |
910689 |
print "Detect differing argument types if second has only ...: $checkniletcargs\n";
|
|
Packit |
910689 |
print "Detect differing argument types by constness: $checkconst\n";
|
|
Packit |
910689 |
print "Detect differing argument types by signedness: $checksign\n";
|
|
Packit |
910689 |
print "Detect differing return types if one is not defined: $checkreturnnil\n";
|
|
Packit |
910689 |
print "Types known: ",join(",",@types),"\n";
|
|
Packit |
910689 |
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my($function,@headers) = @_;
|
|
Packit |
910689 |
@headers = CheckHSymbol($function,@headers);
|
|
Packit |
910689 |
return undef if !@headers;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $rettype = undef;
|
|
Packit |
910689 |
my @args = ();
|
|
Packit |
910689 |
my @validcount = ();
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# Can we check the return type without worry about arguements?
|
|
Packit |
910689 |
if($checkreturn and (!$checknilargs or !$checkniletcargs)) {
|
|
Packit |
910689 |
for (@types) {
|
|
Packit |
910689 |
if(ApplyHeaders("extern $_ $function(". ($checknilargs?"...":"").");main(){}",[@headers])) {
|
|
Packit |
910689 |
$rettype = $_; # Great, we found the return type.
|
|
Packit |
910689 |
last;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if(!defined($rettype) and $checkreturnnil) {
|
|
Packit |
910689 |
die "No way to deduce function prototype in a rational amount of time";
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
my $numargs=-1;
|
|
Packit |
910689 |
my $varargs=0;
|
|
Packit |
910689 |
for (0..32) {
|
|
Packit |
910689 |
if(ApplyHeaders("main(){ $function(".join(",",("0") x $_).");}",@headers)) {
|
|
Packit |
910689 |
$numargs=$_;
|
|
Packit |
910689 |
if(ApplyHeaders("main(){ $function(".join(",",("0") x ($_+1)).");}",@headers)) {
|
|
Packit |
910689 |
$varargs=1;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
last
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
die "Unable to deduce number of arguments" if $numargs==-1;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if($varargs) { $args[$numargs]="..."; }
|
|
Packit |
910689 |
|
|
Packit |
910689 |
# OK, now we know how many arguments the thing takes.
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
if(@args>0 and !defined($rettype)) {
|
|
Packit |
910689 |
for (@types) {
|
|
Packit |
910689 |
if(defined(ApplyHeaders("extern $_ $function(".join(",",@args).");main(){}",[@headers]))) {
|
|
Packit |
910689 |
$rettype = $_; # Great, we found the return type.
|
|
Packit |
910689 |
last;
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
print "Return type: $rettype\nArguments: ",join(",",@args),"\n";
|
|
Packit |
910689 |
print "Valid number of arguments: $numargs\n";
|
|
Packit |
910689 |
print "Accepts variable number of args: $varargs\n";
|
|
Packit |
910689 |
}
|
|
Packit |
910689 |
|
|
Packit |
910689 |
|
|
Packit |
910689 |
#$Verbose=1;
|
|
Packit |
910689 |
|
|
Packit |
910689 |
#print scalar(join("|",CheckHeader("sgtty.h"))),"\n";
|
|
Packit |
910689 |
#print scalar(join("|",FindHeader(CheckHeader("sgtty.h")))),"\n";
|
|
Packit |
910689 |
#print scalar(join("|",CheckSymbol("COLOR_PAIRS","curses.h","-lcurses","ncurses.h","-lncurses","ncurses/ncurses.h","ncurses/libncurses.a"))),"\n";
|
|
Packit |
910689 |
#print scalar(join("|",GetNumericSymbol("PRIO_USER","sys/resource.h",""))),"\n";
|
|
Packit |
910689 |
|