xref: /openbsd-src/gnu/usr.bin/perl/cpan/ExtUtils-Constant/lib/ExtUtils/Constant.pm (revision 5759b3d249badf144a6240f7eec4dcf9df003e6b)
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