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