.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Required to disable full justification in groff 1.23.0. .if n .ds AD l .\" ======================================================================== .\" .IX Title "ExtUtils::ParseXS::Utilities 3perl" .TH ExtUtils::ParseXS::Utilities 3perl 2026-08-11 "perl v5.42.2" "Perl Programmers Reference Guide" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME ExtUtils::ParseXS::Utilities \- Subroutines used with ExtUtils::ParseXS .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 10 \& use ExtUtils::ParseXS::Utilities qw( \& standard_typemap_locations \& trim_whitespace \& C_string \& valid_proto_string \& process_typemaps \& map_type \& standard_XS_defs \& analyze_preprocessor_statement \& set_cond \& Warn \& blurt \& death \& check_conditional_preprocessor_statements \& escape_file_for_line_directive \& report_typemap_failure \& ); .Ve .SH SUBROUTINES .IX Header "SUBROUTINES" The following functions are not considered to be part of the public interface. They are documented here for the benefit of future maintainers of this module. .ie n .SS standard_typemap_locations() .el .SS \f(CWstandard_typemap_locations()\fP .IX Subsection "standard_typemap_locations()" .IP \(bu 4 Purpose .Sp Provide a list of filepaths where \fItypemap\fR files may be found. The filepaths \-\- relative paths to files (not just directory paths) \-\- appear in this list in lowest\-to\-highest priority. .Sp The highest priority is to look in the current directory. .Sp .Vb 1 \& \*(Aqtypemap\*(Aq .Ve .Sp The second and third highest priorities are to look in the parent of the current directory and a directory called \fIlib/ExtUtils\fR underneath the parent directory. .Sp .Vb 2 \& \*(Aq../typemap\*(Aq, \& \*(Aq../lib/ExtUtils/typemap\*(Aq, .Ve .Sp The fourth through ninth highest priorities are to look in the corresponding grandparent, great\-grandparent and great\-great\-grandparent directories. .Sp .Vb 6 \& \*(Aq../../typemap\*(Aq, \& \*(Aq../../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../../../typemap\*(Aq, \& \*(Aq../../../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../../../../typemap\*(Aq, \& \*(Aq../../../../lib/ExtUtils/typemap\*(Aq, .Ve .Sp The tenth and subsequent priorities are to look in directories named \&\fIExtUtils\fR which are subdirectories of directories found in \f(CW@INC\fR \-\- \&\fIprovided\fR a file named \fItypemap\fR actually exists in such a directory. Example: .Sp .Vb 1 \& \*(Aq/usr/local/lib/perl5/5.10.1/ExtUtils/typemap\*(Aq, .Ve .Sp However, these filepaths appear in the list returned by \&\f(CWstandard_typemap_locations()\fR in reverse order, \fIi.e.\fR, lowest\-to\-highest. .Sp .Vb 10 \& \*(Aq/usr/local/lib/perl5/5.10.1/ExtUtils/typemap\*(Aq, \& \*(Aq../../../../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../../../../typemap\*(Aq, \& \*(Aq../../../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../../../typemap\*(Aq, \& \*(Aq../../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../../typemap\*(Aq, \& \*(Aq../lib/ExtUtils/typemap\*(Aq, \& \*(Aq../typemap\*(Aq, \& \*(Aqtypemap\*(Aq .Ve .IP \(bu 4 Arguments .Sp .Vb 1 \& my @stl = standard_typemap_locations( \e@INC ); .Ve .Sp Reference to \f(CW@INC\fR. .IP \(bu 4 Return Value .Sp Array holding list of directories to be searched for \fItypemap\fR files. .ie n .SS trim_whitespace() .el .SS \f(CWtrim_whitespace()\fP .IX Subsection "trim_whitespace()" .IP \(bu 4 Purpose .Sp Perform an in\-place trimming of leading and trailing whitespace from the first argument provided to the function. .IP \(bu 4 Argument .Sp .Vb 1 \& trim_whitespace($arg); .Ve .IP \(bu 4 Return Value .Sp None. Remember: this is an \fIin\-place\fR modification of the argument. .ie n .SS C_string() .el .SS \f(CWC_string()\fP .IX Subsection "C_string()" .IP \(bu 4 Purpose .Sp Escape backslashes (\f(CW\*(C`\e\*(C'\fR) in prototype strings. .IP \(bu 4 Arguments .Sp .Vb 1 \& $ProtoThisXSUB = C_string($_); .Ve .Sp String needing escaping. .IP \(bu 4 Return Value .Sp Properly escaped string. .ie n .SS valid_proto_string() .el .SS \f(CWvalid_proto_string()\fP .IX Subsection "valid_proto_string()" .IP \(bu 4 Purpose .Sp Validate prototype string. .IP \(bu 4 Arguments .Sp String needing checking. .IP \(bu 4 Return Value .Sp Upon success, returns the same string passed as argument. .Sp Upon failure, returns \f(CW0\fR. .ie n .SS process_typemaps() .el .SS \f(CWprocess_typemaps()\fP .IX Subsection "process_typemaps()" .IP \(bu 4 Purpose .Sp Process all typemap files. .IP \(bu 4 Arguments .Sp .Vb 1 \& my $typemaps_object = process_typemaps( $args{typemap}, $pwd ); .Ve .Sp List of two elements: \f(CW\*(C`typemap\*(C'\fR element from \f(CW%args\fR; current working directory. .IP \(bu 4 Return Value .Sp Upon success, returns an ExtUtils::Typemaps object. .ie n .SS """map_type($self, $type, $varname)""" .el .SS "\f(CWmap_type($self, $type, $varname)\fP" .IX Subsection "map_type($self, $type, $varname)" Returns a mapped version of the C type \f(CW$type\fR. In particular, it converts \f(CW\*(C`Foo::bar\*(C'\fR to \f(CW\*(C`Foo_\|_bar\*(C'\fR, converts the special \f(CW\*(C`array(type,n)\*(C'\fR into \f(CW\*(C`type *\*(C'\fR, and inserts \f(CW$varname\fR (if present) into any function pointer type. So \f(CW\*(C`...(*)...\*(C'\fR becomes \f(CW\*(C`...(* foo)...\*(C'\fR. .ie n .SS standard_XS_defs() .el .SS \f(CWstandard_XS_defs()\fP .IX Subsection "standard_XS_defs()" .IP \(bu 4 Purpose .Sp Writes to the \f(CW\*(C`.c\*(C'\fR output file certain preprocessor directives and function headers needed in all such files. .IP \(bu 4 Arguments .Sp None. .IP \(bu 4 Return Value .Sp Returns true. .ie n .SS analyze_preprocessor_statement() .el .SS \f(CWanalyze_preprocessor_statement()\fP .IX Subsection "analyze_preprocessor_statement()" .IP \(bu 4 Purpose .Sp Process a CPP conditional line (\f(CW\*(C`#if\*(C'\fR etc), to keep track of conditional nesting. In particular, it updates \f(CW\*(C`@{$self\->{XS_parse_stack}}\*(C'\fR which contains the current list of nested conditions, and \&\f(CW\*(C`$self\->{XS_parse_stack_top_if_idx}\*(C'\fR which indicates the most recent \&\f(CW\*(C`if\*(C'\fR in that stack. So an \f(CW\*(C`#if\*(C'\fR pushes, an \f(CW\*(C`#endif\*(C'\fR pops, an \f(CW\*(C`#else\*(C'\fR modifies etc. Each element is a hash of the form: .Sp .Vb 3 \& { \& type => \*(Aqif\*(Aq, \& varname => \*(AqXSubPPtmpAAAA\*(Aq, # maintained by caller \& \& # XS functions defined within this branch of the \& # conditional (maintained by caller) \& functions => { \& \*(AqFoo::Bar::baz\*(Aq => 1, \& ... \& } \& # XS functions seen within any previous branch \& other_functions => {... } .Ve .Sp It also updates \f(CW\*(C`$self\->{bootcode_early}\*(C'\fR and \&\f(CW\*(C`$self\->{bootcode_late}\*(C'\fR with extra CPP directives. .IP \(bu 4 Arguments .Sp .Vb 1 \& $self\->analyze_preprocessor_statement($statement); .Ve .ie n .SS set_cond() .el .SS \f(CWset_cond()\fP .IX Subsection "set_cond()" .IP \(bu 4 Purpose .Sp Return a string containing a snippet of C code which tests for the \*(Aqwrong number of arguments passed\*(Aq condition, depending on whether there are default arguments or ellipsis. .IP \(bu 4 Arguments .Sp \&\f(CW\*(C`ellipsis\*(C'\fR true if the xsub\*(Aqs signature has a trailing \f(CW\*(C`, ...\*(C'\fR. .Sp \&\f(CW$min_args\fR the smallest number of args which may be passed. .Sp \&\f(CW$num_args\fR the number of parameters in the signature. .IP \(bu 4 Return Value .Sp The text of a short C code snippet. .ie n .SS current_line_number() .el .SS \f(CWcurrent_line_number()\fP .IX Subsection "current_line_number()" .IP \(bu 4 Purpose .Sp Figures out the current line number in the XS file. .IP \(bu 4 Arguments .Sp \&\f(CW$self\fR .IP \(bu 4 Return Value .Sp The current line number. .SS "Error handling methods" .IX Subsection "Error handling methods" There are four main methods for reporting warnings and errors. .ie n .IP """$self\->Warn(@messages)""" 4 .el .IP \f(CW$self\->Warn(@messages)\fR 4 .IX Item "$self->Warn(@messages)" This is equivalent to: .Sp .Vb 1 \& warn "@messages in foo.xs, line 123\en"; .Ve .Sp The file and line number are based on the file currently being parsed. It is intended for use where you wish to warn, but can continue parsing and still generate a correct C output file. .ie n .IP """$self\->blurt(@messages)""" 4 .el .IP \f(CW$self\->blurt(@messages)\fR 4 .IX Item "$self->blurt(@messages)" This is equivalent to \f(CW\*(C`Warn\*(C'\fR, except that it also increments the internal error count (which can be retrieved with \f(CWreport_error_count()\fR). It is used to report an error, but where parsing can continue (so typically for a semantic error rather than a syntax error). It is expected that the caller will eventually signal failure in some fashion. For example, \&\f(CW\*(C`xsubpp\*(C'\fR has this as its last line: .Sp .Vb 1 \& exit($self\->report_error_count() ? 1 : 0); .Ve .ie n .IP """$self\->death(@messages)""" 4 .el .IP \f(CW$self\->death(@messages)\fR 4 .IX Item "$self->death(@messages)" This normally equivalent to: .Sp .Vb 2 \& $self\->Warn(@messages); \& exit(1); .Ve .Sp It is used for something like a syntax error, where parsing can\*(Aqt continue. However, this is inconvenient for testing purposes, as the error can\*(Aqt be trapped. So if \f(CW$self\fR is created with the \f(CW\*(C`die_on_error\*(C'\fR flag, or if \f(CW$ExtUtils::ParseXS::DIE_ON_ERROR\fR is true when \fBprocess_file()\fR is called, then instead it will \fBdie()\fR with that message. .ie n .IP """$self\->WarnHint(@messages, $hints)""" 4 .el .IP "\f(CW$self\->WarnHint(@messages, $hints)\fR" 4 .IX Item "$self->WarnHint(@messages, $hints)" This is a more obscure twin to \f(CW\*(C`Warn\*(C'\fR, which does the same as \f(CW\*(C`Warn\*(C'\fR, but afterwards, outputs any lines contained in the \f(CW$hints\fR string, with each line wrapped in parentheses. For example: .Sp .Vb 2 \& $self\->WarnHint(@messages, \& "Have you set the foo switch?\enSee the manual for further info"); .Ve .ie n .SS check_conditional_preprocessor_statements() .el .SS \f(CWcheck_conditional_preprocessor_statements()\fP .IX Subsection "check_conditional_preprocessor_statements()" .IP \(bu 4 Purpose .Sp Warn if the lines in \f(CW\*(C`@{ $self\->{line} }\*(C'\fR don\*(Aqt have balanced \f(CW\*(C`#if\*(C'\fR, \&\f(CW\*(C`endif\*(C'\fR etc. .IP \(bu 4 Arguments .Sp None .IP \(bu 4 Return Value .Sp None .ie n .SS escape_file_for_line_directive() .el .SS \f(CWescape_file_for_line_directive()\fP .IX Subsection "escape_file_for_line_directive()" .IP \(bu 4 Purpose .Sp Escapes a given code source name (typically a file name but can also be a command that was read from) so that double\-quotes and backslashes are escaped. .IP \(bu 4 Arguments .Sp A string. .IP \(bu 4 Return Value .Sp A string with escapes for double\-quotes and backslashes. .ie n .SS """report_typemap_failure""" .el .SS \f(CWreport_typemap_failure\fP .IX Subsection "report_typemap_failure" .IP \(bu 4 Purpose .Sp Do error reporting for missing typemaps. .IP \(bu 4 Arguments .Sp The \f(CW\*(C`ExtUtils::ParseXS\*(C'\fR object. .Sp An \f(CW\*(C`ExtUtils::Typemaps\*(C'\fR object. .Sp The string that represents the C type that was not found in the typemap. .Sp Optionally, the string \f(CW\*(C`death\*(C'\fR or \f(CW\*(C`blurt\*(C'\fR to choose whether the error is immediately fatal or not. Default: \f(CW\*(C`blurt\*(C'\fR .IP \(bu 4 Return Value .Sp Returns nothing. Depending on the arguments, this may call \f(CW\*(C`death\*(C'\fR or \f(CW\*(C`blurt\*(C'\fR, the former of which is fatal.