2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
9 static char sccsid
[] = "$Id: seq.c,v 8.21 1993/12/09 19:42:15 bostic Exp $ (Berkeley) $Date: 1993/12/09 19:42:15 $";
12 #include <sys/types.h>
25 * Internal version to enter a sequence.
28 seq_set(sp
, name
, nlen
, input
, ilen
, output
, olen
, stype
, userdef
)
30 char *name
, *input
, *output
;
31 size_t nlen
, ilen
, olen
;
38 #if defined(DEBUG) && 0
39 TRACE(sp
, "seq_set: name {%s} input {%s} output {%s}\n",
40 name
? name
: "", input
, output
);
42 /* Just replace the output field in any previous occurrence. */
43 if ((qp
= seq_find(sp
, &lastqp
, input
, ilen
, stype
, NULL
)) != NULL
) {
44 if ((p
= v_strdup(sp
, output
, olen
)) == NULL
)
46 FREE(qp
->output
, qp
->olen
);
52 /* Allocate and initialize space. */
53 CALLOC(sp
, qp
, SEQ
*, 1, sizeof(SEQ
));
58 else if ((qp
->name
= v_strdup(sp
, name
, nlen
)) == NULL
)
60 if ((qp
->input
= v_strdup(sp
, input
, ilen
)) == NULL
)
62 if ((qp
->output
= v_strdup(sp
, output
, olen
)) == NULL
) {
63 FREE(qp
->input
, ilen
);
64 mem3
: if (qp
->name
!= NULL
)
66 mem2
: FREE(qp
, sizeof(SEQ
));
67 mem1
: msgq(sp
, M_SYSERR
, NULL
);
75 qp
->flags
= userdef
? S_USERDEF
: 0;
77 /* Link into the chain. */
79 LIST_INSERT_HEAD(&sp
->gp
->seqq
, qp
, q
);
81 LIST_INSERT_AFTER(lastqp
, qp
, q
);
84 /* Set the fast lookup bit. */
85 bit_set(sp
->gp
->seqb
, qp
->input
[0]);
95 seq_delete(sp
, input
, ilen
, stype
)
103 if ((qp
= seq_find(sp
, NULL
, input
, ilen
, stype
, NULL
)) == NULL
)
107 if (qp
->name
!= NULL
)
108 FREE(qp
->name
, qp
->nlen
);
109 FREE(qp
->input
, qp
->ilen
);
110 FREE(qp
->output
, qp
->olen
);
111 FREE(qp
, sizeof(SEQ
));
117 * Search the sequence list for a match to a buffer, if ispartial
118 * isn't NULL, partial matches count.
121 seq_find(sp
, lastqp
, input
, ilen
, stype
, ispartialp
)
133 * Ispartialp is a location where we return if there was a
134 * partial match, i.e. if the string were extended it might
138 * Overload the meaning of ispartialp; only the terminal key
139 * search doesn't want the search limited to complete matches,
140 * i.e. ilen may be longer than the match.
142 if (ispartialp
!= NULL
)
144 for (lqp
= NULL
, qp
= sp
->gp
->seqq
.lh_first
;
145 qp
!= NULL
; lqp
= qp
, qp
= qp
->q
.le_next
) {
146 /* Fast checks on the first character and type. */
147 if (qp
->input
[0] > input
[0])
149 if (qp
->input
[0] < input
[0] || qp
->stype
!= stype
)
152 /* Check on the real comparison. */
153 diff
= memcmp(qp
->input
, input
, MIN(qp
->ilen
, ilen
));
159 * If the entry is the same length as the string, return a
160 * match. If the entry is shorter than the string, return a
161 * match if called from the terminal key routine. Otherwise,
162 * keep searching for a complete match.
164 if (qp
->ilen
<= ilen
) {
165 if (qp
->ilen
== ilen
|| ispartialp
!= NULL
) {
173 * If the entry longer than the string, return partial match
174 * if called from the terminal key routine. Otherwise, no
177 if (ispartialp
!= NULL
)
188 * Display the sequence entries of a specified type.
191 seq_dump(sp
, stype
, isname
)
198 int cnt
, len
, olen
, tablen
;
202 cname
= sp
->gp
->cname
;
203 tablen
= O_VAL(sp
, O_TABSTOP
);
204 for (qp
= sp
->gp
->seqq
.lh_first
; qp
!= NULL
; qp
= qp
->q
.le_next
) {
205 if (stype
!= qp
->stype
)
209 olen
= qp
->ilen
, len
= 0; olen
> 0; --olen
, ++len
)
210 (void)ex_printf(EXCOOKIE
, "%s", cname
[*p
++].name
);
211 for (len
= tablen
- len
% tablen
; len
; --len
)
212 (void)ex_printf(EXCOOKIE
, " ");
214 for (p
= qp
->output
, olen
= qp
->olen
; olen
> 0; --olen
)
215 (void)ex_printf(EXCOOKIE
, "%s", cname
[*p
++].name
);
217 if (isname
&& qp
->name
!= NULL
) {
218 for (len
= tablen
- len
% tablen
; len
; --len
)
219 (void)ex_printf(EXCOOKIE
, " ");
220 for (p
= qp
->name
, olen
= qp
->nlen
; olen
> 0; --olen
)
221 (void)ex_printf(EXCOOKIE
,
222 "%s", cname
[*p
++].name
);
224 (void)ex_printf(EXCOOKIE
, "\n");
231 * Save the sequence entries to a file.
234 seq_save(sp
, fp
, prefix
, stype
)
246 /* Write a sequence command for all keys the user defined. */
247 (void)term_key_ch(sp
, K_VLNEXT
, &esc
);
248 for (qp
= sp
->gp
->seqq
.lh_first
; qp
!= NULL
; qp
= qp
->q
.le_next
) {
249 if (!F_ISSET(qp
, S_USERDEF
))
251 if (stype
!= qp
->stype
)
254 (void)fprintf(fp
, "%s", prefix
);
255 for (p
= qp
->input
, olen
= qp
->ilen
; olen
> 0; --olen
) {
257 if (ch
== esc
|| ch
== '|' ||
258 isblank(ch
) || term_key_val(sp
, ch
) == K_NL
)
263 for (p
= qp
->output
, olen
= qp
->olen
; olen
> 0; --olen
) {
265 if (ch
== esc
|| ch
== '|' ||
266 term_key_val(sp
, ch
) == K_NL
)
270 (void)putc('\n', fp
);