OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [io.c] - Blame information for rev 810

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      io.c
4
//
5
//      RedBoot I/O support
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas,hmt,jlarmour
44
// Date:         2000-07-14
45
// Purpose:      
46
// Description:  
47
//              
48
// This code is part of RedBoot (tm).
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include "redboot.h"
55
 
56
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
57
// GDB interface functions
58
extern void ungetDebugChar(char c);
59
#endif
60
 
61
static void
62
do_channel(int argc, char *argv[]);
63
 
64
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
65
RedBoot_cmd("channel",
66
            "Display/switch console channel",
67
            "[-1|<channel number>]",
68
            do_channel
69
    );
70
#else
71
RedBoot_cmd("channel",
72
            "Display/switch console channel",
73
            "[<channel number>]",
74
            do_channel
75
    );
76
#endif
77
 
78
static void
79
do_channel(int argc, char *argv[])
80
{
81
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
82
 
83
    if (argc == 2) {
84
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
85
        if (strcmp( argv[1], "-1") == 0) {
86
            console_selected = false;
87
            console_echo = true;
88
        } else
89
#endif
90
        {
91
            unsigned long chan;
92
            if ( !parse_num( argv[1], &chan, NULL, NULL) ) {
93
                diag_printf("** Error: invalid channel '%s'\n", argv[1]);
94
            } else {
95
                if (chan < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
96
                    CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);
97
                    CYGACC_CALL_IF_SET_DEBUG_COMM(chan);
98
                    if (chan != cur)
99
                        console_echo = true;
100
                }
101
                else {
102
                    diag_printf("**Error: bad channel number '%s'\n", argv[1]);
103
                }
104
            }
105
        }
106
    }
107
    /* else display */
108
    else {
109
        diag_printf("Current console channel id: ");
110
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
111
        if (!console_selected)
112
            diag_printf("-1\n");
113
        else
114
#endif
115
            diag_printf("%d\n", cur);
116
    }
117
}
118
 
119
void
120
mon_write_char(unsigned char c)
121
{
122
    hal_virtual_comm_table_t *__chan;
123
 
124
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
125
    if (!console_selected) {
126
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
127
        int i;
128
        // Send output to all channels
129
        for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
130
            CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
131
            __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
132
            CYGACC_COMM_IF_PUTC(*__chan, c);
133
        }
134
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
135
    } else
136
#endif
137
    {
138
        __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
139
        if (__chan)
140
            CYGACC_COMM_IF_PUTC(*__chan, c);
141
        else {
142
            __chan = CYGACC_CALL_IF_DEBUG_PROCS();
143
            CYGACC_COMM_IF_PUTC(*__chan, c);
144
        }
145
    }
146
}
147
 
148
static void
149
mon_read_char(unsigned char *c)
150
{
151
    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
152
 
153
    if (__chan)
154
        *c = CYGACC_COMM_IF_GETC(*__chan);
155
    else {
156
        __chan = CYGACC_CALL_IF_DEBUG_PROCS();
157
        *c = CYGACC_COMM_IF_GETC(*__chan);
158
    }
159
}
160
 
161
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
162
static int _mon_timeout;
163
#endif
164
 
165
bool
166
mon_read_char_with_timeout(unsigned char *c)
167
{
168
    bool res = false;
169
    hal_virtual_comm_table_t *__chan;
170
 
171
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
172
    if (!console_selected) {
173
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
174
        int i, j, tot;
175
        // Try input from all channels
176
        tot = 0;
177
        while (tot < _mon_timeout) {
178
            for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++, tot++) {
179
                CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
180
                __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
181
                res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
182
                if (res) {
183
                    // Input available on this channel, make it be the console
184
                    if (*c != '\0') {
185
                        // Don't chose this unless real data have arrived
186
                        console_selected = true;
187
                        CYGACC_CALL_IF_SET_DEBUG_COMM(i);
188
                        // Disable interrupts on all channels but this one
189
                        for (j = 0;  j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  j++) {
190
                            if (i != j) {
191
                                CYGACC_CALL_IF_SET_CONSOLE_COMM(j);
192
                                __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
193
                                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
194
                            }
195
                        }
196
                        CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
197
                        return res;
198
                    }
199
                }
200
            }
201
        }
202
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
203
    } else
