File Coverage

blib/lib/XS/Install/FrozenShit/ParseXS/Utilities.pm
Criterion Covered Total %
statement 52 145 35.8
branch 11 50 22.0
condition 0 5 0.0
subroutine 12 23 52.1
pod 16 16 100.0
total 91 239 38.0


line stmt bran cond sub pod time code
1             package
2             XS::Install::FrozenShit::ParseXS::Utilities;
3 1     1   7 use strict;
  1         2  
  1         42  
4 1     1   6 use warnings;
  1         2  
  1         54  
5 1     1   7 use Exporter;
  1         2  
  1         43  
6 1     1   5 use File::Spec;
  1         2  
  1         24  
7 1     1   5 use XS::Install::FrozenShit::ParseXS::Constants ();
  1         1  
  1         2888  
8              
9             our $VERSION = '3.57';
10              
11             our (@ISA, @EXPORT_OK);
12             @ISA = qw(Exporter);
13             @EXPORT_OK = qw(
14             standard_typemap_locations
15             trim_whitespace
16             C_string
17             valid_proto_string
18             process_typemaps
19             map_type
20             standard_XS_defs
21             analyze_preprocessor_statement
22             set_cond
23             Warn
24             WarnHint
25             current_line_number
26             blurt
27             death
28             check_conditional_preprocessor_statements
29             escape_file_for_line_directive
30             report_typemap_failure
31             );
32              
33             =head1 NAME
34              
35             XS::Install::FrozenShit::ParseXS::Utilities - Subroutines used with XS::Install::FrozenShit::ParseXS
36              
37             =head1 SYNOPSIS
38              
39             use XS::Install::FrozenShit::ParseXS::Utilities qw(
40             standard_typemap_locations
41             trim_whitespace
42             C_string
43             valid_proto_string
44             process_typemaps
45             map_type
46             standard_XS_defs
47             analyze_preprocessor_statement
48             set_cond
49             Warn
50             blurt
51             death
52             check_conditional_preprocessor_statements
53             escape_file_for_line_directive
54             report_typemap_failure
55             );
56              
57             =head1 SUBROUTINES
58              
59             The following functions are not considered to be part of the public interface.
60             They are documented here for the benefit of future maintainers of this module.
61              
62             =head2 C
63              
64             =over 4
65              
66             =item * Purpose
67              
68             Provide a list of filepaths where F files may be found. The
69             filepaths -- relative paths to files (not just directory paths) -- appear in this list in lowest-to-highest priority.
70              
71             The highest priority is to look in the current directory.
72              
73             'typemap'
74              
75             The second and third highest priorities are to look in the parent of the
76             current directory and a directory called F underneath the parent
77             directory.
78              
79             '../typemap',
80             '../lib/ExtUtils/typemap',
81              
82             The fourth through ninth highest priorities are to look in the corresponding
83             grandparent, great-grandparent and great-great-grandparent directories.
84              
85             '../../typemap',
86             '../../lib/ExtUtils/typemap',
87             '../../../typemap',
88             '../../../lib/ExtUtils/typemap',
89             '../../../../typemap',
90             '../../../../lib/ExtUtils/typemap',
91              
92             The tenth and subsequent priorities are to look in directories named
93             F which are subdirectories of directories found in C<@INC> --
94             I a file named F actually exists in such a directory.
95             Example:
96              
97             '/usr/local/lib/perl5/5.10.1/ExtUtils/typemap',
98              
99             However, these filepaths appear in the list returned by
100             C in reverse order, I, lowest-to-highest.
101              
102             '/usr/local/lib/perl5/5.10.1/ExtUtils/typemap',
103             '../../../../lib/ExtUtils/typemap',
104             '../../../../typemap',
105             '../../../lib/ExtUtils/typemap',
106             '../../../typemap',
107             '../../lib/ExtUtils/typemap',
108             '../../typemap',
109             '../lib/ExtUtils/typemap',
110             '../typemap',
111             'typemap'
112              
113             =item * Arguments
114              
115             my @stl = standard_typemap_locations( \@INC );
116              
117             Reference to C<@INC>.
118              
119             =item * Return Value
120              
121             Array holding list of directories to be searched for F files.
122              
123             =back
124              
125             =cut
126              
127             SCOPE: {
128             my @tm_template;
129              
130             sub standard_typemap_locations {
131 0     0   0 my $include_ref = shift;
132              
133 0 0       0 if (not @tm_template) {
134 0         0 @tm_template = qw(typemap);
135              
136 0         0 my $updir = File::Spec->updir();
137 0         0 foreach my $dir (
138             File::Spec->catdir(($updir) x 1),
139             File::Spec->catdir(($updir) x 2),
140             File::Spec->catdir(($updir) x 3),
141             File::Spec->catdir(($updir) x 4),
142             ) {
143 0         0 unshift @tm_template, File::Spec->catfile($dir, 'typemap');
144 0         0 unshift @tm_template, File::Spec->catfile($dir, lib => ExtUtils => 'typemap');
145             }
146             }
147              
148 0         0 my @tm = @tm_template;
149 0         0 foreach my $dir (@{ $include_ref}) {
  0         0  
150 0         0 my $file = File::Spec->catfile($dir, ExtUtils => 'typemap');
151 0 0       0 unshift @tm, $file if -e $file;
152             }
153 0         0 return @tm;
154             }
155             } # end SCOPE
156              
157             =head2 C
158              
159             =over 4
160              
161             =item * Purpose
162              
163             Perform an in-place trimming of leading and trailing whitespace from the
164             first argument provided to the function.
165              
166             =item * Argument
167              
168             trim_whitespace($arg);
169              
170             =item * Return Value
171              
172             None. Remember: this is an I modification of the argument.
173              
174             =back
175              
176             =cut
177              
178             sub trim_whitespace {
179 2     2 1 22 $_[0] =~ s/^\s+|\s+$//go;
180             }
181              
182             =head2 C
183              
184             =over 4
185              
186             =item * Purpose
187              
188             Escape backslashes (C<\>) in prototype strings.
189              
190             =item * Arguments
191              
192             $ProtoThisXSUB = C_string($_);
193              
194             String needing escaping.
195              
196             =item * Return Value
197              
198             Properly escaped string.
199              
200             =back
201              
202             =cut
203              
204             sub C_string {
205 0     0 1 0 my($string) = @_;
206              
207 0         0 $string =~ s[\\][\\\\]g;
208 0         0 $string;
209             }
210              
211             =head2 C
212              
213             =over 4
214              
215             =item * Purpose
216              
217             Validate prototype string.
218              
219             =item * Arguments
220              
221             String needing checking.
222              
223             =item * Return Value
224              
225             Upon success, returns the same string passed as argument.
226              
227             Upon failure, returns C<0>.
228              
229             =back
230              
231             =cut
232              
233             sub valid_proto_string {
234 0     0 1 0 my ($string) = @_;
235              
236 0 0       0 if ( $string =~ /^$XS::Install::FrozenShit::ParseXS::Constants::PrototypeRegexp+$/ ) {
237 0         0 return $string;
238             }
239              
240 0         0 return 0;
241             }
242              
243             =head2 C
244              
245             =over 4
246              
247             =item * Purpose
248              
249             Process all typemap files.
250              
251             =item * Arguments
252              
253             my $typemaps_object = process_typemaps( $args{typemap}, $pwd );
254              
255             List of two elements: C element from C<%args>; current working
256             directory.
257              
258             =item * Return Value
259              
260             Upon success, returns an L object.
261              
262             =back
263              
264             =cut
265              
266             sub process_typemaps {
267 1     1 1 6 my ($tmap, $pwd) = @_;
268              
269 1 50       10 my @tm = ref $tmap ? @{$tmap} : ($tmap);
  1         10  
270              
271 1         40 foreach my $typemap (@tm) {
272 2 50       64 die "Can't find $typemap in $pwd\n" unless -r $typemap;
273             }
274              
275 1         19 push @tm, standard_typemap_locations( \@INC );
276              
277 1         23 require XS::Install::FrozenShit::Typemaps;
278 1         25 my $typemap = XS::Install::FrozenShit::Typemaps->new;
279 1         6 foreach my $typemap_loc (@tm) {
280 2 50       67 next unless -f $typemap_loc;
281             # skip directories, binary files etc.
282 2 50       227 warn("Warning: ignoring non-text typemap file '$typemap_loc'\n"), next
283             unless -T $typemap_loc;
284              
285 2         18 $typemap->merge(file => $typemap_loc, replace => 1);
286             }
287              
288 1         10 return $typemap;
289             }
290              
291              
292             =head2 C
293              
294             Returns a mapped version of the C type C<$type>. In particular, it
295             converts C to C, converts the special C
296             into C, and inserts C<$varname> (if present) into any function
297             pointer type. So C<...(*)...> becomes C<...(* foo)...>.
298              
299             =cut
300              
301             sub map_type {
302 6     6 1 13 my XS::Install::FrozenShit::ParseXS $self = shift;
303 6         15 my ($type, $varname) = @_;
304              
305             # C++ has :: in types too so skip this
306 6 50       23 $type =~ tr/:/_/ unless $self->{config_RetainCplusplusHierarchicalTypes};
307              
308             # map the special return type 'array(type, n)' to 'type *'
309 6         13 $type =~ s/^array\(([^,]*),(.*)\).*/$1 */s;
310              
311 6 50       16 if ($varname) {
312 0 0       0 if ($type =~ / \( \s* \* (?= \s* \) ) /xg) {
313 0         0 (substr $type, pos $type, 0) = " $varname ";
314             }
315             else {
316 0         0 $type .= "\t$varname";
317             }
318             }
319 6         41 return $type;
320             }
321              
322              
323             =head2 C
324              
325             =over 4
326              
327             =item * Purpose
328              
329             Writes to the C<.c> output file certain preprocessor directives and function
330             headers needed in all such files.
331              
332             =item * Arguments
333              
334             None.
335              
336             =item * Return Value
337              
338             Returns true.
339              
340             =back
341              
342             =cut
343              
344             sub standard_XS_defs {
345 1     1 1 5 print <<"EOF";
346             #ifndef PERL_UNUSED_VAR
347             # define PERL_UNUSED_VAR(var) if (0) var = var
348             #endif
349              
350             #ifndef dVAR
351             # define dVAR dNOOP
352             #endif
353              
354              
355             /* This stuff is not part of the API! You have been warned. */
356             #ifndef PERL_VERSION_DECIMAL
357             # define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
358             #endif
359             #ifndef PERL_DECIMAL_VERSION
360             # define PERL_DECIMAL_VERSION \\
361             PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
362             #endif
363             #ifndef PERL_VERSION_GE
364             # define PERL_VERSION_GE(r,v,s) \\
365             (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
366             #endif
367             #ifndef PERL_VERSION_LE
368             # define PERL_VERSION_LE(r,v,s) \\
369             (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
370             #endif
371              
372             /* XS_INTERNAL is the explicit static-linkage variant of the default
373             * XS macro.
374             *
375             * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
376             * "STATIC", ie. it exports XSUB symbols. You probably don't want that
377             * for anything but the BOOT XSUB.
378             *
379             * See XSUB.h in core!
380             */
381              
382              
383             /* TODO: This might be compatible further back than 5.10.0. */
384             #if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
385             # undef XS_EXTERNAL
386             # undef XS_INTERNAL
387             # if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
388             # define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
389             # define XS_INTERNAL(name) STATIC XSPROTO(name)
390             # endif
391             # if defined(__SYMBIAN32__)
392             # define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
393             # define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
394             # endif
395             # ifndef XS_EXTERNAL
396             # if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
397             # define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
398             # define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
399             # else
400             # ifdef __cplusplus
401             # define XS_EXTERNAL(name) extern "C" XSPROTO(name)
402             # define XS_INTERNAL(name) static XSPROTO(name)
403             # else
404             # define XS_EXTERNAL(name) XSPROTO(name)
405             # define XS_INTERNAL(name) STATIC XSPROTO(name)
406             # endif
407             # endif
408             # endif
409             #endif
410              
411             /* perl >= 5.10.0 && perl <= 5.15.1 */
412              
413              
414             /* The XS_EXTERNAL macro is used for functions that must not be static
415             * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
416             * macro defined, the best we can do is assume XS is the same.
417             * Dito for XS_INTERNAL.
418             */
419             #ifndef XS_EXTERNAL
420             # define XS_EXTERNAL(name) XS(name)
421             #endif
422             #ifndef XS_INTERNAL
423             # define XS_INTERNAL(name) XS(name)
424             #endif
425              
426             /* Now, finally, after all this mess, we want an XS::Install::FrozenShit::ParseXS
427             * internal macro that we're free to redefine for varying linkage due
428             * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
429             * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
430             */
431              
432             #undef XS_EUPXS
433             #if defined(PERL_EUPXS_ALWAYS_EXPORT)
434             # define XS_EUPXS(name) XS_EXTERNAL(name)
435             #else
436             /* default to internal */
437             # define XS_EUPXS(name) XS_INTERNAL(name)
438             #endif
439              
440             EOF
441              
442 1         7 print <<"EOF";
443             #ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
444             #define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
445              
446             /* prototype to pass -Wmissing-prototypes */
447             STATIC void
448             S_croak_xs_usage(const CV *const cv, const char *const params);
449              
450             STATIC void
451             S_croak_xs_usage(const CV *const cv, const char *const params)
452             {
453             const GV *const gv = CvGV(cv);
454              
455             PERL_ARGS_ASSERT_CROAK_XS_USAGE;
456              
457             if (gv) {
458             const char *const gvname = GvNAME(gv);
459             const HV *const stash = GvSTASH(gv);
460             const char *const hvname = stash ? HvNAME(stash) : NULL;
461              
462             if (hvname)
463             Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
464             else
465             Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
466             } else {
467             /* Pants. I don't think that it should be possible to get here. */
468             Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
469             }
470             }
471             #undef PERL_ARGS_ASSERT_CROAK_XS_USAGE
472              
473             #define croak_xs_usage S_croak_xs_usage
474              
475             #endif
476              
477             /* NOTE: the prototype of newXSproto() is different in versions of perls,
478             * so we define a portable version of newXSproto()
479             */
480             #ifdef newXS_flags
481             #define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
482             #else
483             #define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
484             #endif /* !defined(newXS_flags) */
485              
486             #if PERL_VERSION_LE(5, 21, 5)
487             # define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
488             #else
489             # define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
490             #endif
491              
492             /* simple backcompat versions of the TARGx() macros with no optimisation */
493             #ifndef TARGi
494             # define TARGi(iv, do_taint) sv_setiv_mg(TARG, iv)
495             # define TARGu(uv, do_taint) sv_setuv_mg(TARG, uv)
496             # define TARGn(nv, do_taint) sv_setnv_mg(TARG, nv)
497             #endif
498              
499             EOF
500 1         4 return 1;
501             }
502              
503             =head2 C
504              
505             =over 4
506              
507             =item * Purpose
508              
509             Process a CPP conditional line (C<#if> etc), to keep track of conditional
510             nesting. In particular, it updates C<< @{$self->{XS_parse_stack}} >> which
511             contains the current list of nested conditions, and
512             C<< $self->{XS_parse_stack_top_if_idx} >> which indicates the most recent
513             C in that stack. So an C<#if> pushes, an C<#endif> pops, an C<#else>
514             modifies etc. Each element is a hash of the form:
515              
516             {
517             type => 'if',
518             varname => 'XSubPPtmpAAAA', # maintained by caller
519              
520             # XS functions defined within this branch of the
521             # conditional (maintained by caller)
522             functions => {
523             'Foo::Bar::baz' => 1,
524             ...
525             }
526             # XS functions seen within any previous branch
527             other_functions => {... }
528              
529             It also updates C<< $self->{bootcode_early} >> and
530             C<< $self->{bootcode_late} >> with extra CPP directives.
531              
532             =item * Arguments
533              
534             $self->analyze_preprocessor_statement($statement);
535              
536             =back
537              
538             =cut
539              
540             sub analyze_preprocessor_statement {
541 0     0 1 0 my XS::Install::FrozenShit::ParseXS $self = shift;
542 0         0 my ($statement) = @_;
543              
544 0         0 my $ix = $self->{XS_parse_stack_top_if_idx};
545              
546 0 0       0 if ($statement eq 'if') {
547             # #if or #ifdef
548 0         0 $ix = @{ $self->{XS_parse_stack} };
  0         0  
549 0         0 push(@{ $self->{XS_parse_stack} }, {type => 'if'});
  0         0  
550             }
551             else {
552             # An #else/#elsif/#endif.
553              
554             $self->death("Error: '$statement' with no matching 'if'")
555 0 0       0 if $self->{XS_parse_stack}->[-1]{type} ne 'if';
556              
557 0 0       0 if ($self->{XS_parse_stack}->[-1]{varname}) {
558             # close any '#ifdef XSubPPtmpAAAA' inserted earlier into boot code.
559 0         0 push(@{ $self->{bootcode_early} }, "#endif\n");
  0         0  
560 0         0 push(@{ $self->{bootcode_later} }, "#endif\n");
  0         0  
561             }
562              
563 0         0 my(@fns) = keys %{$self->{XS_parse_stack}->[-1]{functions}};
  0         0  
564              
565 0 0       0 if ($statement ne 'endif') {
566             # Add current functions to the hash of functions seen in previous
567             # branch limbs, then reset for this next limb of the branch.
568 0         0 @{$self->{XS_parse_stack}->[-1]{other_functions}}{@fns} = (1) x @fns;
  0         0  
569 0         0 @{$self->{XS_parse_stack}->[-1]}{qw(varname functions)} = ('', {});
  0         0  
570             }
571             else {
572             # #endif - pop stack and update new top entry
573 0         0 my($tmp) = pop(@{ $self->{XS_parse_stack} });
  0         0  
574             0 while (--$ix
575 0   0     0 && $self->{XS_parse_stack}->[$ix]{type} ne 'if');
576              
577             # For all functions declared within any limb of the just-popped
578             # if/endif, mark them as having appeared within this limb of the
579             # outer nested branch.
580 0         0 push(@fns, keys %{$tmp->{other_functions}});
  0         0  
581 0         0 @{$self->{XS_parse_stack}->[$ix]{functions}}{@fns} = (1) x @fns;
  0         0  
582             }
583             }
584              
585 0         0 $self->{XS_parse_stack_top_if_idx} = $ix;
586             }
587              
588              
589             =head2 C
590              
591             =over 4
592              
593             =item * Purpose
594              
595             Return a string containing a snippet of C code which tests for the 'wrong
596             number of arguments passed' condition, depending on whether there are
597             default arguments or ellipsis.
598              
599             =item * Arguments
600              
601             C true if the xsub's signature has a trailing C<, ...>.
602              
603             C<$min_args> the smallest number of args which may be passed.
604              
605             C<$num_args> the number of parameters in the signature.
606              
607             =item * Return Value
608              
609             The text of a short C code snippet.
610              
611             =back
612              
613             =cut
614              
615             sub set_cond {
616 4     4 1 15 my ($ellipsis, $min_args, $num_args) = @_;
617 4         9 my $cond;
618 4 100       14 if ($ellipsis) {
    50          
619 2 50       12 $cond = ($min_args ? qq(items < $min_args) : 0);
620             }
621             elsif ($min_args == $num_args) {
622 2         7 $cond = qq(items != $min_args);
623             }
624             else {
625 0         0 $cond = qq(items < $min_args || items > $num_args);
626             }
627 4         13 return $cond;
628             }
629              
630             =head2 C
631              
632             =over 4
633              
634             =item * Purpose
635              
636             Figures out the current line number in the XS file.
637              
638             =item * Arguments
639              
640             C<$self>
641              
642             =item * Return Value
643              
644             The current line number.
645              
646             =back
647              
648             =cut
649              
650             sub current_line_number {
651 0     0 1 0 my XS::Install::FrozenShit::ParseXS $self = shift;
652 0         0 my $line_number = $self->{line_no}->[@{ $self->{line_no} } - @{ $self->{line} } -1];
  0         0  
  0         0  
653 0         0 return $line_number;
654             }
655              
656              
657              
658             =head2 Error handling methods
659              
660             There are four main methods for reporting warnings and errors.
661              
662             =over
663              
664             =item C<< $self->Warn(@messages) >>
665              
666             This is equivalent to:
667              
668             warn "@messages in foo.xs, line 123\n";
669              
670             The file and line number are based on the file currently being parsed. It
671             is intended for use where you wish to warn, but can continue parsing and
672             still generate a correct C output file.
673              
674             =item C<< $self->blurt(@messages) >>
675              
676             This is equivalent to C, except that it also increments the internal
677             error count (which can be retrieved with C). It is
678             used to report an error, but where parsing can continue (so typically for
679             a semantic error rather than a syntax error). It is expected that the
680             caller will eventually signal failure in some fashion. For example,
681             C has this as its last line:
682              
683             exit($self->report_error_count() ? 1 : 0);
684              
685             =item C<< $self->death(@messages) >>
686              
687             This normally equivalent to:
688              
689             $self->Warn(@messages);
690             exit(1);
691              
692             It is used for something like a syntax error, where parsing can't
693             continue. However, this is inconvenient for testing purposes, as the
694             error can't be trapped. So if C<$self> is created with the C
695             flag, or if C<$XS::Install::FrozenShit::ParseXS::DIE_ON_ERROR> is true when process_file()
696             is called, then instead it will die() with that message.
697              
698             =item C<< $self->WarnHint(@messages, $hints) >>
699              
700             This is a more obscure twin to C, which does the same as C,
701             but afterwards, outputs any lines contained in the C<$hints> string, with
702             each line wrapped in parentheses. For example:
703              
704             $self->WarnHint(@messages,
705             "Have you set the foo switch?\nSee the manual for further info");
706              
707             =back
708              
709             =cut
710              
711              
712             # see L above
713              
714             sub Warn {
715 0     0 1 0 my XS::Install::FrozenShit::ParseXS $self = shift;
716 0         0 $self->WarnHint(@_,undef);
717             }
718              
719              
720             # see L above
721              
722             sub WarnHint {
723 0     0 1 0 warn _MsgHint(@_);
724             }
725              
726              
727             # see L above
728              
729             sub _MsgHint {
730 0     0   0 my XS::Install::FrozenShit::ParseXS $self = shift;
731 0         0 my $hint = pop;
732 0         0 my $warn_line_number = $self->current_line_number();
733 0         0 my $ret = join("",@_) . " in $self->{in_filename}, line $warn_line_number\n";
734 0 0       0 if ($hint) {
735 0         0 $ret .= " ($_)\n" for split /\n/, $hint;
736             }
737 0         0 return $ret;
738             }
739              
740              
741             # see L above
742              
743             sub blurt {
744 0     0 1 0 my XS::Install::FrozenShit::ParseXS $self = shift;
745 0         0 $self->Warn(@_);
746 0         0 $self->{error_count}++
747             }
748              
749              
750             # see L above
751              
752             sub death {
753 0     0 1 0 my XS::Install::FrozenShit::ParseXS $self = $_[0];
754 0         0 my $message = _MsgHint(@_,"");
755 0 0       0 if ($self->{config_die_on_error}) {
756 0         0 die $message;
757             } else {
758 0         0 warn $message;
759             }
760 0         0 exit 1;
761             }
762              
763              
764             =head2 C
765              
766             =over 4
767              
768             =item * Purpose
769              
770             Warn if the lines in C<< @{ $self->{line} } >> don't have balanced C<#if>,
771             C etc.
772              
773             =item * Arguments
774              
775             None
776              
777             =item * Return Value
778              
779             None
780              
781             =back
782              
783             =cut
784              
785             sub check_conditional_preprocessor_statements {
786 5     5 1 29 my XS::Install::FrozenShit::ParseXS $self = $_[0];
787 5         30 my @cpp = grep(/^\#\s*(?:if|e\w+)/, @{ $self->{line} });
  5         28  
788 5 50       24 if (@cpp) {
789 0         0 my $cpplevel;
790 0         0 for my $cpp (@cpp) {
791 0 0       0 if ($cpp =~ /^\#\s*if/) {
    0          
    0          
792 0         0 $cpplevel++;
793             }
794             elsif (!$cpplevel) {
795 0         0 $self->Warn("Warning: #else/elif/endif without #if in this function");
796             print STDERR " (precede it with a blank line if the matching #if is outside the function)\n"
797 0 0       0 if $self->{XS_parse_stack}->[-1]{type} eq 'if';
798 0         0 return;
799             }
800             elsif ($cpp =~ /^\#\s*endif/) {
801 0         0 $cpplevel--;
802             }
803             }
804 0 0       0 $self->Warn("Warning: #if without #endif in this function") if $cpplevel;
805             }
806             }
807              
808             =head2 C
809              
810             =over 4
811              
812             =item * Purpose
813              
814             Escapes a given code source name (typically a file name but can also
815             be a command that was read from) so that double-quotes and backslashes are escaped.
816              
817             =item * Arguments
818              
819             A string.
820              
821             =item * Return Value
822              
823             A string with escapes for double-quotes and backslashes.
824              
825             =back
826              
827             =cut
828              
829             sub escape_file_for_line_directive {
830 6     6 1 18 my $string = shift;
831 6         17 $string =~ s/\\/\\\\/g;
832 6         15 $string =~ s/"/\\"/g;
833 6         39 return $string;
834             }
835              
836             =head2 C
837              
838             =over 4
839              
840             =item * Purpose
841              
842             Do error reporting for missing typemaps.
843              
844             =item * Arguments
845              
846             The C object.
847              
848             An C object.
849              
850             The string that represents the C type that was not found in the typemap.
851              
852             Optionally, the string C or C to choose
853             whether the error is immediately fatal or not. Default: C
854              
855             =item * Return Value
856              
857             Returns nothing. Depending on the arguments, this
858             may call C or C, the former of which is
859             fatal.
860              
861             =back
862              
863             =cut
864              
865             sub report_typemap_failure {
866 0     0 1   my XS::Install::FrozenShit::ParseXS $self = shift;
867 0           my ($tm, $ctype, $error_method) = @_;
868 0   0       $error_method ||= 'blurt';
869              
870 0           my @avail_ctypes = $tm->list_mapped_ctypes;
871              
872 0           my $err = "Could not find a typemap for C type '$ctype'.\n"
873             . "The following C types are mapped by the current typemap:\n'"
874             . join("', '", @avail_ctypes) . "'\n";
875              
876 0           $self->$error_method($err);
877 0           return();
878             }
879              
880              
881             1;
882              
883             # vim: ts=2 sw=2 et: