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