204
#endif
205
    {
206
        __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
207
        if (__chan)
208
            res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
209
        else {
210
            __chan = CYGACC_CALL_IF_DEBUG_PROCS();
211
            res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c);
212
        }
213
    }
214
    return res;
215
}
216
 
217
void
218
mon_set_read_char_timeout(int ms)
219
{
220
    hal_virtual_comm_table_t *__chan;
221
 
222
#ifdef CYGPKG_REDBOOT_ANY_CONSOLE
223
    if (!console_selected) {
224
        int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
225
        int i;
226
        // Set timeout to minimum on each channel; total amounts to desired value
227
        _mon_timeout = ms;
228
        ms = 1;
229
        for (i = 0;  i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;  i++) {
230
            CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
231
            if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) {
232
                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
233
            }
234
        }
235
        CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
236
    } else
237
#endif
238
    {
239
        if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) {
240
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
241
        }
242
        if ((__chan = CYGACC_CALL_IF_DEBUG_PROCS()) != 0) {
243
            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms);
244
        }
245
    }
246
}
247
 
248
//
249
// Test for ^C on the console.  CAUTION! discards all console input
250
//
251
bool
252
_rb_break(int timeout)
253
{
254
    unsigned char c;
255
    mon_set_read_char_timeout(timeout);
256
    if (mon_read_char_with_timeout(&c)) {
257
        if (c == '\x03') {  // Test for ^C
258
            return true;
259
        }
260
    }
261
    return false;
262
}
263
 
264
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
265
#define __STRINGIFY(x) #x
266
#define _STRINGIFY(x) __STRINGIFY(x)
267
#define _STARTUP_STR _STRINGIFY(CYG_HAL_STARTUP) "}"
268
 
269
//
270
// Read a character from script.
271
// Return true if script character found, false if not.
272
//
273
static int
274
getc_script(char *cp)
275
{
276
    static bool newline = true;
277
    bool skip;
278
 
279
    while (script && *script) {
280
        if (newline && *script == '{') {
281
            skip = false;
282
            ++script;
283
 
284
            // skip if it isn't for this startup type
285
            if (strncmp(script, _STARTUP_STR, strlen(_STARTUP_STR)))
286
                skip = true;
287
 
288
            // skip past "{...}"
289
            while (*script && *script++ != '}')
290
                ;
291
 
292
            // skip script line if neccessary
293
            if (skip) {
294
                while (*script && *script++ != '\n')
295
                    ;
296
            } else
297
                newline = false;
298
 
299
        } else {
300
            *cp = *script++;
301
            if (*cp == '\n') {
302
              newline = true;
303
            } else {
304
              newline = false;
305
            }
306
            return true;
307
        }
308
    }
309
    return false;
310
}
311
#endif
312
 
313
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
314
#define _CL_NUM_LINES CYGNUM_REDBOOT_CMD_LINE_EDITING       // Number of lines to keep
315
static char _cl_lines[_CL_NUM_LINES][CYGPKG_REDBOOT_MAX_CMD_LINE];
316
static int  _cl_index = -1;      // Last known command line
317
static int  _cl_max_index = -1;  // Last command in buffers
318
static int  _cl_real_index = 0;  // Virtual command index (0..N)
319
 
320
#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
321
static void expand_history(char *);
322
#endif
323
#endif
324
 
