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);