This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[inseparable changes from patch from perl5.003_08 to perl5.003_09]
[perl5.git] / ext / POSIX / POSIX.xs
index 8c5988f..a94c942 100644 (file)
@@ -1,4 +1,5 @@
 #include "EXTERN.h"
+#define PERLIO_NOT_STDIO 1
 #include "perl.h"
 #include "XSUB.h"
 #include <ctype.h>
@@ -6,11 +7,9 @@
 #include <dirent.h>
 #endif
 #include <errno.h>
-#include <fcntl.h>
 #ifdef I_FLOAT
 #include <float.h>
 #endif
-#include <grp.h>
 #ifdef I_LIMITS
 #include <limits.h>
 #endif
 #endif
 #include <string.h>
 #include <sys/stat.h>
-#include <sys/times.h>
 #include <sys/types.h>
-#ifdef HAS_UNAME
-#include <sys/utsname.h>
-#endif
-#include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
-#ifdef I_UTIME
-#include <utime.h>
+#if defined(__VMS) && !defined(__POSIX_SOURCE)
+#  include <file.h>         /* == fcntl.h for DECC; no fcntl.h for VAXC */
+#  include <libdef.h>       /* LIB$_INVARG constant */
+#  include <lib$routines.h> /* prototype for lib$ediv() */
+#  include <starlet.h>      /* prototype for sys$gettim() */
+
+#  undef mkfifo  /* #defined in perl.h */
+#  define mkfifo(a,b) (not_here("mkfifo"),-1)
+#  define tzset() not_here("tzset")
+
+   /* The default VMS emulation of Unix signals isn't very POSIXish */
+   typedef int sigset_t;
+#  define sigpending(a) (not_here("sigpending"),0)
+
+   /* sigset_t is atomic under VMS, so these routines are easy */
+   int sigemptyset(sigset_t *set) {
+       if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+       *set = 0; return 0;
+   }
+   int sigfillset(sigset_t *set) {
+       int i;
+       if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+       for (i = 0; i < NSIG; i++) *set |= (1 << i);
+       return 0;
+   }
+   int sigaddset(sigset_t *set, int sig) {
+       if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+       if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+       *set |= (1 << (sig - 1));
+       return 0;
+   }
+   int sigdelset(sigset_t *set, int sig) {
+       if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+       if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+       *set &= ~(1 << (sig - 1));
+       return 0;
+   }
+   int sigismember(sigset_t *set, int sig) {
+       if (!set) { SETERRNO(EFAULT,SS$_ACCVIO); return -1; }
+       if (sig > NSIG) { SETERRNO(EINVAL,LIB$_INVARG); return -1; }
+       *set & (1 << (sig - 1));
+   }
+   /* The tools for sigprocmask() are there, just not the routine itself */
+#  ifndef SIG_UNBLOCK
+#    define SIG_UNBLOCK 1
+#  endif
+#  ifndef SIG_BLOCK
+#    define SIG_BLOCK 2
+#  endif
+#  ifndef SIG_SETMASK
+#    define SIG_SETMASK 3
+#  endif
+   int sigprocmask(int how, sigset_t *set, sigset_t *oset) {
+       if (!set || !oset) {
+         set_errno(EFAULT); set_vaxc_errno(SS$_ACCVIO);
+         return -1;
+       }
+       switch (how) {
+         case SIG_SETMASK:
+           *oset = sigsetmask(*set);
+           break;
+         case SIG_BLOCK:
+           *oset = sigblock(*set);
+           break;
+         case SIG_UNBLOCK:
+           *oset = sigblock(0);
+           sigsetmask(*oset & ~*set);
+           break;
+         default:
+           set_errno(EINVAL); set_vaxc_errno(LIB$_INVARG);
+           return -1;
+       }
+       return 0;
+    }
+#  define sigaction sigvec
+#  define sa_flags sv_onstack
+#  define sa_handler sv_handler
+#  define sa_mask sv_mask
+#  define sigsuspend(set) sigpause(*set)
+
+   /* The POSIX notion of ttyname() is better served by getname() under VMS */
+   static char ttnambuf[64];
+#  define ttyname(fd) (isatty(fd) > 0 ? getname(fd,ttnambuf,0) : NULL)
+
+   /* The non-POSIX CRTL times() has void return type, so we just get the
+      current time directly */
+   clock_t vms_times(struct tms *bufptr) {
+       clock_t retval;
+       /* Get wall time and convert to 10 ms intervals to
+        * produce the return value that the POSIX standard expects */
+#  if defined(__DECC) && defined (__ALPHA)
+#    include <ints.h>
+       uint64 vmstime;
+       _ckvmssts(sys$gettim(&vmstime));
+       vmstime /= 100000;
+       retval = vmstime & 0x7fffffff;
+#  else
+       /* (Older hw or ccs don't have an atomic 64-bit type, so we
+        * juggle 32-bit ints (and a float) to produce a time_t result
+        * with minimal loss of information.) */
+       long int vmstime[2],remainder,divisor = 100000;
+       _ckvmssts(sys$gettim((unsigned long int *)vmstime));
+       vmstime[1] &= 0x7fff;  /* prevent overflow in EDIV */
+       _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder));
+#  endif
+       /* Fill in the struct tms using the CRTL routine . . .*/
+       times((tbuffer_t *)bufptr);
+       return (clock_t) retval;
+   }
+#  define times(t) vms_times(t)
+#else
+#  include <fcntl.h>
+#  include <grp.h>
+#  include <sys/times.h>
+#  ifdef HAS_UNAME
+#    include <sys/utsname.h>
+#  endif
+#  include <sys/wait.h>
+#  ifdef I_UTIME
+#    include <utime.h>
+#  endif
 #endif
 
 typedef int SysRet;