325
//
326
// Read a line of input from the user
327
// Return:
328
//        _GETS_OK: 'n' valid characters received
329
//       _GETS_GDB: '$' (GDB lead-in)
330
//   _GETS_TIMEOUT: No input before timeout
331
//     _GETS_CTRLC: ^C typed
332
//
333
// if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
334
//   Command line history support
335
//    ^P - Select previous line from history
336
//    ^N - Select next line from history
337
//    ^A - Move insertion [cursor] to start of line
338
//    ^E - Move cursor to end of line
339
//    ^B - Move cursor back [previous character]
340
//    ^F - Move cursor forward [next character]
341
// "standard" arrow keys work as well
342
//   left  ^[[D      == ^B
343
//   right ^[[C      == ^F
344
//   up    ^[[A      == ^P
345
//   down  ^[[B      == ^N
346
//   home  ^[[H/^[1~ == ^A
347
//   end   ^[[F/^[OF == ^E
348
//   del   ^[3~      == ^D
349
//
350
int
351
_rb_gets_preloaded(char *buf, int buflen, int timeout)
352
{
353
    char *ip = buf;   // Insertion point
354
    char *eol = buf;  // End of line
355
    char c;
356
    bool res = false;
357
    static char last_ch = '\0';
358
    int _timeout;
359
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
360
    int   _index = _cl_index;  // Last saved line
361
    char *xp;
362
#ifdef CYGSEM_REDBOOT_CMD_LINE_ANSI_SEQUENCES
363
    int   ansi_state = 0;      // Used to drive ANSI parser
364
    char  ansi_char = '\0';
365
#endif
366
#endif
367
 
368
    // Display current buffer data
369
    while (*eol) {
370
        mon_write_char(*eol++);
371
    }
372
    ip = eol;
373
 
374
    while (true) {
375
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
376
        if (getc_script(&c))
377
            do_idle(false);
378
        else
379
#endif
380
        if ((timeout > 0) && (eol == buf)) {
381
#define MIN_TIMEOUT 50
382
            _timeout = timeout > MIN_TIMEOUT ? MIN_TIMEOUT : timeout;
383
            mon_set_read_char_timeout(_timeout);
384
            while (timeout > 0) {
385
                res = mon_read_char_with_timeout(&c);
386
                if (res) {
387
                    // Got a character
388
                    do_idle(false);
389
                    break;
390
                }
391
                timeout -= _timeout;
392
            }
393
            if (res == false) {
394
                do_idle(true);
395
                return _GETS_TIMEOUT;  // Input timed out
396
            }
397
        } else {
398
            mon_read_char(&c);
399
        }
400
        *eol = '\0';
401
#define CTRL(c) ((c)&0x1F)
402
#ifdef CYGSEM_REDBOOT_CMD_LINE_ANSI_SEQUENCES
403
        // Special handling of ANSI keyboard sequences (arrows, etc)
404
        if (c == '\x1B') {
405
            // Leadin for ANSI keyboard sequence
406
            ansi_state = 1;
407
            continue;
408
        }
409
        switch (ansi_state) {
410
        case 0:
411
            // No ANSI sequence in progress
412
            break;
413
        case 1:
414
            // ESC seen, look for '['
415
            if (c == '[') {
416
                ansi_state = 2;
417
            } else if (c == 'O') {
418
                ansi_state = 4;
419
            } else {
420
                // Handle bad sequences?
421
                ansi_state = 0;
422
            }
423
            continue;
424
        case 2:
425
            // ESC+[ seen, process key
426
            ansi_state = 0;
427
            switch (c) {
428
            case 'A':
429
                c = CTRL('P');
430
                break;
431
            case 'B':
432
                c = CTRL('N');
433
                break;
434
            case 'C':
435
                c = CTRL('F');
436
                break;
437
            case 'D':
438
                c = CTRL('B');
439
                break;
440
            case 'F':
441
                c = CTRL('E');
442
                break;
443
            case 'H':
444
                c = CTRL('A');
445
                break;
446
            case '1':
447
                ansi_char = CTRL('A');
448
                ansi_state = 3;
449
                continue;
450
            case '3':
451
                ansi_char = CTRL('D');
452
                ansi_state = 3;
453
                continue;
454
            default:
455
                // Handle bad sequences?
456
                continue;
457
            }
458
            break;
459
        case 3:
460
            // Sequences like ^[[1~ == ^H
461
            ansi_state = 0;
462
            if (c == '~') {
463
                c = ansi_char;
464
            } else {
465
                // Handle bad sequences?
466
                continue;
467
            }
468
            break;
469
        case 4:
470
            // Sequences like ^[OF == ^E
471
            ansi_state = 0;
472
            if (c == 'F') {
473
                c = CTRL('E');
474
            } else {
475
                // Handle bad sequences?
476
                continue;
477
            }
478
            break;
479
        }
480
#endif
481
        switch (c) {
482
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
483
        case CTRL('P'):
484
            // Fetch the previous line into the buffer
485
            if (_index >= 0) {
486
                // Erase the previous line [crude]
487
                while (ip != buf) {
488
                    mon_write_char('\b');
489
                    mon_write_char(' ');
490
                    mon_write_char('\b');
491
                    ip--;
492
                }
493
                strcpy(buf, _cl_lines[_index]);
494
                while (*ip) {
495
                    mon_write_char(*ip++);
496
                }
497
                eol = ip;
498
                // Move to previous line
499
                _index--;
500
                if (_index < 0) {
501
                    _index = _cl_max_index;
502
                }
503
            } else {
504
                mon_write_char(0x07);  // Audible bell on most devices
505
            }
506
            break;
507
        case CTRL('N'):
508
            // Fetch the next line into the buffer
509
            if (_index >= 0) {
510
                if (++_index > _cl_max_index) _index = 0;
511
                // Erase the previous line [crude]
512
                while (ip != buf) {
513
                    mon_write_char('\b');
514
                    mon_write_char(' ');
515
                    mon_write_char('\b');
516
                    ip--;
517
                }
518
                strcpy(buf, _cl_lines[_index]);
519
                while (*ip) {
520
                    mon_write_char(*ip++);
521
                }
522
                eol = ip;
523
            } else {
524
                mon_write_char(0x07);  // Audible bell on most devices
525
            }
526
            break;
527
        case CTRL('B'):
528
            // Move insertion point backwards
529
            if (ip != buf) {
530
                mon_write_char('\b');
531
                ip--;
532
            }
533
            break;
534
        case CTRL('F'):
535
            // Move insertion point forwards
536
            if (ip != eol) {
537
                mon_write_char(*ip++);
538
            }
539
            break;
540
        case CTRL('E'):
541
            // Move insertion point to end of line
542
            while (ip != eol) {
543
                mon_write_char(*ip++);
544
            }
545
            break;
546
        case CTRL('A'):
547
            // Move insertion point to beginning of line
548
            if (ip != buf) {
549
                xp = ip;
550
                while (xp-- != buf) {
551
                    mon_write_char('\b');
552
                }
553
            }
554
            ip = buf;
555
            break;
556
        case CTRL('K'):
557
            // Kill to the end of line
558
            if (ip != eol) {
559
                xp = ip;
560
                while (xp++ != eol) {
561
                    mon_write_char(' ');
562
                }
563
                while (--xp != ip) {
564
                    mon_write_char('\b');
565
                }
566
                eol = ip;
567
            }
568
            break;
569
        case CTRL('D'):
570
            // Erase the character under the cursor
571
            if (ip != eol) {
572
                xp = ip;
573
                eol--;
574
                while (xp != eol) {
575
                    *xp = *(xp+1);
576
                    mon_write_char(*xp++);
577
                }
578
                mon_write_char(' ');  // Erases last character
579
                mon_write_char('\b');
580
                while (xp-- != ip) {
581
                    mon_write_char('\b');
582
                }
583
            }
584
            break;
585
#endif // CYGNUM_REDBOOT_CMD_LINE_EDITING
586
        case CTRL('C'): // ^C
587
            // Abort current input
588
            diag_printf("^C\n");
589
            *buf = '\0';  // Nothing useful in buffer
590
            return _GETS_CTRLC;
591
        case '\n':
592
        case '\r':
593
            // If previous character was the "other" end-of-line, ignore this one
594
            if (((c == '\n') && (last_ch == '\r')) ||
595
                ((c == '\r') && (last_ch == '\n'))) {
596
                c = '\0';
597
                break;
598
            }
599
            // End of line
600
            if (console_echo) {
601
                mon_write_char('\r');
602
                mon_write_char('\n');
603
            }
604
            last_ch = c;
605
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
606
            if (cmd_history) {
607
                // History handling - only when enabled
608
#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
609
                expand_history(buf);
610
#endif
611
                if (*buf != '\0') {
612
                    if (++_cl_index == _CL_NUM_LINES) {
613
                        _cl_index = 0;
614
                    }
615
                    if (_cl_index > _cl_max_index) _cl_max_index = _cl_index;
616
                    strcpy(_cl_lines[_cl_index], buf);
617
                    _cl_real_index++;
618
                }
619
            }
620
#endif
621
            return _GETS_OK;
622
        case '\b':
623
        case 0x7F:  // DEL
624
            if (ip != buf) {
625
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
626
                if (ip != eol) {
627
                    ip--;
628
                    mon_write_char('\b');
629
                    xp = ip;
630
                    while (xp != (eol-1)) {
631
                        *xp = *(xp+1);
632
                        mon_write_char(*xp++);
633
                    }
634
                    mon_write_char(' ');  // Erases last character
635
                    mon_write_char('\b');
636
                    while (xp-- != ip) {
637
                        mon_write_char('\b');
638
                    }
639
                } else {
640
                    if (console_echo) {
641
                        mon_write_char('\b');
642
                        mon_write_char(' ');
643
                        mon_write_char('\b');
644
                    }
645
                    ip--;
646
                }
647
                eol--;
648
#else
649
                if (console_echo) {
650
                    mon_write_char('\b');
651
                    mon_write_char(' ');
652
                    mon_write_char('\b');
653
                }
654
                ip--;
655
                eol--;
656
#endif
657
            }
658
            break;
659
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
660
        case '+': // fall through
661
        case '$':
662
            if (ip == buf || last_ch != '\\')
663
            {
664
                // Give up and try GDB protocol
665
                ungetDebugChar(c);  // Push back character so stubs will see it
666
                return _GETS_GDB;
667
            }
668
            if (last_ch == '\\') {
669
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
670
                if (ip == eol) {
671
                    // Just save \$ as $
672
                    eol = --ip;
673
                } else {
674
                    mon_write_char('\b');
675
                    *--ip = c;
676
                    mon_write_char(c);
677
                    break;
678
                }
679
#else
680
                ip--;  // Save \$ as $
681
#endif
682
            }
683
            // else fall through
684
#endif
685
        default:
686
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
687
            // If the insertion point is not at the end of line, make space for it
688
            if (ip != eol) {
689
                xp = eol;
690
                *++eol = '\0';
691
                while (xp != ip) {
692
                    *xp = *(xp-1);
693
                    xp--;
694
                }
695
            }
696
#endif
697
            if (console_echo) {
698
                mon_write_char((unsigned char)c);
699
            }
700
            if (ip == eol) {
701
                // Advance both pointers
702
                *ip++ = c;
703
                eol = ip;
704
#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
705
            } else {
706
                // Just insert the character
707
                *ip++ = c;
708
                xp = ip;
709
                while (xp != eol) {
710
                    mon_write_char(*xp++);
711
                }
712
                while (xp-- != ip) {
713
                    mon_write_char('\b');
714
                }
715
#endif
716
            }
717
        }
718
        last_ch = c;
719
        if (ip == buf + buflen - 1) { // Buffer full
720
            *ip = '\0';
721
            return buflen;
722
        }
723
    }
724
}
725
 
