[net.emacs] VMS GNUmacs: Wildcard Filespecs!

nz@wucs.UUCP (Neal Ziring) (08/12/86)

	We got in VMS GNU Emacs version 4 about two weeks ago, and
we like it very much (Thanks, Marty!).  However, after a few days
of using it, I wanted to edit every .com file in my project directory.
I typed
		$ gemacs *.com
to DCL.  Well,
Emacs thoughtfully put me in a buffer named "*.COM".  This is Bad!

To remedy the situation, I wrote two Elisp-callable C routines, and modified
some the the GNU Emacs startup code to use them.  Below is my C code, plus
the differences between the old modules and my new versions.  The differences
are the output of the VAX/VMS ``Difference'' utility.

To use this stuff, just take the comple file, FILE_GLOB.C, and put it into
the emacs source directory, and compile it with  CC FILE_GLOB.C.  Then,
using emacs, make the changes to CONFIG.H and EMACS.C (I'd like to see EVE
let you view the differences plus both files, all at the same time!).
All the changes are _very_ minor.  Then, recompile EMACS.C.
Lastly, modify the LINK*.COM file that you use to link in the new 
module, FILE_GLOB.OBJ.  You will now have a new TEMACS.EXE, which you can
re-install or test or whatever.

Have fun!  If you have any questions, mail them to nz@wucs.UUCP soon!
Also, would somebody please forward this letter to the vms-gnu mailing list?
I don't know how to do that.

================================ EMACS_C.DIFF

************
File DUA0:[EMACS.SRC]EMACS.C;17
  144   	Vcommand_line_args
  145   	  = Fcons (build_string (argv[i]), Vcommand_line_args);
  146       }
******
File DUA0:[EMACS.SRC]EMACS.C;33
  144   #ifdef GLOB_VMS
  145   
  146   	/* glob our command line file-names, safe for other args, too */
  147   	Vcommand_line_args 
  148   	  =  Fglob_file_safe ( build_string (argv[i] ), Vcommand_line_args);
  149   #else
  150   	Vcommand_line_args
  151   	  = Fcons (build_string (argv[i]), Vcommand_line_args);
  152   #endif
  153       }
************
************
File DUA0:[EMACS.SRC]EMACS.C;17
  293   #ifdef CLASH_DETECTION
******
File DUA0:[EMACS.SRC]EMACS.C;33
  300   #ifdef GLOB_VMS
  301   
  302         syms_of_file_glob ();
  303   #endif 
  304   #ifdef CLASH_DETECTION
************

Number of difference sections found: 2
Number of difference records found: 13

DIFFERENCES /IGNORE=()/MERGED=1/OUTPUT=DUA0:[EMACS.SRC]EMACS_C.DIFF;1-
    DUA0:[EMACS.SRC]EMACS.C;17-
    DUA0:[EMACS.SRC]EMACS.C;33


============================= FILE_GLOB.C

/* Simple VMS-Native file-name wild-card expansion for GNU Emacs
   Copyright (C) 1986 Richard M. Stallman and Neal Ziring?

This file is part of GNU Emacs.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the GNU Emacs General Public
License for full details.

Everyone is granted permission to copy, modify and redistribute
GNU Emacs, but only under the conditions described in the
GNU Emacs General Public License.   A copy of this license is
supposed to have been given to you along with GNU Emacs so you
can know your rights and responsibilities.  It should be in a
file named COPYING.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */



/* 
 *  most of this code is stolen from the SIFT project, at
 *  Washington University, Summer 1986.  For information about
 *  it, write to nz@wucs.UUCP.  Written by Neal Ziring with
 *  help from Tom Patterson.
 *  For information about the VMS system service calls, see
 *  VMS Documentation Volume 8B.  
 */

#include "config.h"
#include "lisp.h"

/* all the code in this file is in between VMS and GLOB_VMS ifdefs */

#ifdef VMS
#ifdef GLOB_VMS

#include <ssdef.h>

#include <file.h>
#include <rms.h>
#include <descrip.h>


#define DSC  struct dsc$descriptor


/* **************************************************************
 * glob_word: given a string, glob it as a file name, return
 *           a name-list with all the results.
 *
 *     This routine operates in two ways.  When compiled under
 *   UNIX, the routine does a directory in a rather cheap way.
 *   When compiled under VMS, the routine does a directory in
 *   a weird VMS-ish way.
 *
 *   VMS  - call the routine find_file repeatedly to
 *             retrieve all the names that match a given spec.
 *
 *   In all circumstances, the routine passes back a name-list.
 *   If no file matches the spec, Qnil is returned.
 */