@@ -78,6 +191,9 @@ typedef struct termios* POSIX__Termios;
 
 /* Possibly needed prototypes */
 char *cuserid _((char *));
+double strtod _((const char *, char **));
+long strtol _((const char *, char **, int));
+unsigned long strtoul _((const char *, char **, int));
 
 #ifndef HAS_CUSERID
 #define cuserid(a) (char *) not_here("cuserid")
@@ -114,6 +230,15 @@ char *cuserid _((char *));
 #ifndef HAS_STRCOLL
 #define strcoll(s1,s2) not_here("strcoll")
 #endif
+#ifndef HAS_STRTOD
+#define strtod(s1,s2) not_here("strtod")
+#endif
+#ifndef HAS_STRTOL
+#define strtol(s1,s2,b) not_here("strtol")
+#endif
+#ifndef HAS_STRTOUL
+#define strtoul(s1,s2,b) not_here("strtoul")
+#endif
 #ifndef HAS_STRXFRM
 #define strxfrm(s1,s2,n) not_here("strxfrm")
 #endif
@@ -133,13 +258,6 @@ char *cuserid _((char *));
 #define waitpid(a,b,c) not_here("waitpid")
 #endif
 
-#ifndef HAS_FGETPOS
-#define fgetpos(a,b) not_here("fgetpos")
-#endif
-#ifndef HAS_FSETPOS
-#define fsetpos(a,b) not_here("fsetpos")
-#endif
-
 #ifndef HAS_MBLEN
 #ifndef mblen
 #define mblen(a,b) not_here("mblen")
@@ -2613,9 +2731,67 @@ localeconv()
        RETVAL
 
 char *
-setlocale(category, locale)
+setlocale(category, locale = 0)
        int             category
        char *          locale
+    CODE:
+       RETVAL = setlocale(category, locale);
+       if (RETVAL) {
+#ifdef LC_CTYPE
+           if (category == LC_CTYPE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newctype;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newctype = setlocale(LC_CTYPE, NULL);
+               else
+#endif
+                   newctype = RETVAL;
+               perl_new_ctype(newctype);
+           }
+#endif /* LC_CTYPE */
+#ifdef LC_COLLATE
+           if (category == LC_COLLATE
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newcoll;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newcoll = setlocale(LC_COLLATE, NULL);
+               else
+#endif
+                   newcoll = RETVAL;
+               perl_new_collate(newcoll);
+           }
+#endif /* LC_COLLATE */
+#ifdef LC_NUMERIC
+           if (category == LC_NUMERIC
+#ifdef LC_ALL
+               || category == LC_ALL
+#endif
+               )
+           {
+               char *newnum;
+#ifdef LC_ALL
+               if (category == LC_ALL)
+                   newnum = setlocale(LC_NUMERIC, NULL);
+               else
+#endif
+                   newnum = RETVAL;
+               perl_new_numeric(newnum);
+           }
+#endif /* LC_NUMERIC */
+       }
+    OUTPUT:
+       RETVAL
+
 
 double
 acos(x)
@@ -2745,9 +2921,9 @@ sigaction(sig, action, oldaction = 0)
            if (action && oldaction)
                RETVAL = sigaction(sig, & act, & oact);
            else if (action)
-               RETVAL = sigaction(sig, & act, (struct sigaction*)0);
+               RETVAL = sigaction(sig, & act, (struct sigaction *)0);
            else if (oldaction)
-               RETVAL = sigaction(sig, (struct sigaction*)0, & oact);
+               RETVAL = sigaction(sig, (struct sigaction *)0, & oact);
            else
                RETVAL = -1;
 
@@ -2837,8 +3013,7 @@ read(fd, buffer, nbytes)
             SvCUR(sv_buffer) = RETVAL;
             SvPOK_only(sv_buffer);
             *SvEND(sv_buffer) = '\0';
-            if (tainting)
-                sv_magic(sv_buffer, 0, 't', 0, 0);
+            SvTAINTED_on(sv_buffer);
         }
 
 SysRet
@@ -2921,6 +3096,66 @@ strcoll(s1, s2)
        char *          s1
        char *          s2
 
+void
+strtod(str)
+       char *          str
+    PREINIT:
+       double num;
+       char *unparsed;
+    PPCODE:
+       NUMERIC_LOCAL();
+       num = strtod(str, &unparsed);
+       PUSHs(sv_2mortal(newSVnv(num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(sp, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
+void
+strtol(str, base = 0)
+       char *          str
+       int             base
+    PREINIT:
+       long num;
+       char *unparsed;
+    PPCODE:
+       num = strtol(str, &unparsed, base);
+       if (num >= IV_MIN && num <= IV_MAX)
+           PUSHs(sv_2mortal(newSViv((IV)num)));
+       else
+           PUSHs(sv_2mortal(newSVnv((double)num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(sp, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
+void
+strtoul(str, base = 0)
+       char *          str
+       int             base
+    PREINIT:
+       unsigned long num;
+       char *unparsed;
+    PPCODE:
+       num = strtoul(str, &unparsed, base);
+       if (num <= IV_MAX)
+           PUSHs(sv_2mortal(newSViv((IV)num)));
+       else
+           PUSHs(sv_2mortal(newSVnv((double)num)));
+       if (GIMME == G_ARRAY) {
+           EXTEND(sp, 1);
+           if (unparsed)
+               PUSHs(sv_2mortal(newSViv(strlen(unparsed))));
+           else
+               PUSHs(&sv_undef);
+       }
+
 SV *
 strxfrm(src)
        SV *            src