shell.c 21.3 KB
Newer Older
1
/*
B
Bernard Xiong 已提交
2
 *  shell implementation for finsh shell.
3
 *
B
Bernard Xiong 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
 *
 *  This file is part of RT-Thread (http://www.rt-thread.org)
 *  Maintainer: bernard.xiong <bernard.xiong at gmail.com>
 *
 *  All rights reserved.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 25 26
 *
 * Change Logs:
 * Date           Author       Notes
B
Bernard Xiong 已提交
27
 * 2006-04-30     Bernard      the first version for FinSH
28 29 30
 * 2006-05-08     Bernard      change finsh thread stack to 2048
 * 2006-06-03     Bernard      add support for skyeye
 * 2006-09-24     Bernard      remove the code related with hardware
B
bernard.xiong 已提交
31
 * 2010-01-18     Bernard      fix down then up key bug.
32
 * 2010-03-19     Bernard      fix backspace issue and fix device read in shell.
33
 * 2010-04-01     Bernard      add prompt output when start and remove the empty history
34 35
 * 2011-02-23     Bernard      fix variable section end issue of finsh shell
 *                             initialization when use GNU GCC compiler.
armink_ztl's avatar
armink_ztl 已提交
36
 * 2016-11-26     armink       add password authentication
37 38 39 40 41
 */

#include <rthw.h>

#include "finsh.h"
42
#include "shell.h"
43

B
Bernard Xiong 已提交
44 45 46 47
#ifdef FINSH_USING_MSH
#include "msh.h"
#endif

48 49 50 51
#ifdef _WIN32
#include <stdio.h> /* for putchar */
#endif

52
/* finsh thread */
53
static struct rt_thread finsh_thread;
54
ALIGN(RT_ALIGN_SIZE)
55
static char finsh_thread_stack[FINSH_THREAD_STACK_SIZE];
56
struct finsh_shell *shell;
57

58 59
#if defined(FINSH_USING_MSH) || (defined(RT_USING_DFS) && defined(DFS_USING_WORKDIR))
#if defined(RT_USING_DFS)
60
#include <dfs_posix.h>
61
#endif
62
const char *finsh_get_prompt()
63
{
64 65
#define _MSH_PROMPT "msh "
#define _PROMPT     "finsh "
B
bernard 已提交
66
    static char finsh_prompt[RT_CONSOLEBUF_SIZE + 1] = {0};
67 68 69

#ifdef FINSH_USING_MSH
    if (msh_is_used()) strcpy(finsh_prompt, _MSH_PROMPT);
B
bernard 已提交
70
    else
71
#endif
72
        strcpy(finsh_prompt, _PROMPT);
73

74
#if defined(RT_USING_DFS) && defined(DFS_USING_WORKDIR)
B
bernard 已提交
75
    /* get current working directory */
B
bernard 已提交
76
    getcwd(&finsh_prompt[rt_strlen(finsh_prompt)], RT_CONSOLEBUF_SIZE - rt_strlen(finsh_prompt));
77
#endif
78

B
bernard 已提交
79 80 81
    strcat(finsh_prompt, ">");

    return finsh_prompt;
82 83 84
}
#endif

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static char finsh_getchar(void)
{
    RT_ASSERT(shell != RT_NULL);

#ifdef RT_USING_DFS
    return getchar();
#else
    char ch;

    while (rt_device_read(shell->device, -1, &ch, 1) != 1)
        rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER);

    return ch;
#endif
}

#ifndef RT_USING_DFS
102 103
static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
{
B
bernard 已提交
104
    RT_ASSERT(shell != RT_NULL);
105

B
bernard 已提交
106 107
    /* release semaphore to let finsh thread rx data */
    rt_sem_release(&shell->rx_sem);
108

B
bernard 已提交
109
    return RT_EOK;
110 111
}

B
bernard.xiong@gmail.com 已提交
112 113 114 115 116 117 118
/**
 * @ingroup finsh
 *
 * This function sets the input device of finsh shell.
 *
 * @param device_name the name of new input device.
 */
