5.002 beta 1
[p5sagit/p5-mst-13.2.git] / ext / POSIX / POSIX.pm
index b343200..0a3eb82 100644 (file)
@@ -1,8 +1,64 @@
 package POSIX;
 
+=head1 NAME
+
+POSIX - Perl interface to IEEE 1003.1 namespace
+
+=head1 SYNOPSIS
+
+    use POSIX;
+    use POSIX 'strftime';
+
+=head1 DESCRIPTION
+
+The POSIX module permits you to access all (or nearly all) the standard
+POSIX 1003.1 identifiers.  Things which are C<#defines> in C, like EINTR
+or O_NDELAY, are automatically exported into your namespace.  All
+functions are only exported if you ask for them explicitly.  Most likely
+people will prefer to use the fully-qualified function names.
+
+To get a list of all the possible identifiers available to you--and
+their semantics--you should pick up a 1003.1 spec, or look in the
+F<POSIX.pm> module.
+
+=head1 EXAMPLES
+
+    printf "EINTR is %d\n", EINTR;
+
+    POSIX::setsid(0);
+
+    $fd = POSIX::open($path, O_CREAT|O_EXCL|O_WRONLY, 0644);
+       # note: that's a filedescriptor, *NOT* a filehandle
+
+=head1 NOTE
+
+The POSIX module is probably the most complex Perl module supplied with
+the standard distribution.  It incorporates autoloading, namespace games,
+and dynamic loading of code that's in Perl, C, or both.  It's a great
+source of wisdom.
+
+=head1 CAVEATS 
+
+A few functions are not implemented because they are C specific.  If you
+attempt to call these, they will print a message telling you that they
+aren't implemented, and suggest using the Perl equivalent should one
+exist.  For example, trying to access the setjmp() call will elicit the
+message "setjmp() is C-specific: use eval {} instead".
+
+Furthermore, some evil vendors will claim 1003.1 compliance, but in fact
+are not so: they will not pass the PCTS (POSIX Compliance Test Suites).
+For example, one vendor may not define EDEADLK, or the semantics of the
+errno values set by open(2) might not be quite right.  Perl does not
+attempt to verify POSIX compliance.  That means you can currently
+successfully say "use POSIX",  and then later in your program you find
+that your vendor has been lax and there's no usable ICANON macro after
+all.  This could be construed to be a bug.
+
+=cut
+
 use Carp;
 require Exporter;
-require AutoLoader;
+use AutoLoader;
 require DynaLoader;
 require Config;
 @ISA = qw(Exporter DynaLoader);
@@ -60,7 +116,7 @@ require Config;
                LC_TIME NULL localeconv setlocale)],
 
     math_h =>  [qw(HUGE_VAL acos asin atan ceil cosh fabs floor fmod
-               frexp ldexp log10 modf pow sinh tanh)],
+               frexp ldexp log10 modf pow sinh tan tanh)],
 
     pwd_h =>   [qw()],
 
@@ -152,7 +208,7 @@ Exporter::export_tags();
     closedir opendir readdir rewinddir
     fcntl open
     getgrgid getgrnam
-    atan2 cos exp log sin sqrt tan
+    atan2 cos exp log sin sqrt
     getpwnam getpwuid
     kill
     fileno getc printf rename sprintf
@@ -174,32 +230,37 @@ sub import {
     Exporter::import($this,@list);
 }
 