DEFUN ( "glob-file-name", Fglob_file_name, Sglob_file_name,
       2, 2, 0,
       "Return a list of file names matching SPEC.\n\
Return nil if SPEC is not matched by any files.  If\n\
SPEC does match file, prepend them to list SLT and return\n\
the new value of the list")
     (spec, slt)
     Lisp_Object spec,slt; 
{
    int i, e_cnt;
    unsigned char *s1, *s2, *strbuf;
#define FUDGE_LEN  39+39+39+39

    char nbuf[5+FUDGE_LEN];
    Lisp_Object  Vexpansion, Fcons();

    DSC     d_name, d_res, d_rel, d_def;
    unsigned long  context, stv, uflag;

    strbuf = XSTRING (spec)->data;
 
    /* first initialize the descriptors */
    for(s1 = s2 = (char *) &d_name; s2 - s1 < sizeof(DSC); *s2++ = '\0');
    d_name.dsc$b_class = DSC$K_CLASS_D;
    ch$move(sizeof(DSC), &d_name, &d_res);
    ch$move(sizeof(DSC), &d_name, &d_rel);
    ch$move(sizeof(DSC), &d_name, &d_def);
    context = stv = uflag = 0;
    if (strdesc(&d_name, strbuf) < 0) return(Qnil);

    /* now search for files, one at a time */
    for( Vexpansion = slt, e_cnt=0;
      ((i = lib$find_file(&d_name,&d_res,&context,&d_def,&d_rel,&stv,&uflag))
       == RMS$_NORMAL);
	e_cnt++)
      {
	  str$copy_dx(&d_rel, &d_name);
	  for(s1 = d_res.dsc$a_pointer, i = 0;
	      i < d_res.dsc$w_length  &&  i < FUDGE_LEN;
	      nbuf[i++] = *s1++);
	  nbuf[i] = '\0';
	  Vexpansion = Fcons ( build_string (nbuf), Vexpansion);
      }


    /* close down directory-reading operations */
    lib$find_file_end( &context);   /* this better not crash! */
    if ( d_name.dsc$w_length > 0 ) lib$sfree1_dd(&d_name);
    if ( d_res.dsc$w_length > 0 ) lib$sfree1_dd(&d_res);
    if ( d_def.dsc$w_length > 0 ) lib$sfree1_dd(&d_def);
    if ( d_rel.dsc$w_length > 0 ) lib$sfree1_dd(&d_rel);

    if (e_cnt == 0)
      return( Qnil );
    else
      return ( Vexpansion );
}


/* some utility routines for the VAXC part of glob_word */
int strdesc(d,s)
     DSC *d;
     char *s;
{
    unsigned long len;
    len = strlen(s) + 1;
    if ( lib$sget1_dd( &len, d) == SS$_NORMAL) strcpy(d->dsc$a_pointer, s);
    else return(-1);
    return(0);
}

int ch$move(size, from, to)
     int size;
     unsigned char *from, *to;
{
    while( size-- >= 0) *to++ = *from++;
    return(0);
}


DEFUN ( "glob-file-safe", Fglob_file_safe, Sglob_file_safe,
       2, 2
, 0,
       "Return a list of file names matching SPEC.\n\
Return SPEC itself if SPEC is not matched by any files.\n\
The expansion list for spec is prepended to SLT")
     (spec, slt)
     Lisp_Object spec, slt; 
{
    Lisp_Object Vtmp;

    Vtmp = Fglob_file_name(spec,slt);
    if (Vtmp == Qnil) return( Fcons( spec, slt) );
    else return(Vtmp);
}


syms_of_file_glob()
{
	defsubr ( &Sglob_file_name );
	defsubr ( &Sglob_file_safe );
}


#endif GLOB_VMS
#endif VMS

============================

-- 
...nz (Neal Ziring at WU ECL  -  we're here to provide superior computing.)

	{seismo,ihnp4,cbosgd}!wucs!nz   OR   nz@wucs.UUCP

    "You could get an infinite number of wires into this !*$$#!?! junction 
                         box, but we usually don't go that far in practice"
				--   Employee of London Electricity Board, 1959