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 : 157 : 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 [ + + + + ]: 157 : if (!rdl || !write_char || !validate || !complete)
47 : : return -EINVAL;
48 : : memset(rdl, 0, sizeof(*rdl));
49 : 154 : rdl->validate = validate;
50 : 154 : rdl->complete = complete;
51 : 154 : rdl->write_char = write_char;
52 : 154 : rdl->opaque = opaque;
53 : 154 : rdl->status = RDLINE_INIT;
54 : 154 : 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 : 306 : rdline_newline(struct rdline *rdl, const char *prompt)
84 : : {
85 : : unsigned int i;
86 : :
87 [ + + ]: 306 : if (!rdl || !prompt)
88 : : return;
89 : :
90 : 304 : vt100_init(&rdl->vt100);
91 : 304 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
92 : 304 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
93 : :
94 : 304 : rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1);
95 [ + - ]: 304 : if (prompt != rdl->prompt)
96 : 304 : memcpy(rdl->prompt, prompt, rdl->prompt_size);
97 : 304 : rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0';
98 : :
99 [ + + ]: 1825 : for (i=0 ; i<rdl->prompt_size ; i++)
100 : 1521 : rdl->write_char(rdl, rdl->prompt[i]);
101 : 304 : rdl->status = RDLINE_RUNNING;
102 : :
103 : 304 : 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 : 302 : rdline_get_buffer(struct rdline *rdl)
151 : : {
152 [ + + ]: 302 : if (!rdl)
153 : : return NULL;
154 : : unsigned int len_l, len_r;
155 : 301 : cirbuf_align_left(&rdl->left);
156 : 301 : cirbuf_align_left(&rdl->right);
157 : :
158 : 301 : len_l = CIRBUF_GET_LEN(&rdl->left);
159 : 301 : len_r = CIRBUF_GET_LEN(&rdl->right);
160 : 301 : memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r);
161 : :
162 : 301 : rdl->left_buf[len_l + len_r] = '\n';
163 : 301 : rdl->left_buf[len_l + len_r + 1] = '\0';
164 : 301 : return rdl->left_buf;
165 : : }
166 : :
167 : : static void
168 : 2829 : display_right_buffer(struct rdline *rdl, int force)
169 : : {
170 : : unsigned int i;
171 : : char tmp;
172 : :
173 [ + - - + ]: 2829 : 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 : : static void
186 : 0 : rdline_reprint(struct rdline *rdl)
187 : : {
188 : : unsigned int i;
189 : : char tmp;
190 : :
191 [ # # ]: 0 : for (i = 0; i < rdl->prompt_size; i++)
192 : 0 : rdl->write_char(rdl, rdl->prompt[i]);
193 : :
194 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->left, i, tmp) {
195 : 0 : rdl->write_char(rdl, tmp);
196 : : }
197 : 0 : display_right_buffer(rdl, 1);
198 : 0 : }
199 : :
200 : : RTE_EXPORT_SYMBOL(rdline_redisplay)
201 : : void
202 : 1 : rdline_redisplay(struct rdline *rdl)
203 : : {
204 [ - + ]: 1 : if (!rdl)
205 : : return;
206 : : rdline_puts(rdl, vt100_home);
207 : 0 : rdline_reprint(rdl);
208 : : }
209 : :
210 : : static void
211 : 0 : rdline_clear_screen(struct rdline *rdl)
212 : : {
213 : : rdline_puts(rdl, vt100_clear_screen);
214 : : rdline_puts(rdl, vt100_homecursor);
215 : 0 : rdline_reprint(rdl);
216 : 0 : }
217 : :
218 : : RTE_EXPORT_SYMBOL(rdline_char_in)
219 : : int
220 : 2981 : rdline_char_in(struct rdline *rdl, char c)
221 : : {
222 : : unsigned int i;
223 : : int cmd;
224 : : char tmp;
225 : : char *buf;
226 : :
227 [ + + ]: 2981 : if (!rdl)
228 : : return -EINVAL;
229 : :
230 [ + - ]: 2980 : if (rdl->status == RDLINE_EXITED)
231 : : return RDLINE_RES_EXITED;
232 [ + - ]: 2980 : if (rdl->status != RDLINE_RUNNING)
233 : : return RDLINE_RES_NOT_RUNNING;
234 : :
235 : 2980 : cmd = vt100_parser(&rdl->vt100, c);
236 [ + - ]: 2980 : if (cmd == -2)
237 : : return RDLINE_RES_SUCCESS;
238 : :
239 [ + + ]: 2980 : if (cmd >= 0) {
240 [ - - - - : 151 : switch (cmd) {
- - - - -
- - - - -
- + - -
- ]
241 : : /* move caret 1 char to the left */
242 : 0 : case CMDLINE_KEY_CTRL_B:
243 : : case CMDLINE_KEY_LEFT_ARR:
244 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->left))
245 : : break;
246 : 0 : tmp = cirbuf_get_tail(&rdl->left);
247 : 0 : cirbuf_del_tail(&rdl->left);
248 : 0 : cirbuf_add_head(&rdl->right, tmp);
249 : : rdline_puts(rdl, vt100_left_arr);
250 : : break;
251 : :
252 : : /* move caret 1 char to the right */
253 : 0 : case CMDLINE_KEY_CTRL_F:
254 : : case CMDLINE_KEY_RIGHT_ARR:
255 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->right))
256 : : break;
257 : 0 : tmp = cirbuf_get_head(&rdl->right);
258 : 0 : cirbuf_del_head(&rdl->right);
259 : 0 : cirbuf_add_tail(&rdl->left, tmp);
260 : : rdline_puts(rdl, vt100_right_arr);
261 : : break;
262 : :
263 : : /* move caret 1 word to the left */
264 : : /* keyboard equivalent: Alt+B */
265 : : case CMDLINE_KEY_WLEFT:
266 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) &&
267 [ # # ]: 0 : (tmp = cirbuf_get_tail(&rdl->left)) &&
268 [ # # ]: 0 : isblank2(tmp)) {
269 : : rdline_puts(rdl, vt100_left_arr);
270 : 0 : cirbuf_del_tail(&rdl->left);
271 : 0 : cirbuf_add_head(&rdl->right, tmp);
272 : : }
273 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) &&
274 [ # # ]: 0 : (tmp = cirbuf_get_tail(&rdl->left)) &&
275 [ # # ]: 0 : !isblank2(tmp)) {
276 : : rdline_puts(rdl, vt100_left_arr);
277 : 0 : cirbuf_del_tail(&rdl->left);
278 : 0 : cirbuf_add_head(&rdl->right, tmp);
279 : : }
280 : : break;
281 : :
282 : : /* move caret 1 word to the right */
283 : : /* keyboard equivalent: Alt+F */
284 : : case CMDLINE_KEY_WRIGHT:
285 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) &&
286 [ # # ]: 0 : (tmp = cirbuf_get_head(&rdl->right)) &&
287 [ # # ]: 0 : isblank2(tmp)) {
288 : : rdline_puts(rdl, vt100_right_arr);
289 : 0 : cirbuf_del_head(&rdl->right);
290 : 0 : cirbuf_add_tail(&rdl->left, tmp);
291 : : }
292 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) &&
293 [ # # ]: 0 : (tmp = cirbuf_get_head(&rdl->right)) &&
294 [ # # ]: 0 : !isblank2(tmp)) {
295 : : rdline_puts(rdl, vt100_right_arr);
296 : 0 : cirbuf_del_head(&rdl->right);
297 : 0 : cirbuf_add_tail(&rdl->left, tmp);
298 : : }
299 : : break;
300 : :
301 : : /* move caret to the left */
302 : 0 : case CMDLINE_KEY_CTRL_A:
303 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->left))
304 : : break;
305 : 0 : rdline_miniprintf(rdl, vt100_multi_left,
306 : : CIRBUF_GET_LEN(&rdl->left));
307 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left)) {
308 : 0 : tmp = cirbuf_get_tail(&rdl->left);
309 : 0 : cirbuf_del_tail(&rdl->left);
310 : 0 : cirbuf_add_head(&rdl->right, tmp);
311 : : }
312 : : break;
313 : :
314 : : /* move caret to the right */
315 : 0 : case CMDLINE_KEY_CTRL_E:
316 [ # # ]: 0 : if (CIRBUF_IS_EMPTY(&rdl->right))
317 : : break;
318 : 0 : rdline_miniprintf(rdl, vt100_multi_right,
319 : : CIRBUF_GET_LEN(&rdl->right));
320 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right)) {
321 : 0 : tmp = cirbuf_get_head(&rdl->right);
322 : 0 : cirbuf_del_head(&rdl->right);
323 : 0 : cirbuf_add_tail(&rdl->left, tmp);
324 : : }
325 : : break;
326 : :
327 : : /* delete 1 char from the left */
328 : 0 : case CMDLINE_KEY_BKSPACE:
329 : : case CMDLINE_KEY_BKSPACE2:
330 [ # # ]: 0 : if(!cirbuf_del_tail_safe(&rdl->left)) {
331 : : rdline_puts(rdl, vt100_bs);
332 : 0 : display_right_buffer(rdl, 1);
333 : : }
334 : : break;
335 : :
336 : : /* delete 1 char from the right */
337 : 0 : case CMDLINE_KEY_SUPPR:
338 : : case CMDLINE_KEY_CTRL_D:
339 [ # # ]: 0 : if (cmd == CMDLINE_KEY_CTRL_D &&
340 [ # # ]: 0 : CIRBUF_IS_EMPTY(&rdl->left) &&
341 [ # # ]: 0 : CIRBUF_IS_EMPTY(&rdl->right)) {
342 : : return RDLINE_RES_EOF;
343 : : }
344 [ # # ]: 0 : if (!cirbuf_del_head_safe(&rdl->right)) {
345 : 0 : display_right_buffer(rdl, 1);
346 : : }
347 : : break;
348 : :
349 : : /* delete 1 word from the left */
350 : : case CMDLINE_KEY_META_BKSPACE:
351 : : case CMDLINE_KEY_CTRL_W:
352 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) && isblank2(cirbuf_get_tail(&rdl->left))) {
353 : : rdline_puts(rdl, vt100_bs);
354 : 0 : cirbuf_del_tail(&rdl->left);
355 : : }
356 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->left) && !isblank2(cirbuf_get_tail(&rdl->left))) {
357 : : rdline_puts(rdl, vt100_bs);
358 : 0 : cirbuf_del_tail(&rdl->left);
359 : : }
360 : 0 : display_right_buffer(rdl, 1);
361 : 0 : break;
362 : :
363 : : /* delete 1 word from the right */
364 : : case CMDLINE_KEY_META_D:
365 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) && isblank2(cirbuf_get_head(&rdl->right)))
366 : 0 : cirbuf_del_head(&rdl->right);
367 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->right) && !isblank2(cirbuf_get_head(&rdl->right)))
368 : 0 : cirbuf_del_head(&rdl->right);
369 : 0 : display_right_buffer(rdl, 1);
370 : 0 : break;
371 : :
372 : : /* set kill buffer to contents on the right side of caret */
373 : 0 : case CMDLINE_KEY_CTRL_K:
374 : 0 : cirbuf_get_buf_head(&rdl->right, rdl->kill_buf, RDLINE_BUF_SIZE);
375 : 0 : rdl->kill_size = CIRBUF_GET_LEN(&rdl->right);
376 : 0 : cirbuf_del_buf_head(&rdl->right, rdl->kill_size);
377 : : rdline_puts(rdl, vt100_clear_right);
378 : : break;
379 : :
380 : : /* paste contents of kill buffer to the left side of caret */
381 : : case CMDLINE_KEY_CTRL_Y:
382 : : i=0;
383 : 0 : while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
384 [ # # ]: 0 : RDLINE_BUF_SIZE &&
385 [ # # ]: 0 : i < rdl->kill_size) {
386 : 0 : cirbuf_add_tail(&rdl->left, rdl->kill_buf[i]);
387 : 0 : rdl->write_char(rdl, rdl->kill_buf[i]);
388 : 0 : i++;
389 : : }
390 : 0 : display_right_buffer(rdl, 0);
391 : 0 : break;
392 : :
393 : : /* clear and newline */
394 : : case CMDLINE_KEY_CTRL_C:
395 : : rdline_puts(rdl, "\r\n");
396 : 0 : rdline_newline(rdl, rdl->prompt);
397 : 0 : break;
398 : :
399 : : /* clear screen (helps when prompt is lost in other output) */
400 : 0 : case CMDLINE_KEY_CTRL_L:
401 : 0 : rdline_clear_screen(rdl);
402 : 0 : break;
403 : :
404 : : /* autocomplete */
405 : 0 : case CMDLINE_KEY_TAB:
406 : : case CMDLINE_KEY_HELP:
407 : 0 : cirbuf_align_left(&rdl->left);
408 : 0 : rdl->left_buf[CIRBUF_GET_LEN(&rdl->left)] = '\0';
409 [ # # ]: 0 : if (rdl->complete) {
410 : : char tmp_buf[BUFSIZ];
411 : : int complete_state;
412 : : int ret;
413 : : unsigned int tmp_size;
414 : :
415 [ # # ]: 0 : if (cmd == CMDLINE_KEY_TAB)
416 : 0 : complete_state = 0;
417 : : else
418 : 0 : complete_state = -1;
419 : :
420 : : /* see in parse.h for help on complete() */
421 : 0 : ret = rdl->complete(rdl, rdl->left_buf,
422 : : tmp_buf, sizeof(tmp_buf),
423 : : &complete_state);
424 : : /* no completion or error */
425 [ # # ]: 0 : if (ret <= 0) {
426 : 0 : return RDLINE_RES_COMPLETE;
427 : : }
428 : :
429 : 0 : tmp_size = strnlen(tmp_buf, sizeof(tmp_buf));
430 : : /* add chars */
431 [ # # ]: 0 : if (ret == RDLINE_RES_COMPLETE) {
432 : : i=0;
433 : 0 : while(CIRBUF_GET_LEN(&rdl->right) + CIRBUF_GET_LEN(&rdl->left) <
434 [ # # # # ]: 0 : RDLINE_BUF_SIZE &&
435 : : i < tmp_size) {
436 : 0 : cirbuf_add_tail(&rdl->left, tmp_buf[i]);
437 : 0 : rdl->write_char(rdl, tmp_buf[i]);
438 : 0 : i++;
439 : : }
440 : 0 : display_right_buffer(rdl, 1);
441 : 0 : return RDLINE_RES_COMPLETE; /* ?? */
442 : : }
443 : :
444 : : /* choice */
445 : : rdline_puts(rdl, "\r\n");
446 [ # # ]: 0 : while (ret) {
447 : 0 : tmp_size = strnlen(tmp_buf, sizeof(tmp_buf));
448 : 0 : rdl->write_char(rdl, ' ');
449 [ # # ]: 0 : for (i = 0; i < tmp_size; i++)
450 : 0 : rdl->write_char(rdl, tmp_buf[i]);
451 : : rdline_puts(rdl, "\r\n");
452 : 0 : ret = rdl->complete(rdl, rdl->left_buf,
453 : : tmp_buf, sizeof(tmp_buf),
454 : : &complete_state);
455 : : }
456 : :
457 : 0 : rdline_redisplay(rdl);
458 : : }
459 : 0 : return RDLINE_RES_COMPLETE;
460 : :
461 : : /* complete buffer */
462 : 151 : case CMDLINE_KEY_RETURN:
463 : : case CMDLINE_KEY_RETURN2:
464 : 151 : rdline_get_buffer(rdl);
465 : 151 : rdl->status = RDLINE_INIT;
466 : : rdline_puts(rdl, "\r\n");
467 [ - + ]: 151 : if (rdl->history_cur_line != -1)
468 : 0 : rdline_remove_first_history_item(rdl);
469 : :
470 [ + - ]: 151 : if (rdl->validate)
471 : 151 : rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2);
472 : : /* user may have stopped rdline */
473 [ + + ]: 151 : if (rdl->status == RDLINE_EXITED)
474 : : return RDLINE_RES_EXITED;
475 : 150 : return RDLINE_RES_VALIDATED;
476 : :
477 : : /* previous element in history */
478 : 0 : case CMDLINE_KEY_UP_ARR:
479 : : case CMDLINE_KEY_CTRL_P:
480 [ # # ]: 0 : if (rdl->history_cur_line == 0) {
481 : 0 : rdline_remove_first_history_item(rdl);
482 : : }
483 [ # # ]: 0 : if (rdl->history_cur_line <= 0) {
484 : 0 : rdline_add_history(rdl, rdline_get_buffer(rdl));
485 : 0 : rdl->history_cur_line = 0;
486 : : }
487 : :
488 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1);
489 [ # # ]: 0 : if (!buf)
490 : : break;
491 : :
492 : 0 : rdl->history_cur_line ++;
493 : 0 : vt100_init(&rdl->vt100);
494 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
495 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
496 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
497 : 0 : rdline_redisplay(rdl);
498 : 0 : break;
499 : :
500 : : /* next element in history */
501 : 0 : case CMDLINE_KEY_DOWN_ARR:
502 : : case CMDLINE_KEY_CTRL_N:
503 [ # # ]: 0 : if (rdl->history_cur_line - 1 < 0)
504 : : break;
505 : :
506 : 0 : rdl->history_cur_line --;
507 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line);
508 [ # # ]: 0 : if (!buf)
509 : : break;
510 : 0 : vt100_init(&rdl->vt100);
511 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
512 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
513 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
514 : 0 : rdline_redisplay(rdl);
515 : :
516 : 0 : break;
517 : :
518 : :
519 : : default:
520 : : break;
521 : : }
522 : :
523 : 0 : return RDLINE_RES_SUCCESS;
524 : : }
525 : :
526 [ + - ]: 2829 : if (!isprint((int)c))
527 : : return RDLINE_RES_SUCCESS;
528 : :
529 : : /* standard chars */
530 [ + - ]: 2829 : if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE)
531 : : return RDLINE_RES_SUCCESS;
532 : :
533 [ + - ]: 2829 : if (cirbuf_add_tail_safe(&rdl->left, c))
534 : : return RDLINE_RES_SUCCESS;
535 : :
536 : 2829 : rdl->write_char(rdl, c);
537 : 2829 : display_right_buffer(rdl, 0);
538 : :
539 : 2829 : return RDLINE_RES_SUCCESS;
540 : : }
541 : :
542 : :
543 : : /* HISTORY */
544 : :
545 : : static void
546 : 0 : rdline_remove_old_history_item(struct rdline * rdl)
547 : : {
548 : : char tmp;
549 : :
550 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
551 : 0 : tmp = cirbuf_get_head(&rdl->history);
552 : 0 : cirbuf_del_head(&rdl->history);
553 [ # # ]: 0 : if (!tmp)
554 : : break;
555 : : }
556 : 0 : }
557 : :
558 : : static void
559 : 0 : rdline_remove_first_history_item(struct rdline * rdl)
560 : : {
561 : : char tmp;
562 : :
563 [ # # ]: 0 : if ( CIRBUF_IS_EMPTY(&rdl->history) ) {
564 : : return;
565 : : }
566 : : else {
567 : 0 : cirbuf_del_tail(&rdl->history);
568 : : }
569 : :
570 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
571 : 0 : tmp = cirbuf_get_tail(&rdl->history);
572 [ # # ]: 0 : if (!tmp)
573 : : break;
574 : 0 : cirbuf_del_tail(&rdl->history);
575 : : }
576 : : }
577 : :
578 : : static unsigned int
579 : : rdline_get_history_size(struct rdline * rdl)
580 : : {
581 : : unsigned int i, tmp, ret=0;
582 : :
583 [ - + ]: 150 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
584 [ # # ]: 0 : if (tmp == 0)
585 : 0 : ret ++;
586 : : }
587 : :
588 : : return ret;
589 : : }
590 : :
591 : : RTE_EXPORT_SYMBOL(rdline_get_history_item)
592 : : char *
593 : 151 : rdline_get_history_item(struct rdline * rdl, unsigned int idx)
594 : : {
595 : : unsigned int len, i, tmp;
596 : :
597 [ + + ]: 151 : if (!rdl)
598 : : return NULL;
599 : :
600 : : len = rdline_get_history_size(rdl);
601 [ - + ]: 150 : if ( idx >= len ) {
602 : : return NULL;
603 : : }
604 : :
605 : 0 : cirbuf_align_left(&rdl->history);
606 : :
607 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
608 [ # # ]: 0 : if ( idx == len - 1) {
609 : 0 : return rdl->history_buf + i;
610 : : }
611 [ # # ]: 0 : if (tmp == 0)
612 : : len --;
613 : : }
614 : :
615 : : return NULL;
616 : : }
617 : :
618 : : RTE_EXPORT_SYMBOL(rdline_get_history_buffer_size)
619 : : size_t
620 : 1 : rdline_get_history_buffer_size(struct rdline *rdl)
621 : : {
622 [ + - ]: 1 : if (!rdl)
623 : 1 : return 0;
624 : :
625 : : return sizeof(rdl->history_buf);
626 : : }
627 : :
628 : : RTE_EXPORT_SYMBOL(rdline_get_opaque)
629 : : void *
630 : 1 : rdline_get_opaque(struct rdline *rdl)
631 : : {
632 [ - + ]: 1 : return rdl != NULL ? rdl->opaque : NULL;
633 : : }
634 : :
635 : : RTE_EXPORT_SYMBOL(rdline_add_history)
636 : : int
637 : 152 : rdline_add_history(struct rdline * rdl, const char * buf)
638 : : {
639 : : unsigned int len, i;
640 : :
641 [ + + ]: 152 : if (!rdl || !buf)
642 : : return -EINVAL;
643 : :
644 : 150 : len = strnlen(buf, RDLINE_BUF_SIZE);
645 [ + - ]: 2975 : for (i=0; i<len ; i++) {
646 [ + + ]: 2975 : if (buf[i] == '\n') {
647 : : len = i;
648 : : break;
649 : : }
650 : : }
651 : :
652 [ + - ]: 150 : if ( len >= RDLINE_HISTORY_BUF_SIZE )
653 : : return -1;
654 : :
655 [ - + ]: 150 : while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) {
656 : 0 : rdline_remove_old_history_item(rdl);
657 : : }
658 : :
659 : 150 : cirbuf_add_buf_tail(&rdl->history, buf, len);
660 : 150 : cirbuf_add_tail(&rdl->history, 0);
661 : :
662 : 150 : return 0;
663 : : }
664 : :
665 : : RTE_EXPORT_SYMBOL(rdline_clear_history)
666 : : void
667 : 1 : rdline_clear_history(struct rdline * rdl)
668 : : {
669 [ - + ]: 1 : if (!rdl)
670 : : return;
671 : 0 : cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE);
672 : : }
673 : :
674 : :
675 : : /* STATIC USEFUL FUNCS */
676 : :
677 : : static void
678 : : rdline_puts(struct rdline * rdl, const char * buf)
679 : : {
680 : : char c;
681 [ - - - - : 453 : while ( (c = *(buf++)) != '\0' ) {
- - - - -
- - - - -
- - - - -
- - - - -
- - + + -
- - - - -
- - ]
682 : 302 : rdl->write_char(rdl, c);
683 : : }
684 : : }
685 : :
686 : : /* a very very basic printf with one arg and one format 'u' */
687 : : static void
688 : 0 : rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val)
689 : : {
690 : : char c, started=0, div=100;
691 : :
692 [ # # ]: 0 : while ( (c=*(buf++)) ) {
693 [ # # ]: 0 : if (c != '%') {
694 : 0 : rdl->write_char(rdl, c);
695 : 0 : continue;
696 : : }
697 : 0 : c = *(buf++);
698 [ # # ]: 0 : if (c != 'u') {
699 : 0 : rdl->write_char(rdl, '%');
700 : 0 : rdl->write_char(rdl, c);
701 : 0 : continue;
702 : : }
703 : : /* val is never more than 255 */
704 [ # # ]: 0 : while (div) {
705 : 0 : c = (char)(val / div);
706 [ # # ]: 0 : if (c || started) {
707 : 0 : rdl->write_char(rdl, (char)(c+'0'));
708 : : started = 1;
709 : : }
710 : 0 : val %= div;
711 : 0 : div /= 10;
712 : : }
713 : : }
714 : 0 : }
|