119
void finsh_set_device(const char *device_name)
120
{
B
bernard 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133
    rt_device_t dev = RT_NULL;

    RT_ASSERT(shell != RT_NULL);
    dev = rt_device_find(device_name);
    if (dev == RT_NULL)
    {
        rt_kprintf("finsh: can not find device: %s\n", device_name);
        return;
    }

    /* check whether it's a same device */
    if (dev == shell->device) return;
    /* open this device and set the new device in finsh shell */
134
    if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | \
135
                       RT_DEVICE_FLAG_STREAM) == RT_EOK)
B
bernard 已提交
136 137 138 139 140
    {
        if (shell->device != RT_NULL)
        {
            /* close old finsh device */
            rt_device_close(shell->device);
W
weety 已提交
141
            rt_device_set_rx_indicate(shell->device, RT_NULL);
B
bernard 已提交
142
        }
143

144 145 146
        /* clear line buffer before switch to new device */
        memset(shell->line, 0, sizeof(shell->line));
        shell->line_curpos = shell->line_position = 0;
147

B
bernard 已提交
148 149 150
        shell->device = dev;
        rt_device_set_rx_indicate(dev, finsh_rx_ind);
    }
151 152
}

B
bernard.xiong@gmail.com 已提交
153 154 155 156 157 158 159
/**
 * @ingroup finsh
 *
 * This function returns current finsh shell input device.
 *
 * @return the finsh shell input device name is returned.
 */
160
const char *finsh_get_device()
161
{
B
bernard 已提交
162 163
    RT_ASSERT(shell != RT_NULL);
    return shell->device->parent.name;
164
}
165
#endif
166

B
bernard.xiong@gmail.com 已提交
167 168 169 170 171 172 173 174 175 176
/**
 * @ingroup finsh
 *
 * This function set the echo mode of finsh shell.
 *
 * FINSH_OPTION_ECHO=0x01 is echo mode, other values are none-echo mode.
 *
 * @param echo the echo mode
 */
void finsh_set_echo(rt_uint32_t echo)
177
{
B
bernard 已提交
178 179
    RT_ASSERT(shell != RT_NULL);
    shell->echo_mode = (rt_uint8_t)echo;
180 181
}

B
bernard.xiong@gmail.com 已提交
182 183 184 185 186 187 188
/**
 * @ingroup finsh
 *
 * This function gets the echo mode of finsh shell.
 *
 * @return the echo mode
 */
189 190
rt_uint32_t finsh_get_echo()
{
B
bernard 已提交
191
    RT_ASSERT(shell != RT_NULL);
192

B
bernard 已提交
193
    return shell->echo_mode;
194 195
}

196 197 198 199 200 201
#ifdef FINSH_USING_AUTH
/**
 * set a new password for finsh
 *
 * @param password new password
 *
armink_ztl's avatar
armink_ztl 已提交
202 203
 * @return result, RT_EOK on OK, -RT_ERROR on the new password length is less than
 *  FINSH_PASSWORD_MIN or greater than FINSH_PASSWORD_MAX
204 205 206
 */
