source: trunk/third/nvi/common/seq.c @ 14302

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