3 # @INC poking no longer needed w/ new MakeMaker and Makefile.PL's
4 # with $ENV{PERL_CORE} set
5 # In case we need it in future...
6 require Config; import Config;
11 my @orig_ARGV = @ARGV;
12 our $VERSION = do { my @r = (q$Revision: 1.31 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
14 # These may get re-ordered.
15 # RAW is a do_now as inserted by &enter
16 # AGG is an aggreagated do_now, as built up by &process
33 # (See the algorithm in encengine.c - we're building structures for it)
35 # There are two sorts of structures.
36 # "do_now" (an array, two variants of what needs storing) is whatever we need
37 # to do now we've read an input byte.
38 # It's housed in a "do_next" (which is how we got to it), and in turn points
39 # to a "do_next" which contains all the "do_now"s for the next input byte.
41 # There will be a "do_next" which is the start state.
42 # For a single byte encoding it's the only "do_next" - each "do_now" points
43 # back to it, and each "do_now" will cause bytes. There is no state.
45 # For a multi-byte encoding where all characters in the input are the same
46 # length, then there will be a tree of "do_now"->"do_next"->"do_now"
47 # branching out from the start state, one step for each input byte.
48 # The leaf "do_now"s will all be at the same distance from the start state,
49 # only the leaf "do_now"s cause output bytes, and they in turn point back to
52 # For an encoding where there are varaible length input byte sequences, you
53 # will encounter a leaf "do_now" sooner for the shorter input sequences, but
54 # as before the leaves will point back to the start state.
56 # The system will cope with escape encodings (imagine them as a mostly
57 # self-contained tree for each escape state, and cross links between trees
58 # at the state-switching characters) but so far no input format defines these.
60 # The system will also cope with having output "leaves" in the middle of
61 # the bifurcating branches, not just at the extremities, but again no
62 # input format does this yet.
64 # There are two variants of the "do_now" structure. The first, smaller variant
65 # is generated by &enter as the input file is read. There is one structure
66 # for each input byte. Say we are mapping a single byte encoding to a
67 # single byte encoding, with "ABCD" going "abcd". There will be
68 # 4 "do_now"s, {"A" => [...,"a",...], "B" => [...,"b",...], "C"=>..., "D"=>...}
70 # &process then walks the tree, building aggregate "do_now" structres for
71 # adjacent bytes where possible. The aggregate is for a contiguous range of
72 # bytes which each produce the same length of output, each move to the
73 # same next state, and each have the same fallback flag.
74 # So our 4 RAW "do_now"s above become replaced by a single structure
76 # ["A", "D", "abcd", 1, ...]
77 # ie, for an input byte $_ in "A".."D", output 1 byte, found as
78 # substr ("abcd", (ord $_ - ord "A") * 1, 1)
79 # which maps very nicely into pointer arithmetic in C for encengine.c
83 # UTF-8 encode long hand - only covers part of perl's range
85 # chr() works in native space so convert value from table
86 # into that space before using chr().
87 my $ch = chr(utf8::unicode_to_native($_[0]));
88 # Now get core perl to encode that the way it likes.
96 ## my ($ch,$page) = @_; return chr($ch);
102 # encode double byte MS byte first
103 ## my ($ch,$page) = @_; return chr($page).chr($ch);
104 return chr ($_[1]) . chr $_[0];
109 # encode Multi-byte - single for 0..255 otherwise double
110 ## my ($ch,$page) = @_;
111 ## return &encode_D if $page;
113 return chr ($_[1]) . chr $_[0] if $_[1];
117 my %encode_types = (U => \&encode_U,
123 # Win32 does not expand globs on command line
124 eval "\@ARGV = map(glob(\$_),\@ARGV)" if ($^O eq 'MSWin32');
128 # -Q to disable the duplicate codepoint test
129 # -S make mapping errors fatal
130 # -q to remove comments written to output files
131 # -O to enable the (brute force) substring optimiser
132 # -o <output> to specify the output file name (else it's the first arg)
133 # -f <inlist> to give a file with a list of input files (else use the args)
134 # -n <name> to name the encoding (else use the basename of the input file.
135 getopts('CM:SQqOo:f:n:',\%opt);
137 $opt{M} and make_makefile_pl($opt{M}, @ARGV);
138 $opt{C} and make_configlocal_pm($opt{C}, @ARGV);
140 # This really should go first, else the die here causes empty (non-erroneous)
141 # output files to be written.
143 if (exists $opt{'f'}) {
144 # -F is followed by name of file containing list of filenames
145 my $flist = $opt{'f'};
146 open(FLIST,$flist) || die "Cannot open $flist:$!";
147 chomp(@encfiles = <FLIST>);
153 my $cname = (exists $opt{'o'}) ? $opt{'o'} : shift(@ARGV);
154 chmod(0666,$cname) if -f $cname && !-w $cname;
155 open(C,">$cname") || die "Cannot open $cname:$!";
160 my ($doC,$doEnc,$doUcm,$doPet);
162 if ($cname =~ /\.(c|xs)$/i) # VMS may have upcased filenames with DECC$ARGV_PARSE_STYLE defined
165 $dname =~ s/(\.[^\.]*)?$/.exh/;
166 chmod(0666,$dname) if -f $cname && !-w $dname;
167 open(D,">$dname") || die "Cannot open $dname:$!";
168 $hname =~ s/(\.[^\.]*)?$/.h/;
169 chmod(0666,$hname) if -f $cname && !-w $hname;
170 open(H,">$hname") || die "Cannot open $hname:$!";
172 foreach my $fh (\*C,\*D,\*H)
174 print $fh <<"END" unless $opt{'q'};
176 !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
177 This file was autogenerated by:
183 if ($cname =~ /(\w+)\.xs$/)
185 print C "#include <EXTERN.h>\n";
186 print C "#include <perl.h>\n";
187 print C "#include <XSUB.h>\n";
188 print C "#define U8 U8\n";
190 print C "#include \"encode.h\"\n\n";
193 elsif ($cname =~ /\.enc$/)
197 elsif ($cname =~ /\.ucm$/)
201 elsif ($cname =~ /\.pet$/)
217 if ($a =~ /^.*-(\d+)/)
220 if ($b =~ /^.*-(\d+)/)
230 foreach my $enc (sort cmp_name @encfiles)
232 my ($name,$sfx) = $enc =~ /^.*?([\w-]+)\.(enc|ucm)$/;
233 $name = $opt{'n'} if exists $opt{'n'};
238 compile_enc(\*E,lc($name));
242 compile_ucm(\*E,lc($name));
247 warn "Cannot open $enc for $name:$!";
253 print STDERR "Writing compiled form\n";
254 foreach my $name (sort cmp_name keys %encoding)
256 my ($e2u,$u2e,$erep,$min_el,$max_el) = @{$encoding{$name}};
257 process($name.'_utf8',$e2u);
258 addstrings(\*C,$e2u);
260 process('utf8_'.$name,$u2e);
261 addstrings(\*C,$u2e);
263 outbigstring(\*C,"enctable");
264 foreach my $name (sort cmp_name keys %encoding)
266 my ($e2u,$u2e,$erep,$min_el,$max_el) = @{$encoding{$name}};
267 outtable(\*C,$e2u, "enctable");
268 outtable(\*C,$u2e, "enctable");
270 # push(@{$encoding{$name}},outstring(\*C,$e2u->{Cname}.'_def',$erep));
272 foreach my $enc (sort cmp_name keys %encoding)
274 # my ($e2u,$u2e,$rep,$min_el,$max_el,$rsym) = @{$encoding{$enc}};
275 my ($e2u,$u2e,$rep,$min_el,$max_el) = @{$encoding{$enc}};
276 #my @info = ($e2u->{Cname},$u2e->{Cname},$rsym,length($rep),$min_el,$max_el);
278 $replen++ while($rep =~ /\G\\x[0-9A-Fa-f]/g);
279 my @info = ($e2u->{Cname},$u2e->{Cname},qq((U8 *)"$rep"),$replen,$min_el,$max_el);
280 my $sym = "${enc}_encoding";
282 print C "encode_t $sym = \n";
283 # This is to make null encoding work -- dankogai
284 for (my $i = (scalar @info) - 1; $i >= 0; --$i){
287 # end of null tweak -- dankogai
288 print C " {",join(',',@info,"{\"$enc\",(const char *)0}"),"};\n\n";
291 foreach my $enc (sort cmp_name keys %encoding)
293 my $sym = "${enc}_encoding";
295 print H "extern encode_t $sym;\n";
296 print D " Encode_XSEncoding(aTHX_ &$sym);\n";
299 if ($cname =~ /(\w+)\.xs$/)
305 Encode_XSEncoding(pTHX_ encode_t *enc)
308 HV *stash = gv_stashpv("Encode::XS", TRUE);
309 SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(enc))),stash);
315 const char *name = enc->name[i++];
316 XPUSHs(sv_2mortal(newSVpvn(name,strlen(name))));
319 call_pv("Encode::define_encoding",G_DISCARD);
325 print C "\nMODULE = Encode::$mod\tPACKAGE = Encode::$mod\n\n";
326 print C "BOOT:\n{\n";
327 print C "#include \"$dname\"\n";
330 # Close in void context is bad, m'kay
331 close(D) or warn "Error closing '$dname': $!";
332 close(H) or warn "Error closing '$hname': $!";
334 my $perc_saved = $strings/($strings + $saved) * 100;
335 my $perc_subsaved = $strings/($strings + $subsave) * 100;
336 printf STDERR "%d bytes in string tables\n",$strings;
337 printf STDERR "%d bytes (%.3g%%) saved spotting duplicates\n",
338 $saved, $perc_saved if $saved;
339 printf STDERR "%d bytes (%.3g%%) saved using substrings\n",
340 $subsave, $perc_subsaved if $subsave;
344 foreach my $name (sort cmp_name keys %encoding)
346 my ($e2u,$u2e,$erep,$min_el,$max_el) = @{$encoding{$name}};
347 output_enc(\*C,$name,$e2u);
352 foreach my $name (sort cmp_name keys %encoding)
354 my ($e2u,$u2e,$erep,$min_el,$max_el) = @{$encoding{$name}};
355 output_ucm(\*C,$name,$u2e,$erep,$min_el,$max_el);
359 # writing half meg files and then not checking to see if you just filled the
361 close(C) or die "Error closing '$cname': $!";
363 # End of the main program.
375 last if /^\s*CHARMAP\s*$/i;
376 if (/^\s*<(\w+)>\s+"?([^"]*)"?\s*$/i) # " # Grrr
381 if (!defined($cs = $attr{'code_set_name'}))
383 warn "No <code_set_name> in $name\n";
387 $name = $cs unless exists $opt{'n'};
393 if (exists $attr{'subchar'})
396 #$attr{'subchar'} =~ /^\s*/cg;
397 #push(@byte,$1) while $attr{'subchar'} =~ /\G\\x([0-9a-f]+)/icg;
398 #$erep = join('',map(chr(hex($_)),@byte));
399 $erep = $attr{'subchar'};
400 $erep =~ s/^\s+//; $erep =~ s/\s+$//;
402 print "Reading $name ($cs)\n";
408 last if /^\s*END\s+CHARMAP\s*$/i;
410 my (@uni, @byte) = ();
411 my ($uni, $byte, $fb) = m/^(\S+)\s+(\S+)\s+(\S+)\s+/o
412 or die "Bad line: $_";
413 while ($uni =~ m/\G<([U0-9a-fA-F\+]+)>/g){
414 push @uni, map { substr($_, 1) } split(/\+/, $1);
416 while ($byte =~ m/\G\\x([0-9a-fA-F]+)/g){
421 my $uch = join('', map { encode_U(hex($_)) } @uni );
422 my $ech = join('',map(chr(hex($_)),@byte));
423 my $el = length($ech);
424 $max_el = $el if (!defined($max_el) || $el > $max_el);
425 $min_el = $el if (!defined($min_el) || $el < $min_el);
436 # $fb is fallback flag
437 # 0 - round trip safe
438 # 1 - fallback for unicode -> enc
439 # 2 - skip sub-char mapping
440 # 3 - fallback enc -> unicode
441 enter($u2e,$uch,$ech,$u2e,$fb+0) if ($fb =~ /[01]/);
442 enter($e2u,$ech,$uch,$e2u,$fb+0) if ($fb =~ /[03]/);
451 die "$nfb entries without fallback, $hfb entries with\n";
453 $encoding{$name} = [$e2u,$u2e,$erep,$min_el,$max_el];
465 while ($type = <$fh>)
467 last if $type !~ /^\s*#/;
470 return if $type eq 'E';
471 # Do the hash lookup once, rather than once per function call. 4% speedup.
472 my $type_func = $encode_types{$type};
473 my ($def,$sym,$pages) = split(/\s+/,scalar(<$fh>));
474 warn "$type encoded $name\n";
476 # Save a defined test by setting these to defined values.
477 my $min_el = ~0; # A very big integer
478 my $max_el = 0; # Anything must be longer than 0
481 $rep = &$type_func($v & 0xFF, ($v >> 8) & 0xffe);
485 # use -Q to silence the seen test. Makefile.PL uses this by default.
486 $seen = {} unless $opt{Q};
491 my $page = hex($line);
496 # So why is it 1% faster to leave the my here?
498 $line =~ s/\r\n$/\n/;
499 die "$.:${line}Line should be exactly 65 characters long including
500 newline (".length($line).")" unless length ($line) == 65;
501 # Split line into groups of 4 hex digits, convert groups to ints
503 # map {hex $_} $line =~ /(....)/g
504 # This takes 63.75 (2.5% less time)
505 # unpack "n*", pack "H*", $line
506 # There's an implicit loop in map. Loops are bad, m'kay. Ops are bad, m'kay
507 # Doing it as while ($line =~ /(....)/g) took 74.63
508 foreach my $val (unpack "n*", pack "H*", $line)
510 next if $val == 0xFFFD;
511 my $ech = &$type_func($ch,$page);
512 if ($val || (!$ch && !$page))
514 my $el = length($ech);
515 $max_el = $el if $el > $max_el;
516 $min_el = $el if $el < $min_el;
517 my $uch = encode_U($val);
519 # We're doing the test.
520 # We don't need to read this quickly, so storing it as a scalar,
521 # rather than 3 (anon array, plus the 2 scalars it holds) saves
522 # RAM and may make us faster on low RAM systems. [see __END__]
523 if (exists $seen->{$uch})
525 warn sprintf("U%04X is %02X%02X and %04X\n",
526 $val,$page,$ch,$seen->{$uch});
531 $seen->{$uch} = $page << 8 | $ch;
534 # Passing 2 extra args each time is 3.6% slower!
535 # Even with having to add $fallback ||= 0 later
536 enter_fb0($e2u,$ech,$uch);
537 enter_fb0($u2e,$uch,$ech);
541 # No character at this position
542 # enter($e2u,$ech,undef,$e2u);
548 die "\$min_el=$min_el, \$max_el=$max_el - seems we read no lines"
549 if $min_el > $max_el;
550 die "$errors mapping conflicts\n" if ($errors && $opt{'S'});
551 $encoding{$name} = [$e2u,$u2e,$rep,$min_el,$max_el];
554 # my ($a,$s,$d,$t,$fb) = @_;
556 my ($current,$inbytes,$outbytes,$next,$fallback) = @_;
557 # state we shift to after this (multibyte) input character defaults to same
560 # Making sure it is defined seems to be faster than {no warnings;} in
561 # &process, or passing it in as 0 explicity.
562 # XXX $fallback ||= 0;
564 # Start at the beginning and work forwards through the string to zero.
565 # effectively we are removing 1 character from the front each time
566 # but we don't actually edit the string. [this alone seems to be 14% speedup]
567 # Hence -$pos is the length of the remaining string.
568 my $pos = -length $inbytes;
570 my $byte = substr $inbytes, $pos, 1;
573 # RAW_OUT_BYTES => 2,
575 # to unicode an array would seem to be better, because the pages are dense.
576 # from unicode can be very sparse, favouring a hash.
577 # hash using the bytes (all length 1) as keys rather than ord value,
578 # as it's easier to sort these in &process.
580 # It's faster to always add $fallback even if it's undef, rather than
581 # choosing between 3 and 4 element array. (hence why we set it defined
583 my $do_now = $current->{Raw}{$byte} ||= [{},-$pos,'',$fallback];
584 # When $pos was -1 we were at the last input character.
586 $do_now->[RAW_OUT_BYTES] = $outbytes;
587 $do_now->[RAW_NEXT] = $next;
590 # Tail recursion. The intermdiate state may not have a name yet.
591 $current = $do_now->[RAW_NEXT];
595 # This is purely for optimistation. It's just &enter hard coded for $fallback
596 # of 0, using only a 3 entry array ref to save memory for every entry.
598 my ($current,$inbytes,$outbytes,$next) = @_;
601 my $pos = -length $inbytes;
603 my $byte = substr $inbytes, $pos, 1;
604 my $do_now = $current->{Raw}{$byte} ||= [{},-$pos,''];
606 $do_now->[RAW_OUT_BYTES] = $outbytes;
607 $do_now->[RAW_NEXT] = $next;
610 $current = $do_now->[RAW_NEXT];
620 my ($l, $agg_max_in, $agg_next, $agg_in_len, $agg_out_len, $agg_fallback);
623 foreach my $key (sort keys %$raw) {
626 # RAW_OUT_BYTES => 2,
628 my ($next, $in_len, $out_bytes, $fallback) = @{$raw->{$key}};
629 # Now we are converting from raw to aggregate, switch from 1 byte strings
634 # If this == fails, we're going to reset $agg_max_in below anyway.
635 $b == ++$agg_max_in &&
636 # References in numeric context give the pointer as an int.
637 $agg_next == $next &&
638 $agg_in_len == $in_len &&
639 $agg_out_len == length $out_bytes &&
640 $agg_fallback == $fallback
641 # && length($l->[AGG_OUT_BYTES]) < 16
643 # my $i = ord($b)-ord($l->[AGG_MIN_IN]);
644 # we can aggregate this byte onto the end.
645 $l->[AGG_MAX_IN] = $b;
646 $l->[AGG_OUT_BYTES] .= $out_bytes;
650 # AGG_OUT_BYTES => 2,
655 # Reset the last thing we saw, plus set 5 lexicals to save some derefs.
656 # (only gains .6% on euc-jp -- is it worth it?)
657 push @ent, $l = [$b, $agg_max_in = $b, $out_bytes, $agg_next = $next,
658 $agg_in_len = $in_len, $agg_out_len = length $out_bytes,
659 $agg_fallback = $fallback];
661 if (exists $next->{Cname}) {
662 $next->{'Forward'} = 1 if $next != $a;
664 process(sprintf("%s_%02x",$name,$b),$next);
667 # encengine.c rules say that last entry must be for 255
668 if ($agg_max_in < 255) {
669 push @ent, [1+$agg_max_in, 255,undef,$a,0,0];
671 $a->{'Entries'} = \@ent;
678 my $name = $a->{'Cname'};
680 foreach my $b (@{$a->{'Entries'}})
682 next unless $b->[AGG_OUT_LEN];
683 $strings{$b->[AGG_OUT_BYTES]} = undef;
687 my $var = $^O eq 'MacOS' ? 'extern' : 'static';
688 print $fh "$var encpage_t $name\[",scalar(@{$a->{'Entries'}}),"];\n";
690 $a->{'DoneStrings'} = 1;
691 foreach my $b (@{$a->{'Entries'}})
693 my ($s,$e,$out,$t,$end,$l) = @$b;
694 addstrings($fh,$t) unless $t->{'DoneStrings'};
704 # Make the big string in the string accumulator. Longest first, on the hope
705 # that this makes it more likely that we find the short strings later on.
706 # Not sure if it helps sorting strings of the same length lexcically.
707 foreach my $s (sort {length $b <=> length $a || $a cmp $b} keys %strings) {
708 my $index = index $string_acc, $s;
710 $saved += length($s);
711 $strings_in_acc{$s} = $index;
715 my $sublength = length $s;
716 while (--$sublength > 0) {
717 # progressively lop characters off the end, to see if the start of
718 # the new string overlaps the end of the accumulator.
719 if (substr ($string_acc, -$sublength)
720 eq substr ($s, 0, $sublength)) {
721 $subsave += $sublength;
722 $strings_in_acc{$s} = length ($string_acc) - $sublength;
723 # append the last bit on the end.
724 $string_acc .= substr ($s, $sublength);
727 # or if the end of the new string overlaps the start of the
729 next unless substr ($string_acc, 0, $sublength)
730 eq substr ($s, -$sublength);
731 # well, the last $sublength characters of the accumulator match.
732 # so as we're prepending to the accumulator, need to shift all our
733 # existing offsets forwards
734 $_ += $sublength foreach values %strings_in_acc;
735 $subsave += $sublength;
736 $strings_in_acc{$s} = 0;
737 # append the first bit on the start.
738 $string_acc = substr ($s, 0, -$sublength) . $string_acc;
742 # Optimiser (if it ran) found nothing, so just going have to tack the
743 # whole thing on the end.
744 $strings_in_acc{$s} = length $string_acc;
750 $strings = length $string_acc;
751 my $definition = "\nstatic const U8 $name\[$strings] = { " .
752 join(',',unpack "C*",$string_acc);
753 # We have a single long line. Split it at convenient commas.
754 print $fh $1, "\n" while $definition =~ /\G(.{74,77},)/gcs;
755 print $fh substr ($definition, pos $definition), " };\n";
760 my $offset = $strings_in_acc{$s};
761 die "Can't find string " . join (',',unpack "C*",$s) . " in accumulator"
762 unless defined $offset;
768 my ($fh,$a,$bigname) = @_;
769 my $name = $a->{'Cname'};
771 foreach my $b (@{$a->{'Entries'}})
773 my ($s,$e,$out,$t,$end,$l) = @$b;
774 outtable($fh,$t,$bigname) unless $t->{'Done'};
776 print $fh "\nstatic encpage_t $name\[",scalar(@{$a->{'Entries'}}),"] = {\n";
777 foreach my $b (@{$a->{'Entries'}})
779 my ($sc,$ec,$out,$t,$end,$l,$fb) = @$b;
780 # $end |= 0x80 if $fb; # what the heck was on your mind, Nick? -- Dan
784 printf $fh findstring($bigname,$out);
790 print $fh ",",$t->{Cname};
791 printf $fh ",0x%02x,0x%02x,$l,$end},\n",$sc,$ec;
798 my ($fh,$name,$a) = @_;
799 die "Changed - fix me for new structure";
800 foreach my $b (sort keys %$a)
802 my ($s,$e,$out,$t,$end,$l,$fb) = @{$a->{$b}};
814 my $s = do "unicore/Name.pl";
815 die "char_names: unicore/Name.pl: $!\n" unless defined $s;
817 while ($s =~ /\G([0-9a-f]+)\t([0-9a-f]*)\t(.*?)\s*\n/igc)
821 last if $s >= 0x10000;
822 my $e = length($2) ? hex($2) : $s;
823 for (my $i = $s; $i <= $e; $i++)
826 # print sprintf("U%04X $name\n",$i);
833 my ($cmap,$a,$t,$pre) = @_;
834 # warn sprintf("Page %x\n",$pre);
836 foreach my $key (sort keys %$raw) {
839 # RAW_OUT_BYTES => 2,
841 my ($next, $in_len, $out_bytes, $fallback) = @{$raw->{$key}};
845 if ($next != $a && $next != $t) {
846 output_ucm_page($cmap,$a,$next,(($pre|($u &0x3F)) << 6)&0xFFFF);
847 } elsif (length $out_bytes) {
849 $u = $pre|($u &0x3f);
851 my $s = sprintf "<U%04X> ",$u;
852 #foreach my $c (split(//,$out_bytes)) {
853 # $s .= sprintf "\\x%02X",ord($c);
855 # 9.5% faster changing that loop to this:
856 $s .= sprintf +("\\x%02X" x length $out_bytes), unpack "C*", $out_bytes;
857 $s .= sprintf " |%d # %s\n",($fallback ? 1 : 0),$uname[$u];
860 warn join(',',$u, @{$raw->{$key}},$a,$t);
867 my ($fh,$name,$h,$rep,$min_el,$max_el) = @_;
868 print $fh "# $0 @orig_ARGV\n" unless $opt{'q'};
869 print $fh "<code_set_name> \"$name\"\n";
873 print $fh "<mb_cur_min> $min_el\n";
877 print $fh "<mb_cur_max> $max_el\n";
881 print $fh "<subchar> ";
882 foreach my $c (split(//,$rep))
884 printf $fh "\\x%02X",ord($c);
889 output_ucm_page(\@cmap,$h,$h,0);
890 print $fh "#\nCHARMAP\n";
891 foreach my $line (sort { substr($a,8) cmp substr($b,8) } @cmap)
895 print $fh "END CHARMAP\n";
909 eval { require File::Find; };
912 push @inc, $inc unless $inc eq '.'; #skip current dir
916 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
917 $atime,$mtime,$ctime,$blksize,$blocks)
918 = lstat($_) or return;
922 $e2x_dir{$File::Find::dir} ||= $mtime;
926 warn join("\n", keys %e2x_dir), "\n";
927 for my $d (sort {$e2x_dir{$a} <=> $e2x_dir{$b}} keys %e2x_dir){
929 # warn "$_E2X => ", scalar localtime($e2x_dir{$d});
936 eval { require Encode; };
937 $@ and die "You need to install Encode to use enc2xs -M\nerror: $@\n";
938 # our used for variable expanstion
940 $_Version = $VERSION;
943 $_TableFiles = join(",", map {qq('$_')} @_);
944 $_Now = scalar localtime();
946 eval { require File::Spec; };
947 _print_expand(File::Spec->catfile($_E2X,"Makefile_PL.e2x"),"Makefile.PL");
948 _print_expand(File::Spec->catfile($_E2X,"_PM.e2x"), "$_Name.pm");
949 _print_expand(File::Spec->catfile($_E2X,"_T.e2x"), "t/$_Name.t");
950 _print_expand(File::Spec->catfile($_E2X,"README.e2x"), "README");
951 _print_expand(File::Spec->catfile($_E2X,"Changes.e2x"), "Changes");
960 sub make_configlocal_pm
962 eval { require Encode; };
963 $@ and die "Unable to require Encode: $@\n";
964 eval { require File::Spec; };
965 # our used for variable expanstion
966 my %in_core = map {$_=>1}('ascii','iso-8859-1','utf8');
969 my $inc = File::Spec->catfile($d, "Encode");
971 opendir my $dh, $inc or die "$inc:$!";
972 warn "Checking $inc...\n";
973 for my $f (grep /\.pm$/o, readdir($dh)){
974 -f File::Spec->catfile($inc, "$f") or next;
975 $INC{"Encode/$f"} and next;
976 warn "require Encode/$f;\n";
977 eval { require "Encode/$f"; };
978 $@ and die "Can't require Encode/$f: $@\n";
979 for my $enc (Encode->encodings()){
981 $in_core{$enc} and next;
982 $Encode::Config::ExtModule{$enc} and next;
983 my $mod = "Encode/$f";
984 $mod =~ s/\.pm$//o; $mod =~ s,/,::,og;
985 $LocalMod{$enc} ||= $mod;
990 for my $enc (sort keys %LocalMod){
992 qq(\$Encode::ExtModule{'$enc'} =\t"$LocalMod{$enc}";\n);
995 $_LocalVer = _mkversion();
997 $_Inc = $INC{"Encode.pm"}; $_Inc =~ s/\.pm$//o;
998 _print_expand(File::Spec->catfile($_E2X,"ConfigLocal_PM.e2x"),
999 File::Spec->catfile($_Inc,"ConfigLocal.pm"),
1005 my ($ss,$mm,$hh,$dd,$mo,$yyyy) = localtime();
1006 $yyyy += 1900, $mo +=1;
1007 return sprintf("v%04d.%04d.%04d", $yyyy, $mo*100+$dd, $hh*100+$mm);
1011 eval { require File::Basename; };
1012 $@ and die "File::Basename needed. Are you on miniperl?;\nerror: $@\n";
1013 File::Basename->import();
1014 my ($src, $dst, $clobber) = @_;
1015 if (!$clobber and -e $dst){
1016 warn "$dst exists. skipping\n";
1019 warn "Generating $dst...\n";
1020 open my $in, $src or die "$src : $!";
1021 if ((my $d = dirname($dst)) ne '.'){
1022 -d $d or mkdir $d, 0755 or die "mkdir $d : $!";
1024 open my $out, ">$dst" or die "$!";
1027 if (/^#### END_OF_HEADER/){
1030 s/(\$_[A-Z][A-Za-z0-9]+)_/$1/gee unless $asis;
1038 enc2xs -- Perl Encode Module Generator
1043 enc2xs -M ModName mapfiles...
1048 F<enc2xs> builds a Perl extension for use by Encode from either
1049 Unicode Character Mapping files (.ucm) or Tcl Encoding Files (.enc).
1050 Besides being used internally during the build process of the Encode
1051 module, you can use F<enc2xs> to add your own encoding to perl.
1052 No knowledge of XS is necessary.
1056 If you want to know as little about Perl as possible but need to
1057 add a new encoding, just read this chapter and forget the rest.
1063 Have a .ucm file ready. You can get it from somewhere or you can write
1064 your own from scratch or you can grab one from the Encode distribution
1065 and customize it. For the UCM format, see the next Chapter. In the
1066 example below, I'll call my theoretical encoding myascii, defined
1067 in I<my.ucm>. C<$> is a shell prompt.
1074 Issue a command as follows;
1076 $ enc2xs -M My my.ucm
1077 generating Makefile.PL
1082 Now take a look at your current directory. It should look like this.
1085 Makefile.PL My.pm my.ucm t/
1087 The following files were created.
1089 Makefile.PL - MakeMaker script
1090 My.pm - Encode submodule
1097 If you want *.ucm installed together with the modules, do as follows;
1101 $ enc2xs -M My Encode/*ucm
1107 Edit the files generated. You don't have to if you have no time AND no
1108 intention to give it to someone else. But it is a good idea to edit
1109 the pod and to add more tests.
1113 Now issue a command all Perl Mongers love:
1116 Writing Makefile for Encode::My
1120 Now all you have to do is make.
1123 cp My.pm blib/lib/Encode/My.pm
1124 /usr/local/bin/perl /usr/local/bin/enc2xs -Q -O \
1125 -o encode_t.c -f encode_t.fnm
1126 Reading myascii (myascii)
1127 Writing compiled form
1128 128 bytes in string tables
1129 384 bytes (25%) saved spotting duplicates
1130 1 bytes (99.2%) saved using substrings
1132 chmod 644 blib/arch/auto/Encode/My/My.bs
1135 The time it takes varies depending on how fast your machine is and
1136 how large your encoding is. Unless you are working on something big
1137 like euc-tw, it won't take too long.
1141 You can "make install" already but you should test first.
1144 PERL_DL_NONLAZY=1 /usr/local/bin/perl -Iblib/arch -Iblib/lib \
1145 -e 'use Test::Harness qw(&runtests $verbose); \
1146 $verbose=0; runtests @ARGV;' t/*.t
1148 All tests successful.
1149 Files=1, Tests=2, 0 wallclock secs
1150 ( 0.09 cusr + 0.01 csys = 0.09 CPU)
1154 If you are content with the test result, just "make install"
1158 If you want to add your encoding to Encode's demand-loading list
1159 (so you don't have to "use Encode::YourEncoding"), run
1163 to update Encode::ConfigLocal, a module that controls local settings.
1164 After that, "use Encode;" is enough to load your encodings on demand.
1168 =head1 The Unicode Character Map
1170 Encode uses the Unicode Character Map (UCM) format for source character
1171 mappings. This format is used by IBM's ICU package and was adopted
1172 by Nick Ing-Simmons for use with the Encode module. Since UCM is
1173 more flexible than Tcl's Encoding Map and far more user-friendly,
1174 this is the recommended formet for Encode now.
1176 A UCM file looks like this.
1181 <code_set_name> "US-ascii" # Required
1182 <code_set_alias> "ascii" # Optional
1183 <mb_cur_min> 1 # Required; usually 1
1184 <mb_cur_max> 1 # Max. # of bytes/char
1185 <subchar> \x3F # Substitution char
1188 <U0000> \x00 |0 # <control>
1189 <U0001> \x01 |0 # <control>
1190 <U0002> \x02 |0 # <control>
1192 <U007C> \x7C |0 # VERTICAL LINE
1193 <U007D> \x7D |0 # RIGHT CURLY BRACKET
1194 <U007E> \x7E |0 # TILDE
1195 <U007F> \x7F |0 # <control>
1202 Anything that follows C<#> is treated as a comment.
1206 The header section continues until a line containing the word
1207 CHARMAP. This section has a form of I<E<lt>keywordE<gt> value>, one
1208 pair per line. Strings used as values must be quoted. Barewords are
1209 treated as numbers. I<\xXX> represents a byte.
1211 Most of the keywords are self-explanatory. I<subchar> means
1212 substitution character, not subcharacter. When you decode a Unicode
1213 sequence to this encoding but no matching character is found, the byte
1214 sequence defined here will be used. For most cases, the value here is
1215 \x3F; in ASCII, this is a question mark.
1219 CHARMAP starts the character map section. Each line has a form as
1222 <UXXXX> \xXX.. |0 # comment
1224 | | +- Fallback flag
1225 | +-------- Encoded byte sequence
1226 +-------------- Unicode Character ID in hex
1228 The format is roughly the same as a header section except for the
1229 fallback flag: | followed by 0..3. The meaning of the possible
1230 values is as follows:
1236 Round trip safe. A character decoded to Unicode encodes back to the
1237 same byte sequence. Most characters have this flag.
1241 Fallback for unicode -> encoding. When seen, enc2xs adds this
1242 character for the encode map only.
1246 Skip sub-char mapping should there be no code point.
1250 Fallback for encoding -> unicode. When seen, enc2xs adds this
1251 character for the decode map only.
1257 And finally, END OF CHARMAP ends the section.
1261 When you are manually creating a UCM file, you should copy ascii.ucm
1262 or an existing encoding which is close to yours, rather than write
1263 your own from scratch.
1265 When you do so, make sure you leave at least B<U0000> to B<U0020> as
1266 is, unless your environment is EBCDIC.
1268 B<CAVEAT>: not all features in UCM are implemented. For example,
1269 icu:state is not used. Because of that, you need to write a perl
1270 module if you want to support algorithmical encodings, notably
1271 the ISO-2022 series. Such modules include L<Encode::JP::2022_JP>,
1272 L<Encode::KR::2022_KR>, and L<Encode::TW::HZ>.
1274 =head2 Coping with duplicate mappings
1276 When you create a map, you SHOULD make your mappings round-trip safe.
1277 That is, C<encode('your-encoding', decode('your-encoding', $data)) eq
1278 $data> stands for all characters that are marked as C<|0>. Here is
1285 Sort your map in Unicode order.
1289 When you have a duplicate entry, mark either one with '|1' or '|3'.
1293 And make sure the '|1' or '|3' entry FOLLOWS the '|0' entry.
1297 Here is an example from big5-eten.
1302 Internally Encoding -> Unicode and Unicode -> Encoding Map looks like
1306 --------------------------------------
1307 \xF9\xF9 => U2550 U2550 => \xF9\xF9
1310 So it is round-trip safe for \xF9\xF9. But if the line above is upside
1311 down, here is what happens.
1314 --------------------------------------
1315 \xA2\xA4 => U2550 U2550 => \xF9\xF9
1316 (\xF9\xF9 => U2550 is now overwritten!)
1318 The Encode package comes with F<ucmlint>, a crude but sufficient
1319 utility to check the integrity of a UCM file. Check under the
1320 Encode/bin directory for this.
1330 L<http://oss.software.ibm.com/icu/>
1334 ICU Character Mapping Tables
1335 L<http://oss.software.ibm.com/icu/charset/>
1340 L<http://oss.software.ibm.com/icu/userguide/conversion-data.html>
1352 # -Q to disable the duplicate codepoint test
1353 # -S make mapping errors fatal
1354 # -q to remove comments written to output files
1355 # -O to enable the (brute force) substring optimiser
1356 # -o <output> to specify the output file name (else it's the first arg)
1357 # -f <inlist> to give a file with a list of input files (else use the args)
1358 # -n <name> to name the encoding (else use the basename of the input file.
1360 With %seen holding array refs:
1362 865.66 real 28.80 user 8.79 sys
1363 7904 maximum resident set size
1364 1356 average shared memory size
1365 18566 average unshared data size
1366 229 average unshared stack size
1370 With %seen holding simple scalars:
1372 342.16 real 27.11 user 3.54 sys
1373 8388 maximum resident set size
1374 1394 average shared memory size
1375 14969 average unshared data size
1376 236 average unshared stack size
1380 Yes, 5 minutes is faster than 15. Above is for CP936 in CN. Only difference is
1381 how %seen is storing things its seen. So it is pathalogically bad on a 16M
1382 RAM machine, but it's going to help even on modern machines.
1383 Swapping is bad, m'kay :-)