hammer2 - Fix bug in comp:autozero mode
[dragonfly.git] / contrib / nvi2 / common / seq.c
blob61c7fcd0b2851f5f9650f70b2f67b24191494258
1 /*-
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.
8 */
10 #include "config.h"
12 #ifndef lint
13 static const char sccsid[] = "$Id: seq.c,v 10.18 2011/12/11 23:13:00 zy Exp $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #include <sys/time.h>
20 #include <bitstring.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "common.h"
31 * seq_set --
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);
37 int
38 seq_set(
39 SCR *sp,
40 CHAR_T *name,
41 size_t nlen,
42 CHAR_T *input,
43 size_t ilen,
44 CHAR_T *output,
45 size_t olen,
46 seq_t stype,
47 int flags)
49 CHAR_T *p;
50 SEQ *lastqp, *qp;
51 int sv_errno;
54 * An input string must always be present. The output string
55 * can be NULL, when set internally, that's how we throw away
56 * input.
58 * Just replace the output field if the string already set.
60 if ((qp =
61 seq_find(sp, &lastqp, NULL, input, ilen, stype, NULL)) != NULL) {
62 if (LF_ISSET(SEQ_NOOVERWRITE))
63 return (0);
64 if (output == NULL || olen == 0) {
65 p = NULL;
66 olen = 0;
67 } else if ((p = v_wstrdup(sp, output, olen)) == NULL) {
68 sv_errno = errno;
69 goto mem1;
71 if (qp->output != NULL)
72 free(qp->output);
73 qp->olen = olen;
74 qp->output = p;
75 return (0);
78 /* Allocate and initialize SEQ structure. */
79 CALLOC(sp, qp, SEQ *, 1, sizeof(SEQ));
80 if (qp == NULL) {
81 sv_errno = errno;
82 goto mem1;
85 /* Name. */
86 if (name == NULL || nlen == 0)
87 qp->name = NULL;
88 else if ((qp->name = v_wstrdup(sp, name, nlen)) == NULL) {
89 sv_errno = errno;
90 goto mem2;
92 qp->nlen = nlen;
94 /* Input. */
95 if ((qp->input = v_wstrdup(sp, input, ilen)) == NULL) {
96 sv_errno = errno;
97 goto mem3;
99 qp->ilen = ilen;
101 /* Output. */
102 if (output == NULL) {
103 qp->output = NULL;
104 olen = 0;
105 } else if ((qp->output = v_wstrdup(sp, output, olen)) == NULL) {
106 sv_errno = errno;
107 free(qp->input);
108 mem3: if (qp->name != NULL)
109 free(qp->name);
110 mem2: free(qp);
111 mem1: errno = sv_errno;
112 msgq(sp, M_SYSERR, NULL);
113 return (1);
115 qp->olen = olen;
117 /* Type, flags. */
118 qp->stype = stype;
119 qp->flags = flags;
121 /* Link into the chain. */
122 if (lastqp == NULL) {
123 SLIST_INSERT_HEAD(sp->gp->seqq, qp, q);
124 } else {
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]);
132 return (0);
136 * seq_delete --
137 * Delete a sequence.
139 * PUBLIC: int seq_delete(SCR *, CHAR_T *, size_t, seq_t);
142 seq_delete(
143 SCR *sp,
144 CHAR_T *input,
145 size_t ilen,
146 seq_t stype)
148 SEQ *qp, *pre_qp = NULL;
149 int diff;
151 SLIST_FOREACH(qp, sp->gp->seqq, q) {
152 if (qp->stype == stype && qp->ilen == ilen) {
153 diff = MEMCMP(qp->input, input, ilen);
154 if (!diff) {
155 if (F_ISSET(qp, SEQ_FUNCMAP))
156 break;
157 if (qp == SLIST_FIRST(sp->gp->seqq))
158 SLIST_REMOVE_HEAD(sp->gp->seqq, q);
159 else
160 SLIST_REMOVE_AFTER(pre_qp, q);
161 return (seq_free(qp));
163 if (diff > 0)
164 break;
166 pre_qp = qp;
168 return (1);
172 * seq_free --
173 * Free a map entry.
175 * PUBLIC: int seq_free(SEQ *);
178 seq_free(SEQ *qp)
180 if (qp->name != NULL)
181 free(qp->name);
182 if (qp->input != NULL)
183 free(qp->input);
184 if (qp->output != NULL)
185 free(qp->output);
186 free(qp);
187 return (0);
191 * seq_find --
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 *);
198 SEQ *
199 seq_find(
200 SCR *sp,
201 SEQ **lastqp,
202 EVENT *e_input,
203 CHAR_T *c_input,
204 size_t ilen,
205 seq_t stype,
206 int *ispartialp)
208 SEQ *lqp = NULL, *qp;
209 int diff;
212 * Ispartialp is a location where we return if there was a
213 * partial match, i.e. if the string were extended it might
214 * match something.
216 * XXX
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)
222 *ispartialp = 0;
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
227 * a real comparison.
229 if (e_input == NULL) {
230 if (qp->input[0] > c_input[0])
231 break;
232 if (qp->input[0] < c_input[0] ||
233 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
234 continue;
235 diff = MEMCMP(qp->input, c_input, MIN(qp->ilen, ilen));
236 } else {
237 if (qp->input[0] > e_input->e_c)
238 break;
239 if (qp->input[0] < e_input->e_c ||
240 qp->stype != stype || F_ISSET(qp, SEQ_FUNCMAP))
241 continue;
242 diff =
243 e_memcmp(qp->input, e_input, MIN(qp->ilen, ilen));
245 if (diff > 0)
246 break;
247 if (diff < 0)
248 continue;
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) {
257 if (lastqp != NULL)
258 *lastqp = lqp;
259 return (qp);
261 continue;
264 * If the entry longer than the string, return partial match
265 * if called from the terminal key routine. Otherwise, no
266 * match.
268 if (ispartialp != NULL)
269 *ispartialp = 1;
270 break;
272 if (lastqp != NULL)
273 *lastqp = lqp;
274 return (NULL);
278 * seq_close --
279 * Discard all sequences.
281 * PUBLIC: void seq_close(GS *);
283 void
284 seq_close(GS *gp)
286 SEQ *qp;
288 while ((qp = SLIST_FIRST(gp->seqq)) != NULL) {
289 SLIST_REMOVE_HEAD(gp->seqq, q);
290 (void)seq_free(qp);
295 * seq_dump --
296 * Display the sequence entries of a specified type.
298 * PUBLIC: int seq_dump(SCR *, seq_t, int);
301 seq_dump(
302 SCR *sp,
303 seq_t stype,
304 int isname)
306 CHAR_T *p;
307 GS *gp;
308 SEQ *qp;
309 int cnt, len, olen;
311 cnt = 0;
312 gp = sp->gp;
313 SLIST_FOREACH(qp, sp->gp->seqq, q) {
314 if (stype != qp->stype || F_ISSET(qp, SEQ_FUNCMAP))
315 continue;
316 ++cnt;
317 for (p = qp->input,
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)
324 for (p = qp->output,
325 olen = qp->olen, len = 0; olen > 0; --olen, ++p)
326 len += ex_puts(sp, KEY_NAME(sp, *p));
327 else
328 len = 0;
330 if (isname && qp->name != NULL) {
331 for (len = STANDARD_TAB - len % STANDARD_TAB; len > 0;)
332 len -= ex_puts(sp, " ");
333 for (p = qp->name,
334 olen = qp->nlen; olen > 0; --olen, ++p)
335 (void)ex_puts(sp, KEY_NAME(sp, *p));
337 (void)ex_puts(sp, "\n");
339 return (cnt);
343 * seq_save --
344 * Save the sequence entries to a file.
346 * PUBLIC: int seq_save(SCR *, FILE *, char *, seq_t);
349 seq_save(
350 SCR *sp,
351 FILE *fp,
352 char *prefix,
353 seq_t stype)
355 CHAR_T *p;
356 SEQ *qp;
357 size_t olen;
358 int ch;
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))
363 continue;
364 if (prefix)
365 (void)fprintf(fp, "%s", prefix);
366 for (p = qp->input, olen = qp->ilen; olen > 0; --olen) {
367 ch = *p++;
368 if (ch == CH_LITERAL || ch == '|' ||
369 cmdskip(ch) || KEY_VAL(sp, ch) == K_NL)
370 (void)putc(CH_LITERAL, fp);
371 (void)putc(ch, fp);
373 (void)putc(' ', fp);
374 if (qp->output != NULL)
375 for (p = qp->output,
376 olen = qp->olen; olen > 0; --olen) {
377 ch = *p++;
378 if (ch == CH_LITERAL || ch == '|' ||
379 KEY_VAL(sp, ch) == K_NL)
380 (void)putc(CH_LITERAL, fp);
381 (void)putc(ch, fp);
383 (void)putc('\n', fp);
385 return (0);
389 * e_memcmp --
390 * Compare a string of EVENT's to a string of CHAR_T's.
392 * PUBLIC: int e_memcmp(CHAR_T *, EVENT *, size_t);
395 e_memcmp(
396 CHAR_T *p1,
397 EVENT *ep,
398 size_t n)
400 if (n != 0) {
401 do {
402 if (*p1++ != ep->e_c)
403 return (*--p1 - ep->e_c);
404 ++ep;
405 } while (--n != 0);
407 return (0);