rt_err_t finsh_set_password(const char *password) {
    rt_ubase_t level;
armink_ztl's avatar
armink_ztl 已提交
207
    rt_size_t pw_len = rt_strlen(password);
208

armink_ztl's avatar
armink_ztl 已提交
209
    if (pw_len < FINSH_PASSWORD_MIN || pw_len > FINSH_PASSWORD_MAX)
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
        return -RT_ERROR;

    level = rt_hw_interrupt_disable();
    rt_strncpy(shell->password, password, FINSH_PASSWORD_MAX);
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

/**
 * get the finsh password
 *
 * @return password
 */
const char *finsh_get_password(void)
{
    return shell->password;
}

static void finsh_wait_auth(void)
{
    char ch;
    rt_bool_t input_finish = RT_FALSE;
    char password[FINSH_PASSWORD_MAX] = { 0 };
    rt_size_t cur_pos = 0;
235 236 237
    /* password not set */
    if (rt_strlen(finsh_get_password()) == 0) return;
    
238 239
    while (1)
    {
240
        rt_kprintf("Password for login: ");
241 242
        while (!input_finish)
        {
243
            while (1)
244
            {
245 246 247
                /* read one character from device */
                ch = finsh_getchar();

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
                if (ch >= ' ' && ch <= '~' && cur_pos < FINSH_PASSWORD_MAX)
                {
                    /* change the printable characters to '*' */
                    rt_kprintf("*");
                    password[cur_pos++] = ch;
                }
                else if (ch == '\b' && cur_pos > 0)
                {
                    /* backspace */
                    password[cur_pos] = '\0';
                    cur_pos--;
                    rt_kprintf("\b \b");
                }
                else if (ch == '\r' || ch == '\n')
                {
                    rt_kprintf("\n");
                    input_finish = RT_TRUE;
                    break;
                }
            }
        }
        if (!rt_strncmp(shell->password, password, FINSH_PASSWORD_MAX)) return;
        else
        {
            /* authentication failed, delay 2S for retry */
            rt_thread_delay(2 * RT_TICK_PER_SECOND);
            rt_kprintf("Sorry, try again.\n");
            cur_pos = 0;
            input_finish = RT_FALSE;
            rt_memset(password, '\0', FINSH_PASSWORD_MAX);
        }
    }
}
#endif /* FINSH_USING_AUTH */

283
static void shell_auto_complete(char *prefix)
284 285
{

B
bernard 已提交
286
    rt_kprintf("\n");
B
Bernard Xiong 已提交
287
#ifdef FINSH_USING_MSH
B
bernard 已提交
288 289 290 291
    if (msh_is_used() == RT_TRUE)
    {
        msh_auto_complete(prefix);
    }
292
    else
B
Bernard Xiong 已提交
293
#endif
B
bernard 已提交
294
    {
295 296
#ifndef FINSH_USING_MSH_ONLY
        extern void list_prefix(char * prefix);
B
bernard 已提交
297
        list_prefix(prefix);
B
bernard 已提交
298
#endif
B
bernard 已提交
299
    }
B
Bernard Xiong 已提交
300

B
bernard 已提交
301
    rt_kprintf("%s%s", FINSH_PROMPT, prefix);
302
}
303

B
bernard 已提交
304
#ifndef FINSH_USING_MSH_ONLY
305
void finsh_run_line(struct finsh_parser *parser, const char *line)
306
{
307
    const char *err_str;
B
bernard 已提交
308

309 310
    if(shell->echo_mode)
        rt_kprintf("\n");
311
    finsh_parser_run(parser, (unsigned char *)line);
B
bernard 已提交
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333

    /* compile node root */
    if (finsh_errno() == 0)
    {
        finsh_compiler_run(parser->root);
    }
    else
    {
        err_str = finsh_error_string(finsh_errno());
        rt_kprintf("%s\n", err_str);
    }

    /* run virtual machine */
    if (finsh_errno() == 0)
    {
        char ch;
        finsh_vm_run();

        ch = (unsigned char)finsh_stack_bottom();
        if (ch > 0x20 && ch < 0x7e)
        {
            rt_kprintf("\t'%c', %d, 0x%08x\n",
334 335 336
                       (unsigned char)finsh_stack_bottom(),
                       (unsigned int)finsh_stack_bottom(),
                       (unsigned int)finsh_stack_bottom());
B
bernard 已提交
337 338 339 340
        }
        else
        {
            rt_kprintf("\t%d, 0x%08x\n",
341 342
                       (unsigned int)finsh_stack_bottom(),
                       (unsigned int)finsh_stack_bottom());
B
bernard 已提交
343 344
        }
    }
345

346 347
    finsh_flush(parser);
}
B
bernard 已提交
348
#endif
349

350
#ifdef FINSH_USING_HISTORY
351
static rt_bool_t shell_handle_history(struct finsh_shell *shell)
352
{
353
#if defined(_WIN32)
B
bernard 已提交
354 355
    int i;
    rt_kprintf("\r");
356

357
    for (i = 0; i <= 60; i++)
B
bernard 已提交
358 359
        putchar(' ');
    rt_kprintf("\r");
360 361

#else
B
bernard 已提交
362
    rt_kprintf("\033[2K\r");
363
#endif
B
bernard 已提交
364 365
    rt_kprintf("%s%s", FINSH_PROMPT, shell->line);
    return RT_FALSE;
366 367
}

368
static void shell_push_history(struct finsh_shell *shell)
369
{
B
bernard 已提交
370 371 372 373 374 375 376 377 378 379
    if (shell->line_position != 0)
    {
        /* push history */
        if (shell->history_count >= FINSH_HISTORY_LINES)
        {
            /* move history */
            int index;
            for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
            {
                memcpy(&shell->cmd_history[index][0],
380
                       &shell->cmd_history[index + 1][0], FINSH_CMD_SIZE);
B
bernard 已提交
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
            }
            memset(&shell->cmd_history[index][0], 0, FINSH_CMD_SIZE);
            memcpy(&shell->cmd_history[index][0], shell->line, shell->line_position);

            /* it's the maximum history */
            shell->history_count = FINSH_HISTORY_LINES;
        }
        else
        {
            memset(&shell->cmd_history[shell->history_count][0], 0, FINSH_CMD_SIZE);
            memcpy(&shell->cmd_history[shell->history_count][0], shell->line, shell->line_position);

            /* increase count and set current history position */
            shell->history_count ++;
        }
    }
    shell->current_history = shell->history_count;
398 399 400 401 402 403
}
#endif

#ifndef RT_USING_HEAP
struct finsh_shell _shell;
#endif
404
void finsh_thread_entry(void *parameter)
405 406 407
{
    char ch;

B
bernard 已提交
408 409
    /* normal is echo mode */
    shell->echo_mode = 1;
410

B
bernard 已提交
411
#ifndef FINSH_USING_MSH_ONLY
412
    finsh_init(&shell->parser);
B
bernard 已提交
413
#endif
414

415
#ifndef RT_USING_DFS
B
bernard 已提交
416 417 418
    /* set console device as shell device */
    if (shell->device == RT_NULL)
    {
419 420 421 422 423
        rt_device_t console = rt_console_get_device();
        if (console)
        {
            finsh_set_device(console->parent.name);
        }
B
bernard 已提交
424
    }
425
#endif
B
bernard 已提交
426

427 428 429
#ifdef FINSH_USING_AUTH
    /* set the default password when the password isn't setting */
    if (rt_strlen(finsh_get_password()) == 0)
430 431 432 433 434 435
    {
        if (finsh_set_password(FINSH_DEFAULT_PASSWORD) != RT_EOK)
        {
            rt_kprintf("Finsh password set failed.\n");
        }
    }
436 437 438 439 440 441
    /* waiting authenticate success */
    finsh_wait_auth();
#endif

    rt_kprintf(FINSH_PROMPT);

B
bernard 已提交
442 443
    while (1)
    {
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
        ch = finsh_getchar();

        /*
         * handle control key
         * up key  : 0x1b 0x5b 0x41
         * down key: 0x1b 0x5b 0x42
         * right key:0x1b 0x5b 0x43
         * left key: 0x1b 0x5b 0x44
         */
        if (ch == 0x1b)
        {
            shell->stat = WAIT_SPEC_KEY;
            continue;
        }
        else if (shell->stat == WAIT_SPEC_KEY)
B
bernard 已提交
459
        {
460
            if (ch == 0x5b)
B
bernard 已提交
461
            {
462
                shell->stat = WAIT_FUNC_KEY;
B
bernard 已提交
463 464
                continue;
            }
465 466 467 468 469 470 471 472

            shell->stat = WAIT_NORMAL;
        }
        else if (shell->stat == WAIT_FUNC_KEY)
        {
            shell->stat = WAIT_NORMAL;

            if (ch == 0x41) /* up key */
B
bernard 已提交
473
            {
474 475 476 477 478
#ifdef FINSH_USING_HISTORY
                /* prev history */
                if (shell->current_history > 0)
                    shell->current_history --;
                else
B
bernard 已提交
479
                {
480
                    shell->current_history = 0;
B
bernard 已提交
481 482 483
                    continue;
                }

484 485 486 487 488 489 490
                /* copy the history command */
                memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
                       FINSH_CMD_SIZE);
                shell->line_curpos = shell->line_position = strlen(shell->line);
                shell_handle_history(shell);
#endif
                continue;
B
bernard 已提交
491
            }
492
            else if (ch == 0x42) /* down key */
B
bernard 已提交
493
            {
494
#ifdef FINSH_USING_HISTORY
495 496 497 498
                /* next history */
                if (shell->current_history < shell->history_count - 1)
                    shell->current_history ++;
                else
B
bernard 已提交
499
                {
500 501 502
                    /* set to the end of history */
                    if (shell->history_count != 0)
                        shell->current_history = shell->history_count - 1;
B
bernard 已提交
503
                    else
504
                        continue;
B
bernard 已提交
505 506
                }

507 508 509 510 511 512
                memcpy(shell->line, &shell->cmd_history[shell->current_history][0],
                       FINSH_CMD_SIZE);
                shell->line_curpos = shell->line_position = strlen(shell->line);
                shell_handle_history(shell);
#endif
                continue;
B
bernard 已提交
513
            }
514
            else if (ch == 0x44) /* left key */
B
bernard 已提交
515
            {
516
                if (shell->line_curpos)
517
                {
B
bernard 已提交
518
                    rt_kprintf("\b");
519 520
                    shell->line_curpos --;
                }
B
bernard 已提交
521 522 523

                continue;
            }
524
            else if (ch == 0x43) /* right key */
B
bernard 已提交
525
            {
526
                if (shell->line_curpos < shell->line_position)
B
bernard 已提交
527
                {
528 529
                    rt_kprintf("%c", shell->line[shell->line_curpos]);
                    shell->line_curpos ++;
B
bernard 已提交
530 531 532 533
                }

                continue;
            }
534
        }
B
bernard 已提交
535

536 537 538 539 540 541 542 543 544
        /* handle CR key */
        if (ch == '\0') continue;
        /* handle tab key */
        else if (ch == '\t')
        {
            int i;
            /* move the cursor to the beginning of line */
            for (i = 0; i < shell->line_curpos; i++)
                rt_kprintf("\b");
B
bernard 已提交
545

546 547 548 549
            /* auto complete */
            shell_auto_complete(&shell->line[0]);
            /* re-calculate position */
            shell->line_curpos = shell->line_position = strlen(shell->line);
B
bernard 已提交
550

551 552 553 554 555 556 557 558
            continue;
        }
        /* handle backspace key */
        else if (ch == 0x7f || ch == 0x08)
        {
            /* note that shell->line_curpos >= 0 */
            if (shell->line_curpos == 0)
                continue;
B
bernard 已提交
559

560 561
            shell->line_position--;
            shell->line_curpos--;
B
bernard 已提交
562

563
            if (shell->line_position > shell->line_curpos)
B
bernard 已提交
564 565 566
            {
                int i;

567 568
                rt_memmove(&shell->line[shell->line_curpos],
                           &shell->line[shell->line_curpos + 1],
B
bernard 已提交
569
                           shell->line_position - shell->line_curpos);
570 571 572
                shell->line[shell->line_position] = 0;

                rt_kprintf("\b%s  \b", &shell->line[shell->line_curpos]);
B
bernard 已提交
573

574 575
                /* move the cursor to the origin position */
                for (i = shell->line_curpos; i <= shell->line_position; i++)
B
bernard 已提交
576 577 578 579
                    rt_kprintf("\b");
            }
            else
            {
580 581
                rt_kprintf("\b \b");
                shell->line[shell->line_position] = 0;
B
bernard 已提交
582 583
            }

584 585 586 587 588 589 590 591 592 593 594 595
            continue;
        }

        /* handle end of line, break */
        if (ch == '\r' || ch == '\n')
        {
#ifdef FINSH_USING_HISTORY
            shell_push_history(shell);
#endif

#ifdef FINSH_USING_MSH
            if (msh_is_used() == RT_TRUE)
596
            {
597 598 599
                if (shell->echo_mode)
                    rt_kprintf("\n");
                msh_exec(shell->line, shell->line_position);
600
            }
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
            else
#endif
            {
#ifndef FINSH_USING_MSH_ONLY
                /* add ';' and run the command line */
                shell->line[shell->line_position] = ';';

                if (shell->line_position != 0) finsh_run_line(&shell->parser, shell->line);
                else
                    if (shell->echo_mode) rt_kprintf("\n");
#endif
            }

            rt_kprintf(FINSH_PROMPT);
            memset(shell->line, 0, sizeof(shell->line));
            shell->line_curpos = shell->line_position = 0;
            continue;
        }

        /* it's a large line, discard it */
        if (shell->line_position >= FINSH_CMD_SIZE)
            shell->line_position = 0;

        /* normal character */
        if (shell->line_curpos < shell->line_position)
        {
            int i;

            rt_memmove(&shell->line[shell->line_curpos + 1],
                       &shell->line[shell->line_curpos],
                       shell->line_position - shell->line_curpos);
            shell->line[shell->line_curpos] = ch;
            if (shell->echo_mode)
                rt_kprintf("%s", &shell->line[shell->line_curpos]);

            /* move the cursor to new position */
            for (i = shell->line_curpos; i < shell->line_position; i++)
                rt_kprintf("\b");
        }
        else
        {
            shell->line[shell->line_position] = ch;
            if (shell->echo_mode)
                rt_kprintf("%c", ch);
        }

        ch = 0;
        shell->line_position ++;
        shell->line_curpos++;
        if (shell->line_position >= FINSH_CMD_SIZE)
        {
            /* clear command line */
            shell->line_position = 0;
            shell->line_curpos = 0;
        }
    } /* end of device read */
657 658
}

