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 : 151 : 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 [ + + + + ]: 151 : if (!rdl || !write_char || !validate || !complete)
47 : : return -EINVAL;
48 : : memset(rdl, 0, sizeof(*rdl));
49 : 148 : rdl->validate = validate;
50 : 148 : rdl->complete = complete;
51 : 148 : rdl->write_char = write_char;
52 : 148 : rdl->opaque = opaque;
53 : 148 : rdl->status = RDLINE_INIT;
54 : 148 : 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 : 294 : rdline_newline(struct rdline *rdl, const char *prompt)
84 : : {
85 : : unsigned int i;
86 : :
87 [ + + ]: 294 : if (!rdl || !prompt)
88 : : return;
89 : :
90 : 292 : vt100_init(&rdl->vt100);
91 : 292 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
92 : 292 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
93 : :
94 : 292 : rdl->prompt_size = strnlen(prompt, RDLINE_PROMPT_SIZE-1);
95 [ + - ]: 292 : if (prompt != rdl->prompt)
96 : 292 : memcpy(rdl->prompt, prompt, rdl->prompt_size);
97 : 292 : rdl->prompt[RDLINE_PROMPT_SIZE-1] = '\0';
98 : :
99 [ + + ]: 1753 : for (i=0 ; i<rdl->prompt_size ; i++)
100 : 1461 : rdl->write_char(rdl, rdl->prompt[i]);
101 : 292 : rdl->status = RDLINE_RUNNING;
102 : :
103 : 292 : 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 : 290 : rdline_get_buffer(struct rdline *rdl)
151 : : {
152 [ + + ]: 290 : if (!rdl)
153 : : return NULL;
154 : : unsigned int len_l, len_r;
155 : 289 : cirbuf_align_left(&rdl->left);
156 : 289 : cirbuf_align_left(&rdl->right);
157 : :
158 : 289 : len_l = CIRBUF_GET_LEN(&rdl->left);
159 : 289 : len_r = CIRBUF_GET_LEN(&rdl->right);
160 : 289 : memcpy(rdl->left_buf+len_l, rdl->right_buf, len_r);
161 : :
162 : 289 : rdl->left_buf[len_l + len_r] = '\n';
163 : 289 : rdl->left_buf[len_l + len_r + 1] = '\0';
164 : 289 : return rdl->left_buf;
165 : : }
166 : :
167 : : static void
168 : 2675 : display_right_buffer(struct rdline *rdl, int force)
169 : : {
170 : : unsigned int i;
171 : : char tmp;
172 : :
173 [ + - - + ]: 2675 : 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 : 2821 : rdline_char_in(struct rdline *rdl, char c)
221 : : {
222 : : unsigned int i;
223 : : int cmd;
224 : : char tmp;
225 : : char *buf;
226 : :
227 [ + + ]: 2821 : if (!rdl)
228 : : return -EINVAL;
229 : :
230 [ + - ]: 2820 : if (rdl->status == RDLINE_EXITED)
231 : : return RDLINE_RES_EXITED;
232 [ + - ]: 2820 : if (rdl->status != RDLINE_RUNNING)
233 : : return RDLINE_RES_NOT_RUNNING;
234 : :
235 : 2820 : cmd = vt100_parser(&rdl->vt100, c);
236 [ + - ]: 2820 : if (cmd == -2)
237 : : return RDLINE_RES_SUCCESS;
238 : :
239 [ + + ]: 2820 : if (cmd >= 0) {
240 [ - - - - : 145 : 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 : rdl->write_char(rdl, ' ');
448 [ # # ]: 0 : for (i=0 ; tmp_buf[i] ; i++)
449 : 0 : rdl->write_char(rdl, tmp_buf[i]);
450 : : rdline_puts(rdl, "\r\n");
451 : 0 : ret = rdl->complete(rdl, rdl->left_buf,
452 : : tmp_buf, sizeof(tmp_buf),
453 : : &complete_state);
454 : : }
455 : :
456 : 0 : rdline_redisplay(rdl);
457 : : }
458 : 0 : return RDLINE_RES_COMPLETE;
459 : :
460 : : /* complete buffer */
461 : 145 : case CMDLINE_KEY_RETURN:
462 : : case CMDLINE_KEY_RETURN2:
463 : 145 : rdline_get_buffer(rdl);
464 : 145 : rdl->status = RDLINE_INIT;
465 : : rdline_puts(rdl, "\r\n");
466 [ - + ]: 145 : if (rdl->history_cur_line != -1)
467 : 0 : rdline_remove_first_history_item(rdl);
468 : :
469 [ + - ]: 145 : if (rdl->validate)
470 : 145 : rdl->validate(rdl, rdl->left_buf, CIRBUF_GET_LEN(&rdl->left)+2);
471 : : /* user may have stopped rdline */
472 [ + + ]: 145 : if (rdl->status == RDLINE_EXITED)
473 : : return RDLINE_RES_EXITED;
474 : 144 : return RDLINE_RES_VALIDATED;
475 : :
476 : : /* previous element in history */
477 : 0 : case CMDLINE_KEY_UP_ARR:
478 : : case CMDLINE_KEY_CTRL_P:
479 [ # # ]: 0 : if (rdl->history_cur_line == 0) {
480 : 0 : rdline_remove_first_history_item(rdl);
481 : : }
482 [ # # ]: 0 : if (rdl->history_cur_line <= 0) {
483 : 0 : rdline_add_history(rdl, rdline_get_buffer(rdl));
484 : 0 : rdl->history_cur_line = 0;
485 : : }
486 : :
487 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line + 1);
488 [ # # ]: 0 : if (!buf)
489 : : break;
490 : :
491 : 0 : rdl->history_cur_line ++;
492 : 0 : vt100_init(&rdl->vt100);
493 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
494 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
495 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
496 : 0 : rdline_redisplay(rdl);
497 : 0 : break;
498 : :
499 : : /* next element in history */
500 : 0 : case CMDLINE_KEY_DOWN_ARR:
501 : : case CMDLINE_KEY_CTRL_N:
502 [ # # ]: 0 : if (rdl->history_cur_line - 1 < 0)
503 : : break;
504 : :
505 : 0 : rdl->history_cur_line --;
506 : 0 : buf = rdline_get_history_item(rdl, rdl->history_cur_line);
507 [ # # ]: 0 : if (!buf)
508 : : break;
509 : 0 : vt100_init(&rdl->vt100);
510 : 0 : cirbuf_init(&rdl->left, rdl->left_buf, 0, RDLINE_BUF_SIZE);
511 : 0 : cirbuf_init(&rdl->right, rdl->right_buf, 0, RDLINE_BUF_SIZE);
512 : 0 : cirbuf_add_buf_tail(&rdl->left, buf, strnlen(buf, RDLINE_BUF_SIZE));
513 : 0 : rdline_redisplay(rdl);
514 : :
515 : 0 : break;
516 : :
517 : :
518 : : default:
519 : : break;
520 : : }
521 : :
522 : 0 : return RDLINE_RES_SUCCESS;
523 : : }
524 : :
525 [ + - ]: 2675 : if (!isprint((int)c))
526 : : return RDLINE_RES_SUCCESS;
527 : :
528 : : /* standard chars */
529 [ + - ]: 2675 : if (CIRBUF_GET_LEN(&rdl->left) + CIRBUF_GET_LEN(&rdl->right) >= RDLINE_BUF_SIZE)
530 : : return RDLINE_RES_SUCCESS;
531 : :
532 [ + - ]: 2675 : if (cirbuf_add_tail_safe(&rdl->left, c))
533 : : return RDLINE_RES_SUCCESS;
534 : :
535 : 2675 : rdl->write_char(rdl, c);
536 : 2675 : display_right_buffer(rdl, 0);
537 : :
538 : 2675 : return RDLINE_RES_SUCCESS;
539 : : }
540 : :
541 : :
542 : : /* HISTORY */
543 : :
544 : : static void
545 : 0 : rdline_remove_old_history_item(struct rdline * rdl)
546 : : {
547 : : char tmp;
548 : :
549 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
550 : 0 : tmp = cirbuf_get_head(&rdl->history);
551 : 0 : cirbuf_del_head(&rdl->history);
552 [ # # ]: 0 : if (!tmp)
553 : : break;
554 : : }
555 : 0 : }
556 : :
557 : : static void
558 : 0 : rdline_remove_first_history_item(struct rdline * rdl)
559 : : {
560 : : char tmp;
561 : :
562 [ # # ]: 0 : if ( CIRBUF_IS_EMPTY(&rdl->history) ) {
563 : : return;
564 : : }
565 : : else {
566 : 0 : cirbuf_del_tail(&rdl->history);
567 : : }
568 : :
569 [ # # ]: 0 : while (! CIRBUF_IS_EMPTY(&rdl->history) ) {
570 : 0 : tmp = cirbuf_get_tail(&rdl->history);
571 [ # # ]: 0 : if (!tmp)
572 : : break;
573 : 0 : cirbuf_del_tail(&rdl->history);
574 : : }
575 : : }
576 : :
577 : : static unsigned int
578 : : rdline_get_history_size(struct rdline * rdl)
579 : : {
580 : : unsigned int i, tmp, ret=0;
581 : :
582 [ - + ]: 144 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
583 [ # # ]: 0 : if (tmp == 0)
584 : 0 : ret ++;
585 : : }
586 : :
587 : : return ret;
588 : : }
589 : :
590 : : RTE_EXPORT_SYMBOL(rdline_get_history_item)
591 : : char *
592 : 145 : rdline_get_history_item(struct rdline * rdl, unsigned int idx)
593 : : {
594 : : unsigned int len, i, tmp;
595 : :
596 [ + + ]: 145 : if (!rdl)
597 : : return NULL;
598 : :
599 : : len = rdline_get_history_size(rdl);
600 [ - + ]: 144 : if ( idx >= len ) {
601 : : return NULL;
602 : : }
603 : :
604 : 0 : cirbuf_align_left(&rdl->history);
605 : :
606 [ # # ]: 0 : CIRBUF_FOREACH(&rdl->history, i, tmp) {
607 [ # # ]: 0 : if ( idx == len - 1) {
608 : 0 : return rdl->history_buf + i;
609 : : }
610 [ # # ]: 0 : if (tmp == 0)
611 : : len --;
612 : : }
613 : :
614 : : return NULL;
615 : : }
616 : :
617 : : RTE_EXPORT_SYMBOL(rdline_get_history_buffer_size)
618 : : size_t
619 : 1 : rdline_get_history_buffer_size(struct rdline *rdl)
620 : : {
621 : 1 : return sizeof(rdl->history_buf);
622 : : }
623 : :
624 : : RTE_EXPORT_SYMBOL(rdline_get_opaque)
625 : : void *
626 : 1 : rdline_get_opaque(struct rdline *rdl)
627 : : {
628 [ - + ]: 1 : return rdl != NULL ? rdl->opaque : NULL;
629 : : }
630 : :
631 : : RTE_EXPORT_SYMBOL(rdline_add_history)
632 : : int
633 : 146 : rdline_add_history(struct rdline * rdl, const char * buf)
634 : : {
635 : : unsigned int len, i;
636 : :
637 [ + + ]: 146 : if (!rdl || !buf)
638 : : return -EINVAL;
639 : :
640 : 144 : len = strnlen(buf, RDLINE_BUF_SIZE);
641 [ + - ]: 2815 : for (i=0; i<len ; i++) {
642 [ + + ]: 2815 : if (buf[i] == '\n') {
643 : : len = i;
644 : : break;
645 : : }
646 : : }
647 : :
648 [ + - ]: 144 : if ( len >= RDLINE_HISTORY_BUF_SIZE )
649 : : return -1;
650 : :
651 [ - + ]: 144 : while ( len >= CIRBUF_GET_FREELEN(&rdl->history) ) {
652 : 0 : rdline_remove_old_history_item(rdl);
653 : : }
654 : :
655 : 144 : cirbuf_add_buf_tail(&rdl->history, buf, len);
656 : 144 : cirbuf_add_tail(&rdl->history, 0);
657 : :
658 : 144 : return 0;
659 : : }
660 : :
661 : : RTE_EXPORT_SYMBOL(rdline_clear_history)
662 : : void
663 : 1 : rdline_clear_history(struct rdline * rdl)
664 : : {
665 [ - + ]: 1 : if (!rdl)
666 : : return;
667 : 0 : cirbuf_init(&rdl->history, rdl->history_buf, 0, RDLINE_HISTORY_BUF_SIZE);
668 : : }
669 : :
670 : :
671 : : /* STATIC USEFUL FUNCS */
672 : :
673 : : static void
674 : : rdline_puts(struct rdline * rdl, const char * buf)
675 : : {
676 : : char c;
677 [ - - - - : 435 : while ( (c = *(buf++)) != '\0' ) {
- - - - -
- - - - -
- - - - -
- - - - -
- - + + -
- - - - -
- - ]
678 : 290 : rdl->write_char(rdl, c);
679 : : }
680 : : }
681 : :
682 : : /* a very very basic printf with one arg and one format 'u' */
683 : : static void
684 : 0 : rdline_miniprintf(struct rdline *rdl, const char * buf, unsigned int val)
685 : : {
686 : : char c, started=0, div=100;
687 : :
688 [ # # ]: 0 : while ( (c=*(buf++)) ) {
689 [ # # ]: 0 : if (c != '%') {
690 : 0 : rdl->write_char(rdl, c);
691 : 0 : continue;
692 : : }
693 : 0 : c = *(buf++);
694 [ # # ]: 0 : if (c != 'u') {
695 : 0 : rdl->write_char(rdl, '%');
696 : 0 : rdl->write_char(rdl, c);
697 : 0 : continue;
698 : : }
699 : : /* val is never more than 255 */
700 [ # # ]: 0 : while (div) {
701 : 0 : c = (char)(val / div);
702 [ # # ]: 0 : if (c || started) {
703 : 0 : rdl->write_char(rdl, (char)(c+'0'));
704 : : started = 1;
705 : : }
706 : 0 : val %= div;
707 : 0 : div /= 10;
708 : : }
709 : : }
710 : 0 : }
|