[comp.os.vms] WILD --- a utility for doing wildcard searches in a file

KARNEY%PPC.MFENET@NMFECC.ARPA (09/30/87)

Below is a program for doing wildcard searches (using VMS' wildcard
characters * and %) in a file.  I wrote it to do lookup on a phone
directory where the user might not be sure of the spelling of someone's
name.
    Charles Karney
    Plasma Physics Laboratory   Phone:   609/683-2607
    Princeton University        MFENet:  Karney@PPC.MFENET
    PO Box 451                  ARPANet: Karney%PPC.MFENET@NMFECC.ARPA
    Princeton, NJ 08544-0451    Bitnet:  Karney%PPC.MFENET@ANLVMS.BITNET
....................... Cut between dotted lines and save ......................
$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-4.04 15-Sep-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by KARNEY
$!      on Wednesday 30-SEP-1987 12:35:47.08
$!
$! It contains the following 4 files:
$! WILD.HLP WILD.PAS WILD.COM WILD_CLD.CLD
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set (Output_File,b,o);
Position (Beginning_of(b));Loop x:=Erase_Character(1); Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;Move_Horizontal
(-Current_Offset);EndLoop;Move_Vertical(1);ExitIf Mark(None)=End_of(b)
EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="WILD.HLP"
$ Check_Sum_is=858023099
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X1 WILD
XWILD does wildcard searches on a text file.  To use WILD put
X    $ WILD :== $USR:[UTILITY]WILD
Xinto your LOGIN.COM file or else type
X    $ SETUP WILD
X
XUsage:
X    $ WILD file pat1[,pat2[,pat3...]]
Xwhere file is a text file to search and pat1... are the wildcard patterns to
Xsearch for.
X
XBugs, questions, etc. to Charles Karney
X2 Description
XWILD looks through the specified file matching each line of file against the
Xvarious patterns.  All matching lines are printed to SYS$OUTPUT.  If no
Xmatching lines are found WILD returned an informational message (i.e.,
X$SEVERITY = 3).
X
XThe patterns can contain the wildcard characters * and % which match an
Xarbitrary string and a single character respectively.
X
XThe match is to the entire line of the input file unless the qualifiers
X /POSITION and /SIZE are specified.  These defined a range of columns in the
Xinput file to be used.  In addition the /PARTIAL qualifier is equivalent to
Xprefixing and suffixing each pattern with a '*'.  The match is case
Xinsensitive unless /EXACT is specified.  The /TRIM qualifier is used to
Xremove trailing blanks from the file and the patterns before the match is
Xattempted.
X2 Qualifiers
X/EXACT
X /EXACT
X /NOEXACT (D)
XIf /EXACT is specified then the match is case sensitive.
X
X/TRIM
X /TRIM
X /NOTRIM (D)
XIf /TRIM is specified the patterns and the lines in the file are trimmed of
Xtrailing blanks before the match is made
X
X/POSITION
X /POSITION=integer
Xspecifies a starting column in the file at which the attempted match is
Xbegun.  Default is /POSITION=1, i.e., the beginning of the line.
X
X/SIZE
X /SIZE=integer
Xspecifies the number of columns used in the match.  The default is to use
Xthe whole line beginning at /POSITION.
X
X/PARTIAL
X /PARTIAL
X /NOPARTIAL (D)
XIf /PARTIAL is specified then the match is made on partial lines.  This is
Xachieved by converting pati to *pati*.
X2 Restrictions
XAt most 32 match patterns can be specified.
XThe maximum length of lines in file is 512 characters.
$ GoSub Convert_File
$ File_is="WILD.PAS"
$ Check_Sum_is=1013804588
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X(* Call wild_match on every line of a file, printing out the matches.
XUsage
X    wild file str1[,str2[,str3...]]
X
XRestrictions
X    maximum of 32 pattern can be searched for
X    file must be a text file with lines of at most 512 characters
X
XWritten by Charles Karney (Karney%PPC.MFENET@NMFECC.ARPA), Sept 9, 1987.
X
X*)
X
X[inherit ('SYS$LIBRARY:STARLET')]
Xprogram wild(output);
Xconst
X    linel=512;
X    maxstring=32;
X    cli$_absent=%x'000381F0';
X    cli$_concat=%x'0003FD29';
X    cli$_defaulted=%x'0003FD21';
X    cli$_locneg=%x'00038230';
X    cli$_locpres=%x'0003FD31';
X    cli$_negated=%x'000381F8';
X    cli$_present=%x'0003FD19';
Xtype
X    uword=[word] 0..65535;
X    line=varying [linel] of char;
X    sigarr=array [0..20] of integer;
X    mecharr=array [0..4] of integer;
Xlabel 3;
Xvar
X    cmd_line,file_name,input_line,buf1,buf2:line;
X    match:array [0..maxstring-1] of line;
X    input_file:text;
X    status,nstrings,i,position,size,length:integer;
X    found,exact,trim,partial:boolean;
X    lib$get_input,wild_match_cld:[external] unsigned;
X
Xfunction lib$get_foreign(
X  %stdescr cmdlin:[volatile] packed array [l1..u1:integer] of char
X       :=%immed 0;
X  %stdescr prompt:[volatile] packed array [l2..u2:integer] of char
X       :=%immed 0;
X  var len : [volatile] uword := %immed 0;
X  var flag : [volatile] integer := %immed 0):integer; external;
Xfunction cli$dcl_parse(
X  %stdescr cmd_string:packed array [l1..u1:integer] of char
X    :=%immed 0;
X  var table:unsigned:=%immed 0;
X  var param_routine:unsigned:=%immed 0;
X  var prompt_routine:unsigned:=%immed 0;
X  %stdescr prompt_string:packed array [l2..u2:integer] of char
X    :=%immed 0):integer; external;
Xfunction cli$present(
X  %stdescr name:packed array[l..u:integer] of char):integer; external;
Xfunction cli$get_value(
X  %stdescr name:packed array[l1..u1:integer] of char;
X  %stdescr retbuf:packed array[l2..u2:integer] of char;
X  var ret_len : uword := %immed 0):integer; external;
Xfunction str$upcase(
X  var dst_str : varying [len1] of char;
X  src_str : varying [len2] of char):unsigned; external;
Xfunction str$trim(
X  var dst_str : varying [len1] of char;
X  src_str : varying [len2] of char;
X  var out_len : uword := %immed 0):integer;external;
Xfunction str$match_wild(
X  cand_str : varying [len1] of char;
X  pattern_str : varying [len2] of char):integer; external;
X[asynchronous] function err_handler
X  (var sigargs : sigarr;
X   var mechargs : mecharr) : integer;
Xbegin
X  mechargs[3]:=sigargs[1];
X  $unwind(mechargs[2]);
X  err_handler := ss$_resignal;
Xend;
Xbegin
X    status := lib$get_foreign(cmd_line.body,,cmd_line.length,);
X    if not odd(status) then $exit(status);
X    establish(err_handler);
X    status := cli$dcl_parse('wild_match '+cmd_line,wild_match_cld,
X       lib$get_input);
X    revert;
X    if not odd(status) then $exit(status);
X    cli$get_value('source',file_name.body,file_name.length);
X    nstrings:=0;
X    exact:=odd(cli$present('exact'));
X    trim:=odd(cli$present('trim'));
X    partial:=odd(cli$present('partial'));
X    while (nstrings<maxstring) and
X       odd(cli$get_value('string',buf1.body,buf1.length))
X    do begin
X       if not(exact) then str$upcase(buf2,buf1) else buf2:=buf1;
X       if trim then str$trim(match[nstrings],buf2) else match[nstrings]:=buf2;
X       if partial then match[nstrings]:='*'+match[nstrings]+'*';
X       nstrings:=nstrings+1;
X    end;
X    if odd(cli$present('position')) then begin
X       cli$get_value('position',buf1.body,buf1.length);
X       readv(buf1,position);
X    end else position:=1;
X    if odd(cli$present('size')) then begin
X       cli$get_value('size',buf1.body,buf1.length);
X       readv(buf1,size);
X    end else size:=linel;
X    open(file_variable:=input_file,
X        file_name:=file_name,
X         history:=readonly);
X    reset(input_file);
X    found:=false;
X    while not eof(input_file) do begin
X       readln(input_file,input_line);
X       length:=min(input_line.length+1-position,size);
X       buf2:=substr(input_line,position,length);
X       if buf2.length>0 then begin
X           if not(exact) then str$upcase(buf1,buf2) else buf1:=buf2;
X           if trim then str$trim(buf2,buf1) else buf2:=buf1;
X           for i:=0 to nstrings do
X              if odd(str$match_wild(buf2,match[i])) then begin
X                   writeln(input_line);
X                   found:=true;
X                   goto 3;
X               end;
X3:     end;
X    end;
X    close(file_variable:=input_file);
X    if not found then begin
X       writeln('%WILD-I-NOMATCHES, no strings matched');
X       $exit(sts$k_info+sts$m_inhib_msg);
X    end;
Xend.
$ GoSub Convert_File
$ File_is="WILD.COM"
$ Check_Sum_is=138234923
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$ pascal/opt/nochec/nodeb wild
X$ set command/obj wild_cld
X$ link/notrace wild,wild_cld
$ GoSub Convert_File
$ File_is="WILD_CLD.CLD"
$ Check_Sum_is=355996817
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
Xmodule wild_match_cld
Xdefine verb wild_match
X   parameter p1 , label=source , prompt="filename"
X      value (required,list,type=$infile)
X   parameter p2 , label=string , prompt="pattern(s)"
X      value (required,list)
X   qualifier trim, negatable
X   qualifier exact, negatable
X   qualifier partial, negatable
X   qualifier position, negatable, value(required,type=$number)
X   qualifier size, negatable, value(required,type=$number)
$ GoSub Convert_File
$ Exit

CC:
        info-vax@KL.SRI.COM
        KARNEY