Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation.
3 : : * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include <stdlib.h>
8 : : #include <stdio.h>
9 : : #include <string.h>
10 : : #include <errno.h>
11 : : #include <ctype.h>
12 : :
13 : : #include "cmdline_cirbuf.h"
14 : : #include "cmdline_private.h"
15 : : #include "cmdline_rdline.h"
16 : :
17 : : #include <eal_export.h>
18 : :
19 : : static void rdline_puts(struct rdline *rdl, const char *buf);
20 : : static void rdline_miniprintf(struct rdline *rdl,
21 : : const char *buf, unsigned int val);
22 : :
23 : : static void rdline_remove_old_history_item(struct rdline *rdl);
24 : : static void rdline_remove_first_history_item(struct rdline *rdl);
25 : : static unsigned int rdline_get_history_size(struct rdline *rdl);
26 : :
27 : :
28 : : /* isblank() needs _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE, so use our
29 : : * own. */
30 : : static int
31 : : isblank2(char c)
32 : : {
33 : 0 : if (c == ' ' ||
34 [ # # # # : 0 : c == '\t' )
# # # # ]
35 : : return 1;
36 : : return 0;
37 : : }
38 : :
39 : : int
40 : 132 : rdline_init(struct rdline *rdl,
41 : : rdline_write_char_t *write_char,
42 : : rdline_validate_t *validate,
43 : : rdline_complete_t *complete,
44 : : void *opaque)
45 : : {
46 [ + + + + ]: 132 : if (!rdl || !write_char || !validate || !complete)
47 : : return -EINVAL;
48 : : memset(rdl, 0, sizeof(*rdl));
49 : 129 : rdl->validate = validate;
50 : 129 : rdl->complete = complete;
51 : 129 : rdl->write_char = write_char;
52 : 129 : rdl->opaque = opaque;
53 : 129 : rdl->status = RDLINE_INIT;
54 : 129 : return cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE);
55 : : }
56 : :
57 : : RTE_EXPORT_SYMBOL(rdline_new)
58 : : struct rdline *
59 : 3 : rdline_new(rdline_write_char_t *write_char,
60 : : rdline_validate_t *validate,
61 : : rdline_complete_t *complete,
62 : : void *opaque)
63 : : {
64 : : struct rdline *rdl;
65 : :
66 : 3 : rdl = malloc(sizeof(*rdl));
67 [ + - ]: 3 : if (rdline_init(rdl, write_char, validate, complete, opaque) < 0) {
68 : 3 : free(rdl);
69 : : rdl = NULL;
70 : : }
71 : 3 : return rdl;
72 : : }
73 : :
74 : : RTE_EXPORT_SYMBOL(rdline_free)
75 : : void
76 : 2 : rdline_free(struct rdline *rdl)
77 : : {
78 : 2 : free(rdl);
79 : 2 : }
80 : :
81 : : RTE_EXPORT_SYMBOL(rdline_newline)
82 : : void
83 : 251 : rdline_newline(struct rdline *rdl, const char *prompt)
84 : : {
85 : : unsigned int i;
86 : :
87 [ + + ]: 251 : if (!rdl || !prompt)
88 : : return;
89 : :
90 : 249 : vt100_init(&rdl->vt100);
91 : 249 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
92 : 249 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
93 : :
94 : 249 : rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1);
95 [ + - ]: 249 : if (prompt != rdl->prompt)
96 : 249 : memcpy(rdl->prompt, prompt, rdl->prompt_size);
97 : 249 : rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0';
98 : :
99 [ + + ]: 1495 : for (i=0 ; i<rdl->prompt_size ; i++)
100 : 1246 : rdl->write_char(rdl, rdl->prompt[i]);
101 : 249 : rdl->status = RDLINE_RUNNING;
102 : :
103 : 249 : rdl->history_cur_line = -1;
104 : : }
105 : :
106 : : RTE_EXPORT_SYMBOL(rdline_stop)
107 : : void
108 : 1 : rdline_stop(struct rdline *rdl)
109 : : {
110 [ - + ]: 1 : if (!rdl)
111 : : return;
112 : 0 : rdl->status = RDLINE_INIT;
113 : : }
114 : :
115 : : RTE_EXPORT_SYMBOL(rdline_quit)
116 : : void
117 : 2 : rdline_quit(struct rdline *rdl)
118 : : {
119 [ + + ]: 2 : if (!rdl)
120 : : return;
121 : 1 : rdl->status = RDLINE_EXITED;
122 : : }
123 : :
124 : : RTE_EXPORT_SYMBOL(rdline_restart)
125 : : void
126 : 1 : rdline_restart(struct rdline *rdl)
127 : : {
128 [ - + ]: 1 : if (!rdl)
129 : : return;
130 : 0 : rdl->status = RDLINE_RUNNING;
131 : : }
132 : :
133 : : RTE_EXPORT_SYMBOL(rdline_reset)
134 : : void
135 : 1 : rdline_reset(struct rdline *rdl)
136 : : {
137 [ - + ]: 1 : if (!rdl)
138 : : return;
139 : 0 : vt100_init(&rdl->vt100);
140 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
141 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
142 : :
143 : 0 : rdl->status = RDLINE_RUNNING;
144 : :
145 : 0 : rdl->history_cur_line = -1;
146 : : }
147 : :
148 : : RTE_EXPORT_SYMBOL(rdline_get_buffer)
149 : : const char *
150 : 247 : rdline_get_buffer(struct rdline *rdl)
151 : : {
152 [ + + ]: 247 : if (!rdl)
153 : : return NULL;
154 : : unsigned int len_l, len_r;
155 : 246 : cirbuf_align_left(&rdl->left);
156 : 246 : cirbuf_align_left(&rdl->right);
157 : :
158 : 246 : len_l = CIRBUF_GET_LEN(&rdl->left);
159 : 246 : len_r = CIRBUF_GET_LEN(&rdl->right);
160 : 246 : memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r);
161 : :
162 : 246 : rdl->left_buf[len_l + len_r] = '\n';
163 : 246 : rdl->left_buf[len_l + len_r + 1] = '\0';
164 : 246 : return rdl->left_buf;
165 : : }
166 : :
167 : : static void
168 : 2179 : display_right_buffer(struct rdline *rdl, int force)
169 : : {
170 : : unsigned int i;
171 : : char tmp;
172 : :
173 [ + - - + ]: 2179 : if (!force && CIRBUF_IS_EMPTY(&rdl->right))
174 : : return;
175 : :
176 : : rdline_puts(rdl, vt100_clear_right);
177 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->right, i, tmp) {
178 : 0 : rdl->write_char(rdl, tmp);
179 : : }
180 [ # # ]: 0 : if (!CIRBUF_IS_EMPTY(&rdl->right))
181 : 0 : rdline_miniprintf(rdl, vt100_multi_left,
182 : : CIRBUF_GET_LEN(&rdl->right));
183 : : }
184 : :
185 : : RTE_EXPORT_SYMBOL(rdline_redisplay)
186 : : void
187 : 1 : rdline_redisplay(struct rdline *rdl)
188 : : {
189 : : unsigned int i;
190 : : char tmp;
191 : :
192 [ - + ]: 1 : if (!rdl)
193 : : return;
194 : :
195 : : rdline_puts(rdl, vt100_home);
196 [ # # ]: 0 : for (i=0 ; i<rdl->prompt_size ; i++)
197 : 0 : rdl->write_char(rdl, rdl->prompt[i]);
198 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->left, i, tmp) {
199 : 0 : rdl->write_char(rdl, tmp);
200 : : }
201 : 0 : display_right_buffer(rdl, 1);
202 : : }
203 : :
204 : : RTE_EXPORT_SYMBOL(rdline_char_in)
205 : : int
206 : 2306 : rdline_char_in(struct rdline *rdl, char c)
207 : : {
208 : : unsigned int i;
209 : : int cmd;
210 : : char tmp;
211 : : char *buf;
212 : :
213 [ + + ]: 2306 : if (!rdl)
214 : : return -EINVAL;
215 : :
216 [ + - ]: 2305 : if (rdl->status == RDLINE_EXITED)
217 : : return RDLINE_RES_EXITED;
218 [ + - ]: 2305 : if (rdl->status != RDLINE_RUNNING)
219 : : return RDLINE_RES_NOT_RUNNING;
220 : :
221 : 2305 : cmd = vt100_parser(&rdl->vt100, c);
222 [ + - ]: 2305 : if (cmd == -2)
223 : : return RDLINE_RES_SUCCESS;
224 : :
225 [ + + ]: 2305 : if (cmd >= 0) {
226 [ - - - - : 126 : switch (cmd) {
- - - - -
- - - - -
- + - -
- ]
227 : : /* move caret 1 char to the left */
228 : 0 : case CMDLINE_KEY_CTRL_B:
229 : : case CMDLINE_KEY_LEFT_ARR:
230 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->left))
231 : : break;
232 : 0 : tmp = cirbuf_get_tail(&rdl->left);
233 : 0 : cirbuf_del_tail(&rdl->left);
234 : 0 : cirbuf_add_head(&rdl->right, tmp);
235 : : rdline_puts(rdl, vt100_left_arr);
236 : : break;
237 : :
238 : : /* move caret 1 char to the right */
239 : 0 : case CMDLINE_KEY_CTRL_F:
240 : : case CMDLINE_KEY_RIGHT_ARR:
241 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->right))
242 : : break;
243 : 0 : tmp = cirbuf_get_head(&rdl->right);
244 : 0 : cirbuf_del_head(&rdl->right);
245 : 0 : cirbuf_add_tail(&rdl->left, tmp);
246 : : rdline_puts(rdl, vt100_right_arr);
247 : : break;
248 : :
249 : : /* move caret 1 word to the left */
250 : : /* keyboard equivalent: Alt+B */
251 : : case CMDLINE_KEY_WLEFT:
252 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) &&
253 [ # # ]: 0 : (tmp = cirbuf_get_tail(&rdl->left)) &&
254 [ # # ]: 0 : isblank2(tmp)) {
255 : : rdline_puts(rdl, vt100_left_arr);
256 : 0 : cirbuf_del_tail(&rdl->left);
257 : 0 : cirbuf_add_head(&rdl->right, tmp);
258 : : }
259 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) &&
260 [ # # ]: 0 : (tmp = cirbuf_get_tail(&rdl->left)) &&
261 [ # # ]: 0 : !isblank2(tmp)) {
262 : : rdline_puts(rdl, vt100_left_arr);
263 : 0 : cirbuf_del_tail(&rdl->left);
264 : 0 : cirbuf_add_head(&rdl->right, tmp);
265 : : }
266 : : break;
267 : :
268 : : /* move caret 1 word to the right */
269 : : /* keyboard equivalent: Alt+F */
270 : : case CMDLINE_KEY_WRIGHT:
271 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) &&
272 [ # # ]: 0 : (tmp = cirbuf_get_head(&rdl->right)) &&
273 [ # # ]: 0 : isblank2(tmp)) {
274 : : rdline_puts(rdl, vt100_right_arr);
275 : 0 : cirbuf_del_head(&rdl->right);
276 : 0 : cirbuf_add_tail(&rdl->left, tmp);
277 : : }
278 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) &&
279 [ # # ]: 0 : (tmp = cirbuf_get_head(&rdl->right)) &&
280 [ # # ]: 0 : !isblank2(tmp)) {
281 : : rdline_puts(rdl, vt100_right_arr);
282 : 0 : cirbuf_del_head(&rdl->right);
283 : 0 : cirbuf_add_tail(&rdl->left, tmp);
284 : : }
285 : : break;
286 : :
287 : : /* move caret to the left */
288 : 0 : case CMDLINE_KEY_CTRL_A:
289 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->left))
290 : : break;
291 : 0 : rdline_miniprintf(rdl, vt100_multi_left,
292 : : CIRBUF_GET_LEN(&rdl->left));
293 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left)) {
294 : 0 : tmp = cirbuf_get_tail(&rdl->left);
295 : 0 : cirbuf_del_tail(&rdl->left);
296 : 0 : cirbuf_add_head(&rdl->right, tmp);
297 : : }
298 : : break;
299 : :
300 : : /* move caret to the right */
301 : 0 : case CMDLINE_KEY_CTRL_E:
302 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->right))
303 : : break;
304 : 0 : rdline_miniprintf(rdl, vt100_multi_right,
305 : : CIRBUF_GET_LEN(&rdl->right));
306 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right)) {
307 : 0 : tmp = cirbuf_get_head(&rdl->right);
308 : 0 : cirbuf_del_head(&rdl->right);
309 : 0 : cirbuf_add_tail(&rdl->left, tmp);
310 : : }
311 : : break;
312 : :
313 : : /* delete 1 char from the left */
314 : 0 : case CMDLINE_KEY_BKSPACE:
315 : : case CMDLINE_KEY_BKSPACE2:
316 [ # # ]: 0 : if(!cirbuf_del_tail_safe(&rdl->left)) {
317 : : rdline_puts(rdl, vt100_bs);
318 : 0 : display_right_buffer(rdl, 1);
319 : : }
320 : : break;
321 : :
322 : : /* delete 1 char from the right */
323 : 0 : case CMDLINE_KEY_SUPPR:
324 : : case CMDLINE_KEY_CTRL_D:
325 [ # # ]: 0 : if (cmd == CMDLINE_KEY_CTRL_D &&
326 [ # # ]: 0 : CIRBUF_IS_EMPTY(&rdl->left) &&
327 [ # # ]: 0 : CIRBUF_IS_EMPTY(&rdl->right)) {
328 : : return RDLINE_RES_EOF;
329 : : }
330 [ # # ]: 0 : if (!cirbuf_del_head_safe(&rdl->right)) {
331 : 0 : display_right_buffer(rdl, 1);
332 : : }
333 : : break;
334 : :
335 : : /* delete 1 word from the left */
336 : : case CMDLINE_KEY_META_BKSPACE:
337 : : case CMDLINE_KEY_CTRL_W:
338 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) {
339 : : rdline_puts(rdl, vt100_bs);
340 : 0 : cirbuf_del_tail(&rdl->left);
341 : : }
342 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) {
343 : : rdline_puts(rdl, vt100_bs);
344 : 0 : cirbuf_del_tail(&rdl->left);
345 : : }
346 : 0 : display_right_buffer(rdl, 1);
347 : 0 : break;
348 : :
349 : : /* delete 1 word from the right */
350 : : case CMDLINE_KEY_META_D:
351 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right)))
352 : 0 : cirbuf_del_head(&rdl->right);
353 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right)))
354 : 0 : cirbuf_del_head(&rdl->right);
355 : 0 : display_right_buffer(rdl, 1);
356 : 0 : break;
357 : :
358 : : /* set kill buffer to contents on the right side of caret */
359 : 0 : case CMDLINE_KEY_CTRL_K:
360 : 0 : cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE);
361 : 0 : rdl->kill_size = CIRBUF_GET_LEN(&rdl->right);
362 : 0 : cirbuf_del_buf_head(&rdl->right, rdl->kill_size);
363 : : rdline_puts(rdl, vt100_clear_right);
364 : : break;
365 : :
366 : : /* paste contents of kill buffer to the left side of caret */
367 : : case CMDLINE_KEY_CTRL_Y:
368 : : i=0;
369 : 0 : while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
370 [ # # ]: 0 : RDLINE_BUF_SIZE &&
371 [ # # ]: 0 : i < rdl->kill_size) {
372 : 0 : cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]);
373 : 0 : rdl->write_char(rdl, rdl->kill_buf[i]);
374 : 0 : i++;
375 : : }
376 : 0 : display_right_buffer(rdl, 0);
377 : 0 : break;
378 : :
379 : : /* clear and newline */
380 : : case CMDLINE_KEY_CTRL_C:
381 : : rdline_puts(rdl, "\r\n");
382 : 0 : rdline_newline(rdl, rdl->prompt);
383 : 0 : break;
384 : :
385 : : /* redisplay (helps when prompt is lost in other output) */
386 : 0 : case CMDLINE_KEY_CTRL_L:
387 : 0 : rdline_redisplay(rdl);
388 : 0 : break;
389 : :
390 : : /* autocomplete */
391 : 0 : case CMDLINE_KEY_TAB:
392 : : case CMDLINE_KEY_HELP:
393 : 0 : cirbuf_align_left(&rdl->left);
394 : 0 : rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0';
395 [ # # ]: 0 : if (rdl->complete) {
396 : : char tmp_buf[BUFSIZ];
397 : : int complete_state;
398 : : int ret;
399 : : unsigned int tmp_size;
400 : :
401 [ # # ]: 0 : if (cmd == CMDLINE_KEY_TAB)
402 : 0 : complete_state = 0;
403 : : else
404 : 0 : complete_state = -1;
405 : :
406 : : /* see in parse.h for help on complete() */
407 : 0 : ret = rdl->complete(rdl, rdl->left_buf,
408 : : tmp_buf, sizeof(tmp_buf),
409 : : &complete_state);
410 : : /* no completion or error */
411 [ # # ]: 0 : if (ret <= 0) {
412 : 0 : return RDLINE_RES_COMPLETE;
413 : : }
414 : :
415 : 0 : tmp_size = strnlen(tmp_buf, sizeof(tmp_buf));
416 : : /* add chars */
417 [ # # ]: 0 : if (ret == RDLINE_RES_COMPLETE) {
418 : : i=0;
419 : 0 : while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
420 [ # # # # ]: 0 : RDLINE_BUF_SIZE &&
421 : : i < tmp_size) {
422 : 0 : cirbuf_add_tail(&rdl->left, tmp_buf[i]);
423 : 0 : rdl->write_char(rdl, tmp_buf[i]);
424 : 0 : i++;
425 : : }
426 : 0 : display_right_buffer(rdl, 1);
427 : 0 : return RDLINE_RES_COMPLETE; /* ?? */
428 : : }
429 : :
430 : : /* choice */
431 : : rdline_puts(rdl, "\r\n");
432 [ # # ]: 0 : while (ret) {
433 : 0 : rdl->write_char(rdl, ' ');
434 [ # # ]: 0 : for (i=0 ; tmp_buf[i] ; i++)
435 : 0 : rdl->write_char(rdl, tmp_buf[i]);
436 : : rdline_puts(rdl, "\r\n");
437 : 0 : ret = rdl->complete(rdl, rdl->left_buf,
438 : : tmp_buf, sizeof(tmp_buf),
439 : : &complete_state);
440 : : }
441 : :
442 : 0 : rdline_redisplay(rdl);
443 : : }
444 : 0 : return RDLINE_RES_COMPLETE;
445 : :
446 : : /* complete buffer */
447 : 126 : case CMDLINE_KEY_RETURN:
448 : : case CMDLINE_KEY_RETURN2:
449 : 126 : rdline_get_buffer(rdl);
450 : 126 : rdl->status = RDLINE_INIT;
451 : : rdline_puts(rdl, "\r\n");
452 [ - + ]: 126 : if (rdl->history_cur_line != -1)
453 : 0 : rdline_remove_first_history_item(rdl);
454 : :
455 [ + - ]: 126 : if (rdl->validate)
456 : 126 : rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2);
457 : : /* user may have stopped rdline */
458 [ + + ]: 121 : if (rdl->status == RDLINE_EXITED)
459 : : return RDLINE_RES_EXITED;
460 : 120 : return RDLINE_RES_VALIDATED;
461 : :
462 : : /* previous element in history */
463 : 0 : case CMDLINE_KEY_UP_ARR:
464 : : case CMDLINE_KEY_CTRL_P:
465 [ # # ]: 0 : if (rdl->history_cur_line == 0) {
466 : 0 : rdline_remove_first_history_item(rdl);
467 : : }
468 [ # # ]: 0 : if (rdl->history_cur_line <= 0) {
469 : 0 : rdline_add_history(rdl, rdline_get_buffer(rdl));
470 : 0 : rdl->history_cur_line = 0;
471 : : }
472 : :
473 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1);
474 [ # # ]: 0 : if (!buf)
475 : : break;
476 : :
477 : 0 : rdl->history_cur_line ++;
478 : 0 : vt100_init(&rdl->vt100);
479 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
480 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
481 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
482 : 0 : rdline_redisplay(rdl);
483 : 0 : break;
484 : :
485 : : /* next element in history */
486 : 0 : case CMDLINE_KEY_DOWN_ARR:
487 : : case CMDLINE_KEY_CTRL_N:
488 [ # # ]: 0 : if (rdl->history_cur_line - 1 < 0)
489 : : break;
490 : :
491 : 0 : rdl->history_cur_line --;
492 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line);
493 [ # # ]: 0 : if (!buf)
494 : : break;
495 : 0 : vt100_init(&rdl->vt100);
496 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
497 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
498 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
499 : 0 : rdline_redisplay(rdl);
500 : :
501 : 0 : break;
502 : :
503 : :
504 : : default:
505 : : break;
506 : : }
507 : :
508 : 0 : return RDLINE_RES_SUCCESS;
509 : : }
510 : :
511 [ + - ]: 2179 : if (!isprint((int)c))
512 : : return RDLINE_RES_SUCCESS;
513 : :
514 : : /* standard chars */
515 [ + - ]: 2179 : if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE)
516 : : return RDLINE_RES_SUCCESS;
517 : :
518 [ + - ]: 2179 : if (cirbuf_add_tail_safe(&rdl->left, c))
519 : : return RDLINE_RES_SUCCESS;
520 : :
521 : 2179 : rdl->write_char(rdl, c);
522 : 2179 : display_right_buffer(rdl, 0);
523 : :
524 : 2179 : return RDLINE_RES_SUCCESS;
525 : : }
526 : :
527 : :
528 : : /* HISTORY */
529 : :
530 : : static void
531 : 0 : rdline_remove_old_history_item(struct rdline * rdl)
532 : : {
533 : : char tmp;
534 : :
535 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
536 : 0 : tmp = cirbuf_get_head(&rdl->history);
537 : 0 : cirbuf_del_head(&rdl->history);
538 [ # # ]: 0 : if (!tmp)
539 : : break;
540 : : }
541 : 0 : }
542 : :
543 : : static void
544 : 0 : rdline_remove_first_history_item(struct rdline * rdl)
545 : : {
546 : : char tmp;
547 : :
548 [ # # ]: 0 : if ( CIRBUF_IS_EMPTY(&rdl->history) ) {
549 : : return;
550 : : }
551 : : else {
552 : 0 : cirbuf_del_tail(&rdl->history);
553 : : }
554 : :
555 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
556 : 0 : tmp = cirbuf_get_tail(&rdl->history);
557 [ # # ]: 0 : if (!tmp)
558 : : break;
559 : 0 : cirbuf_del_tail(&rdl->history);
560 : : }
561 : : }
562 : :
563 : : static unsigned int
564 : : rdline_get_history_size(struct rdline * rdl)
565 : : {
566 : : unsigned int i, tmp, ret=0;
567 : :
568 [ - + ]: 120 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
569 [ # # ]: 0 : if (tmp == 0)
570 : 0 : ret ++;
571 : : }
572 : :
573 : : return ret;
574 : : }
575 : :
576 : : RTE_EXPORT_SYMBOL(rdline_get_history_item)
577 : : char *
578 : 121 : rdline_get_history_item(struct rdline * rdl, unsigned int idx)
579 : : {
580 : : unsigned int len, i, tmp;
581 : :
582 [ + + ]: 121 : if (!rdl)
583 : : return NULL;
584 : :
585 : : len = rdline_get_history_size(rdl);
586 [ - + ]: 120 : if ( idx >= len ) {
587 : : return NULL;
588 : : }
589 : :
590 : 0 : cirbuf_align_left(&rdl->history);
591 : :
592 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
593 [ # # ]: 0 : if ( idx == len - 1) {
594 : 0 : return rdl->history_buf + i;
595 : : }
596 [ # # ]: 0 : if (tmp == 0)
597 : : len --;
598 : : }
599 : :
600 : : return NULL;
601 : : }
602 : :
603 : : RTE_EXPORT_SYMBOL(rdline_get_history_buffer_size)
604 : : size_t
605 : 1 : rdline_get_history_buffer_size(struct rdline *rdl)
606 : : {
607 : 1 : return sizeof(rdl->history_buf);
608 : : }
609 : :
610 : : RTE_EXPORT_SYMBOL(rdline_get_opaque)
611 : : void *
612 : 1 : rdline_get_opaque(struct rdline *rdl)
613 : : {
614 [ - + ]: 1 : return rdl != NULL ? rdl->opaque : NULL;
615 : : }
616 : :
617 : : RTE_EXPORT_SYMBOL(rdline_add_history)
618 : : int
619 : 122 : rdline_add_history(struct rdline * rdl, const char * buf)
620 : : {
621 : : unsigned int len, i;
622 : :
623 [ + + ]: 122 : if (!rdl || !buf)
624 : : return -EINVAL;
625 : :
626 : 120 : len = strnlen(buf, RDLINE_BUF_SIZE);
627 [ + - ]: 2225 : for (i=0; i<len ; i++) {
628 [ + + ]: 2225 : if (buf[i] == '\n') {
629 : : len = i;
630 : : break;
631 : : }
632 : : }
633 : :
634 [ + - ]: 120 : if ( len >= RDLINE_HISTORY_BUF_SIZE )
635 : : return -1;
636 : :
637 [ - + ]: 120 : while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) {
638 : 0 : rdline_remove_old_history_item(rdl);
639 : : }
640 : :
641 : 120 : cirbuf_add_buf_tail(&rdl->history, buf, len);
642 : 120 : cirbuf_add_tail(&rdl->history, 0);
643 : :
644 : 120 : return 0;
645 : : }
646 : :
647 : : RTE_EXPORT_SYMBOL(rdline_clear_history)
648 : : void
649 : 1 : rdline_clear_history(struct rdline * rdl)
650 : : {
651 [ - + ]: 1 : if (!rdl)
652 : : return;
653 : 0 : cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE);
654 : : }
655 : :
656 : :
657 : : /* STATIC USEFUL FUNCS */
658 : :
659 : : static void
660 : : rdline_puts(struct rdline * rdl, const char * buf)
661 : : {
662 : : char c;
663 [ - - - - : 378 : while ( (c = *(buf++)) != '\0' ) {
- - - - -
- - - - -
- - - - -
- - - - -
- - + + -
- - - ]
664 : 252 : rdl->write_char(rdl, c);
665 : : }
666 : : }
667 : :
668 : : /* a very very basic printf with one arg and one format 'u' */
669 : : static void
670 : 0 : rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val)
671 : : {
672 : : char c, started=0, div=100;
673 : :
674 [ # # ]: 0 : while ( (c=*(buf++)) ) {
675 [ # # ]: 0 : if (c != '%') {
676 : 0 : rdl->write_char(rdl, c);
677 : 0 : continue;
678 : : }
679 : 0 : c = *(buf++);
680 [ # # ]: 0 : if (c != 'u') {
681 : 0 : rdl->write_char(rdl, '%');
682 : 0 : rdl->write_char(rdl, c);
683 : 0 : continue;
684 : : }
685 : : /* val is never more than 255 */
686 [ # # ]: 0 : while (div) {
687 : 0 : c = (char)(val / div);
688 [ # # ]: 0 : if (c || started) {
689 : 0 : rdl->write_char(rdl, (char)(c+'0'));
690 : : started = 1;
691 : : }
692 : 0 : val %= div;
693 : 0 : div /= 10;
694 : : }
695 : : }
696 : 0 : }
|