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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <ctype.h>
include "help.h"
.help tlist
.nf __________________________________________________________________________
TLIST -- Routines for processing the template list.
Functions:
tl_open Expand the template list into a list
of unambiguous templates.
tl_read Fetch next template from the list.
tl_close Close the list.
Do not confuse these routines with those used to expand and read from the
template for a single package. Our main function is to pass through the
template list, adding package names where they were left out by the user.
If no package name is given all packages in the database are searched.
.endhelp ______________________________________________________________________
define SZ_TLSBUF 1024 # local string buffer
define INC_SZTLSBUF 512 # increment if overflow
define SZ_CURPACK 31 # allocation for curpack name string
define LEN_TLSTRUCT 7
define TL_CTRL Memi[$1] # string buffer
define TL_SBUF Memi[$1+1] # string buffer
define TL_SZSBUF Memi[$1+2] # size of string buffer
define TL_NEXTCH Memi[$1+3] # index of next char in sbuf
define TL_LISTPTR Memi[$1+4] # for fetching list elements
define TL_CURPACK Memi[$1+5] # offset of name of current package
define TL_LISTLEN Memi[$1+6] # number of elements in list
# TL_OPEN -- Take the template list supplied by the user and produce as
# output a list wherein each element has an explicit package name. If an
# element is a module name or a module matching template, it gets replaced
# by a set of such templates, one for each package in the database.
# If a package matching template is given, it is expanded into a list of
# packages.
pointer procedure tl_open (db, hp, tlist, ctrl)
pointer db # database descriptor
pointer hp # system package directory
char tlist[ARB] # template list string
pointer ctrl
int ip, junk
pointer sp, op, tl, sbuf, template, pakstr, modstr
int tl_fetchelem(), tl_matchpak(), tl_putstr(), tl_getcurpack()
errchk tl_getcurpack, tl_ambiguous, tl_matchpak
define paknotfound_ 91
begin
call smark (sp)
call salloc (template, SZ_LINE, TY_CHAR)
call salloc (pakstr, SZ_FNAME, TY_CHAR)
call salloc (modstr, SZ_FNAME, TY_CHAR)
call calloc (tl, LEN_TLSTRUCT, TY_STRUCT)
call malloc (sbuf, SZ_TLSBUF, TY_CHAR)
TL_CTRL(tl) = ctrl
TL_SBUF(tl) = sbuf
TL_SZSBUF(tl) = SZ_TLSBUF
TL_NEXTCH(tl) = SZ_CURPACK + 2
TL_LISTPTR(tl) = SZ_CURPACK + 2
TL_LISTLEN(tl) = 0
# If null template list, set to "curpack.". This will cause the
# help for the current package to be printed. Otherwise expand
# the template. Template expansion can produce a very big list.
for (ip=1; IS_WHITE (tlist[ip]); ip=ip+1)
;
if (tlist[ip] == EOS) {
# Put current package name into list.
op = template + tl_getcurpack (tl, Memc[template], SZ_LINE)
Memc[op] = '.'
Memc[op+1] = EOS
junk = tl_putstr (tl, Memc[template])
} else {
# Expand nonnull template list. Each time through the loop
# processes the next comma delimited template.
while (tl_fetchelem (tlist,ip,Memc[pakstr],Memc[modstr]) > 0) {
if (Memc[pakstr] == EOS) {
if (H_OPTION(ctrl) == O_DIR) {
# User wants to print a help directory, but left out
# the "." in the package name. Assume the package
# name is an abbreviation and all all packages which
# match to the list.
if (tl_matchpak (tl, hp, Memc[modstr], "") == 0)
goto paknotfound_
} else
call tl_ambiguous (tl, db, hp, Memc[modstr])
} else if (tl_matchpak (tl,hp,Memc[pakstr],Memc[modstr]) == 0) {
# Explicit package template was given by user, but no
# matches were made to packages installed in the system
# help directory. Inform user.
paknotfound_
call eprintf ("Cannot find help for package `%s'\n")
call pargstr (Memc[pakstr])
}
}
}
# Return unused space in string buffer. Copy length of list to
# the main help structure.
call realloc (TL_SBUF(tl), TL_NEXTCH(tl), TY_CHAR)
TL_SZSBUF(tl) = TL_NEXTCH(tl)
H_LENTL(ctrl) = TL_LISTLEN(tl)
call sfree (sp)
return (tl)
end
# TL_CLOSE -- Close a template list opened with TL_OPEN.
procedure tl_close (tl)
pointer tl
begin
call mfree (TL_SBUF(tl), TY_CHAR)
call mfree (tl, TY_STRUCT)
end
# TL_READ -- Get the next template from the template list.
# Returns EOF when end of list is reached, else nchars in template.
int procedure tl_read (tl, outstr, maxch)
pointer tl
char outstr[ARB]
int maxch
int offset, nchars
int gstrcpy()
begin
if (TL_LISTPTR(tl) >= TL_NEXTCH(tl))
return (EOF)
offset = TL_LISTPTR(tl)
nchars = gstrcpy (Memc[TL_SBUF(tl)+offset], outstr, maxch)
TL_LISTPTR(tl) = offset + nchars + 1
return (nchars)
end
# TL_MATCHPACK -- Match package name against the system package list,
# add each package matched to the list.
int procedure tl_matchpak (tl, hp, package, module)
pointer tl
pointer hp
char package[ARB]
char module[ARB]
int paklen, junk, ngen, modnum
pointer sp, template, op, ml
int tl_putstr(), ml_read()
pointer ml_open()
errchk ml_open, ml_read, tl_putstr
begin
call smark (sp)
call salloc (template, SZ_LINE, TY_CHAR)
ngen = 0
ml = ml_open (hp, package)
repeat {
paklen = ml_read (ml, modnum, Memc[template], SZ_LINE)
if (paklen == EOF)
break
op = template + paklen
Memc[op] = '.'
call strcpy (module, Memc[op+1], SZ_LINE-paklen-1)
junk = tl_putstr (tl, Memc[template])
ngen = ngen + 1
}
call ml_close (ml)
call sfree (sp)
return (ngen)
end
# TL_AMBIGUOUS -- Called to expand an ambiguous template, i.e., one which did
# not include the "." delimiter to denote the package and module fields.
# We handle this by generating a series of module matching templates, one for
# each package in the database, starting with the current package. If the
# ambiguous pattern contains any pattern matching metacharacters we match only
# against the modules in the current package. Otherwise (completely ambiguous
# template) we match against:
#
# [1] all modules in the current package
# [2] all modules in all packages, except the current package
#
# For example, "alpha" might be expanded into the list
# curpack.alpha, pak1.alpha, pak2.alpha, ...
#
# The search [2] is a depth-first search of all packages in the root. Since
# each non-root package is a module of some other package, this search will
# find all non-root packages as well as modules. For the root packages to be
# found they must reference themselves as modules, but NOT as subpackages,
# otherwise recursion will occur.
procedure tl_ambiguous (tl, db, hp, module)
pointer tl # template list descriptor
pointer db # database descriptor
pointer hp # package directory
char module[ARB] # module template
int paklen, junk, ip, pk
pointer sp, curpack, template, op
bool streq()
int tl_putstr(), stridx(), tl_getcurpack(), hd_getname()
errchk tl_putstr, tl_getcurpack, hd_getname
begin
call smark (sp)
call salloc (template, SZ_LINE, TY_CHAR)
call salloc (curpack, SZ_FNAME, TY_CHAR)
# Output the template for the current package. Save the name of
# the current package for later use.
op = template + tl_getcurpack (tl, Memc[template], SZ_LINE)
call strcpy (Memc[template], Memc[curpack], SZ_FNAME)
Memc[op] = '.'
call strcpy (module, Memc[op+1], SZ_LINE-(op-template)-1)
junk = tl_putstr (tl, Memc[template])
# Check for pattern matching metacharacters. If present we match
# only against the current package, hence we are all done.
for (ip=1; module[ip] != EOS; ip=ip+1)
if (stridx (module[ip], "*?[]") > 0) {
call sfree (sp)
return
}
# Output a template for each remaining package in the database,
# excluding the current package which gets searched first and has
# already been put in the list. Template is "pakname.module".
pk = 1
repeat {
paklen = hd_getname (hp, pk, TY_MODNAME, Memc[template], SZ_LINE)
pk = pk + 1
if (paklen <= 0)
break
if (streq (Memc[template], Memc[curpack]))
next
op = template + paklen
Memc[op] = '.'
call strcpy (module, Memc[op+1], SZ_LINE-paklen-1)
junk = tl_putstr (tl, Memc[template])
}
call sfree (sp)
end
# TL_FETCHELEM -- Extract next element from template list. An element
# consists of the package pattern, module pattern, both, or either.
# Set output strings to the null string if field not present. Return
# the number of chars in the full element, zero when EOS is reached on
# the template list.
int procedure tl_fetchelem (tlist, ip, pakstr, modstr)
char tlist[ARB]
int ip
char pakstr[SZ_FNAME]
char modstr[SZ_FNAME]
bool package_seen
char ch
int op, ip_save
begin
package_seen = false
pakstr[1] = EOS
# Skip whitespace, the comma delimiters between list elements,
# and any null list elements (i.e. ",,").
while (IS_WHITE (tlist[ip]) || tlist[ip] == ',')
ip = ip + 1
ip_save = ip
# Extract the first field. If period is seen, this is the package
# field, copy it to pakstr. Remainder is the module name.
op = 1
ch = tlist[ip]
while (ch != ',' && ch != '\n' && ch != EOS) {
modstr[op] = ch
if (ch == '.') {
if (package_seen)
call error (18, "Too many '.' delims in help template")
package_seen = true
modstr[op] = EOS
call strcpy (modstr, pakstr, SZ_FNAME)
op = 1
} else
op = op + 1
ip = ip + 1
ch = tlist[ip]
}
modstr[op] = EOS
return (ip - ip_save)
end
# TL_GETCURPACK -- Get the name of the current package. The hidden CL command
# "_curpack" prints the name of the current package.
int procedure tl_getcurpack (tl, pakname, maxch)
pointer tl # template list
char pakname[maxch] # package name (output)
int maxch
pointer ctrl
int nchars, junk
int gstrcpy(), fscan()
bool strne()
errchk clcmd
begin
# The current package is read only once for each tlist expansion.
# The following uses the CL global parameter "list" to read the
# package list. The CL interface is violated by sending an explicit
# command to the CL. Poor practice, but the query can be disabled
# by setting the help.curpack parameter, if this causes a problem.
if (TL_CURPACK(tl) == NULL) {
# Was the current package set via a help task parameter?
ctrl = TL_CTRL(tl)
if (H_CURPACK(ctrl) != EOS)
if (strne (H_CURPACK(ctrl), "AskCL")) {
call strcpy (H_CURPACK(ctrl),
Memc[TL_SBUF(tl)+1], SZ_CURPACK)
TL_CURPACK(tl) = 1
}
if (TL_CURPACK(tl) == NULL) {
# Send "_curpack" command to the CL, read the response (a single
# line) from CLIN.
call clcmd ("_curpack")
junk = fscan (CLIN)
call gargwrd (Memc[TL_SBUF(tl)+1], SZ_CURPACK)
TL_CURPACK(tl) = 1
}
}
nchars = gstrcpy (Memc[TL_SBUF(tl) + TL_CURPACK(tl)], pakname, maxch)
return (nchars)
end
# TL_PUTSTR -- Put a string (incl EOS) in the string buffer at nextch.
# If there is not enough space in the buffer, reallocate a larger buffer.
# Return the index of the string in the string buffer.
int procedure tl_putstr (tl, str)
pointer tl
char str[ARB]
int nextch, nchars, strlen()
errchk realloc
begin
# Null strings are not stored and cause a null index to be returned.
nchars = strlen (str)
if (nchars == 0)
return (0)
nextch = TL_NEXTCH(tl)
if (nextch + nchars + 1 > TL_SZSBUF(tl)) {
TL_SZSBUF(tl) = TL_SZSBUF(tl) + INC_SZTLSBUF
call realloc (TL_SBUF(tl), TL_SZSBUF(tl), TY_CHAR)
}
call strcpy (str, Memc[TL_SBUF(tl) + nextch], ARB)
TL_NEXTCH(tl) = nextch + nchars + 1
TL_LISTLEN(tl) = TL_LISTLEN(tl) + 1
return (nextch)
end
|