aboutsummaryrefslogtreecommitdiff
path: root/pkg/system/help/tlist.x
blob: 5bd61ab158b944097c92386a706ab1c6cf5ab077 (plain) (blame)
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