2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid
[] = "$Id: seq.c,v 10.18 2011/12/11 23:13:00 zy Exp $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
20 #include <bitstring.h>
32 * Internal version to enter a sequence.
34 * PUBLIC: int seq_set(SCR *, CHAR_T *,
35 * PUBLIC: size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int);
54 * An input string must always be present. The output string
55 * can be NULL, when set internally, that's how we throw away
58 * Just replace the output field if the string already set.
61 seq_find(sp
, &lastqp
, NULL
, input
, ilen
, stype
, NULL
)) != NULL
) {
62 if (LF_ISSET(SEQ_NOOVERWRITE
))
64 if (output
== NULL
|| olen
== 0) {
67 } else if ((p
= v_wstrdup(sp
, output
, olen
)) == NULL
) {
71 if (qp
->output
!= NULL
)
78 /* Allocate and initialize SEQ structure. */
79 CALLOC(sp
, qp
, SEQ
*, 1, sizeof(SEQ
));
86 if (name
== NULL
|| nlen
== 0)
88 else if ((qp
->name
= v_wstrdup(sp
, name
, nlen
)) == NULL
) {
95 if ((qp
->input
= v_wstrdup(sp
, input
, ilen
)) == NULL
) {
102 if (output
== NULL
) {
105 } else if ((qp
->output
= v_wstrdup(sp
, output
, olen
)) == NULL
) {
108 mem3
: if (qp
->name
!= NULL
)
111 mem1
: errno
= sv_errno
;
112 msgq(sp
, M_SYSERR
, NULL
);
121 /* Link into the chain. */
122 if (lastqp
== NULL
) {
123 SLIST_INSERT_HEAD(sp
->gp
->seqq
, qp
, q
);
125 SLIST_INSERT_AFTER(lastqp
, qp
, q
);
128 /* Set the fast lookup bit. */
129 if ((qp
->input
[0] & ~MAX_BIT_SEQ
) == 0)
130 bit_set(sp
->gp
->seqb
, qp
->input
[0]);
139 * PUBLIC: int seq_delete(SCR *, CHAR_T *, size_t, seq_t);
148 SEQ
*qp
, *pre_qp
= NULL
;
151 SLIST_FOREACH(qp
, sp
->gp
->seqq
, q
) {
152 if (qp
->stype
== stype
&& qp
->ilen
== ilen
) {
153 diff
= MEMCMP(qp
->input
, input
, ilen
);
155 if (F_ISSET(qp
, SEQ_FUNCMAP
))
157 if (qp
== SLIST_FIRST(sp
->gp
->seqq
))
158 SLIST_REMOVE_HEAD(sp
->gp
->seqq
, q
);
160 SLIST_REMOVE_AFTER(pre_qp
, q
);
161 return (seq_free(qp
));
175 * PUBLIC: int seq_free(SEQ *);
180 if (qp
->name
!= NULL
)
182 if (qp
->input
!= NULL
)
184 if (qp
->output
!= NULL
)
192 * Search the sequence list for a match to a buffer, if ispartial
193 * isn't NULL, partial matches count.
195 * PUBLIC: SEQ *seq_find
196 * PUBLIC: (SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *);
208 SEQ
*lqp
= NULL
, *qp
;
212 * Ispartialp is a location where we return if there was a
213 * partial match, i.e. if the string were extended it might
217 * Overload the meaning of ispartialp; only the terminal key
218 * search doesn't want the search limited to complete matches,
219 * i.e. ilen may be longer than the match.
221 if (ispartialp
!= NULL
)
223 for (qp
= SLIST_FIRST(sp
->gp
->seqq
); qp
!= NULL
;
224 lqp
= qp
, qp
= SLIST_NEXT(qp
, q
)) {
226 * Fast checks on the first character and type, and then
229 if (e_input
== NULL
) {
230 if (qp
->input
[0] > c_input
[0])
232 if (qp
->input
[0] < c_input
[0] ||
233 qp
->stype
!= stype
|| F_ISSET(qp
, SEQ_FUNCMAP
))
235 diff
= MEMCMP(qp
->input
, c_input
, MIN(qp
->ilen
, ilen
));
237 if (qp
->input
[0] > e_input
->e_c
)
239 if (qp
->input
[0] < e_input
->e_c
||
240 qp
->stype
!= stype
|| F_ISSET(qp
, SEQ_FUNCMAP
))
243 e_memcmp(qp
->input
, e_input
, MIN(qp
->ilen
, ilen
));
250 * If the entry is the same length as the string, return a
251 * match. If the entry is shorter than the string, return a
252 * match if called from the terminal key routine. Otherwise,
253 * keep searching for a complete match.
255 if (qp
->ilen
<= ilen
) {
256 if (qp
->ilen
== ilen
|| ispartialp
!= NULL
) {
264 * If the entry longer than the string, return partial match
265 * if called from the terminal key routine. Otherwise, no
268 if (ispartialp
!= NULL
)
279 * Discard all sequences.
281 * PUBLIC: void seq_close(GS *);
288 while ((qp
= SLIST_FIRST(gp
->seqq
)) != NULL
) {
289 SLIST_REMOVE_HEAD(gp
->seqq
, q
);
296 * Display the sequence entries of a specified type.
298 * PUBLIC: int seq_dump(SCR *, seq_t, int);
313 SLIST_FOREACH(qp
, sp
->gp
->seqq
, q
) {
314 if (stype
!= qp
->stype
|| F_ISSET(qp
, SEQ_FUNCMAP
))
318 olen
= qp
->ilen
, len
= 0; olen
> 0; --olen
, ++p
)
319 len
+= ex_puts(sp
, KEY_NAME(sp
, *p
));
320 for (len
= STANDARD_TAB
- len
% STANDARD_TAB
; len
> 0;)
321 len
-= ex_puts(sp
, " ");
323 if (qp
->output
!= NULL
)
325 olen
= qp
->olen
, len
= 0; olen
> 0; --olen
, ++p
)
326 len
+= ex_puts(sp
, KEY_NAME(sp
, *p
));
330 if (isname
&& qp
->name
!= NULL
) {
331 for (len
= STANDARD_TAB
- len
% STANDARD_TAB
; len
> 0;)
332 len
-= ex_puts(sp
, " ");
334 olen
= qp
->nlen
; olen
> 0; --olen
, ++p
)
335 (void)ex_puts(sp
, KEY_NAME(sp
, *p
));
337 (void)ex_puts(sp
, "\n");
344 * Save the sequence entries to a file.
346 * PUBLIC: int seq_save(SCR *, FILE *, char *, seq_t);
360 /* Write a sequence command for all keys the user defined. */
361 SLIST_FOREACH(qp
, sp
->gp
->seqq
, q
) {
362 if (stype
!= qp
->stype
|| !F_ISSET(qp
, SEQ_USERDEF
))
365 (void)fprintf(fp
, "%s", prefix
);
366 for (p
= qp
->input
, olen
= qp
->ilen
; olen
> 0; --olen
) {
368 if (ch
== CH_LITERAL
|| ch
== '|' ||
369 cmdskip(ch
) || KEY_VAL(sp
, ch
) == K_NL
)
370 (void)putc(CH_LITERAL
, fp
);
374 if (qp
->output
!= NULL
)
376 olen
= qp
->olen
; olen
> 0; --olen
) {
378 if (ch
== CH_LITERAL
|| ch
== '|' ||
379 KEY_VAL(sp
, ch
) == K_NL
)
380 (void)putc(CH_LITERAL
, fp
);
383 (void)putc('\n', fp
);
390 * Compare a string of EVENT's to a string of CHAR_T's.
392 * PUBLIC: int e_memcmp(CHAR_T *, EVENT *, size_t);
402 if (*p1
++ != ep
->e_c
)
403 return (*--p1
- ep
->e_c
);