Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / common / seq.c
blob8847367de654048cc5588e7b03e00164a7037945
1 /* $NetBSD: seq.c,v 1.1.1.2 2008/05/18 14:29:52 aymeric Exp $ */
3 /*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
9 * See the LICENSE file for redistribution information.
12 #include "config.h"
14 #ifndef lint
15 static const char sccsid[] = "Id: seq.c,v 10.15 2001/06/25 15:19:12 skimo Exp (Berkeley) Date: 2001/06/25 15:19:12";
16 #endif /* not lint */
18 #include <sys/types.h>
19 #include <sys/queue.h>
21 #include <bitstring.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #include "common.h"
32 * seq_set --
33 * Internal version to enter a sequence.
35 * PUBLIC: int seq_set __P((SCR *, CHAR_T *,
36 * PUBLIC: size_t, CHAR_T *, size_t, CHAR_T *, size_t, seq_t, int));
38 int
39 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)
41 CHAR_T *p;
42 SEQ *lastqp, *qp;
43 int sv_errno;
46 * An input string must always be present. The output string
47 * can be NULL, when set internally, that's how we throw away
48 * input.
50 * Just replace the output field if the string already set.
52 if ((qp =
53 seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
54 if (LF_ISSET(SEQ_NOOVERWRITE))
55 return (0);
56 if (output == NULL || olen == 0) {
57 p = NULL;
58 olen = 0;
59 } else if ((p = v_wstrdup(sp, output, olen)) == NULL) {
60 sv_errno = errno;
61 goto mem1;
63 if (qp->output != NULL)
64 free(qp->output);
65 qp->olen = olen;
66 qp->output = p;
67 return (0);
70 /* Allocate and initialize SEQ structure. */
71 CALLOC(sp, qp, SEQ *, 1, sizeof(SEQ));
72 if (qp == NULL) {
73 sv_errno = errno;
74 goto mem1;
77 /* Name. */
78 if (name == NULL || nlen == 0)
79 qp->name = NULL;
80 else if ((qp->name = v_wstrdup(sp, name, nlen)) == NULL) {
81 sv_errno = errno;
82 goto mem2;
84 qp->nlen = nlen;
86 /* Input. */
87 if ((qp->input = v_wstrdup(sp, input, ilen)) == NULL) {
88 sv_errno = errno;
89 goto mem3;
91 qp->ilen = ilen;
93 /* Output. */
94 if (output == NULL) {
95 qp->output = NULL;
96 olen = 0;
97 } else if ((qp->output = v_wstrdup(sp, output, olen)) == NULL) {
98 sv_errno = errno;
99 free(qp->input);
100 mem3: if (qp->name != NULL)
101 free(qp->name);
102 mem2: free(qp);
103 mem1: errno = sv_errno;
104 msgq(sp, M_SYSERR, NULL);
105 return (1);
107 qp->olen = olen;
109 /* Type, flags. */
110 qp->stype = stype;
111 qp->flags = flags;
113 /* Link into the chain. */
114 if (lastqp == NULL) {
115 LIST_INSERT_HEAD(&sp->gp->seqq, qp, q);
116 } else {
117 LIST_INSERT_AFTER(lastqp, qp, q);
120 /* Set the fast lookup bit. */
121 if ((UCHAR_T)qp->input[0] < MAX_BIT_SEQ)
122 bit_set(sp->gp->seqb, qp->input[0]);
124 return (0);
128 * seq_delete --
129 * Delete a sequence.
131 * PUBLIC: int seq_delete __P((SCR *, CHAR_T *, size_t, seq_t));
134 seq_delete(SCR *sp, CHAR_T *input, size_t ilen, seq_t stype)
136 SEQ *qp;
138 if ((qp = seq_find(sp, NULL, NULL, input, ilen, stype, NULL)) == NULL)
139 return (1);
140 return (seq_mdel(qp));
144 * seq_mdel --
145 * Delete a map entry, without lookup.
147 * PUBLIC: int seq_mdel __P((SEQ *));
150 seq_mdel(SEQ *qp)
152 LIST_REMOVE(qp, q);
153 if (qp->name != NULL)
154 free(qp->name);
155 free(qp->input);
156 if (qp->output != NULL)
157 free(qp->output);
158 free(qp);
159 return (0);
163 * seq_find --
164 * Search the sequence list for a match to a buffer, if ispartial
165 * isn't NULL, partial matches count.
167 * PUBLIC: SEQ *seq_find
168 * PUBLIC: __P((SCR *, SEQ **, EVENT *, CHAR_T *, size_t, seq_t, int *));
170 SEQ *
171 seq_find(SCR *sp, SEQ **lastqp, EVENT *e_input, CHAR_T *c_input, size_t ilen, seq_t stype, int *ispartialp)
173 SEQ *lqp, *qp;
174 int diff;
177 * Ispartialp is a location where we return if there was a
178 * partial match, i.e. if the string were extended it might
179 * match something.
181 * XXX
182 * Overload the meaning of ispartialp; only the terminal key
183 * search doesn't want the search limited to complete matches,
184 * i.e. ilen may be longer than the match.
186 if (ispartialp != NULL)
187 *ispartialp = 0;
188 for (lqp = NULL, qp = sp->gp->seqq.lh_first;
189 qp != NULL; lqp = qp, qp = qp->q.le_next) {
191 * Fast checks on the first character and type, and then
192 * a real comparison.
194 if (e_input == NULL) {
195 if (qp->input[0] > c_input[0])
196 break;
197 if (qp->input[0] < c_input[0] ||
198 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
199 continue;
200 diff = MEMCMP(qp->input, c_input, MIN(qp->ilen, ilen));
201 } else {
202 if (qp->input[0] > e_input->e_c)
203 break;
204 if (qp->input[0] < e_input->e_c ||
205 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
206 continue;
207 diff =
208 e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
210 if (diff > 0)
211 break;
212 if (diff < 0)
213 continue;
215 * If the entry is the same length as the string, return a
216 * match. If the entry is shorter than the string, return a
217 * match if called from the terminal key routine. Otherwise,
218 * keep searching for a complete match.
220 if (qp->ilen <= ilen) {
221 if (qp->ilen == ilen || ispartialp != NULL) {
222 if (lastqp != NULL)
223 *lastqp = lqp;
224 return (qp);
226 continue;
229 * If the entry longer than the string, return partial match
230 * if called from the terminal key routine. Otherwise, no
231 * match.
233 if (ispartialp != NULL)
234 *ispartialp = 1;
235 break;
237 if (lastqp != NULL)
238 *lastqp = lqp;
239 return (NULL);
243 * seq_close --
244 * Discard all sequences.
246 * PUBLIC: void seq_close __P((GS *));
248 void
249 seq_close(GS *gp)
251 SEQ *qp;
253 while ((qp = gp->seqq.lh_first) != NULL) {
254 if (qp->name != NULL)
255 free(qp->name);
256 if (qp->input != NULL)
257 free(qp->input);
258 if (qp->output != NULL)
259 free(qp->output);
260 LIST_REMOVE(qp, q);
261 free(qp);
266 * seq_dump --
267 * Display the sequence entries of a specified type.
269 * PUBLIC: int seq_dump __P((SCR *, seq_t, int));
272 seq_dump(SCR *sp, seq_t stype, int isname)
274 CHAR_T *p;
275 GS *gp;
276 SEQ *qp;
277 int cnt, len, olen;
279 cnt = 0;
280 gp = sp->gp;
281 for (qp = gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
282 if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
283 continue;
284 ++cnt;
285 for (p = qp->input,
286 olen = qp->ilen, len = 0; olen > 0; --olen, ++p)
287 len += ex_puts(sp, (char *)KEY_NAME(sp, *p));
288 for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
289 len -= ex_puts(sp, " ");
291 if (qp->output != NULL)
292 for (p = qp->output,
293 olen = qp->olen, len = 0; olen > 0; --olen, ++p)
294 len += ex_puts(sp, (char *)KEY_NAME(sp, *p));
295 else
296 len = 0;
298 if (isname && qp->name != NULL) {
299 for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
300 len -= ex_puts(sp, " ");
301 for (p = qp->name,
302 olen = qp->nlen; olen > 0; --olen, ++p)
303 (void)ex_puts(sp, (char *)KEY_NAME(sp, *p));
305 (void)ex_puts(sp, "\n");
307 return (cnt);
311 * seq_save --
312 * Save the sequence entries to a file.
314 * PUBLIC: int seq_save __P((SCR *, FILE *, char *, seq_t));
317 seq_save(SCR *sp, FILE *fp, const char *prefix, seq_t stype)
319 CHAR_T *p;
320 SEQ *qp;
321 size_t olen;
322 int ch;
324 /* Write a sequence command for all keys the user defined. */
325 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
326 if (stype != qp->stype || !F_ISSET(qp, SEQ_USERDEF))
327 continue;
328 if (prefix)
329 (void)fprintf(fp, "%s", prefix);
330 for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
331 ch = *p++;
332 if (ch == CH_LITERAL || ch == '|' ||
333 isblank(ch) || KEY_VAL(sp, ch) == K_NL)
334 (void)putc(CH_LITERAL, fp);
335 (void)putc(ch, fp);
337 (void)putc(' ', fp);
338 if (qp->output != NULL)
339 for (p = qp->output,
340 olen = qp->olen; olen > 0; --olen) {
341 ch = *p++;
342 if (ch == CH_LITERAL || ch == '|' ||
343 KEY_VAL(sp, ch) == K_NL)
344 (void)putc(CH_LITERAL, fp);
345 (void)putc(ch, fp);
347 (void)putc('\n', fp);
349 return (0);
353 * e_memcmp --
354 * Compare a string of EVENT's to a string of CHAR_T's.
356 * PUBLIC: int e_memcmp __P((CHAR_T *, EVENT *, size_t));
359 e_memcmp(CHAR_T *p1, EVENT *ep, size_t n)
361 if (n != 0) {
362 do {
363 if (*p1++ != ep->e_c)
364 return (*--p1 - ep->e_c);
365 ++ep;
366 } while (--n != 0);
368 return (0);