726
int
727
_rb_gets(char *buf, int buflen, int timeout)
728
{
729
    *buf = '\0';  // Empty buffer
730
    return _rb_gets_preloaded(buf, buflen, timeout);
731
}
732
 
733
static bool
734
_verify_action(int timeout, char *fmt, va_list ap)
735
{
736
    char ans[8];
737
    int ret;
738
#ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
739
    // Don't ask if we're executing a script
740
    if (script && *script)
741
        return 1;
742
#endif
743
 
744
    diag_vprintf(fmt, ap);
745
    diag_printf(" - continue (y/n)? ");
746
    if ((ret = _rb_gets(ans, sizeof(ans), timeout)) > 0) {
747
        return ((ans[0] == 'y') || (ans[0] == 'Y'));
748
    } else {
749
        if (ret == _GETS_TIMEOUT) {
750
            diag_printf(" ** Timed out!\n");
751
        }
752
        return 0;  // Timed out or ^C
753
    }
754
}
755
 
756
bool
757
verify_action(char *fmt, ...)
758
{
759
    va_list ap;
760
 
761
    va_start(ap, fmt);
762
    return _verify_action(0, fmt, ap);
763
}
764
 
765
bool
766
verify_action_with_timeout(int timeout, char *fmt, ...)
767
{
768
    va_list ap;
769
 
770
    va_start(ap, fmt);
771
    return _verify_action(timeout, fmt, ap);
772
}
773
 
