1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <ctype.h>
include <error.h>
include "help.h"
include "helpdir.h"
.help modlist
.nf ___________________________________________________________________________
MODLIST -- Routines for expanding a template into a list of module names,
and accessing successive elements of the list, given a template and a help
directory defining the pattern matching domain as input.
The permissible complexity of a help template is somewhat less than that of
a file template; we do not have to deal with logical directories, virtual
file names, and list files. The class of characters permitted in a CL
module name is fairly limited. By the time we are called, the template
list will already have been expanded into a list of templates, wherein
each list element has a full package name (the package field has already
been expanded). Our job is to process a single template.
* all modules
im* all modules whose names start with 'im'
[a-z]?* all modules beg. with lowercase letter
alpha all modules alpha*
Note that a simple alphanumeric name like 'alpha' is treated as an
abbreviation, i.e., as 'alpha?*'. All occurrences of the closure metacharacter
* are converted to ?*, except after a character class.
Entry points in this package include:
ml_open set up to match and extract module names
ml_read get next module name which matches pattern
ml_close called when done to return buffers
.endhelp ______________________________________________________________________
define LEN_MLSTRUCT 165 # module list structure
define SZ_PATBUF 159
define ML_HP Memi[$1] # help directory
define ML_INDEX Memi[$1+1] # index of next module in helpdir
define ML_SIMPAT Memi[$1+2] # pattern is simple (no metacharacters)
define ML_PATBUF Memc[P2C($1+5)] # encoded pattern buffer
# ML_OPEN -- Set up to read module names from a directory which match
# a certain pattern. Allocate descriptor, save pointer to directory,
# encode pattern, rewind module index.
pointer procedure ml_open (hp, template)
pointer hp # help directory
char template[ARB] # "alpha", "*", etc.
bool metachars
int ip
pointer ml, sp, pat, op
int patmake()
begin
call smark (sp)
call salloc (pat, SZ_LINE, TY_CHAR)
iferr (call calloc (ml, LEN_MLSTRUCT, TY_STRUCT))
call erract (EA_FATAL)
ML_INDEX(ml) = 1
ML_HP(ml) = hp
# Match only at beginning of module name. Remember to scrap this
# metacharacter if matching a SIMPAT simple pattern.
Memc[pat] = '^'
op = pat + 1
# If no metacharacters present in pattern set SIMPAT flag so that we
# can use a more efficient pattern matching algorithm. If closure
# metacharacter is present and it does not follow ], replace it with ?*.
metachars = false
for (ip=1; template[ip] != EOS && op-pat < SZ_LINE; ip=ip+1) {
switch (template[ip]) {
case '?', '[', ']':
metachars = true
case '*':
metachars = true
if (ip == 1 || (ip > 1 && template[ip-1] != ']')) {
Memc[op] = '?'
op = op + 1
}
}
Memc[op] = template[ip]
op = op + 1
}
Memc[op] = EOS
if (!metachars) {
ML_SIMPAT(ml) = YES
# Copy pattern string, stripping off the leading '^'.
call strcpy (Memc[pat+1], ML_PATBUF(ml), SZ_PATBUF)
} else {
ML_SIMPAT(ml) = NO
if (patmake (Memc[pat], ML_PATBUF(ml), SZ_PATBUF) == ERR)
call error (16, "Cannot encode help pattern")
}
call sfree (sp)
return (ml)
end
# ML_READ -- Get next module name from help directory matching the
# encoded pattern. Return EOF when directory is exhausted. We directly
# access the HD structure for efficiency.
int procedure ml_read (ml, modnum, module, maxch)
pointer ml # pointer to module list descriptor
int modnum # module number (output)
char module[ARB] # module name (output)
int maxch
bool match_found
char first_char
int m
pointer hp, sbuf, mp, modname
int patmatch(), ml_patmatch(), gstrcpy()
errchk patmatch
begin
if (ml == NULL)
call error (17, "help.ml_read called with null descriptor")
hp = ML_HP(ml)
sbuf = HD_SBUF(hp)
first_char = ML_PATBUF(ml)
m = ML_INDEX(ml)
match_found = false
# Scan down the list of modules in the package, returning the name
# of each matching the pattern in successive calls. Return EOF when
# the list is exhausted.
while (m <= HD_NMODULES(hp)) {
mp = HD_MODULE(hp, m)
modname = sbuf + M_NAME(mp)
m = m + 1
if (ML_SIMPAT(ml) == YES) {
if (Memc[modname] == first_char)
if (ml_patmatch (Memc[modname], ML_PATBUF(ml)) > 0) {
match_found = true
break
}
} else if (patmatch (Memc[modname], ML_PATBUF(ml)) > 0) {
match_found = true
break
}
}
ML_INDEX(ml) = m
modnum = m - 1
# If no modules were found matching the template then we can only be
# at the end of the list.
if (match_found)
return (gstrcpy (Memc[modname], module, maxch))
else {
module[1] = EOS
return (EOF)
}
end
# ML_PATMATCH -- Determine if a SIMPAT simple pattern is an abbreviation of
# a module name. The pattern is simple, i.e., contains no metacharacters.
int procedure ml_patmatch (module, pattern)
char module[ARB] # module name to be compared to pattern
char pattern[ARB] # pattern of the form "^abbrev"
int ip
begin
for (ip=1; pattern[ip] != EOS; ip=ip+1)
if (pattern[ip] != module[ip])
return (0)
return (1)
end
# ML_CLOSE -- Return buffers allocated by open_template.
procedure ml_close (ml)
pointer ml
begin
call mfree (ml, TY_STRUCT)
end
|