File Coverage

blib/lib/ExtUtils/ParseXS/Utilities.pm
Criterion Covered Total %
statement 135 148 91.2
branch 49 54 90.7
condition 1 5 20.0
subroutine 22 24 91.6
pod 18 18 100.0
total 225 249 90.3


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