774
 
775
#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
776
// parse for history index number. Return number or -1 if not
777
// an index number.
778
static int
779
parse_history_index(char *s)
780
{
781
    int val = 0;
782
 
783
    while ('0' <= *s && *s <= '9')
784
        val = (val * 10) + (*s++ - '0');
785
 
786
    if (*s)
787
        return -1;
788
 
789
    return val;
790
}
791
 
792
// Check input line to see if it needs history expansion. If so,
793
// try to find matching command and replace buffer as appropriate.
794
static void
795
expand_history(char *buf)
796
{
797
    int ncmds = _cl_max_index + 1;
798
    int i, index, len;
799
 
800
    if (buf[0] != '!' || buf[1] == '\0')
801
        return;
802
 
803
    if (ncmds > 0) {
804
        if (!strcmp(buf, "!!")) {
805
            strcpy(buf, _cl_lines[_cl_index]);
806
            return;
807
        }
808
        if ((index = parse_history_index(buf + 1)) >= 0) {
809
            if (index <= _cl_real_index) {
810
                while (index >= _CL_NUM_LINES) {
811
                    index -= _CL_NUM_LINES;
812
                }
813
                strcpy(buf, _cl_lines[index]);
814
                return;
815
            }
816
        } else {
817
            len = strlen(buf + 1);
818
            for (i = 0, index = _cl_index; i < ncmds; i++) {
819
                if (!strncmp(_cl_lines[index], buf+1, len)) {
820
                    strcpy(buf, _cl_lines[index]);
821
                    return;
822
                }
823
                if (--index < 0)
824
                    index = _cl_max_index;
825
            }
826
        }
827
    }
828
 
829
    diag_printf("%s: event not found\n", buf);
830
    *buf = '\0';
831
}
832
 
833
static void
834
do_history(int argc, char *argv[])
835
{
836
    int ncmds = _cl_max_index + 1;
837
    int i, index;
838
 
839
    if (_cl_index == _cl_max_index) {
840
        // history has not wrapped around
841
        for (i = 0; i < ncmds; i++)
842
            diag_printf("%3d %s\n", i, _cl_lines[i]);
843
    } else {
844
        diag_printf("_cl_index = %d\n", _cl_index);
845
        for (i = 0, index = _cl_index + 1; i < ncmds; i++) {
846
            diag_printf("%3d %s\n", i+_cl_real_index-_CL_NUM_LINES, _cl_lines[index++]);
847
            if (index > _cl_max_index)
848
                index = 0;
849
        }
850
    }
851
}
852
 
853
RedBoot_cmd("history",
854
            "Display command history",
855
            "",
856
            do_history
857
    );
858
#endif  // CYGBLD_REDBOOT_CMD_LINE_HISTORY

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.