1b8ba871bSPeter Wemm /*-
2b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994
3b8ba871bSPeter Wemm * The Regents of the University of California. All rights reserved.
4b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994, 1995, 1996
5b8ba871bSPeter Wemm * Keith Bostic. All rights reserved.
6b8ba871bSPeter Wemm *
7b8ba871bSPeter Wemm * See the LICENSE file for redistribution information.
8b8ba871bSPeter Wemm */
9b8ba871bSPeter Wemm
10b8ba871bSPeter Wemm #include "config.h"
11b8ba871bSPeter Wemm
12b8ba871bSPeter Wemm #include <sys/types.h>
13b8ba871bSPeter Wemm #include <sys/queue.h>
14f0957ccaSPeter Wemm #include <sys/time.h>
15b8ba871bSPeter Wemm
16b8ba871bSPeter Wemm #include <bitstring.h>
17b8ba871bSPeter Wemm #include <ctype.h>
18b8ba871bSPeter Wemm #include <errno.h>
19b8ba871bSPeter Wemm #include <limits.h>
20b8ba871bSPeter Wemm #include <stdio.h>
21b8ba871bSPeter Wemm #include <stdlib.h>
22b8ba871bSPeter Wemm #include <string.h>
23b8ba871bSPeter Wemm
24b8ba871bSPeter Wemm #include "common.h"
25b8ba871bSPeter Wemm
26b8ba871bSPeter Wemm /*
27b8ba871bSPeter Wemm * seq_set --
28b8ba871bSPeter Wemm * Internal version to enter a sequence.
29b8ba871bSPeter Wemm *
30c271fa92SBaptiste Daroussin * PUBLIC: int seq_set(SCR *, CHAR_T *,
31c271fa92SBaptiste Daroussin * PUBLIC: size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int);
32b8ba871bSPeter Wemm */
33b8ba871bSPeter Wemm int
seq_set(SCR * sp,CHAR_T * name,size_t nlen,CHAR_T * input,size_t ilen,CHAR_T * output,size_t olen,seq_t stype,int flags)34*110d525eSBaptiste Daroussin seq_set(SCR *sp, CHAR_T *name, size_t nlen, CHAR_T *input, size_t ilen,
35*110d525eSBaptiste Daroussin CHAR_T *output, size_t olen, seq_t stype, int flags)
36b8ba871bSPeter Wemm {
37b8ba871bSPeter Wemm CHAR_T *p;
38b8ba871bSPeter Wemm SEQ *lastqp, *qp;
39b8ba871bSPeter Wemm int sv_errno;
40b8ba871bSPeter Wemm
41b8ba871bSPeter Wemm /*
42b8ba871bSPeter Wemm * An input string must always be present. The output string
43b8ba871bSPeter Wemm * can be NULL, when set internally, that's how we throw away
44b8ba871bSPeter Wemm * input.
45b8ba871bSPeter Wemm *
46b8ba871bSPeter Wemm * Just replace the output field if the string already set.
47b8ba871bSPeter Wemm */
48b8ba871bSPeter Wemm if ((qp =
49b8ba871bSPeter Wemm seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
50b8ba871bSPeter Wemm if (LF_ISSET(SEQ_NOOVERWRITE))
51b8ba871bSPeter Wemm return (0);
52b8ba871bSPeter Wemm if (output == NULL || olen == 0) {
53b8ba871bSPeter Wemm p = NULL;
54b8ba871bSPeter Wemm olen = 0;
55f0957ccaSPeter Wemm } else if ((p = v_wstrdup(sp, output, olen)) == NULL) {
56b8ba871bSPeter Wemm sv_errno = errno;
57b8ba871bSPeter Wemm goto mem1;
58b8ba871bSPeter Wemm }
59b8ba871bSPeter Wemm free(qp->output);
60b8ba871bSPeter Wemm qp->olen = olen;
61b8ba871bSPeter Wemm qp->output = p;
62b8ba871bSPeter Wemm return (0);
63b8ba871bSPeter Wemm }
64b8ba871bSPeter Wemm
65b8ba871bSPeter Wemm /* Allocate and initialize SEQ structure. */
66*110d525eSBaptiste Daroussin CALLOC(sp, qp, 1, sizeof(SEQ));
67b8ba871bSPeter Wemm if (qp == NULL) {
68b8ba871bSPeter Wemm sv_errno = errno;
69b8ba871bSPeter Wemm goto mem1;
70b8ba871bSPeter Wemm }
71b8ba871bSPeter Wemm
72b8ba871bSPeter Wemm /* Name. */
73b8ba871bSPeter Wemm if (name == NULL || nlen == 0)
74b8ba871bSPeter Wemm qp->name = NULL;
75f0957ccaSPeter Wemm else if ((qp->name = v_wstrdup(sp, name, nlen)) == NULL) {
76b8ba871bSPeter Wemm sv_errno = errno;
77b8ba871bSPeter Wemm goto mem2;
78b8ba871bSPeter Wemm }
79b8ba871bSPeter Wemm qp->nlen = nlen;
80b8ba871bSPeter Wemm
81b8ba871bSPeter Wemm /* Input. */
82f0957ccaSPeter Wemm if ((qp->input = v_wstrdup(sp, input, ilen)) == NULL) {
83b8ba871bSPeter Wemm sv_errno = errno;
84b8ba871bSPeter Wemm goto mem3;
85b8ba871bSPeter Wemm }
86b8ba871bSPeter Wemm qp->ilen = ilen;
87b8ba871bSPeter Wemm
88b8ba871bSPeter Wemm /* Output. */
89b8ba871bSPeter Wemm if (output == NULL) {
90b8ba871bSPeter Wemm qp->output = NULL;
91b8ba871bSPeter Wemm olen = 0;
92f0957ccaSPeter Wemm } else if ((qp->output = v_wstrdup(sp, output, olen)) == NULL) {
93b8ba871bSPeter Wemm sv_errno = errno;
94b8ba871bSPeter Wemm free(qp->input);
95*110d525eSBaptiste Daroussin mem3: free(qp->name);
96b8ba871bSPeter Wemm mem2: free(qp);
97b8ba871bSPeter Wemm mem1: errno = sv_errno;
98b8ba871bSPeter Wemm msgq(sp, M_SYSERR, NULL);
99b8ba871bSPeter Wemm return (1);
100b8ba871bSPeter Wemm }
101b8ba871bSPeter Wemm qp->olen = olen;
102b8ba871bSPeter Wemm
103b8ba871bSPeter Wemm /* Type, flags. */
104b8ba871bSPeter Wemm qp->stype = stype;
105b8ba871bSPeter Wemm qp->flags = flags;
106b8ba871bSPeter Wemm
107b8ba871bSPeter Wemm /* Link into the chain. */
108b8ba871bSPeter Wemm if (lastqp == NULL) {
109f0957ccaSPeter Wemm SLIST_INSERT_HEAD(sp->gp->seqq, qp, q);
110b8ba871bSPeter Wemm } else {
111f0957ccaSPeter Wemm SLIST_INSERT_AFTER(lastqp, qp, q);
112b8ba871bSPeter Wemm }
113b8ba871bSPeter Wemm
114b8ba871bSPeter Wemm /* Set the fast lookup bit. */
115f0957ccaSPeter Wemm if ((qp->input[0] & ~MAX_BIT_SEQ) == 0)
116b8ba871bSPeter Wemm bit_set(sp->gp->seqb, qp->input[0]);
117b8ba871bSPeter Wemm
118b8ba871bSPeter Wemm return (0);
119b8ba871bSPeter Wemm }
120b8ba871bSPeter Wemm
121b8ba871bSPeter Wemm /*
122b8ba871bSPeter Wemm * seq_delete --
123b8ba871bSPeter Wemm * Delete a sequence.
124b8ba871bSPeter Wemm *
125c271fa92SBaptiste Daroussin * PUBLIC: int seq_delete(SCR *, CHAR_T *, size_t, seq_t);
126b8ba871bSPeter Wemm */
127b8ba871bSPeter Wemm int
seq_delete(SCR * sp,CHAR_T * input,size_t ilen,seq_t stype)128*110d525eSBaptiste Daroussin seq_delete(SCR *sp, CHAR_T *input, size_t ilen, seq_t stype)
129b8ba871bSPeter Wemm {
130f0957ccaSPeter Wemm SEQ *qp, *pre_qp = NULL;
131f0957ccaSPeter Wemm int diff;
132b8ba871bSPeter Wemm
133f0957ccaSPeter Wemm SLIST_FOREACH(qp, sp->gp->seqq, q) {
134f0957ccaSPeter Wemm if (qp->stype == stype && qp->ilen == ilen) {
135f0957ccaSPeter Wemm diff = MEMCMP(qp->input, input, ilen);
136f0957ccaSPeter Wemm if (!diff) {
137f0957ccaSPeter Wemm if (F_ISSET(qp, SEQ_FUNCMAP))
138f0957ccaSPeter Wemm break;
139f0957ccaSPeter Wemm if (qp == SLIST_FIRST(sp->gp->seqq))
140f0957ccaSPeter Wemm SLIST_REMOVE_HEAD(sp->gp->seqq, q);
141f0957ccaSPeter Wemm else
142f0957ccaSPeter Wemm SLIST_REMOVE_AFTER(pre_qp, q);
143f0957ccaSPeter Wemm return (seq_free(qp));
144f0957ccaSPeter Wemm }
145f0957ccaSPeter Wemm if (diff > 0)
146f0957ccaSPeter Wemm break;
147f0957ccaSPeter Wemm }
148f0957ccaSPeter Wemm pre_qp = qp;
149f0957ccaSPeter Wemm }
150b8ba871bSPeter Wemm return (1);
151b8ba871bSPeter Wemm }
152b8ba871bSPeter Wemm
153b8ba871bSPeter Wemm /*
154f0957ccaSPeter Wemm * seq_free --
155f0957ccaSPeter Wemm * Free a map entry.
156b8ba871bSPeter Wemm *
157c271fa92SBaptiste Daroussin * PUBLIC: int seq_free(SEQ *);
158b8ba871bSPeter Wemm */
159b8ba871bSPeter Wemm int
seq_free(SEQ * qp)160f0957ccaSPeter Wemm seq_free(SEQ *qp)
161b8ba871bSPeter Wemm {
162b8ba871bSPeter Wemm free(qp->name);
163b8ba871bSPeter Wemm free(qp->input);
164b8ba871bSPeter Wemm free(qp->output);
165b8ba871bSPeter Wemm free(qp);
166b8ba871bSPeter Wemm return (0);
167b8ba871bSPeter Wemm }
168b8ba871bSPeter Wemm
169b8ba871bSPeter Wemm /*
170b8ba871bSPeter Wemm * seq_find --
171b8ba871bSPeter Wemm * Search the sequence list for a match to a buffer, if ispartial
172b8ba871bSPeter Wemm * isn't NULL, partial matches count.
173b8ba871bSPeter Wemm *
174b8ba871bSPeter Wemm * PUBLIC: SEQ *seq_find
175c271fa92SBaptiste Daroussin * PUBLIC: (SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *);
176b8ba871bSPeter Wemm */
177b8ba871bSPeter Wemm SEQ *
seq_find(SCR * sp,SEQ ** lastqp,EVENT * e_input,CHAR_T * c_input,size_t ilen,seq_t stype,int * ispartialp)178*110d525eSBaptiste Daroussin seq_find(SCR *sp, SEQ **lastqp, EVENT *e_input, CHAR_T *c_input, size_t ilen,
179*110d525eSBaptiste Daroussin seq_t stype, int *ispartialp)
180b8ba871bSPeter Wemm {
181f0957ccaSPeter Wemm SEQ *lqp = NULL, *qp;
182b8ba871bSPeter Wemm int diff;
183b8ba871bSPeter Wemm
184b8ba871bSPeter Wemm /*
185b8ba871bSPeter Wemm * Ispartialp is a location where we return if there was a
186b8ba871bSPeter Wemm * partial match, i.e. if the string were extended it might
187b8ba871bSPeter Wemm * match something.
188b8ba871bSPeter Wemm *
189b8ba871bSPeter Wemm * XXX
190b8ba871bSPeter Wemm * Overload the meaning of ispartialp; only the terminal key
191b8ba871bSPeter Wemm * search doesn't want the search limited to complete matches,
192b8ba871bSPeter Wemm * i.e. ilen may be longer than the match.
193b8ba871bSPeter Wemm */
194b8ba871bSPeter Wemm if (ispartialp != NULL)
195b8ba871bSPeter Wemm *ispartialp = 0;
196f0957ccaSPeter Wemm for (qp = SLIST_FIRST(sp->gp->seqq); qp != NULL;
197f0957ccaSPeter Wemm lqp = qp, qp = SLIST_NEXT(qp, q)) {
198b8ba871bSPeter Wemm /*
199b8ba871bSPeter Wemm * Fast checks on the first character and type, and then
200b8ba871bSPeter Wemm * a real comparison.
201b8ba871bSPeter Wemm */
202b8ba871bSPeter Wemm if (e_input == NULL) {
203b8ba871bSPeter Wemm if (qp->input[0] > c_input[0])
204b8ba871bSPeter Wemm break;
205b8ba871bSPeter Wemm if (qp->input[0] < c_input[0] ||
206b8ba871bSPeter Wemm qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
207b8ba871bSPeter Wemm continue;
208f0957ccaSPeter Wemm diff = MEMCMP(qp->input, c_input, MIN(qp->ilen, ilen));
209b8ba871bSPeter Wemm } else {
210b8ba871bSPeter Wemm if (qp->input[0] > e_input->e_c)
211b8ba871bSPeter Wemm break;
212b8ba871bSPeter Wemm if (qp->input[0] < e_input->e_c ||
213b8ba871bSPeter Wemm qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
214b8ba871bSPeter Wemm continue;
215b8ba871bSPeter Wemm diff =
216b8ba871bSPeter Wemm e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
217b8ba871bSPeter Wemm }
218b8ba871bSPeter Wemm if (diff > 0)
219b8ba871bSPeter Wemm break;
220b8ba871bSPeter Wemm if (diff < 0)
221b8ba871bSPeter Wemm continue;
222b8ba871bSPeter Wemm /*
223b8ba871bSPeter Wemm * If the entry is the same length as the string, return a
224b8ba871bSPeter Wemm * match. If the entry is shorter than the string, return a
225b8ba871bSPeter Wemm * match if called from the terminal key routine. Otherwise,
226b8ba871bSPeter Wemm * keep searching for a complete match.
227b8ba871bSPeter Wemm */
228b8ba871bSPeter Wemm if (qp->ilen <= ilen) {
229b8ba871bSPeter Wemm if (qp->ilen == ilen || ispartialp != NULL) {
230b8ba871bSPeter Wemm if (lastqp != NULL)
231b8ba871bSPeter Wemm *lastqp = lqp;
232b8ba871bSPeter Wemm return (qp);
233b8ba871bSPeter Wemm }
234b8ba871bSPeter Wemm continue;
235b8ba871bSPeter Wemm }
236b8ba871bSPeter Wemm /*
237b8ba871bSPeter Wemm * If the entry longer than the string, return partial match
238b8ba871bSPeter Wemm * if called from the terminal key routine. Otherwise, no
239b8ba871bSPeter Wemm * match.
240b8ba871bSPeter Wemm */
241b8ba871bSPeter Wemm if (ispartialp != NULL)
242b8ba871bSPeter Wemm *ispartialp = 1;
243b8ba871bSPeter Wemm break;
244b8ba871bSPeter Wemm }
245b8ba871bSPeter Wemm if (lastqp != NULL)
246b8ba871bSPeter Wemm *lastqp = lqp;
247b8ba871bSPeter Wemm return (NULL);
248b8ba871bSPeter Wemm }
249b8ba871bSPeter Wemm
250b8ba871bSPeter Wemm /*
251b8ba871bSPeter Wemm * seq_close --
252b8ba871bSPeter Wemm * Discard all sequences.
253b8ba871bSPeter Wemm *
254c271fa92SBaptiste Daroussin * PUBLIC: void seq_close(GS *);
255b8ba871bSPeter Wemm */
256b8ba871bSPeter Wemm void
seq_close(GS * gp)257f0957ccaSPeter Wemm seq_close(GS *gp)
258b8ba871bSPeter Wemm {
259b8ba871bSPeter Wemm SEQ *qp;
260b8ba871bSPeter Wemm
261f0957ccaSPeter Wemm while ((qp = SLIST_FIRST(gp->seqq)) != NULL) {
262f0957ccaSPeter Wemm SLIST_REMOVE_HEAD(gp->seqq, q);
263f0957ccaSPeter Wemm (void)seq_free(qp);
264b8ba871bSPeter Wemm }
265b8ba871bSPeter Wemm }
266b8ba871bSPeter Wemm
267b8ba871bSPeter Wemm /*
268b8ba871bSPeter Wemm * seq_dump --
269b8ba871bSPeter Wemm * Display the sequence entries of a specified type.
270b8ba871bSPeter Wemm *
271c271fa92SBaptiste Daroussin * PUBLIC: int seq_dump(SCR *, seq_t, int);
272b8ba871bSPeter Wemm */
273b8ba871bSPeter Wemm int
seq_dump(SCR * sp,seq_t stype,int isname)274*110d525eSBaptiste Daroussin seq_dump(SCR *sp, seq_t stype, int isname)
275b8ba871bSPeter Wemm {
276b8ba871bSPeter Wemm CHAR_T *p;
277b8ba871bSPeter Wemm GS *gp;
278b8ba871bSPeter Wemm SEQ *qp;
279b8ba871bSPeter Wemm int cnt, len, olen;
280b8ba871bSPeter Wemm
281b8ba871bSPeter Wemm cnt = 0;
282b8ba871bSPeter Wemm gp = sp->gp;
283f0957ccaSPeter Wemm SLIST_FOREACH(qp, sp->gp->seqq, q) {
284b8ba871bSPeter Wemm if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
285b8ba871bSPeter Wemm continue;
286b8ba871bSPeter Wemm ++cnt;
287b8ba871bSPeter Wemm for (p = qp->input,
288b8ba871bSPeter Wemm olen = qp->ilen, len = 0; olen > 0; --olen, ++p)
289b8ba871bSPeter Wemm len += ex_puts(sp, KEY_NAME(sp, *p));
290b8ba871bSPeter Wemm for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
291b8ba871bSPeter Wemm len -= ex_puts(sp, " ");
292b8ba871bSPeter Wemm
293b8ba871bSPeter Wemm if (qp->output != NULL)
294b8ba871bSPeter Wemm for (p = qp->output,
295b8ba871bSPeter Wemm olen = qp->olen, len = 0; olen > 0; --olen, ++p)
296b8ba871bSPeter Wemm len += ex_puts(sp, KEY_NAME(sp, *p));
297b8ba871bSPeter Wemm else
298b8ba871bSPeter Wemm len = 0;
299b8ba871bSPeter Wemm
300b8ba871bSPeter Wemm if (isname && qp->name != NULL) {
301b8ba871bSPeter Wemm for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
302b8ba871bSPeter Wemm len -= ex_puts(sp, " ");
303b8ba871bSPeter Wemm for (p = qp->name,
304b8ba871bSPeter Wemm olen = qp->nlen; olen > 0; --olen, ++p)
305b8ba871bSPeter Wemm (void)ex_puts(sp, KEY_NAME(sp, *p));
306b8ba871bSPeter Wemm }
307b8ba871bSPeter Wemm (void)ex_puts(sp, "\n");
308b8ba871bSPeter Wemm }
309b8ba871bSPeter Wemm return (cnt);
310b8ba871bSPeter Wemm }
311b8ba871bSPeter Wemm
312b8ba871bSPeter Wemm /*
313b8ba871bSPeter Wemm * seq_save --
314b8ba871bSPeter Wemm * Save the sequence entries to a file.
315b8ba871bSPeter Wemm *
316c271fa92SBaptiste Daroussin * PUBLIC: int seq_save(SCR *, FILE *, char *, seq_t);
317b8ba871bSPeter Wemm */
318b8ba871bSPeter Wemm int
seq_save(SCR * sp,FILE * fp,char * prefix,seq_t stype)319*110d525eSBaptiste Daroussin seq_save(SCR *sp, FILE *fp, char *prefix, seq_t stype)
320b8ba871bSPeter Wemm {
321b8ba871bSPeter Wemm CHAR_T *p;
322b8ba871bSPeter Wemm SEQ *qp;
323b8ba871bSPeter Wemm size_t olen;
324b8ba871bSPeter Wemm int ch;
325b8ba871bSPeter Wemm
326b8ba871bSPeter Wemm /* Write a sequence command for all keys the user defined. */
327f0957ccaSPeter Wemm SLIST_FOREACH(qp, sp->gp->seqq, q) {
328b8ba871bSPeter Wemm if (stype != qp->stype || !F_ISSET(qp, SEQ_USERDEF))
329b8ba871bSPeter Wemm continue;
330b8ba871bSPeter Wemm if (prefix)
331b8ba871bSPeter Wemm (void)fprintf(fp, "%s", prefix);
332b8ba871bSPeter Wemm for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
333b8ba871bSPeter Wemm ch = *p++;
334b8ba871bSPeter Wemm if (ch == CH_LITERAL || ch == '|' ||
335f0957ccaSPeter Wemm cmdskip(ch) || KEY_VAL(sp, ch) == K_NL)
336b8ba871bSPeter Wemm (void)putc(CH_LITERAL, fp);
337b8ba871bSPeter Wemm (void)putc(ch, fp);
338b8ba871bSPeter Wemm }
339b8ba871bSPeter Wemm (void)putc(' ', fp);
340b8ba871bSPeter Wemm if (qp->output != NULL)
341b8ba871bSPeter Wemm for (p = qp->output,
342b8ba871bSPeter Wemm olen = qp->olen; olen > 0; --olen) {
343b8ba871bSPeter Wemm ch = *p++;
344b8ba871bSPeter Wemm if (ch == CH_LITERAL || ch == '|' ||
345b8ba871bSPeter Wemm KEY_VAL(sp, ch) == K_NL)
346b8ba871bSPeter Wemm (void)putc(CH_LITERAL, fp);
347b8ba871bSPeter Wemm (void)putc(ch, fp);
348b8ba871bSPeter Wemm }
349b8ba871bSPeter Wemm (void)putc('\n', fp);
350b8ba871bSPeter Wemm }
351b8ba871bSPeter Wemm return (0);
352b8ba871bSPeter Wemm }
353b8ba871bSPeter Wemm
354b8ba871bSPeter Wemm /*
355b8ba871bSPeter Wemm * e_memcmp --
356b8ba871bSPeter Wemm * Compare a string of EVENT's to a string of CHAR_T's.
357b8ba871bSPeter Wemm *
358c271fa92SBaptiste Daroussin * PUBLIC: int e_memcmp(CHAR_T *, EVENT *, size_t);
359b8ba871bSPeter Wemm */
360b8ba871bSPeter Wemm int
e_memcmp(CHAR_T * p1,EVENT * ep,size_t n)361*110d525eSBaptiste Daroussin e_memcmp(CHAR_T *p1, EVENT *ep, size_t n)
362b8ba871bSPeter Wemm {
363b8ba871bSPeter Wemm if (n != 0) {
364b8ba871bSPeter Wemm do {
365b8ba871bSPeter Wemm if (*p1++ != ep->e_c)
366b8ba871bSPeter Wemm return (*--p1 - ep->e_c);
367b8ba871bSPeter Wemm ++ep;
368b8ba871bSPeter Wemm } while (--n != 0);
369b8ba871bSPeter Wemm }
370b8ba871bSPeter Wemm return (0);
371b8ba871bSPeter Wemm }
372