This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
929a70e38b92ba6136486894907780575aca457c
[perl5.git] / dist / Locale-Maketext / lib / Locale / Maketext.pm
1 package Locale::Maketext;
2 use strict;
3 use vars qw( @ISA $VERSION $MATCH_SUPERS $USING_LANGUAGE_TAGS
4 $USE_LITERALS $MATCH_SUPERS_TIGHTLY);
5 use Carp ();
6 use I18N::LangTags 0.30 ();
7
8 #--------------------------------------------------------------------------
9
10 BEGIN { unless(defined &DEBUG) { *DEBUG = sub () {0} } }
11 # define the constant 'DEBUG' at compile-time
12
13 # turn on utf8 if we have it (this is what GutsLoader.pm used to do essentially )
14 #    use if (exists $INC{'utf8.pm'} || eval 'use utf8'), 'utf8';
15 BEGIN {
16
17     # if we have it || we can load it
18     if ( exists $INC{'utf8.pm'} || eval { local $SIG{'__DIE__'};require utf8; } ) {
19         utf8->import();
20         DEBUG and warn " utf8 on for _compile()\n";
21     }
22     else {
23         DEBUG and warn " utf8 not available for _compile() ($INC{'utf8.pm'})\n$@\n";
24     }
25 }
26
27
28 $VERSION = '1.15';
29 @ISA = ();
30
31 $MATCH_SUPERS = 1;
32 $MATCH_SUPERS_TIGHTLY = 1;
33 $USING_LANGUAGE_TAGS  = 1;
34 # Turning this off is somewhat of a security risk in that little or no
35 # checking will be done on the legality of tokens passed to the
36 # eval("use $module_name") in _try_use.  If you turn this off, you have
37 # to do your own taint checking.
38
39 $USE_LITERALS = 1 unless defined $USE_LITERALS;
40 # a hint for compiling bracket-notation things.
41
42 my %isa_scan = ();
43
44 ###########################################################################
45
46 sub quant {
47     my($handle, $num, @forms) = @_;
48
49     return $num if @forms == 0; # what should this mean?
50     return $forms[2] if @forms > 2 and $num == 0; # special zeroth case
51
52     # Normal case:
53     # Note that the formatting of $num is preserved.
54     return( $handle->numf($num) . ' ' . $handle->numerate($num, @forms) );
55     # Most human languages put the number phrase before the qualified phrase.
56 }
57
58
59 sub numerate {
60     # return this lexical item in a form appropriate to this number
61     my($handle, $num, @forms) = @_;
62     my $s = ($num == 1);
63
64     return '' unless @forms;
65     if(@forms == 1) { # only the headword form specified
66         return $s ? $forms[0] : ($forms[0] . 's'); # very cheap hack.
67     }
68     else { # sing and plural were specified
69         return $s ? $forms[0] : $forms[1];
70     }
71 }
72
73 #--------------------------------------------------------------------------
74
75 sub numf {
76     my($handle, $num) = @_[0,1];
77     if($num < 10_000_000_000 and $num > -10_000_000_000 and $num == int($num)) {
78         $num += 0;  # Just use normal integer stringification.
79         # Specifically, don't let %G turn ten million into 1E+007
80     }
81     else {
82         $num = CORE::sprintf('%G', $num);
83         # "CORE::" is there to avoid confusion with the above sub sprintf.
84     }
85     while( $num =~ s/^([-+]?\d+)(\d{3})/$1,$2/s ) {1}  # right from perlfaq5
86     # The initial \d+ gobbles as many digits as it can, and then we
87     #  backtrack so it un-eats the rightmost three, and then we
88     #  insert the comma there.
89
90     $num =~ tr<.,><,.> if ref($handle) and $handle->{'numf_comma'};
91     # This is just a lame hack instead of using Number::Format
92     return $num;
93 }
94
95 sub sprintf {
96     no integer;
97     my($handle, $format, @params) = @_;
98     return CORE::sprintf($format, @params);
99     # "CORE::" is there to avoid confusion with myself!
100 }
101
102 #=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
103
104 use integer; # vroom vroom... applies to the whole rest of the module
105
106 sub language_tag {
107     my $it = ref($_[0]) || $_[0];
108     return undef unless $it =~ m/([^':]+)(?:::)?$/s;
109     $it = lc($1);
110     $it =~ tr<_><->;
111     return $it;
112 }
113
114 sub encoding {
115     my $it = $_[0];
116     return(
117         (ref($it) && $it->{'encoding'})
118         || 'iso-8859-1'   # Latin-1
119     );
120 }
121
122 #--------------------------------------------------------------------------
123
124 sub fallback_languages { return('i-default', 'en', 'en-US') }
125
126 sub fallback_language_classes { return () }
127
128 #--------------------------------------------------------------------------
129
130 sub fail_with { # an actual attribute method!
131     my($handle, @params) = @_;
132     return unless ref($handle);
133     $handle->{'fail'} = $params[0] if @params;
134     return $handle->{'fail'};
135 }
136
137 #--------------------------------------------------------------------------
138
139 sub failure_handler_auto {
140     # Meant to be used like:
141     #  $handle->fail_with('failure_handler_auto')
142
143     my $handle = shift;
144     my $phrase = shift;
145
146     $handle->{'failure_lex'} ||= {};
147     my $lex = $handle->{'failure_lex'};
148
149     my $value;
150     $lex->{$phrase} ||= ($value = $handle->_compile($phrase));
151
152     # Dumbly copied from sub maketext:
153     return ${$value} if ref($value) eq 'SCALAR';
154     return $value    if ref($value) ne 'CODE';
155     {
156         local $SIG{'__DIE__'};
157         eval { $value = &$value($handle, @_) };
158     }
159     # If we make it here, there was an exception thrown in the
160     #  call to $value, and so scream:
161     if($@) {
162         my $err = $@;
163         # pretty up the error message
164         $err =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?}
165                  {\n in bracket code [compiled line $1],}s;
166         #$err =~ s/\n?$/\n/s;
167         Carp::croak "Error in maketexting \"$phrase\":\n$err as used";
168         # Rather unexpected, but suppose that the sub tried calling
169         # a method that didn't exist.
170     }
171     else {
172         return $value;
173     }
174 }
175
176 #==========================================================================
177
178 sub new {
179     # Nothing fancy!
180     my $class = ref($_[0]) || $_[0];
181     my $handle = bless {}, $class;
182     $handle->init;
183     return $handle;
184 }
185
186 sub init { return } # no-op
187
188 ###########################################################################
189
190 sub maketext {
191     # Remember, this can fail.  Failure is controllable many ways.
192     Carp::croak 'maketext requires at least one parameter' unless @_ > 1;
193
194     my($handle, $phrase) = splice(@_,0,2);
195     Carp::confess('No handle/phrase') unless (defined($handle) && defined($phrase));
196
197
198     # Don't interefere with $@ in case that's being interpolated into the msg.
199     local $@;
200
201     # Look up the value:
202
203     my $value;
204     if (exists $handle->{'_external_lex_cache'}{$phrase}) {
205         DEBUG and warn "* Using external lex cache version of \"$phrase\"\n";
206         $value = $handle->{'_external_lex_cache'}{$phrase};
207     }
208     else {
209         foreach my $h_r (
210             @{  $isa_scan{ref($handle) || $handle} || $handle->_lex_refs  }
211         ) {
212             DEBUG and warn "* Looking up \"$phrase\" in $h_r\n";
213             if(exists $h_r->{$phrase}) {
214                 DEBUG and warn "  Found \"$phrase\" in $h_r\n";
215                 unless(ref($value = $h_r->{$phrase})) {
216                     # Nonref means it's not yet compiled.  Compile and replace.
217                     if ($handle->{'use_external_lex_cache'}) {
218                         $value = $handle->{'_external_lex_cache'}{$phrase} = $handle->_compile($value);
219                     }
220                     else {
221                         $value = $h_r->{$phrase} = $handle->_compile($value);
222                     }
223                 }
224                 last;
225             }
226             # extending packages need to be able to localize _AUTO and if readonly can't "local $h_r->{'_AUTO'} = 1;"
227             # but they can "local $handle->{'_external_lex_cache'}{'_AUTO'} = 1;"
228             elsif($phrase !~ m/^_/s and ($handle->{'use_external_lex_cache'} ? ( exists $handle->{'_external_lex_cache'}{'_AUTO'} ? $handle->{'_external_lex_cache'}{'_AUTO'} : $h_r->{'_AUTO'} ) : $h_r->{'_AUTO'})) {
229                 # it's an auto lex, and this is an autoable key!
230                 DEBUG and warn "  Automaking \"$phrase\" into $h_r\n";
231                 if ($handle->{'use_external_lex_cache'}) {
232                     $value = $handle->{'_external_lex_cache'}{$phrase} = $handle->_compile($phrase);
233                 }
234                 else {
235                     $value = $h_r->{$phrase} = $handle->_compile($phrase);
236                 }
237                 last;
238             }
239             DEBUG>1 and print "  Not found in $h_r, nor automakable\n";
240             # else keep looking
241         }
242     }
243
244     unless(defined($value)) {
245         DEBUG and warn "! Lookup of \"$phrase\" in/under ", ref($handle) || $handle, " fails.\n";
246         if(ref($handle) and $handle->{'fail'}) {
247             DEBUG and warn "WARNING0: maketext fails looking for <$phrase>\n";
248             my $fail;
249             if(ref($fail = $handle->{'fail'}) eq 'CODE') { # it's a sub reference
250                 return &{$fail}($handle, $phrase, @_);
251                 # If it ever returns, it should return a good value.
252             }
253             else { # It's a method name
254                 return $handle->$fail($phrase, @_);
255                 # If it ever returns, it should return a good value.
256             }
257         }
258         else {
259             # All we know how to do is this;
260             Carp::croak("maketext doesn't know how to say:\n$phrase\nas needed");
261         }
262     }
263
264     return $$value if ref($value) eq 'SCALAR';
265     return $value unless ref($value) eq 'CODE';
266
267     {
268         local $SIG{'__DIE__'};
269         eval { $value = &$value($handle, @_) };
270     }
271     # If we make it here, there was an exception thrown in the
272     #  call to $value, and so scream:
273     if ($@) {
274         my $err = $@;
275         # pretty up the error message
276         $err =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?}
277                  {\n in bracket code [compiled line $1],}s;
278         #$err =~ s/\n?$/\n/s;
279         Carp::croak "Error in maketexting \"$phrase\":\n$err as used";
280         # Rather unexpected, but suppose that the sub tried calling
281         # a method that didn't exist.
282     }
283     else {
284         return $value;
285     }
286 }
287
288 ###########################################################################
289
290 sub get_handle {  # This is a constructor and, yes, it CAN FAIL.
291     # Its class argument has to be the base class for the current
292     # application's l10n files.
293
294     my($base_class, @languages) = @_;
295     $base_class = ref($base_class) || $base_class;
296     # Complain if they use __PACKAGE__ as a project base class?
297
298     if( @languages ) {
299         DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
300         if($USING_LANGUAGE_TAGS) {   # An explicit language-list was given!
301             @languages =
302             map {; $_, I18N::LangTags::alternate_language_tags($_) }
303             # Catch alternation
304             map I18N::LangTags::locale2language_tag($_),
305             # If it's a lg tag, fine, pass thru (untainted)
306             # If it's a locale ID, try converting to a lg tag (untainted),
307             # otherwise nix it.
308             @languages;
309             DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
310         }
311     }
312     else {
313         @languages = $base_class->_ambient_langprefs;
314     }
315
316     @languages = $base_class->_langtag_munging(@languages);
317
318     my %seen;
319     foreach my $module_name ( map { $base_class . '::' . $_ }  @languages ) {
320         next unless length $module_name; # sanity
321         next if $seen{$module_name}++        # Already been here, and it was no-go
322         || !&_try_use($module_name); # Try to use() it, but can't it.
323         return($module_name->new); # Make it!
324     }
325
326     return undef; # Fail!
327 }
328
329 ###########################################################################
330
331 sub _langtag_munging {
332     my($base_class, @languages) = @_;
333
334     # We have all these DEBUG statements because otherwise it's hard as hell
335     # to diagnose ifwhen something goes wrong.
336
337     DEBUG and warn 'Lgs1: ', map("<$_>", @languages), "\n";
338
339     if($USING_LANGUAGE_TAGS) {
340         DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
341         @languages     = $base_class->_add_supers( @languages );
342
343         push @languages, I18N::LangTags::panic_languages(@languages);
344         DEBUG and warn "After adding panic languages:\n",
345         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
346
347         push @languages, $base_class->fallback_languages;
348         # You are free to override fallback_languages to return empty-list!
349         DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
350
351         @languages =  # final bit of processing to turn them into classname things
352         map {
353             my $it = $_;  # copy
354             $it =~ tr<-A-Z><_a-z>; # lc, and turn - to _
355             $it =~ tr<_a-z0-9><>cd;  # remove all but a-z0-9_
356             $it;
357         } @languages
358         ;
359         DEBUG and warn "Nearing end of munging:\n",
360         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
361     }
362     else {
363         DEBUG and warn "Bypassing language-tags.\n",
364         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
365     }
366
367     DEBUG and warn "Before adding fallback classes:\n",
368     ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
369
370     push @languages, $base_class->fallback_language_classes;
371     # You are free to override that to return whatever.
372
373     DEBUG and warn "Finally:\n",
374     ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
375
376     return @languages;
377 }
378
379 ###########################################################################
380
381 sub _ambient_langprefs {
382     require I18N::LangTags::Detect;
383     return  I18N::LangTags::Detect::detect();
384 }
385
386 ###########################################################################
387
388 sub _add_supers {
389     my($base_class, @languages) = @_;
390
391     if (!$MATCH_SUPERS) {
392         # Nothing
393         DEBUG and warn "Bypassing any super-matching.\n",
394         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
395
396     }
397     elsif( $MATCH_SUPERS_TIGHTLY ) {
398         DEBUG and warn "Before adding new supers tightly:\n",
399         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
400         @languages = I18N::LangTags::implicate_supers( @languages );
401         DEBUG and warn "After adding new supers tightly:\n",
402         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
403
404     }
405     else {
406         DEBUG and warn "Before adding supers to end:\n",
407         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
408         @languages = I18N::LangTags::implicate_supers_strictly( @languages );
409         DEBUG and warn "After adding supers to end:\n",
410         ' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
411     }
412
413     return @languages;
414 }
415
416 ###########################################################################
417 #
418 # This is where most people should stop reading.
419 #
420 ###########################################################################
421
422 my %tried = ();
423 # memoization of whether we've used this module, or found it unusable.
424
425 sub _try_use {   # Basically a wrapper around "require Modulename"
426     # "Many men have tried..."  "They tried and failed?"  "They tried and died."
427     return $tried{$_[0]} if exists $tried{$_[0]};  # memoization
428
429     my $module = $_[0];   # ASSUME sane module name!
430     { no strict 'refs';
431         return($tried{$module} = 1)
432         if %{$module . '::Lexicon'} or @{$module . '::ISA'};
433         # weird case: we never use'd it, but there it is!
434     }
435
436     DEBUG and warn " About to use $module ...\n";
437     {
438         local $SIG{'__DIE__'};
439         eval "require $module"; # used to be "use $module", but no point in that.
440     }
441     if($@) {
442         DEBUG and warn "Error using $module \: $@\n";
443         return $tried{$module} = 0;
444     }
445     else {
446         DEBUG and warn " OK, $module is used\n";
447         return $tried{$module} = 1;
448     }
449 }
450
451 #--------------------------------------------------------------------------
452
453 sub _lex_refs {  # report the lexicon references for this handle's class
454     # returns an arrayREF!
455     no strict 'refs';
456     no warnings 'once';
457     my $class = ref($_[0]) || $_[0];
458     DEBUG and warn "Lex refs lookup on $class\n";
459     return $isa_scan{$class} if exists $isa_scan{$class};  # memoization!
460
461     my @lex_refs;
462     my $seen_r = ref($_[1]) ? $_[1] : {};
463
464     if( defined( *{$class . '::Lexicon'}{'HASH'} )) {
465         push @lex_refs, *{$class . '::Lexicon'}{'HASH'};
466         DEBUG and warn '%' . $class . '::Lexicon contains ',
467             scalar(keys %{$class . '::Lexicon'}), " entries\n";
468     }
469
470     # Implements depth(height?)-first recursive searching of superclasses.
471     # In hindsight, I suppose I could have just used Class::ISA!
472     foreach my $superclass (@{$class . '::ISA'}) {
473         DEBUG and warn " Super-class search into $superclass\n";
474         next if $seen_r->{$superclass}++;
475         push @lex_refs, @{&_lex_refs($superclass, $seen_r)};  # call myself
476     }
477
478     $isa_scan{$class} = \@lex_refs; # save for next time
479     return \@lex_refs;
480 }
481
482 sub clear_isa_scan { %isa_scan = (); return; } # end on a note of simplicity!
483
484 #--------------------------------------------------------------------------
485
486 sub _compile {
487     # This big scary routine compiles an entry.
488     # It returns either a coderef if there's brackety bits in this, or
489     #  otherwise a ref to a scalar.
490
491     my $target = ref($_[0]) || $_[0];
492
493     my(@code);
494     my(@c) = (''); # "chunks" -- scratch.
495     my $call_count = 0;
496     my $big_pile = '';
497     {
498         my $in_group = 0; # start out outside a group
499         my($m, @params); # scratch
500
501         while($_[1] =~  # Iterate over chunks.
502             m/\G(
503                 [^\~\[\]]+  # non-~[] stuff
504                 |
505                 ~.       # ~[, ~], ~~, ~other
506                 |
507                 \[          # [ presumably opening a group
508                 |
509                 \]          # ] presumably closing a group
510                 |
511                 ~           # terminal ~ ?
512                 |
513                 $
514             )/xgs
515         ) {
516             DEBUG>2 and warn qq{  "$1"\n};
517
518             if($1 eq '[' or $1 eq '') {       # "[" or end
519                 # Whether this is "[" or end, force processing of any
520                 #  preceding literal.
521                 if($in_group) {
522                     if($1 eq '') {
523                         $target->_die_pointing($_[1], 'Unterminated bracket group');
524                     }
525                     else {
526                         $target->_die_pointing($_[1], 'You can\'t nest bracket groups');
527                     }
528                 }
529                 else {
530                     if ($1 eq '') {
531                         DEBUG>2 and warn "   [end-string]\n";
532                     }
533                     else {
534                         $in_group = 1;
535                     }
536                     die "How come \@c is empty?? in <$_[1]>" unless @c; # sanity
537                     if(length $c[-1]) {
538                         # Now actually processing the preceding literal
539                         $big_pile .= $c[-1];
540                         if($USE_LITERALS and (
541                                 (ord('A') == 65)
542                                 ? $c[-1] !~ m/[^\x20-\x7E]/s
543                                 # ASCII very safe chars
544                                 : $c[-1] !~ m/[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~\x07]/s
545                                 # EBCDIC very safe chars
546                             )) {
547                             # normal case -- all very safe chars
548                             $c[-1] =~ s/'/\\'/g;
549                             push @code, q{ '} . $c[-1] . "',\n";
550                             $c[-1] = ''; # reuse this slot
551                         }
552                         else {
553                             push @code, ' $c[' . $#c . "],\n";
554                             push @c, ''; # new chunk
555                         }
556                     }
557                     # else just ignore the empty string.
558                 }
559
560             }
561             elsif($1 eq ']') {  # "]"
562                 # close group -- go back in-band
563                 if($in_group) {
564                     $in_group = 0;
565
566                     DEBUG>2 and warn "   --Closing group [$c[-1]]\n";
567
568                     # And now process the group...
569
570                     if(!length($c[-1]) or $c[-1] =~ m/^\s+$/s) {
571                         DEBUG>2 and warn "   -- (Ignoring)\n";
572                         $c[-1] = ''; # reset out chink
573                         next;
574                     }
575
576                     #$c[-1] =~ s/^\s+//s;
577                     #$c[-1] =~ s/\s+$//s;
578                     ($m,@params) = split(/,/, $c[-1], -1);  # was /\s*,\s*/
579
580                     # A bit of a hack -- we've turned "~,"'s into DELs, so turn
581                     #  'em into real commas here.
582                     if (ord('A') == 65) { # ASCII, etc
583                         foreach($m, @params) { tr/\x7F/,/ }
584                     }
585                     else {              # EBCDIC (1047, 0037, POSIX-BC)
586                         # Thanks to Peter Prymmer for the EBCDIC handling
587                         foreach($m, @params) { tr/\x07/,/ }
588                     }
589
590                     # Special-case handling of some method names:
591                     if($m eq '_*' or $m =~ m/^_(-?\d+)$/s) {
592                         # Treat [_1,...] as [,_1,...], etc.
593                         unshift @params, $m;
594                         $m = '';
595                     }
596                     elsif($m eq '*') {
597                         $m = 'quant'; # "*" for "times": "4 cars" is 4 times "cars"
598                     }
599                     elsif($m eq '#') {
600                         $m = 'numf';  # "#" for "number": [#,_1] for "the number _1"
601                     }
602
603                     # Most common case: a simple, legal-looking method name
604                     if($m eq '') {
605                         # 0-length method name means to just interpolate:
606                         push @code, ' (';
607                     }
608                     elsif($m =~ /^\w+(?:\:\:\w+)*$/s
609                             and $m !~ m/(?:^|\:)\d/s
610                         # exclude starting a (sub)package or symbol with a digit
611                     ) {
612                         # Yes, it even supports the demented (and undocumented?)
613                         #  $obj->Foo::bar(...) syntax.
614                         $target->_die_pointing(
615                             $_[1], q{Can't use "SUPER::" in a bracket-group method},
616                             2 + length($c[-1])
617                         )
618                         if $m =~ m/^SUPER::/s;
619                         # Because for SUPER:: to work, we'd have to compile this into
620                         #  the right package, and that seems just not worth the bother,
621                         #  unless someone convinces me otherwise.
622
623                         push @code, ' $_[0]->' . $m . '(';
624                     }
625                     else {
626                         # TODO: implement something?  or just too icky to consider?
627                         $target->_die_pointing(
628                             $_[1],
629                             "Can't use \"$m\" as a method name in bracket group",
630                             2 + length($c[-1])
631                         );
632                     }
633
634                     pop @c; # we don't need that chunk anymore
635                     ++$call_count;
636
637                     foreach my $p (@params) {
638                         if($p eq '_*') {
639                             # Meaning: all parameters except $_[0]
640                             $code[-1] .= ' @_[1 .. $#_], ';
641                             # and yes, that does the right thing for all @_ < 3
642                         }
643                         elsif($p =~ m/^_(-?\d+)$/s) {
644                             # _3 meaning $_[3]
645                             $code[-1] .= '$_[' . (0 + $1) . '], ';
646                         }
647                         elsif($USE_LITERALS and (
648                                 (ord('A') == 65)
649                                 ? $p !~ m/[^\x20-\x7E]/s
650                                 # ASCII very safe chars
651                                 : $p !~ m/[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~\x07]/s
652                                 # EBCDIC very safe chars
653                             )) {
654                             # Normal case: a literal containing only safe characters
655                             $p =~ s/'/\\'/g;
656                             $code[-1] .= q{'} . $p . q{', };
657                         }
658                         else {
659                             # Stow it on the chunk-stack, and just refer to that.
660                             push @c, $p;
661                             push @code, ' $c[' . $#c . '], ';
662                         }
663                     }
664                     $code[-1] .= "),\n";
665
666                     push @c, '';
667                 }
668                 else {
669                     $target->_die_pointing($_[1], q{Unbalanced ']'});
670                 }
671
672             }
673             elsif(substr($1,0,1) ne '~') {
674                 # it's stuff not containing "~" or "[" or "]"
675                 # i.e., a literal blob
676                 $c[-1] .= $1;
677
678             }
679             elsif($1 eq '~~') { # "~~"
680                 $c[-1] .= '~';
681
682             }
683             elsif($1 eq '~[') { # "~["
684                 $c[-1] .= '[';
685
686             }
687             elsif($1 eq '~]') { # "~]"
688                 $c[-1] .= ']';
689
690             }
691             elsif($1 eq '~,') { # "~,"
692                 if($in_group) {
693                     # This is a hack, based on the assumption that no-one will actually
694                     # want a DEL inside a bracket group.  Let's hope that's it's true.
695                     if (ord('A') == 65) { # ASCII etc
696                         $c[-1] .= "\x7F";
697                     }
698                     else {              # EBCDIC (cp 1047, 0037, POSIX-BC)
699                         $c[-1] .= "\x07";
700                     }
701                 }
702                 else {
703                     $c[-1] .= '~,';
704                 }
705
706             }
707             elsif($1 eq '~') { # possible only at string-end, it seems.
708                 $c[-1] .= '~';
709
710             }
711             else {
712                 # It's a "~X" where X is not a special character.
713                 # Consider it a literal ~ and X.
714                 $c[-1] .= $1;
715             }
716         }
717     }
718
719     if($call_count) {
720         undef $big_pile; # Well, nevermind that.
721     }
722     else {
723         # It's all literals!  Ahwell, that can happen.
724         # So don't bother with the eval.  Return a SCALAR reference.
725         return \$big_pile;
726     }
727
728     die q{Last chunk isn't null??} if @c and length $c[-1]; # sanity
729     DEBUG and warn scalar(@c), " chunks under closure\n";
730     if(@code == 0) { # not possible?
731         DEBUG and warn "Empty code\n";
732         return \'';
733     }
734     elsif(@code > 1) { # most cases, presumably!
735         unshift @code, "join '',\n";
736     }
737     unshift @code, "use strict; sub {\n";
738     push @code, "}\n";
739
740     DEBUG and warn @code;
741     my $sub = eval(join '', @code);
742     die "$@ while evalling" . join('', @code) if $@; # Should be impossible.
743     return $sub;
744 }
745
746 #--------------------------------------------------------------------------
747
748 sub _die_pointing {
749     # This is used by _compile to throw a fatal error
750     my $target = shift; # class name
751     # ...leaving $_[0] the error-causing text, and $_[1] the error message
752
753     my $i = index($_[0], "\n");
754
755     my $pointy;
756     my $pos = pos($_[0]) - (defined($_[2]) ? $_[2] : 0) - 1;
757     if($pos < 1) {
758         $pointy = "^=== near there\n";
759     }
760     else { # we need to space over
761         my $first_tab = index($_[0], "\t");
762         if($pos > 2 and ( -1 == $first_tab  or  $first_tab > pos($_[0]))) {
763             # No tabs, or the first tab is harmlessly after where we will point to,
764             # AND we're far enough from the margin that we can draw a proper arrow.
765             $pointy = ('=' x $pos) . "^ near there\n";
766         }
767         else {
768             # tabs screw everything up!
769             $pointy = substr($_[0],0,$pos);
770             $pointy =~ tr/\t //cd;
771             # make everything into whitespace, but preseving tabs
772             $pointy .= "^=== near there\n";
773         }
774     }
775
776     my $errmsg = "$_[1], in\:\n$_[0]";
777
778     if($i == -1) {
779         # No newline.
780         $errmsg .= "\n" . $pointy;
781     }
782     elsif($i == (length($_[0]) - 1)  ) {
783         # Already has a newline at end.
784         $errmsg .= $pointy;
785     }
786     else {
787         # don't bother with the pointy bit, I guess.
788     }
789     Carp::croak( "$errmsg via $target, as used" );
790 }
791
792 1;