659
void finsh_system_function_init(const void *begin, const void *end)
660
{
661 662
    _syscall_table_begin = (struct finsh_syscall *) begin;
    _syscall_table_end = (struct finsh_syscall *) end;
663 664
}

665
void finsh_system_var_init(const void *begin, const void *end)
666
{
667 668
    _sysvar_table_begin = (struct finsh_sysvar *) begin;
    _sysvar_table_end = (struct finsh_sysvar *) end;
669 670
}

淡漠想敏's avatar
淡漠想敏 已提交
671
#if defined(__ICCARM__) || defined(__ICCRX__)               /* for IAR compiler */
672 673 674 675
#ifdef FINSH_USING_SYMTAB
#pragma section="FSymTab"
#pragma section="VSymTab"
#endif
676
#elif defined(__ADSPBLACKFIN__) /* for VisaulDSP++ Compiler*/
677 678 679 680 681 682
#ifdef FINSH_USING_SYMTAB
extern "asm" int __fsymtab_start;
extern "asm" int __fsymtab_end;
extern "asm" int __vsymtab_start;
extern "asm" int __vsymtab_end;
#endif
683 684 685 686
#elif defined(_MSC_VER)
#pragma section("FSymTab$a", read)
const char __fsym_begin_name[] = "__start";
const char __fsym_begin_desc[] = "begin of finsh";
687
__declspec(allocate("FSymTab$a")) const struct finsh_syscall __fsym_begin =
688
{
B
bernard 已提交
689 690 691
    __fsym_begin_name,
    __fsym_begin_desc,
    NULL
692 693 694 695 696
};

