Even more Todo.
[p5sagit/p5-mst-13.2.git] / vms / vms.c
index 1212555..031f1c6 100644 (file)
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -106,6 +106,18 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
                                  {LNM$C_NAMLENGTH, LNM$_STRING, eqv, &eqvlen},
                                  {0, 0, 0, 0}};
     $DESCRIPTOR(crtlenv,"CRTL_ENV");  $DESCRIPTOR(clisym,"CLISYM");
+#if defined(USE_THREADS)
+    /* We jump through these hoops because we can be called at */
+    /* platform-specific initialization time, which is before anything is */
+    /* set up--we can't even do a plain dTHR since that relies on the */
+    /* interpreter structure to be initialized */
+    struct perl_thread *thr;
+    if (PL_curinterp) {
+      thr = PL_threadnum? THR : (struct perl_thread*)SvPVX(PL_thrsv);
+    } else {
+      thr = NULL;
+    }
+#endif
 
     if (!lnm || !eqv || idx > LNM$_MAX_INDEX) {
       set_errno(EINVAL); set_vaxc_errno(SS$_BADPARAM); return 0;
@@ -159,8 +171,22 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
             if (eqvlen > 1024) {
               set_errno(EVMSERR); set_vaxc_errno(LIB$_STRTRU);
               eqvlen = 1024;
-              if (ckWARN(WARN_MISC))
-                warner(WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm);
+             /* Special hack--we might be called before the interpreter's */
+             /* fully initialized, in which case either thr or PL_curcop */
+             /* might be bogus. We have to check, since ckWARN needs them */
+             /* both to be valid if running threaded */
+#if defined(USE_THREADS)
+             if (thr && PL_curcop) {
+#endif
+               if (ckWARN(WARN_MISC)) {
+                 warner(WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm);
+               }
+#if defined(USE_THREADS)
+             } else {
+                 warner(WARN_MISC,"Value of CLI symbol \"%s\" too long",lnm);
+             }
+#endif
+             
             }
             strncpy(eqv,eqvdsc.dsc$a_pointer,eqvlen);
           }
@@ -188,7 +214,6 @@ vmstrnenv(const char *lnm, char *eqv, unsigned long int idx,
 }  /* end of vmstrnenv */
 /*}}}*/
 
-
 /*{{{ int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx)*/
 /* Define as a function so we can access statics. */
 int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx)
@@ -207,7 +232,7 @@ int my_trnlnm(const char *lnm, char *eqv, unsigned long int idx)
  * Note: Uses Perl temp to store result so char * can be returned to
  * caller; this pointer will be invalidated at next Perl statement
  * transition.
- * We define this as a function rather than a macro in terms of my_getenv_sv()
+ * We define this as a function rather than a macro in terms of my_getenv_len()
  * so that it'll work when PL_curinterp is undefined (and we therefore can't
  * allocate SVs).
  */
@@ -256,17 +281,28 @@ my_getenv(const char *lnm, bool sys)
 /*}}}*/
 
 
