1b39c5158Smillertpackage ExtUtils::Constant; 2b39c5158Smillertuse vars qw (@ISA $VERSION @EXPORT_OK %EXPORT_TAGS); 3*5759b3d2Safresh1$VERSION = '0.25'; 4b39c5158Smillert 5b39c5158Smillert=head1 NAME 6b39c5158Smillert 7b39c5158SmillertExtUtils::Constant - generate XS code to import C header constants 8b39c5158Smillert 9b39c5158Smillert=head1 SYNOPSIS 10b39c5158Smillert 11b39c5158Smillert use ExtUtils::Constant qw (WriteConstants); 12b39c5158Smillert WriteConstants( 13b39c5158Smillert NAME => 'Foo', 14b39c5158Smillert NAMES => [qw(FOO BAR BAZ)], 15b39c5158Smillert ); 16b39c5158Smillert # Generates wrapper code to make the values of the constants FOO BAR BAZ 17b39c5158Smillert # available to perl 18b39c5158Smillert 19b39c5158Smillert=head1 DESCRIPTION 20b39c5158Smillert 21b39c5158SmillertExtUtils::Constant facilitates generating C and XS wrapper code to allow 22b39c5158Smillertperl modules to AUTOLOAD constants defined in C library header files. 23b39c5158SmillertIt is principally used by the C<h2xs> utility, on which this code is based. 24b39c5158SmillertIt doesn't contain the routines to scan header files to extract these 25b39c5158Smillertconstants. 26b39c5158Smillert 27b39c5158Smillert=head1 USAGE 28b39c5158Smillert 29b39c5158SmillertGenerally one only needs to call the C<WriteConstants> function, and then 30b39c5158Smillert 31b39c5158Smillert #include "const-c.inc" 32b39c5158Smillert 33b39c5158Smillertin the C section of C<Foo.xs> 34b39c5158Smillert 35b39c5158Smillert INCLUDE: const-xs.inc 36b39c5158Smillert 37b39c5158Smillertin the XS section of C<Foo.xs>. 38b39c5158Smillert 39b39c5158SmillertFor greater flexibility use C<constant_types()>, C<C_constant> and 40b39c5158SmillertC<XS_constant>, with which C<WriteConstants> is implemented. 41b39c5158Smillert 42b39c5158SmillertCurrently this module understands the following types. h2xs may only know 43b39c5158Smillerta subset. The sizes of the numeric types are chosen by the C<Configure> 44b39c5158Smillertscript at compile time. 45b39c5158Smillert 46b39c5158Smillert=over 4 47b39c5158Smillert 48b39c5158Smillert=item IV 49b39c5158Smillert 50b39c5158Smillertsigned integer, at least 32 bits. 51b39c5158Smillert 52b39c5158Smillert=item UV 53b39c5158Smillert 54b39c5158Smillertunsigned integer, the same size as I<IV> 55b39c5158Smillert 56b39c5158Smillert=item NV 57b39c5158Smillert 58b39c5158Smillertfloating point type, probably C<double>, possibly C<long double> 59b39c5158Smillert 60b39c5158Smillert=item PV 61b39c5158Smillert 62b39c5158SmillertNUL terminated string, length will be determined with C<strlen> 63b39c5158Smillert 64b39c5158Smillert=item PVN 65b39c5158Smillert 66b39c5158SmillertA fixed length thing, given as a [pointer, length] pair. If you know the 67b39c5158Smillertlength of a string at compile time you may use this instead of I<PV> 68b39c5158Smillert 69b39c5158Smillert=item SV 70b39c5158Smillert 71b39c5158SmillertA B<mortal> SV. 72b39c5158Smillert 73b39c5158Smillert=item YES 74b39c5158Smillert 75b39c5158SmillertTruth. (C<PL_sv_yes>) The value is not needed (and ignored). 76b39c5158Smillert 77b39c5158Smillert=item NO 78b39c5158Smillert 79b39c5158SmillertDefined Falsehood. (C<PL_sv_no>) The value is not needed (and ignored). 80b39c5158Smillert 81b39c5158Smillert=item UNDEF 82b39c5158Smillert 83b39c5158SmillertC<undef>. The value of the macro is not needed. 84b39c5158Smillert 85b39c5158Smillert=back 86b39c5158Smillert 87b39c5158Smillert=head1 FUNCTIONS 88b39c5158Smillert 89b39c5158Smillert=over 4 90b39c5158Smillert 91b39c5158Smillert=cut 92b39c5158Smillert 93b39c5158Smillertif ($] >= 5.006) { 94b39c5158Smillert eval "use warnings; 1" or die $@; 95b39c5158Smillert} 96b39c5158Smillertuse strict; 97b39c5158Smillertuse Carp qw(croak cluck); 98b39c5158Smillert 99b39c5158Smillertuse Exporter; 100b39c5158Smillertuse ExtUtils::Constant::Utils qw(C_stringify); 101b39c5158Smillertuse ExtUtils::Constant::XS qw(%XS_Constant %XS_TypeSet); 102b39c5158Smillert 103b39c5158Smillert@ISA = 'Exporter'; 104b39c5158Smillert 105b39c5158Smillert%EXPORT_TAGS = ( 'all' => [ qw( 106b39c5158Smillert XS_constant constant_types return_clause memEQ_clause C_stringify 107b39c5158Smillert C_constant autoload WriteConstants WriteMakefileSnippet 108b39c5158Smillert) ] ); 109b39c5158Smillert 110b39c5158Smillert@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 111b39c5158Smillert 112b39c5158Smillert=item constant_types 113b39c5158Smillert 114b39c5158SmillertA function returning a single scalar with C<#define> definitions for the 115b39c5158Smillertconstants used internally between the generated C and XS functions. 116b39c5158Smillert 117b39c5158Smillert=cut 118b39c5158Smillert 119b39c5158Smillertsub constant_types { 120b39c5158Smillert ExtUtils::Constant::XS->header(); 121b39c5158Smillert} 122b39c5158Smillert 123b39c5158Smillertsub memEQ_clause { 124b39c5158Smillert cluck "ExtUtils::Constant::memEQ_clause is deprecated"; 125b39c5158Smillert ExtUtils::Constant::XS->memEQ_clause({name=>$_[0], checked_at=>$_[1], 126b39c5158Smillert indent=>$_[2]}); 127b39c5158Smillert} 128b39c5158Smillert 129b39c5158Smillertsub return_clause ($$) { 130b39c5158Smillert cluck "ExtUtils::Constant::return_clause is deprecated"; 131b39c5158Smillert my $indent = shift; 132b39c5158Smillert ExtUtils::Constant::XS->return_clause({indent=>$indent}, @_); 133b39c5158Smillert} 134b39c5158Smillert 135b39c5158Smillertsub switch_clause { 136b39c5158Smillert cluck "ExtUtils::Constant::switch_clause is deprecated"; 137b39c5158Smillert my $indent = shift; 138b39c5158Smillert my $comment = shift; 139b39c5158Smillert ExtUtils::Constant::XS->switch_clause({indent=>$indent, comment=>$comment}, 140b39c5158Smillert @_); 141b39c5158Smillert} 142b39c5158Smillert 143b39c5158Smillertsub C_constant { 144b39c5158Smillert my ($package, $subname, $default_type, $what, $indent, $breakout, @items) 145b39c5158Smillert = @_; 146b39c5158Smillert ExtUtils::Constant::XS->C_constant({package => $package, subname => $subname, 147b39c5158Smillert default_type => $default_type, 148b39c5158Smillert types => $what, indent => $indent, 149b39c5158Smillert breakout => $breakout}, @items); 150b39c5158Smillert} 151b39c5158Smillert 152b39c5158Smillert=item XS_constant PACKAGE, TYPES, XS_SUBNAME, C_SUBNAME 153b39c5158Smillert 154b39c5158SmillertA function to generate the XS code to implement the perl subroutine 155b39c5158SmillertI<PACKAGE>::constant used by I<PACKAGE>::AUTOLOAD to load constants. 156b39c5158SmillertThis XS code is a wrapper around a C subroutine usually generated by 157b39c5158SmillertC<C_constant>, and usually named C<constant>. 158b39c5158Smillert 159b39c5158SmillertI<TYPES> should be given either as a comma separated list of types that the 160b39c5158SmillertC subroutine C<constant> will generate or as a reference to a hash. It should 161b39c5158Smillertbe the same list of types as C<C_constant> was given. 162b39c5158Smillert[Otherwise C<XS_constant> and C<C_constant> may have different ideas about 163b39c5158Smillertthe number of parameters passed to the C function C<constant>] 164b39c5158Smillert 165b39c5158SmillertYou can call the perl visible subroutine something other than C<constant> if 166b39c5158Smillertyou give the parameter I<XS_SUBNAME>. The C subroutine it calls defaults to 167b39c5158Smillertthe name of the perl visible subroutine, unless you give the parameter 168b39c5158SmillertI<C_SUBNAME>. 169b39c5158Smillert 170b39c5158Smillert=cut 171b39c5158Smillert 172b39c5158Smillertsub XS_constant { 173b39c5158Smillert my $package = shift; 174b39c5158Smillert my $what = shift; 175b39c5158Smillert my $XS_subname = shift; 176b39c5158Smillert my $C_subname = shift; 177b39c5158Smillert $XS_subname ||= 'constant'; 178b39c5158Smillert $C_subname ||= $XS_subname; 179b39c5158Smillert 180b39c5158Smillert if (!ref $what) { 181b39c5158Smillert # Convert line of the form IV,UV,NV to hash 182b39c5158Smillert $what = {map {$_ => 1} split /,\s*/, ($what)}; 183b39c5158Smillert } 184b39c5158Smillert my $params = ExtUtils::Constant::XS->params ($what); 185b39c5158Smillert my $type; 186b39c5158Smillert 187b39c5158Smillert my $xs = <<"EOT"; 188b39c5158Smillertvoid 189b39c5158Smillert$XS_subname(sv) 190b39c5158Smillert PREINIT: 191b39c5158Smillert#ifdef dXSTARG 192b39c5158Smillert dXSTARG; /* Faster if we have it. */ 193b39c5158Smillert#else 194b39c5158Smillert dTARGET; 195b39c5158Smillert#endif 196b39c5158Smillert STRLEN len; 197b39c5158Smillert int type; 198b39c5158SmillertEOT 199b39c5158Smillert 200b39c5158Smillert if ($params->{IV}) { 201*5759b3d2Safresh1 $xs .= " IV iv = 0; /* avoid uninit var warning */\n"; 202b39c5158Smillert } else { 203b39c5158Smillert $xs .= " /* IV\t\tiv;\tUncomment this if you need to return IVs */\n"; 204b39c5158Smillert } 205b39c5158Smillert if ($params->{NV}) { 206*5759b3d2Safresh1 $xs .= " NV nv = 0.0; /* avoid uninit var warning */\n"; 207b39c5158Smillert } else { 208b39c5158Smillert $xs .= " /* NV\t\tnv;\tUncomment this if you need to return NVs */\n"; 209b39c5158Smillert } 210b39c5158Smillert if ($params->{PV}) { 211*5759b3d2Safresh1 $xs .= " const char *pv = NULL; /* avoid uninit var warning */\n"; 212b39c5158Smillert } else { 213b39c5158Smillert $xs .= 214b39c5158Smillert " /* const char\t*pv;\tUncomment this if you need to return PVs */\n"; 215b39c5158Smillert } 216b39c5158Smillert 217b39c5158Smillert $xs .= << 'EOT'; 218b39c5158Smillert INPUT: 219b39c5158Smillert SV * sv; 220b39c5158Smillert const char * s = SvPV(sv, len); 221b39c5158SmillertEOT 222b39c5158Smillert if ($params->{''}) { 223b39c5158Smillert $xs .= << 'EOT'; 224b39c5158Smillert INPUT: 225b39c5158Smillert int utf8 = SvUTF8(sv); 226b39c5158SmillertEOT 227b39c5158Smillert } 228b39c5158Smillert $xs .= << 'EOT'; 229b39c5158Smillert PPCODE: 230b39c5158SmillertEOT 231b39c5158Smillert 232b39c5158Smillert if ($params->{IV} xor $params->{NV}) { 233b39c5158Smillert $xs .= << "EOT"; 234b39c5158Smillert /* Change this to $C_subname(aTHX_ s, len, &iv, &nv); 235b39c5158Smillert if you need to return both NVs and IVs */ 236b39c5158SmillertEOT 237b39c5158Smillert } 238b39c5158Smillert $xs .= " type = $C_subname(aTHX_ s, len"; 239b39c5158Smillert $xs .= ', utf8' if $params->{''}; 240b39c5158Smillert $xs .= ', &iv' if $params->{IV}; 241b39c5158Smillert $xs .= ', &nv' if $params->{NV}; 242b39c5158Smillert $xs .= ', &pv' if $params->{PV}; 243b39c5158Smillert $xs .= ', &sv' if $params->{SV}; 244b39c5158Smillert $xs .= ");\n"; 245b39c5158Smillert 246b39c5158Smillert # If anyone is insane enough to suggest a package name containing % 247b39c5158Smillert my $package_sprintf_safe = $package; 248b39c5158Smillert $package_sprintf_safe =~ s/%/%%/g; 249b39c5158Smillert 250b39c5158Smillert $xs .= << "EOT"; 251b39c5158Smillert /* Return 1 or 2 items. First is error message, or undef if no error. 252b39c5158Smillert Second, if present, is found value */ 253b39c5158Smillert switch (type) { 254b39c5158Smillert case PERL_constant_NOTFOUND: 255b39c5158Smillert sv = 256b39c5158Smillert sv_2mortal(newSVpvf("%s is not a valid $package_sprintf_safe macro", s)); 257b39c5158Smillert PUSHs(sv); 258b39c5158Smillert break; 259b39c5158Smillert case PERL_constant_NOTDEF: 260b39c5158Smillert sv = sv_2mortal(newSVpvf( 261b39c5158Smillert "Your vendor has not defined $package_sprintf_safe macro %s, used", 262b39c5158Smillert s)); 263b39c5158Smillert PUSHs(sv); 264b39c5158Smillert break; 265b39c5158SmillertEOT 266b39c5158Smillert 267b39c5158Smillert foreach $type (sort keys %XS_Constant) { 268b39c5158Smillert # '' marks utf8 flag needed. 269b39c5158Smillert next if $type eq ''; 270b39c5158Smillert $xs .= "\t/* Uncomment this if you need to return ${type}s\n" 271b39c5158Smillert unless $what->{$type}; 272b39c5158Smillert $xs .= " case PERL_constant_IS$type:\n"; 273b39c5158Smillert if (length $XS_Constant{$type}) { 274b39c5158Smillert $xs .= << "EOT"; 275*5759b3d2Safresh1 EXTEND(SP, 2); 276b39c5158Smillert PUSHs(&PL_sv_undef); 277b39c5158Smillert $XS_Constant{$type}; 278b39c5158SmillertEOT 279b39c5158Smillert } else { 280b39c5158Smillert # Do nothing. return (), which will be correctly interpreted as 281b39c5158Smillert # (undef, undef) 282b39c5158Smillert } 283b39c5158Smillert $xs .= " break;\n"; 284b39c5158Smillert unless ($what->{$type}) { 285b39c5158Smillert chop $xs; # Yes, another need for chop not chomp. 286b39c5158Smillert $xs .= " */\n"; 287b39c5158Smillert } 288b39c5158Smillert } 289b39c5158Smillert $xs .= << "EOT"; 290b39c5158Smillert default: 291b39c5158Smillert sv = sv_2mortal(newSVpvf( 292b39c5158Smillert "Unexpected return type %d while processing $package_sprintf_safe macro %s, used", 293b39c5158Smillert type, s)); 294b39c5158Smillert PUSHs(sv); 295b39c5158Smillert } 296b39c5158SmillertEOT 297b39c5158Smillert 298b39c5158Smillert return $xs; 299b39c5158Smillert} 300b39c5158Smillert 301b39c5158Smillert 302b39c5158Smillert=item autoload PACKAGE, VERSION, AUTOLOADER 303b39c5158Smillert 304b39c5158SmillertA function to generate the AUTOLOAD subroutine for the module I<PACKAGE> 305b39c5158SmillertI<VERSION> is the perl version the code should be backwards compatible with. 306b39c5158SmillertIt defaults to the version of perl running the subroutine. If I<AUTOLOADER> 307b39c5158Smillertis true, the AUTOLOAD subroutine falls back on AutoLoader::AUTOLOAD for all 308b39c5158Smillertnames that the constant() routine doesn't recognise. 309b39c5158Smillert 310b39c5158Smillert=cut 311b39c5158Smillert 312b39c5158Smillert# ' # Grr. syntax highlighters that don't grok pod. 313b39c5158Smillert 314b39c5158Smillertsub autoload { 315b39c5158Smillert my ($module, $compat_version, $autoloader) = @_; 316b39c5158Smillert $compat_version ||= $]; 317b39c5158Smillert croak "Can't maintain compatibility back as far as version $compat_version" 318b39c5158Smillert if $compat_version < 5; 319b39c5158Smillert my $func = "sub AUTOLOAD {\n" 320b39c5158Smillert . " # This AUTOLOAD is used to 'autoload' constants from the constant()\n" 321b39c5158Smillert . " # XS function."; 322b39c5158Smillert $func .= " If a constant is not found then control is passed\n" 323b39c5158Smillert . " # to the AUTOLOAD in AutoLoader." if $autoloader; 324b39c5158Smillert 325b39c5158Smillert 326b39c5158Smillert $func .= "\n\n" 327b39c5158Smillert . " my \$constname;\n"; 328b39c5158Smillert $func .= 329b39c5158Smillert " our \$AUTOLOAD;\n" if ($compat_version >= 5.006); 330b39c5158Smillert 331b39c5158Smillert $func .= <<"EOT"; 332b39c5158Smillert (\$constname = \$AUTOLOAD) =~ s/.*:://; 333b39c5158Smillert croak "&${module}::constant not defined" if \$constname eq 'constant'; 334b39c5158Smillert my (\$error, \$val) = constant(\$constname); 335b39c5158SmillertEOT 336b39c5158Smillert 337b39c5158Smillert if ($autoloader) { 338b39c5158Smillert $func .= <<'EOT'; 339b39c5158Smillert if ($error) { 340b39c5158Smillert if ($error =~ /is not a valid/) { 341b39c5158Smillert $AutoLoader::AUTOLOAD = $AUTOLOAD; 342b39c5158Smillert goto &AutoLoader::AUTOLOAD; 343b39c5158Smillert } else { 344b39c5158Smillert croak $error; 345b39c5158Smillert } 346b39c5158Smillert } 347b39c5158SmillertEOT 348b39c5158Smillert } else { 349b39c5158Smillert $func .= 350b39c5158Smillert " if (\$error) { croak \$error; }\n"; 351b39c5158Smillert } 352b39c5158Smillert 353b39c5158Smillert $func .= <<'END'; 354b39c5158Smillert { 355b39c5158Smillert no strict 'refs'; 356b39c5158Smillert # Fixed between 5.005_53 and 5.005_61 357b39c5158Smillert#XXX if ($] >= 5.00561) { 358b39c5158Smillert#XXX *$AUTOLOAD = sub () { $val }; 359b39c5158Smillert#XXX } 360b39c5158Smillert#XXX else { 361b39c5158Smillert *$AUTOLOAD = sub { $val }; 362b39c5158Smillert#XXX } 363b39c5158Smillert } 364b39c5158Smillert goto &$AUTOLOAD; 365b39c5158Smillert} 366b39c5158Smillert 367b39c5158SmillertEND 368b39c5158Smillert 369b39c5158Smillert return $func; 370b39c5158Smillert} 371b39c5158Smillert 372b39c5158Smillert 373b39c5158Smillert=item WriteMakefileSnippet 374b39c5158Smillert 375b39c5158SmillertWriteMakefileSnippet ATTRIBUTE =E<gt> VALUE [, ...] 376b39c5158Smillert 377b39c5158SmillertA function to generate perl code for Makefile.PL that will regenerate 378b39c5158Smillertthe constant subroutines. Parameters are named as passed to C<WriteConstants>, 379b39c5158Smillertwith the addition of C<INDENT> to specify the number of leading spaces 380b39c5158Smillert(default 2). 381b39c5158Smillert 382b39c5158SmillertCurrently only C<INDENT>, C<NAME>, C<DEFAULT_TYPE>, C<NAMES>, C<C_FILE> and 383b39c5158SmillertC<XS_FILE> are recognised. 384b39c5158Smillert 385b39c5158Smillert=cut 386b39c5158Smillert 387b39c5158Smillertsub WriteMakefileSnippet { 388b39c5158Smillert my %args = @_; 389b39c5158Smillert my $indent = $args{INDENT} || 2; 390b39c5158Smillert 391b39c5158Smillert my $result = <<"EOT"; 392b39c5158SmillertExtUtils::Constant::WriteConstants( 393b39c5158Smillert NAME => '$args{NAME}', 394b39c5158Smillert NAMES => \\\@names, 395b39c5158Smillert DEFAULT_TYPE => '$args{DEFAULT_TYPE}', 396b39c5158SmillertEOT 397b39c5158Smillert foreach (qw (C_FILE XS_FILE)) { 398b39c5158Smillert next unless exists $args{$_}; 399b39c5158Smillert $result .= sprintf " %-12s => '%s',\n", 400b39c5158Smillert $_, $args{$_}; 401b39c5158Smillert } 402b39c5158Smillert $result .= <<'EOT'; 403b39c5158Smillert ); 404b39c5158SmillertEOT 405b39c5158Smillert 406b39c5158Smillert $result =~ s/^/' 'x$indent/gem; 407b39c5158Smillert return ExtUtils::Constant::XS->dump_names({default_type=>$args{DEFAULT_TYPE}, 408b39c5158Smillert indent=>$indent,}, 409b39c5158Smillert @{$args{NAMES}}) 410b39c5158Smillert . $result; 411b39c5158Smillert} 412b39c5158Smillert 413b39c5158Smillert=item WriteConstants ATTRIBUTE =E<gt> VALUE [, ...] 414b39c5158Smillert 415b39c5158SmillertWrites a file of C code and a file of XS code which you should C<#include> 416b39c5158Smillertand C<INCLUDE> in the C and XS sections respectively of your module's XS 417b39c5158Smillertcode. You probably want to do this in your C<Makefile.PL>, so that you can 418b39c5158Smillerteasily edit the list of constants without touching the rest of your module. 419b39c5158SmillertThe attributes supported are 420b39c5158Smillert 421b39c5158Smillert=over 4 422b39c5158Smillert 423b39c5158Smillert=item NAME 424b39c5158Smillert 425b39c5158SmillertName of the module. This must be specified 426b39c5158Smillert 427b39c5158Smillert=item DEFAULT_TYPE 428b39c5158Smillert 429b39c5158SmillertThe default type for the constants. If not specified C<IV> is assumed. 430b39c5158Smillert 431b39c5158Smillert=item BREAKOUT_AT 432b39c5158Smillert 433b39c5158SmillertThe names of the constants are grouped by length. Generate child subroutines 434b39c5158Smillertfor each group with this number or more names in. 435b39c5158Smillert 436b39c5158Smillert=item NAMES 437b39c5158Smillert 438b39c5158SmillertAn array of constants' names, either scalars containing names, or hashrefs 439b39c5158Smillertas detailed in L<"C_constant">. 440b39c5158Smillert 441b39c5158Smillert=item PROXYSUBS 442b39c5158Smillert 443b39c5158SmillertIf true, uses proxy subs. See L<ExtUtils::Constant::ProxySubs>. 444b39c5158Smillert 445b39c5158Smillert=item C_FH 446b39c5158Smillert 447b39c5158SmillertA filehandle to write the C code to. If not given, then I<C_FILE> is opened 448b39c5158Smillertfor writing. 449b39c5158Smillert 450b39c5158Smillert=item C_FILE 451b39c5158Smillert 452b39c5158SmillertThe name of the file to write containing the C code. The default is 453b39c5158SmillertC<const-c.inc>. The C<-> in the name ensures that the file can't be 454b39c5158Smillertmistaken for anything related to a legitimate perl package name, and 455b39c5158Smillertnot naming the file C<.c> avoids having to override Makefile.PL's 456b39c5158SmillertC<.xs> to C<.c> rules. 457b39c5158Smillert 458b39c5158Smillert=item XS_FH 459b39c5158Smillert 460b39c5158SmillertA filehandle to write the XS code to. If not given, then I<XS_FILE> is opened 461b39c5158Smillertfor writing. 462b39c5158Smillert 463b39c5158Smillert=item XS_FILE 464b39c5158Smillert 465b39c5158SmillertThe name of the file to write containing the XS code. The default is 466b39c5158SmillertC<const-xs.inc>. 467b39c5158Smillert 468b39c5158Smillert=item XS_SUBNAME 469b39c5158Smillert 470b39c5158SmillertThe perl visible name of the XS subroutine generated which will return the 471b39c5158Smillertconstants. The default is C<constant>. 472b39c5158Smillert 473b39c5158Smillert=item C_SUBNAME 474b39c5158Smillert 475b39c5158SmillertThe name of the C subroutine generated which will return the constants. 476b39c5158SmillertThe default is I<XS_SUBNAME>. Child subroutines have C<_> and the name 477b39c5158Smillertlength appended, so constants with 10 character names would be in 478b39c5158SmillertC<constant_10> with the default I<XS_SUBNAME>. 479b39c5158Smillert 480b39c5158Smillert=back 481b39c5158Smillert 482b39c5158Smillert=cut 483b39c5158Smillert 484b39c5158Smillertsub WriteConstants { 485b39c5158Smillert my %ARGS = 486b39c5158Smillert ( # defaults 487b39c5158Smillert C_FILE => 'const-c.inc', 488b39c5158Smillert XS_FILE => 'const-xs.inc', 489b39c5158Smillert XS_SUBNAME => 'constant', 490b39c5158Smillert DEFAULT_TYPE => 'IV', 491b39c5158Smillert @_); 492b39c5158Smillert 493b39c5158Smillert $ARGS{C_SUBNAME} ||= $ARGS{XS_SUBNAME}; # No-one sane will have C_SUBNAME eq '0' 494b39c5158Smillert 495b39c5158Smillert croak "Module name not specified" unless length $ARGS{NAME}; 496b39c5158Smillert 497898184e3Ssthen # Do this before creating (empty) files, in case it fails: 498898184e3Ssthen require ExtUtils::Constant::ProxySubs if $ARGS{PROXYSUBS}; 499898184e3Ssthen 500b39c5158Smillert my $c_fh = $ARGS{C_FH}; 501b39c5158Smillert if (!$c_fh) { 502b39c5158Smillert if ($] <= 5.008) { 503b39c5158Smillert # We need these little games, rather than doing things 504b39c5158Smillert # unconditionally, because we're used in core Makefile.PLs before 505b39c5158Smillert # IO is available (needed by filehandle), but also we want to work on 506b39c5158Smillert # older perls where undefined scalars do not automatically turn into 507b39c5158Smillert # anonymous file handles. 508b39c5158Smillert require FileHandle; 509b39c5158Smillert $c_fh = FileHandle->new(); 510b39c5158Smillert } 511b39c5158Smillert open $c_fh, ">$ARGS{C_FILE}" or die "Can't open $ARGS{C_FILE}: $!"; 512b39c5158Smillert } 513b39c5158Smillert 514b39c5158Smillert my $xs_fh = $ARGS{XS_FH}; 515b39c5158Smillert if (!$xs_fh) { 516b39c5158Smillert if ($] <= 5.008) { 517b39c5158Smillert require FileHandle; 518b39c5158Smillert $xs_fh = FileHandle->new(); 519b39c5158Smillert } 520b39c5158Smillert open $xs_fh, ">$ARGS{XS_FILE}" or die "Can't open $ARGS{XS_FILE}: $!"; 521b39c5158Smillert } 522b39c5158Smillert 523b39c5158Smillert # As this subroutine is intended to make code that isn't edited, there's no 524b39c5158Smillert # need for the user to specify any types that aren't found in the list of 525b39c5158Smillert # names. 526b39c5158Smillert 527b39c5158Smillert if ($ARGS{PROXYSUBS}) { 528b39c5158Smillert $ARGS{C_FH} = $c_fh; 529b39c5158Smillert $ARGS{XS_FH} = $xs_fh; 530b39c5158Smillert ExtUtils::Constant::ProxySubs->WriteConstants(%ARGS); 531b39c5158Smillert } else { 532b39c5158Smillert my $types = {}; 533b39c5158Smillert 534b39c5158Smillert print $c_fh constant_types(); # macro defs 535b39c5158Smillert print $c_fh "\n"; 536b39c5158Smillert 537b39c5158Smillert # indent is still undef. Until anyone implements indent style rules with 538b39c5158Smillert # it. 539b39c5158Smillert foreach (ExtUtils::Constant::XS->C_constant({package => $ARGS{NAME}, 540b39c5158Smillert subname => $ARGS{C_SUBNAME}, 541b39c5158Smillert default_type => 542b39c5158Smillert $ARGS{DEFAULT_TYPE}, 543b39c5158Smillert types => $types, 544b39c5158Smillert breakout => 545b39c5158Smillert $ARGS{BREAKOUT_AT}}, 546b39c5158Smillert @{$ARGS{NAMES}})) { 547b39c5158Smillert print $c_fh $_, "\n"; # C constant subs 548b39c5158Smillert } 549b39c5158Smillert print $xs_fh XS_constant ($ARGS{NAME}, $types, $ARGS{XS_SUBNAME}, 550b39c5158Smillert $ARGS{C_SUBNAME}); 551b39c5158Smillert } 552b39c5158Smillert 553b39c5158Smillert close $c_fh or warn "Error closing $ARGS{C_FILE}: $!" unless $ARGS{C_FH}; 554b39c5158Smillert close $xs_fh or warn "Error closing $ARGS{XS_FILE}: $!" unless $ARGS{XS_FH}; 555b39c5158Smillert} 556b39c5158Smillert 557b39c5158Smillert1; 558b39c5158Smillert__END__ 559b39c5158Smillert 560b39c5158Smillert=back 561b39c5158Smillert 562b39c5158Smillert=head1 AUTHOR 563b39c5158Smillert 564b39c5158SmillertNicholas Clark <nick@ccl4.org> based on the code in C<h2xs> by Larry Wall and 565b39c5158Smillertothers 566b39c5158Smillert 567b39c5158Smillert=cut 568