+
+bootstrap POSIX;
+
+my $EINVAL = constant("EINVAL", 0);
+my $EAGAIN = constant("EAGAIN", 0);
+
 sub AUTOLOAD {
     if ($AUTOLOAD =~ /::(_?[a-z])/) {
        $AutoLoader::AUTOLOAD = $AUTOLOAD;
        goto &AutoLoader::AUTOLOAD
     }
-    local $constname = $AUTOLOAD;
+    local $! = 0;
+    my $constname = $AUTOLOAD;
     $constname =~ s/.*:://;
-    $val = constant($constname, $_[0]);
-    if ($! != 0) {
-       if ($! =~ /Invalid/) {
-           croak "$constname is not a valid POSIX macro";
-       }
-       else {
-           croak "Your vendor has not defined POSIX macro $constname, used";
-       }
+    my $val = constant($constname, $_[0]);
+    if ($! == 0) {
+       *$AUTOLOAD = sub { $val };
+    }
+    elsif ($! == $EAGAIN) {    # Not really a constant, so always call.
+       *$AUTOLOAD = sub { constant($constname, $_[0]) };
+    }
+    elsif ($! == $EINVAL) {
+       croak "$constname is not a valid POSIX macro";
     }
-    eval "sub $AUTOLOAD { $val }";
+    else {
+       croak "Your vendor has not defined POSIX macro $constname, used";
+    }
+
     goto &$AUTOLOAD;
 }
 
-
-@liblist = ();
-@liblist = split ' ', $Config::Config{"POSIX_loadlibs"} 
-    if defined $Config::Config{"POSIX_loadlibs"};
-bootstrap POSIX @liblist;
-
 sub usage { 
     local ($mess) = @_;
     croak "Usage: POSIX::$mess";
@@ -216,16 +277,13 @@ sub unimpl {
     croak "Unimplemented: POSIX::$mess";
 }
 
-$gensym = "SYM000";
-
 sub gensym {
-    *{"POSIX::" . $gensym++};
+    my $pkg = @_ ? ref($_[0]) || $_[0] : "";
+    local *{$pkg . "::GLOB" . ++$seq};
+    \delete ${$pkg . "::"}{'GLOB' . $seq};
 }
 
 sub ungensym {
-    local($x) = shift;
-    $x =~ s/.*:://;
-    delete $POSIX::{$x};
 }
 
 ############################
@@ -241,23 +299,23 @@ package FileHandle;
 sub new {
     POSIX::usage "FileHandle->new(filename, posixmode)" if @_ != 3;
     local($class,$filename,$mode) = @_;
-    local($glob) = &POSIX::gensym;
+    local($sym) = $class->POSIX::gensym;
     $mode =~ s/a.*/>>/ ||
     $mode =~ s/w.*/>/ ||
     ($mode = '<');
-    open($glob, "$mode $filename") and
-    bless \$glob;
+    open($sym, "$mode $filename") and
+    bless $sym => $class;
 }
 
 sub new_from_fd {
     POSIX::usage "FileHandle->new_from_fd(fd,mode)" if @_ != 3;
     local($class,$fd,$mode) = @_;
-    local($glob) = &POSIX::gensym;
+    local($sym) = $class->POSIX::gensym;
     $mode =~ s/a.*/>>/ ||
     $mode =~ s/w.*/>/ ||
     ($mode = '<');
-    open($glob, "$mode&=$fd") and
-    bless \$glob;
+    open($sym, "$mode&=$fd") and
+    bless $sym => $class;
 }
 
 sub clearerr {
@@ -272,7 +330,6 @@ sub close {
 
 sub DESTROY {
     close($_[0]);
-    ungensym($_[0]);
 }
 
 sub eof {
@@ -330,15 +387,14 @@ sub toupper {
 sub closedir {
     usage "closedir(dirhandle)" if @_ != 1;
     closedir($_[0]);
-    ungensym($_[0]);
 }
 
 sub opendir {
     usage "opendir(directory)" if @_ != 1;
-    local($dirhandle) = &gensym;
+    local($dirhandle) = POSIX->gensym;
     opendir($dirhandle, $_[0])
        ? $dirhandle
-       : (ungensym($dirhandle), undef);
+       : undef;
 }
 
 sub readdir {
@@ -416,11 +472,6 @@ sub sqrt {
     sqrt($_[0]);
 }
 
-sub tan {
-    usage "tan(x)" if @_ != 1;
-    tan($_[0]);
-}
-
 sub getpwnam {
     usage "getpwnam(name)" if @_ != 1;
     getpwnam($_[0]);
@@ -808,7 +859,7 @@ sub strtok {
 }
 
 sub chmod {
-    usage "chmod(filename, mode)" if @_ != 2;
+    usage "chmod(mode, filename)" if @_ != 2;
     chmod($_[0], $_[1]);
 }