--- a/DirectoryStream.st Sat Sep 16 19:14:32 1995 +0200
+++ b/DirectoryStream.st Sun Sep 17 19:57:55 1995 +0200
@@ -21,7 +21,7 @@
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
-$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.22 1995-09-16 17:13:04 claus Exp $
+$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.23 1995-09-17 17:56:01 claus Exp $
'!
!DirectoryStream class methodsFor:'documentation'!
@@ -42,7 +42,7 @@
version
"
-$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.22 1995-09-16 17:13:04 claus Exp $
+$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.23 1995-09-17 17:56:01 claus Exp $
"
!
@@ -73,7 +73,9 @@
# ifdef NEXT
# include <sys/dir.h>
# else
-# include <dirent.h>
+# ifndef VMS
+# include <dirent.h>
+# endif /* not VMS */
# endif
# endif
#endif
@@ -88,6 +90,285 @@
%}
! !
+!DirectoryStream primitiveFunctions!
+
+%{
+#ifdef VMS
+
+/*
+** VMS readdir() routines.
+** Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
+** This code has no copyright.
+*/
+
+/* 12-NOV-1990 added d_namlen field and special case "." name -GJC@MITECH.COM
+ */
+
+#ifndef _STDIO_H_INCLUDED_
+# include <stdio.h>
+# define _STDIO_H_INCLUDED_
+#endif
+
+#ifndef _CTYPE_H_INCLUDED_
+# include <ctype.h>
+# define _CTYPE_H_INCLUDED_
+#endif
+
+#ifndef _ERRNO_H_INCLUDED_
+# include <errno.h>
+# define _ERRNO_H_INCLUDED_
+#endif
+
+#ifndef _DESCRIP_H_INCLUDED_
+# include <descrip.h>
+# define _DESCRIP_H_INCLUDED_
+#endif
+
+#ifndef _RMSDEF_H_INCLUDED_
+# include <rmsdef.h>
+# define _RMSDEF_H_INCLUDED_
+#endif
+
+/*
+ * actually, the following has to go into dirent.h ...
+ */
+/* BEGIN dirent.h
+ *
+** Header file for VMS readdir() routines.
+** Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
+** This code has no copyright.
+**
+** You must #include <descrip.h> before this file.
+*/
+
+/* 12-NOV-1990 added d_namlen field -GJC@MITECH.COM */
+
+ /* Data structure returned by READDIR(). */
+struct dirent {
+ char d_name[100]; /* File name */
+ int d_namlen;
+ int vms_verscount; /* Number of versions */
+ int vms_versions[20]; /* Version numbers */
+};
+
+ /* Handle returned by opendir(), used by the other routines. You
+ * are not supposed to care what's inside this structure. */
+typedef struct _dirdesc {
+ long context;
+ int vms_wantversions;
+ char *pattern;
+ struct dirent entry;
+ struct dsc$descriptor_s pat;
+} DIR;
+
+
+#define rewinddir(dirp) seekdir((dirp), 0L)
+
+
+extern DIR *opendir();
+extern struct dirent *readdir();
+extern long telldir();
+extern void seekdir();
+extern void closedir();
+extern void vmsreaddirversions();
+#define _DIRENT_H_INCLUDED_
+/*
+ * END dirent.h
+ */
+
+
+ /* Number of elements in vms_versions array */
+#define VERSIZE(e) (sizeof e->vms_versions / sizeof e->vms_versions[0])
+
+ /* Linked in later. */
+extern char *strrchr();
+extern char *strcpy();
+/* Don't need this when all these programs are lumped together. RLD
+extern char *malloc();
+*/
+
+/*
+** Open a directory, return a handle for later use.
+*/
+DIR *
+opendir(name)
+ char *name;
+{
+ DIR *dd;
+
+ /* Get memory for the handle, and the pattern. */
+ if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ if (strcmp(".",name) == 0) name = "";
+
+ dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1));
+ if (dd->pattern == NULL) {
+ free((char *)dd);
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ /* Fill in the fields; mainly playing with the descriptor. */
+ (void)sprintf(dd->pattern, "%s*.*", name);
+ dd->context = 0;
+ dd->vms_wantversions = 0;
+ dd->pat.dsc$a_pointer = dd->pattern;
+ dd->pat.dsc$w_length = strlen(dd->pattern);
+ dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
+ dd->pat.dsc$b_class = DSC$K_CLASS_S;
+
+ return dd;
+}
+
+/*
+** Set the flag to indicate we want versions or not.
+*/
+void
+vmsreaddirversions(dd, flag)
+ DIR *dd;
+ int flag;
+{
+ dd->vms_wantversions = flag;
+}
+
+/*
+** Free up an opened directory.
+*/
+void
+closedir(dd)
+ DIR *dd;
+{
+ free(dd->pattern);
+ free((char *)dd);
+}
+
+/*
+** Collect all the version numbers for the current file.
+*/
+static void
+collectversions(dd)
+ DIR *dd;
+{
+ struct dsc$descriptor_s pat;
+ struct dsc$descriptor_s res;
+ struct dirent *e;
+ char *p;
+ char buff[sizeof dd->entry.d_name];
+ int i;
+ char *text;
+ long context;
+
+ /* Convenient shorthand. */
+ e = &dd->entry;
+
+ /* Add the version wildcard, ignoring the "*.*" put on before */
+ i = strlen(dd->pattern);
+ text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1));
+ if (text == NULL)
+ return;
+ (void)strcpy(text, dd->pattern);
+ (void)sprintf(&text[i - 3], "%s;*", e->d_name);
+
+ /* Set up the pattern descriptor. */
+ pat.dsc$a_pointer = text;
+ pat.dsc$w_length = strlen(text);
+ pat.dsc$b_dtype = DSC$K_DTYPE_T;
+ pat.dsc$b_class = DSC$K_CLASS_S;
+
+ /* Set up result descriptor. */
+ res.dsc$a_pointer = buff;
+ res.dsc$w_length = sizeof buff - 2;
+ res.dsc$b_dtype = DSC$K_DTYPE_T;
+ res.dsc$b_class = DSC$K_CLASS_S;
+
+ /* Read files, collecting versions. */
+ for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) {
+ if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0)
+ break;
+ buff[sizeof buff - 1] = '\0';
+ if (p = strchr(buff, ';'))
+ e->vms_versions[e->vms_verscount] = atoi(p + 1);
+ else
+ e->vms_versions[e->vms_verscount] = -1;
+ }
+
+ free(text);
+}
+
+/*
+** Read the next entry from the directory.
+*/
+struct dirent *
+readdir(dd)
+ DIR *dd;
+{
+ struct dsc$descriptor_s res;
+ char *p;
+ char buff[sizeof dd->entry.d_name];
+ int i;
+
+ /* Set up result descriptor, and get next file. */
+ res.dsc$a_pointer = buff;
+ res.dsc$w_length = sizeof buff - 2;
+ res.dsc$b_dtype = DSC$K_DTYPE_T;
+ res.dsc$b_class = DSC$K_CLASS_S;
+ if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF
+ || dd->context == 0L)
+ /* None left... */
+ return NULL;
+
+ /* Force the buffer to end with a NUL. */
+ buff[sizeof buff - 1] = '\0';
+ for (p = buff; !isspace(*p); p++)
+ ;
+ *p = '\0';
+
+ /* Skip any directory component and just copy the name. */
+ if (p = strchr(buff, ']'))
+ (void)strcpy(dd->entry.d_name, p + 1);
+ else
+ (void)strcpy(dd->entry.d_name, buff);
+
+ /* Clobber the version. */
+ if (p = strchr(dd->entry.d_name, ';'))
+ *p = '\0';
+
+ dd->entry.d_namlen = strlen(dd->entry.d_name);
+
+ dd->entry.vms_verscount = 0;
+ if (dd->vms_wantversions)
+ collectversions(dd);
+ return &dd->entry;
+}
+
+/*
+** Return something that can be used in a seekdir later.
+*/
+long
+telldir(dd)
+ DIR *dd;
+{
+ return dd->context;
+}
+
+/*
+** Return to a spot where we used to be.
+*/
+void
+seekdir(dd, pos)
+ DIR *dd;
+ long pos;
+{
+ dd->context = pos;
+}
+
+#endif /* VMS */
+%}
+! !
+
!DirectoryStream methodsFor:'instance release'!
closeFile