libalias-perl-2.32/ 40755 1750 62 0 6712462232 13065 5ustar mdormanstafflibalias-perl-2.32/Makefile.PL100444 1750 62 313 6656670477 15132 0ustar mdormanstaffuse ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'Alias', 'VERSION_FROM' => 'Alias.pm', 'linkext' => {LINKTYPE => 'dynamic'}, 'dist' => {COMPRESS=>'gzip -9f', SUFFIX => 'gz'} ); libalias-perl-2.32/Changes100444 1750 62 3455 6712461466 14472 0ustar mdormanstaff=head1 NAME HISTORY - release history for Alias =head1 DESCRIPTION =over 8 =item 2.32 No change in functionality. Added #defines for compatibility with the 5.006 development branch (courtesy Nathan Torkington ). =item 2.31 save_gp() is now exported from core, so use it instead of our own version. Thanks to Larry Virden for the bug report. Require 5.004. =item 2.3 The developer versions after 5.003 broke XSUB call semantics when the C<-d> switch is used (to invoke debugger or profiler). The problem is fixed in versions >= 5.003_19. Added the necessary logic to make use of the escape in Alias.xs. Thanks to Josh Purinton for reporting the problem. Objects are not automatically dereferenced by attr(). They are available as scalars instead, thanks to a feature request from Peter Seibel . ***INCOMPATIBLE CHANGE*** Using attr() in DESTROY subs resulted in deep recursion, fixed. Thanks to Helmut Jarausch . =item 2.2 Two new options C<$KeyFilter>, and C<$AttrPrefix> added for controlling which hash entries are aliased by C. This offers one way to avoid C when using C. Documentation, testsuite additions. =item 2.1 C now returns the passed value. We C. C is now prototyped to ($). *a = \*b work around has been removed (fixed in 5.002) "private" methods are now supported. Documentation, testsuite additions. =item 2.0 Added implicit localization for C via XS code. =item 1.3 Added C (unreleased). =item 1.2 Bugfix in the while loop, and other cleanup. Thanks to Ian Phillips . =item 1.1 Added named closures to pod. =item 1.0 Released to perl5-porters@nicoh.com. =back =cut libalias-perl-2.32/Alias.xs100444 1750 62 11570 6712461275 14617 0ustar mdormanstaff#ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __cplusplus } #endif #ifndef PERL_VERSION #include "patchlevel.h" #define PERL_REVISION 5 #define PERL_VERSION PATCHLEVEL #define PERL_SUBVERSION SUBVERSION #endif #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 )) #define PL_stack_sp stack_sp #endif static void process_flag _((char *varname, SV **svp, char **strp, STRLEN *lenp)); static void process_flag(varname, svp, strp, lenp) char *varname; SV **svp; char **strp; STRLEN *lenp; { GV *vargv = gv_fetchpv(varname, FALSE, SVt_PV); SV *sv = Nullsv; char *str = Nullch; STRLEN len = 0; if (vargv && (sv = GvSV(vargv))) { if (SvROK(sv)) { if (SvTYPE(SvRV(sv)) != SVt_PVCV) croak("$%s not a subroutine reference", varname); } else if (SvOK(sv)) str = SvPV(sv, len); } *svp = sv; *strp = str; *lenp = len; } MODULE = Alias PACKAGE = Alias PREFIX = alias_ PROTOTYPES: ENABLE BOOT: { GV *gv = gv_fetchpv("Alias::attr", FALSE, SVt_PVCV); if (gv && GvCV(gv)) CvNODEBUG_on(GvCV(gv)); } void alias_attr(hashref) SV * hashref PROTOTYPE: $ PPCODE: { HV *hv; int in_destroy = 0; int deref_call; if (SvREFCNT(hashref) == 0) in_destroy = 1; ++SvREFCNT(hashref); /* in case LEAVE wants to clobber us */ if (SvROK(hashref) && (hv = (HV *)SvRV(hashref)) && (SvTYPE(hv) == SVt_PVHV)) { SV *val, *tmpsv; char *key; I32 klen; SV *keypfx, *attrpfx, *deref; char *keypfx_c, *attrpfx_c, *deref_c; STRLEN keypfx_l, attrpfx_l, deref_l; process_flag("Alias::KeyFilter", &keypfx, &keypfx_c, &keypfx_l); process_flag("Alias::AttrPrefix", &attrpfx, &attrpfx_c, &attrpfx_l); process_flag("Alias::Deref", &deref, &deref_c, &deref_l); deref_call = (deref && !deref_c); LEAVE; /* operate at a higher level */ (void)hv_iterinit(hv); while ((val = hv_iternextsv(hv, &key, &klen))) { GV *gv; int stype = SvTYPE(val); int deref_this = 1; int deref_objects = 0; /* check the key for validity by either looking at * its prefix, or by calling &$Alias::KeyFilter */ if (keypfx) { if (keypfx_c) { if (keypfx_l && klen > keypfx_l && strncmp(key, keypfx_c, keypfx_l)) continue; } else { dSP; SV *ret = Nullsv; I32 i; ENTER; SAVETMPS; PUSHMARK(sp); XPUSHs(sv_2mortal(newSVpv(key,klen))); PUTBACK; if (perl_call_sv(keypfx, G_SCALAR)) ret = *PL_stack_sp--; SPAGAIN; i = SvTRUE(ret); FREETMPS; LEAVE; if (!i) continue; } } if (SvROK(val) && deref) { if (deref_c) { if (deref_l && !(deref_l == 1 && *deref_c == '0')) deref_objects = 1; } else { dSP; SV *ret = Nullsv; ENTER; SAVETMPS; PUSHMARK(sp); XPUSHs(sv_2mortal(newSVpv(key,klen))); XPUSHs(sv_2mortal(newSVsv(val))); PUTBACK; if (perl_call_sv(deref, G_SCALAR)) ret = *PL_stack_sp--; SPAGAIN; deref_this = SvTRUE(ret); FREETMPS; LEAVE; } } /* attributes may need to be prefixed/renamed */ if (attrpfx) { STRLEN len; if (attrpfx_c) { if (attrpfx_l) { SV *keysv = sv_2mortal(newSVpv(attrpfx_c, attrpfx_l)); sv_catpvn(keysv, key, klen); key = SvPV(keysv, len); klen = len; } } else { dSP; SV *ret = Nullsv; ENTER; PUSHMARK(sp); XPUSHs(sv_2mortal(newSVpv(key,klen))); PUTBACK; if (perl_call_sv(attrpfx, G_SCALAR)) ret = *PL_stack_sp--; SPAGAIN; LEAVE; key = SvPV(ret, len); klen = len; } } if (SvROK(val) && (tmpsv = SvRV(val))) { if (deref_call) { if (!deref_this) goto no_deref; } else if (!deref_objects && SvOBJECT(tmpsv)) goto no_deref; stype = SvTYPE(tmpsv); if (stype == SVt_PVGV) val = tmpsv; } else if (stype != SVt_PVGV) { no_deref: val = sv_2mortal(newRV(val)); } /* add symbol, forgoing "used once" warnings */ gv = gv_fetchpv(key, GV_ADDMULTI, SVt_PVGV); switch (stype) { case SVt_PVAV: save_ary(gv); break; case SVt_PVHV: save_hash(gv); break; case SVt_PVGV: save_gp(gv,TRUE); /* hide previous entry in symtab */ break; case SVt_PVCV: SAVESPTR(GvCV(gv)); GvCV(gv) = Null(CV*); break; default: save_scalar(gv); break; } sv_setsv((SV*)gv, val); /* alias the SV */ } ENTER; /* in lieu of the LEAVE far beyond */ } if (in_destroy) --SvREFCNT(hashref); /* avoid calling DESTROY forever */ else SvREFCNT_dec(hashref); XPUSHs(hashref); /* simply return what we got */ } libalias-perl-2.32/Alias.pm100444 1750 62 25346 6712461227 14604 0ustar mdormanstaff# # Documentation at the __END__ # package Alias; require 5.004; require Exporter; require DynaLoader; @ISA = qw(Exporter DynaLoader); @EXPORT = qw(alias attr); @EXPORT_OK = qw(const); $VERSION = $VERSION = '2.32'; use Carp; bootstrap Alias; $Alias::KeyFilter = ""; $Alias::AttrPrefix = ""; $Alias::Deref = ""; # don't deref objects sub alias { croak "Need even number of args" if @_ % 2; my($pkg) = caller; # for namespace soundness while (@_) { # *foo = \*bar works in 5.002 *{"$pkg\:\:$_[0]"} = (defined($_[1]) and ref($_[1])) ? $_[1] : \$_[1]; shift; shift; } } # alias the elements of hashref # same as alias %{$_[0]}, but also localizes the aliases and # returns the hashref sub attr; alias const => \&alias; # alias the alias :-) 1; __END__ =head1 NAME alias - declare symbolic aliases for perl data attr - auto-declare hash attributes for convenient access const - define compile-time scalar constants =head1 SYNOPSIS use Alias qw(alias const attr); alias TEN => $ten, Ten => \$ten, Ten => \&ten, Ten => \@ten, Ten => \%ten, TeN => \*ten; { local @Ten; my $ten = [1..10]; alias Ten => $ten; # local @Ten } const pi => 3.14, ten => 10; package Foo; use Alias; sub new { bless {foo => 1, _bar => [2, 3]}, $_[0] } sub a_method { my $s = attr shift; # $foo, @_bar are now local aliases for # $_[0]{foo}, @{$_[0]{_bar}} etc. } sub b_method { local $Alias::KeyFilter = "_"; local $Alias::AttrPrefix = "main::"; my $s = attr shift; # local @::_bar is now available, ($foo, $::foo are not) } sub c_method { local $Alias::KeyFilter = sub { $_ = shift; return (/^_/ ? 1 : 0) }; local $Alias::AttrPrefix = sub { $_ = shift; s/^_(.+)$/main::$1/; return $_ }; my $s = attr shift; # local @::bar is now available, ($foo, $::foo are not) } =head1 DESCRIPTION Provides general mechanisms for aliasing perl data for convenient access. This module works by putting some values on the symbol table with user-supplied names. Values that are references will get dereferenced into their base types. This means that a value of C<[1,2,3]> with a name of "foo" will be made available as C<@foo>, not C<$foo>. The exception to this rule is the default behavior of the C function, which will not dereference values which are blessed references (aka objects). See L<$Alias::Deref> for how to change this default behavior. =head2 Functions =over 4 =item alias Given a list of name => value pairs, declares aliases in the Cs namespace. If the value supplied is a reference, the alias is created for the underlying value instead of the reference itself (there is no need to use this module to alias references--they are automatically "aliased" on assignment). This allows the user to alias most of the basic types. If the value supplied is a scalar compile-time constant, the aliases become read-only. Any attempt to write to them will fail with a run time error. Aliases can be dynamically scoped by pre-declaring the target variable as C. Using C for this purpose is more convenient, and recommended. =item attr Given a hash reference, aliases the values of the hash to the names that correspond to the keys. It always returns the supplied value. The aliases are local to the enclosing block. If any of the values are unblessed references, they are available as their dereferenced types. Thus the action is similar to saying: alias %{$_[0]} but, in addition, also localizes the aliases, and does not dereference objects. Dereferencing of objects can be forced by setting the C option. See L<$Alias::Deref>. This can be used for convenient access to hash values and hash-based object attributes. Note that this makes available the semantics of C subroutines and methods. That makes for some nifty possibilities. We could make truly private methods by putting anonymous subs within an object. These subs would be available within methods where we use C, and will not be visible to the outside world as normal methods. We could forbid recursion in methods by always putting an empty sub in the object hash with the same key as the method name. This would be useful where a method has to run code from other modules, but cannot be certain whether that module will call it back again. The default behavior is to create aliases for all the entries in the hash, in the callers namespace. This can be controlled by setting a few options. See L for details. =item const This is simply a function alias for C, described above. Provided on demand at C time, since it reads better for constant declarations. Note that hashes and arrays cannot be so Crained. =back =head2 Configuration Variables The following configuration variables can be used to control the behavior of the C function. They are typically set after the C statement. Another typical usage is to Cize them in a block so that their values are only effective within that block. =over 4 =item $Alias::KeyFilter Specifies the key prefix used for determining which hash entries will be interned by C. Can be a CODE reference, in which case it will be called with the key, and the boolean return value will determine if that hash entry is a candidate attribute. =item $Alias::AttrPrefix Specifies a prefix to prepend to the names of localized attributes created by C. Can be a CODE reference, in which case it will be called with the key, and the result will determine the full name of the attribute. The value can have embedded package delimiters ("::" or "'"), which cause the attributes to be interned in that namespace instead of the Cs own namespace. For example, setting it to "main::" makes C somewhat more palatable (since we can refer to the attributes as C<$::foo>, etc., without actually declaring the attributes). =item $Alias::Deref Controls the implicit dereferencing behavior of C. If it is set to "" or 0, C will not dereference blessed references. If it is a true value (anything but "", 0, or a CODE reference), all references will be made available as their dereferenced types, including values that may be objects. The default is "". This option can be used as a filter if it is set to a CODE reference, in which case it will be called with the key and the value (whenever the value happens to be a reference), and the boolean return value will determine if that particular reference must be dereferenced. =back =head2 Exports =over 4 =item alias =item attr =back =head1 EXAMPLES Run these code snippets and observe the results to become more familiar with the features of this module. use Alias qw(alias const attr); $ten = 10; alias TEN => $ten, Ten => \$ten, Ten => \&ten, Ten => \@ten, Ten => \%ten; alias TeN => \*ten; # same as *TeN = *ten # aliasing basic types $ten = 20; print "$TEN|$Ten|$ten\n"; # should print "20|20|20" sub ten { print "10\n"; } @ten = (1..10); %ten = (a..j); &Ten; # should print "10" print @Ten, "|", %Ten, "\n"; # this will fail at run time const _TEN_ => 10; eval { $_TEN_ = 20 }; print $@ if $@; # dynamically scoped aliases @DYNAMIC = qw(m n o); { my $tmp = [ qw(a b c d) ]; local @DYNAMIC; alias DYNAMIC => $tmp, PERM => $tmp; $DYNAMIC[2] = 'zzz'; # prints "abzzzd|abzzzd|abzzzd" print @$tmp, "|", @DYNAMIC, "|", @PERM, "\n"; @DYNAMIC = qw(p q r); # prints "pqr|pqr|pqr" print @$tmp, "|", @DYNAMIC, "|", @PERM, "\n"; } # prints "mno|pqr" print @DYNAMIC, "|", @PERM, "\n"; # named closures my($lex) = 'abcd'; $closure = sub { print $lex, "\n" }; alias NAMEDCLOSURE => \&$closure; NAMEDCLOSURE(); # prints "abcd" $lex = 'pqrs'; NAMEDCLOSURE(); # prints "pqrs" # hash/object attributes package Foo; use Alias; sub new { bless { foo => 1, bar => [2,3], buz => { a => 4}, privmeth => sub { "private" }, easymeth => sub { die "to recurse or to die, is the question" }, }, $_[0]; } sub easymeth { my $s = attr shift; # localizes $foo, @bar, %buz etc with values eval { $s->easymeth }; # should fail print $@ if $@; # prints "1|2|3|a|4|private|" print join '|', $foo, @bar, %buz, $s->privmeth, "\n"; } $foo = 6; @bar = (7,8); %buz = (b => 9); Foo->new->easymeth; # this will not recurse endlessly # prints "6|7|8|b|9|" print join '|', $foo, @bar, %buz, "\n"; # this should fail at run-time eval { Foo->new->privmeth }; print $@ if $@; =head1 NOTES It is worth repeating that the aliases created by C and C will be created in the Cs namespace (we can use the C option to specify a different namespace for C). If that namespace happens to be Cized, the aliases created will be local to that block. C localizes the aliases for us. Remember that references will be available as their dereferenced types. Aliases cannot be lexical, since, by neccessity, they live on the symbol table. Lexicals can be aliased. Note that this provides a means of reversing the action of anonymous type generators C<\>, C<[]> and C<{}>. This allows us to anonymously construct data or code and give it a symbol-table presence when we choose. Any occurrence of C<::> or C<'> in names will be treated as package qualifiers, and the value will be interned in that namespace. Remember that aliases are very much like references, only we don't have to dereference them as often. Which means we won't have to pound on the dollars so much. We can dynamically make subroutines and named closures with this scheme. It is possible to alias packages, but that might be construed as abuse. Using this module will dramatically reduce noise characters in object-oriented perl code. =head1 BUGS C is not very usable, since we B so much on the symbol table. You can declare the attributes with C to avoid warnings. Setting C<$Alias::AttrPrefix> to "main::" is one way to avoid C and frustration. Tied variables cannot be aliased properly, yet. =head1 VERSION Version 2.32 30 Apr 1999 =head1 AUTHOR Gurusamy Sarathy gsar@umich.edu Copyright (c) 1995-99 Gurusamy Sarathy. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO perl(1) =cut libalias-perl-2.32/Todo100444 1750 62 723 6656670477 14015 0ustar mdormanstaff=head1 NAME TODO - aspirations for Alias =head1 DESCRIPTION =over 4 =item 1. C ought to move into perl core when I get around to hacking it in. Object attributes can then be lexically scoped instead of dynamically, or both. =item 2. (nonitem) You'd think C could be made to work for hashes and arrays via XSive code. But it turns out that the perl source must be heavily involved. Using C to achieve this is probably simpler. =back =cut libalias-perl-2.32/README100444 1750 62 3512 6712461672 14050 0ustar mdormanstaffThis is the README file for "Alias", the Perl module that performs aliasing services. This is Version 2.32. Perl Version 5.003 or later is required, and you need to be on a system supported by MakeMaker (which comes with perl) and a C compiler. You may find this module useful if you: * are tired of dereferencing hash-based object attributes * wish perl could make-do with fewer $, -> and {} things * are a little scared of using typeglobs * want the freedom to put what you want, when you want in the symbol table without having to deal with wierd syntax * need to use scalar constants in your program since you don't trust yourself from changing $PI Most notably, there is an C function that installs a whole hash on the symbol table with implicit localization. This allows you to access object attributes without having to deref the object everytime, as in most other OO languages. The other functions are just convenient wrappers for "obscure" perl functionality. The C functionality may belong in the perl core, but I am making it available as part of this module for folks to see what it "feels like" to have it first. It would be interesting to benchmark how much less/more efficient C is when compared to regular hash access of object attributes under various degrees of use. Comments are always very welcome. - Sarathy. gsar@umich.edu ------------------- INSTALL Installation is via the standard mantra. The distribution assumes you have dynamic linking available. Type perl Makefile.PL make make test If the tests pass, you can type make install to install the module. Look for newer versions of this module on CPAN. The master site for CPAN currently is: ftp://ftp.funet.fi/pub/languages/perl/CPAN There may be many others closer to your location. libalias-perl-2.32/t/ 40755 1750 62 0 6712462232 13330 5ustar mdormanstafflibalias-perl-2.32/t/alias.t100444 1750 62 10371 6656670477 14746 0ustar mdormanstaff#!/usr/bin/perl use Alias qw(alias const attr); my $TNUM = 0; sub T { ++$TNUM; my $res = shift; print $res ? "ok $TNUM\n" : "not ok $TNUM\n" }; print "1..34\n"; $TEN = ""; $ten = 10; $TWENTY = 20; alias TEN => $ten, TWENTY => \*ten; print '#\\$TEN is ', \$TEN, "\n"; print '#\\$ten is ', \$ten, "\n"; T(\$TEN eq \$ten); T($TEN eq $TWENTY); const _TEN_ => \10; eval { $_TEN_ = 20 }; T($@); $dyn = "abcd"; { local $dyn; alias dyn => "pqrs"; T($dyn eq "pqrs"); } T($dyn eq "abcd"); my($lex) = 'abcd'; $closure = sub { return "$lex"; }; alias NAMEDCLOSURE => \&$closure; $lex = 'pqrs'; T(NAMEDCLOSURE() eq "pqrs"); package Foo; # "in life", my moma always said, "you gotta pass those tests # before you can be o' some use to yerself" :-) *T = \&main::T; use Alias; sub new { bless { foo => 1, bar => [2,3], buz => { a => 4}, fuz => *easy, privmeth => sub { "private" }, easymeth => sub { die "to recurse or to die, is the question" }, }, $_[0]; } sub easy { "gulp" } sub easymeth { my $s = attr shift; # localizes $foo, @bar, and %buz with hash values T(defined($s) and ref($s) eq 'Foo'); T(defined (*fuz) and ref(\*fuz) eq ref(\*easy)); print '#easy() is ', easy(), "\n"; print '#fuz() is ', fuz(), "\n"; T(easy() eq fuz()); eval { $s->easymeth }; # should fail print "#\$\@ is: $@\n"; T($@); join '|', $foo, @bar, %buz, $s->privmeth; } $foo = 6; @bar = (7,8); %buz = (b => 9); T(Foo->new->easymeth eq '1|2|3|a|4|private'); T(join('|', $foo, @bar, %buz) eq '6|7|8|b|9'); eval { fuz() }; # the local subroutine shouldn't be here now print "# after fuz(): $@"; T($@); eval { Foo->new->privmeth }; # private method shouldn't exist either print "# after Foo->new->privmeth: $@"; T($@); package Bar; *T = \&main::T; use Alias; $Alias::KeyFilter = "_"; $Alias::AttrPrefix = "s"; $Alias::Deref = ""; sub new { my $s = { _foo => 1, _bar => [2,3], buz => { a => 4}, fuz => *easy, _privmeth => sub { "private" }, _easymeth => sub { "recursion" }, }; $s->{_this} = $s; return bless $s, $_[0]; } sub easy { "gulp" } sub s_easymeth { my $s = attr shift; # localizes $s_foo, @s_bar, and %s_buz T($s and ref($s) eq 'Bar'); print "# |$s_this|$s|\n"; T(defined($s_this) and $s_this eq $s); T(not defined &fuz); T(not defined &s_fuz); T(not scalar (keys %s_buz)); T($s->s_easymeth eq "recursion"); join '|', $s_foo, @s_bar, %buz, $s->s_privmeth; } $s_foo = 6; @s_bar = (7,8); %s_buz = (); %buz = (b => 9); T(Bar->new->s_easymeth eq '1|2|3|b|9|private'); T(join('|', $s_foo, @s_bar) eq '6|7|8'); { local $Alias::Deref = 1; my $s = attr(Bar->new); T(!$s_this and \%s_this eq $s); } eval { Bar->new->s_privmeth }; # private method shouldn't exist either print "# after Bar->new->s_privmeth: $@"; T($@); package Baz; *T = \&main::T; use Alias; $Alias::KeyFilter = sub { local $_ = shift; my($r) = (/^_.+_$/ ? 1 : 0); print "# |$_, $r|\n"; return $r }; $Alias::AttrPrefix = sub { local $_ = shift; s/^_(.+)_$/$1/; return "s_$_" if /meth$/; return "main::s_$_" }; $Alias::Deref = sub { my($n, $v) = @_; ; my $r = $n ne "_this_"; print "# |$n, $v, $r|\n"; return $r}; sub new { my $s = bless { _foo_ => 1, _bar_ => [2,3], buz_ => { a => 4}, fuz_ => *easy, _privmeth_ => sub { "private" }, _easymeth_ => sub { "recursion" }, }, $_[0]; $s->{_this_} = $s; $s->{_other_} = $s; return $s; } sub easy { "gulp" } sub s_easymeth { my $s = attr shift; # localizes $s_foo, @s_bar, and %s_buz print "# |", $::s_this, "|$s|\n"; T($::s_this and $::s_this eq $s); print "# |", join(',', keys %::s_other),"|$s|\n"; T(!$::s_other and \%::s_other eq $s); T(defined($s) and ref($s) eq 'Baz'); T(not defined &::fuz_); T(not defined &::s_fuz); T(not %::s_buz); T($s->s_easymeth eq "recursion"); join '|', $::s_foo, @::s_bar, %::buz_, $s->s_privmeth; } $::s_foo = 6; @::s_bar = (7,8); %::s_buz = (); %::buz_ = (b => 9); T(Baz->new->s_easymeth eq '1|2|3|b|9|private'); T(join('|', $::s_foo, @::s_bar) eq '6|7|8'); eval { Baz->new->s_privmeth }; # private method shouldn't exist either print "# after Baz->new->s_privmeth: $@"; T($@); __END__ libalias-perl-2.32/MANIFEST100444 1750 62 105 6656670477 14310 0ustar mdormanstaffREADME Changes Todo Alias.pm Alias.xs MANIFEST Makefile.PL t/alias.t