#pragma section("FSymTab$z", read)
const char __fsym_end_name[] = "__end";
const char __fsym_end_desc[] = "end of finsh";
697
__declspec(allocate("FSymTab$z")) const struct finsh_syscall __fsym_end =
698
{
B
bernard 已提交
699 700 701
    __fsym_end_name,
    __fsym_end_desc,
    NULL
702
};
703
#endif
B
bernard.xiong@gmail.com 已提交
704 705 706 707 708 709

/*
 * @ingroup finsh
 *
 * This function will initialize finsh shell
 */
B
Bernard Xiong 已提交
710
int finsh_system_init(void)
711
{
B
bernard 已提交
712
    rt_err_t result;
713 714 715

#ifdef FINSH_USING_SYMTAB
#ifdef __CC_ARM                 /* ARM C Compiler */
wuyangyong's avatar
wuyangyong 已提交
716 717 718 719
    extern const int FSymTab$$Base;
    extern const int FSymTab$$Limit;
    extern const int VSymTab$$Base;
    extern const int VSymTab$$Limit;
B
bernard 已提交
720
    finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);
721
#ifndef FINSH_USING_MSH_ONLY
B
bernard 已提交
722
    finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit);
723
#endif
淡漠想敏's avatar
淡漠想敏 已提交
724
#elif defined (__ICCARM__) || defined(__ICCRX__)      /* for IAR Compiler */
725 726 727 728
    finsh_system_function_init(__section_begin("FSymTab"),
                               __section_end("FSymTab"));
    finsh_system_var_init(__section_begin("VSymTab"),
                          __section_end("VSymTab"));
