[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

<DIRHANDLE>



The appended patch implements <>/readline() for directory handles, and
makes it return a filename for each line read.

What do people think of this idea?

(I know the actual code could stand some improvement, such as renaming
readdir_helper and moving it to util.c, eliminating more repeated code
from readline, and so on. But I'll bother with all that only if anyone
is actually interested in the patch.)

In any case, pp_readdir() deserves to be cleaned up. I will.

-- ams

==== //depot/perl/pp_hot.c#326 - /home/ams/build/perl/current/pp_hot.c ====
--- /tmp/tmp.22706.0	Sat Sep  6 04:48:19 2003
+++ /home/ams/build/perl/current/pp_hot.c	Sat Sep  6 04:34:37 2003
@@ -1471,14 +1471,35 @@ Perl_do_readline(pTHX)
 		}
 		fp = nextargv(PL_last_in_gv);
 		if (!fp) { /* Note: fp != IoIFP(io) */
-		    (void)do_close(PL_last_in_gv, FALSE); /* now it does*/
+		    (void)do_close(PL_last_in_gv, FALSE); /* now it does */
 		}
 	    }
-	    else if (type == OP_GLOB)
+	    else if (type == OP_GLOB) {
 		fp = Perl_start_glob(aTHX_ POPs, io);
+            }
+            else if (IoDIRP(io)) {
+                extern int readdir_helper(IO *io, SV *sv);
+                if (gimme == G_SCALAR) {
+                    if (readdir_helper(io, TARG) < 0)
+                        RETPUSHUNDEF;
+                    PUSHTARG;
+                    RETURN;
+                }
+                else {
+                    do {
+                        SV *sv = sv_2mortal(newSVpvn("", 0));
+                        if (readdir_helper(io, sv) < 0)
+                            break;
+                        XPUSHs(sv);
+                    }
+                    while (1);
+                    RETURN;
+                }
+            }
 	}
-	else if (type == OP_GLOB)
+	else if (type == OP_GLOB) {
 	    SP--;
+        }
 	else if (ckWARN(WARN_IO) && IoTYPE(io) == IoTYPE_WRONLY) {
 	    report_evil_fh(PL_last_in_gv, io, OP_phoney_OUTPUT_ONLY);
 	}

==== //depot/perl/pp_sys.c#355 - /home/ams/build/perl/current/pp_sys.c ====
--- /tmp/tmp.22706.1	Sat Sep  6 04:48:33 2003
+++ /home/ams/build/perl/current/pp_sys.c	Sat Sep  6 04:21:08 2003
@@ -3794,62 +3794,61 @@ nope:
 #endif
 }
 
-PP(pp_readdir)
+int
+readdir_helper(register IO *io, SV *sv)
 {
-#if defined(Direntry_t) && defined(HAS_READDIR)
-    dSP;
+#if !defined(Direntry_t) || !defined(HAS_READDIR)
+    DIE(aTHX_ PL_no_dir_func, "readdir");
+#else
 #if !defined(I_DIRENT) && !defined(VMS)
     Direntry_t *readdir (DIR *);
 #endif
     register Direntry_t *dp;
-    GV *gv = (GV*)POPs;
-    register IO *io = GvIOn(gv);
-    SV *sv;
 
     if (!io || !IoDIRP(io))
-	goto nope;
+        goto nope;
 
-    if (GIMME == G_ARRAY) {
-	/*SUPPRESS 560*/
-	while ((dp = (Direntry_t *)PerlDir_read(IoDIRP(io)))) {
+    dp = (Direntry_t *)PerlDir_read(IoDIRP(io));
+    if (dp) {
 #ifdef DIRNAMLEN
-	    sv = newSVpvn(dp->d_name, dp->d_namlen);
+        sv_setpvn(sv, dp->d_name, dp->d_namlen);
 #else
-	    sv = newSVpv(dp->d_name, 0);
+        sv_setpv(sv, dp->d_name);
 #endif
 #ifndef INCOMPLETE_TAINTS
-	    if (!(IoFLAGS(io) & IOf_UNTAINT))
-		SvTAINTED_on(sv);
+        if (!(IoFLAGS(io) & IOf_UNTAINT))
+            SvTAINTED_on(sv);
 #endif
-	    XPUSHs(sv_2mortal(sv));
-	}
+        return 0;
     }
-    else {
-	if (!(dp = (Direntry_t *)PerlDir_read(IoDIRP(io))))
-	    goto nope;
-#ifdef DIRNAMLEN
-	sv = newSVpvn(dp->d_name, dp->d_namlen);
-#else
-	sv = newSVpv(dp->d_name, 0);
-#endif
-#ifndef INCOMPLETE_TAINTS
-	if (!(IoFLAGS(io) & IOf_UNTAINT))
-	    SvTAINTED_on(sv);
-#endif
-	XPUSHs(sv_2mortal(sv));
-    }
-    RETURN;
 
 nope:
     if (!errno)
-	SETERRNO(EBADF,RMS_ISI);
-    if (GIMME == G_ARRAY)
-	RETURN;
-    else
-	RETPUSHUNDEF;
-#else
-    DIE(aTHX_ PL_no_dir_func, "readdir");
+        SETERRNO(EBADF,RMS_ISI);
+    return -1;
 #endif
+}
+
+PP(pp_readdir)
+{
+    dSP;
+    int n = 0;
+    int gimme = GIMME;
+    GV *gv = (GV *)POPs;
+
+    do {
+        SV *sv = sv_2mortal(newSVpvn("", 0));
+
+        if (readdir_helper(GvIOn(gv), sv) < 0)
+            break;
+        XPUSHs(sv);
+        n++;
+    }
+    while (gimme == G_ARRAY);
+
+    if (n == 0 && gimme != G_ARRAY)
+        RETPUSHUNDEF;
+    RETURN;
 }
 
 PP(pp_telldir)


Follow-Ups from:
Michael G Schwern <schwern@pobox.com>
Mark Jason Dominus <mjd@plover.com>
Tassilo von Parseval <tassilo.parseval@post.rwth-aachen.de>
Yitzchak Scott-Thoennes <sthoenna@efn.org>

[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]