-/*{{{ SV *my_getenv_sv(const char *lnm, bool sys)*/
-SV *
-my_getenv_sv(const char *lnm, bool sys)
+/*{{{ SV *my_getenv_len(const char *lnm, bool sys)*/
+char *
+my_getenv_len(const char *lnm, unsigned long *len, bool sys)
 {
-    char buf[LNM$C_NAMLENGTH+1], *cp1, *cp2;
-    unsigned long int len, idx = 0;
-
+    char *buf, *cp1, *cp2;
+    unsigned long idx = 0;
+    static char __my_getenv_len_eqv[LNM$C_NAMLENGTH+1];
+    SV *tmpsv;
+    
+    if (PL_curinterp) {  /* Perl interpreter running -- may be threaded */
+      /* Set up a temporary buffer for the return value; Perl will
+       * clean it up at the next statement transition */
+      tmpsv = sv_2mortal(newSVpv("",LNM$C_NAMLENGTH+1));
+      if (!tmpsv) return NULL;
+      buf = SvPVX(tmpsv);
+    }
+    else buf = __my_getenv_len_eqv;  /* Assume no interpreter ==> single thread */
     for (cp1 = (char *)lnm, cp2 = buf; *cp1; cp1++,cp2++) *cp2 = _toupper(*cp1);
     if (cp1 - lnm == 7 && !strncmp(buf,"DEFAULT",7)) {
       getcwd(buf,LNM$C_NAMLENGTH);
-      return newSVpv(buf,0);
+      *len = strlen(buf);
+      return buf;
     }
     else {
       if ((cp2 = strchr(lnm,';')) != NULL) {
@@ -275,18 +311,20 @@ my_getenv_sv(const char *lnm, bool sys)
         idx = strtoul(cp2+1,NULL,0);
         lnm = buf;
       }
-      if ((len = vmstrnenv(lnm,buf,idx,
+      if ((*len = vmstrnenv(lnm,buf,idx,
                            sys ? fildev : NULL,
 #ifdef SECURE_INTERNAL_GETENV
                            sys ? PERL__TRNENV_SECURE : 0
 #else
                                                        0
 #endif
-                                                         ))) return newSVpv(buf,len);
-      else return &PL_sv_undef;
+                                                         )))
+         return buf;
+      else
+         return Nullch;
     }
 
-}  /* end of my_getenv_sv() */
+}  /* end of my_getenv_len() */
 /*}}}*/
 
 static void create_mbx(unsigned short int *, struct dsc$descriptor_s *);
@@ -428,15 +466,22 @@ prime_env_iter(void)
       key = cp1;  keylen = cp2 - cp1;
       if (keylen && hv_exists(seenhv,key,keylen)) continue;
       while (*cp2 && *cp2 != '=') cp2++;