G
Grissiom 已提交
729 730
#elif defined (__GNUC__) || defined(__TI_COMPILER_VERSION__)
    /* GNU GCC Compiler and TI CCS */
B
bernard 已提交
731 732 733 734 735 736
    extern const int __fsymtab_start;
    extern const int __fsymtab_end;
    extern const int __vsymtab_start;
    extern const int __vsymtab_end;
    finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
    finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);
737 738 739
#elif defined(__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */
    finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
    finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);
740
#elif defined(_MSC_VER)
B
bernard 已提交
741
    unsigned int *ptr_begin, *ptr_end;
742

743 744
    ptr_begin = (unsigned int *)&__fsym_begin;
    ptr_begin += (sizeof(struct finsh_syscall) / sizeof(unsigned int));
B
bernard 已提交
745
    while (*ptr_begin == 0) ptr_begin ++;
746

747 748
    ptr_end = (unsigned int *) &__fsym_end;
    ptr_end --;
B
bernard 已提交
749
    while (*ptr_end == 0) ptr_end --;
750

B
bernard 已提交
751
    finsh_system_function_init(ptr_begin, ptr_end);
752 753 754
#endif
#endif

B
bernard 已提交
755
    /* create or set shell structure */
756
#ifdef RT_USING_HEAP
757
    shell = (struct finsh_shell *)rt_malloc(sizeof(struct finsh_shell));
B
bernard 已提交
758 759 760 761 762
    if (shell == RT_NULL)
    {
        rt_kprintf("no memory for shell\n");
        return -1;
    }
B
bernard 已提交
763
#else
B
bernard 已提交
764
    shell = &_shell;
B
bernard 已提交
765 766
#endif

B
bernard 已提交
767
    memset(shell, 0, sizeof(struct finsh_shell));
768

B
bernard 已提交
769 770
    rt_sem_init(&(shell->rx_sem), "shrx", 0, 0);
    result = rt_thread_init(&finsh_thread,
771 772 773 774
                            "tshell",
                            finsh_thread_entry, RT_NULL,
                            &finsh_thread_stack[0], sizeof(finsh_thread_stack),
                            FINSH_THREAD_PRIORITY, 10);
775

B
bernard 已提交
776 777 778
    if (result == RT_EOK)
        rt_thread_startup(&finsh_thread);
    return 0;
779
}
780
INIT_APP_EXPORT(finsh_system_init);
B
Bernard Xiong 已提交
781