-      while (*cp2 && *cp2 != '"') cp2++;
-      for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
-      if ((!keylen || (cp1 - cp2 <= 0)) && ckWARN(WARN_INTERNAL)) {
+      while (*cp2 && *cp2 == '=') cp2++;
+      while (*cp2 && *cp2 == ' ') cp2++;
+      if (*cp2 == '"') {  /* String translation; may embed "" */
+        for (cp1 = buf + retlen; *cp1 != '"'; cp1--) ;
+        cp2++;  cp1--; /* Skip "" surrounding translation */
+      }
+      else {  /* Numeric translation */
+        for (cp1 = cp2; *cp1 && *cp1 != ' '; cp1++) ;
+        cp1--;  /* stop on last non-space char */
+      }
+      if ((!keylen || (cp1 - cp2 < -1)) && ckWARN(WARN_INTERNAL)) {
         warner(WARN_INTERNAL,"Ill-formed message in prime_env_iter: |%s|",buf);
         continue;
       }
-      /* Skip "" surrounding translation */
       PERL_HASH(hash,key,keylen);
-      hv_store(envhv,key,keylen,newSVpv(cp2+1,cp1 - cp2 - 1),hash);
+      hv_store(envhv,key,keylen,newSVpvn(cp2,cp1 - cp2 + 1),hash);
       hv_store(seenhv,key,keylen,&PL_sv_yes,hash);
     }
     if (cmddsc.dsc$w_length == 14) { /* We just read LNM$FILE_DEV */
@@ -879,7 +924,7 @@ static int waitpid_asleep = 0;
  * to a mbx; that's the caller's responsibility.
  */
 static unsigned long int
-pipe_eof(FILE *fp)
+pipe_eof(FILE *fp, int immediate)
 {
   char devnam[NAM$C_MAXRSS+1], *cp;
   unsigned long int chan, iosb[2], retsts, retsts2;
@@ -891,7 +936,8 @@ pipe_eof(FILE *fp)
     if ((cp = strrchr(devnam,':')) != NULL) *(cp+1) = '\0';
     devdsc.dsc$w_length = strlen(devnam);
     _ckvmssts(sys$assign(&devdsc,&chan,0,0));
-    retsts = sys$qiow(0,chan,IO$_WRITEOF,iosb,0,0,0,0,0,0,0,0);
+    retsts = sys$qiow(0,chan,IO$_WRITEOF|(immediate?IO$M_NOW|IO$M_NORSWAIT:0),
+             iosb,0,0,0,0,0,0,0,0);
     if (retsts & 1) retsts = iosb[0];
     retsts2 = sys$dassgn(chan);  /* Be sure to deassign the channel */
     if (retsts & 1) retsts = retsts2;
@@ -918,7 +964,7 @@ pipe_exit_routine()
 
     while (info) {
       if (info->mode != 'r' && !info->done) {
-        if (pipe_eof(info->fp) & 1) did_stuff = 1;
+        if (pipe_eof(info->fp, 1) & 1) did_stuff = 1;
       }
       info = info->next;
     }
@@ -1060,7 +1106,7 @@ I32 my_pclose(FILE *fp)
     /* If we were writing to a subprocess, insure that someone reading from
      * the mailbox gets an EOF.  It looks like a simple fclose() doesn't
      * produce an EOF record in the mailbox.  */
-    if (info->mode != 'r' && !info->done) pipe_eof(info->fp);
+    if (info->mode != 'r' && !info->done) pipe_eof(info->fp,0);
     PerlIO_close(info->fp);
 
     if (info->done) retsts = info->completion;
@@ -1081,6 +1127,7 @@ Pid_t
 my_waitpid(Pid_t pid, int *statusp, int flags)
 {
     struct pipe_details *info;
+    dTHR;
     
     for (info = open_pipes; info != NULL; info = info->next)
         if (info->pid == pid) break;
@@ -3379,6 +3426,7 @@ bool
 vms_do_exec(char *cmd)
 {
 
+  dTHR;
   if (vfork_called) {             /* this follows a vfork - act Unixish */
     vfork_called--;
     if (vfork_called < 0) {
@@ -3443,6 +3491,7 @@ unsigned long int
 do_spawn(char *cmd)
 {
   unsigned long int sts, substs, hadcmd = 1;
+  dTHR;
 
   TAINT_ENV();
   TAINT_PROPER("spawn");
@@ -4497,17 +4546,19 @@ flex_fstat(int fd, Stat_t *statbufp)
 }  /* end of flex_fstat() */
 /*}}}*/
 
-/*{{{ int flex_stat(char *fspec, Stat_t *statbufp)*/
+/*{{{ int flex_stat(const char *fspec, Stat_t *statbufp)*/
 int
-flex_stat(char *fspec, Stat_t *statbufp)
+flex_stat(const char *fspec, Stat_t *statbufp)
 {
     dTHR;
     char fileified[NAM$C_MAXRSS+1];
+    char temp_fspec[NAM$C_MAXRSS+300];
     int retval = -1;
 
+    strcpy(temp_fspec, fspec);
     if (statbufp == (Stat_t *) &PL_statcache)
-      do_tovmsspec(fspec,namecache,0);
-    if (is_null_device(fspec)) { /* Fake a stat() for the null device */
+      do_tovmsspec(temp_fspec,namecache,0);
+    if (is_null_device(temp_fspec)) { /* Fake a stat() for the null device */
       memset(statbufp,0,sizeof *statbufp);
       statbufp->st_dev = encode_dev("_NLA0:");
       statbufp->st_mode = S_IFBLK | S_IREAD | S_IWRITE | S_IEXEC;
@@ -4526,12 +4577,12 @@ flex_stat(char *fspec, Stat_t *statbufp)
      * the file with null type, specify this by calling flex_stat() with
      * a '.' at the end of fspec.
      */
-    if (do_fileify_dirspec(fspec,fileified,0) != NULL) {
+    if (do_fileify_dirspec(temp_fspec,fileified,0) != NULL) {
       retval = stat(fileified,(stat_t *) statbufp);
       if (!retval && statbufp == (Stat_t *) &PL_statcache)
         strcpy(namecache,fileified);
     }
-    if (retval) retval = stat(fspec,(stat_t *) statbufp);
+    if (retval) retval = stat(temp_fspec,(stat_t *) statbufp);
     if (!retval) {
       statbufp->st_dev = encode_dev(statbufp->st_devnam);
 #     ifdef RTL_USES_UTC