port http://sourceforge.net/projects/tinysh to mbed enviroment

Dependents:   kl25z-tinyshell-demo HelloWorld_IHM02A1

This library is a port of tiny shell library to mbed enviroment.

Features

  • Autocomplete
  • Command history
  • Linux like

Tiny Shell minimal example

#include "mbed.h"
#include "tinysh.h"

//serial port to use 
Serial pc(USBTX, USBRX);

//custom function
void foo_fnt(int argc, char **argv)
{
    printf("foo command called\r\n");
    for(int i=0; i<argc; i++) {
        printf("argv[%d]=\"%s\"\r\n",i,argv[i]);
    }
}
//custom command
tinysh_cmd_t myfoocmd= {0,"foo","foo command","[args]",foo_fnt,0,0,0};



//mandatory tiny shell output function
void tinysh_char_out(unsigned char c)
{
    pc.putc(c);
}


void main(void){

   //configure serial baudrate
    pc.baud(115200);

   //print build date
    pc.printf("tiny shell build %s %s\r\n",__DATE__,__TIME__);

    //set prompt
    tinysh_set_prompt("$ ");

    //add custom commands here
    tinysh_add_command(&myfoocmd);

   //run command parser loop foverer 
    while(true) {
        tinysh_char_in( pc.getc() );
    }
}
Committer:
murilopontes
Date:
Tue Mar 11 05:19:36 2014 +0000
Revision:
1:71580bf962fe
Parent:
0:78b46c0d5246
update \r e \n

Who changed what in which revision?

UserRevisionLine numberNew contents of line
murilopontes 0:78b46c0d5246 1 /*
murilopontes 0:78b46c0d5246 2 * tinysh.c
murilopontes 0:78b46c0d5246 3 *
murilopontes 0:78b46c0d5246 4 * Minimal portable shell
murilopontes 0:78b46c0d5246 5 *
murilopontes 0:78b46c0d5246 6 * Copyright (C) 2001 Michel Gutierrez <mig@nerim.net>
murilopontes 0:78b46c0d5246 7 *
murilopontes 0:78b46c0d5246 8 * This library is free software; you can redistribute it and/or
murilopontes 0:78b46c0d5246 9 * modify it under the terms of the GNU Lesser General Public
murilopontes 0:78b46c0d5246 10 * License as published by the Free Software Foundation; either
murilopontes 0:78b46c0d5246 11 * version 2.1 of the License, or (at your option) any later version.
murilopontes 0:78b46c0d5246 12 *
murilopontes 0:78b46c0d5246 13 * This library is distributed in the hope that it will be useful,
murilopontes 0:78b46c0d5246 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
murilopontes 0:78b46c0d5246 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
murilopontes 0:78b46c0d5246 16 * Lesser General Public License for more details.
murilopontes 0:78b46c0d5246 17 *
murilopontes 0:78b46c0d5246 18 * You should have received a copy of the GNU Lesser General Public
murilopontes 0:78b46c0d5246 19 * License along with this library; if not, write to the Free
murilopontes 0:78b46c0d5246 20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
murilopontes 0:78b46c0d5246 21 */
murilopontes 0:78b46c0d5246 22
murilopontes 0:78b46c0d5246 23 #include "tinysh.h"
murilopontes 0:78b46c0d5246 24
murilopontes 0:78b46c0d5246 25 #ifndef BUFFER_SIZE
murilopontes 0:78b46c0d5246 26 #define BUFFER_SIZE 64
murilopontes 0:78b46c0d5246 27 #endif
murilopontes 0:78b46c0d5246 28 #ifndef HISTORY_DEPTH
murilopontes 0:78b46c0d5246 29 #define HISTORY_DEPTH 3
murilopontes 0:78b46c0d5246 30 #endif
murilopontes 0:78b46c0d5246 31 #ifndef MAX_ARGS
murilopontes 0:78b46c0d5246 32 #define MAX_ARGS 4
murilopontes 0:78b46c0d5246 33 #endif
murilopontes 0:78b46c0d5246 34 #ifndef PROMPT_SIZE
murilopontes 0:78b46c0d5246 35 #define PROMPT_SIZE 4
murilopontes 0:78b46c0d5246 36 #endif
murilopontes 0:78b46c0d5246 37 #ifndef TOPCHAR
murilopontes 0:78b46c0d5246 38 #define TOPCHAR '/'
murilopontes 0:78b46c0d5246 39 #endif
murilopontes 0:78b46c0d5246 40
murilopontes 0:78b46c0d5246 41
murilopontes 0:78b46c0d5246 42 typedef unsigned char uchar;
murilopontes 0:78b46c0d5246 43 /* redefine some useful and maybe missing utilities to avoid conflicts */
murilopontes 0:78b46c0d5246 44 #define strlen tinysh_strlen
murilopontes 0:78b46c0d5246 45 #define puts tinysh_puts
murilopontes 0:78b46c0d5246 46 #define putchar tinysh_char_out
murilopontes 0:78b46c0d5246 47
murilopontes 0:78b46c0d5246 48 static void help_fnt(int argc, char **argv);
murilopontes 0:78b46c0d5246 49
murilopontes 0:78b46c0d5246 50 static tinysh_cmd_t help_cmd={
murilopontes 0:78b46c0d5246 51 0,"help","display help","<cr>",help_fnt,0,0,0 };
murilopontes 0:78b46c0d5246 52
murilopontes 0:78b46c0d5246 53 static uchar input_buffers[HISTORY_DEPTH][BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 54 static uchar trash_buffer[BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 55 static int cur_buf_index=0;
murilopontes 0:78b46c0d5246 56 static uchar context_buffer[BUFFER_SIZE+1]={0};
murilopontes 0:78b46c0d5246 57 static int cur_context=0;
murilopontes 0:78b46c0d5246 58 static int cur_index=0;
murilopontes 0:78b46c0d5246 59 static int echo=1;
murilopontes 0:78b46c0d5246 60 static char prompt[PROMPT_SIZE+1]="$ ";
murilopontes 0:78b46c0d5246 61 static tinysh_cmd_t *root_cmd=&help_cmd;
murilopontes 0:78b46c0d5246 62 static tinysh_cmd_t *cur_cmd_ctx=0;
murilopontes 0:78b46c0d5246 63 static void *tinysh_arg=0;
murilopontes 0:78b46c0d5246 64
murilopontes 0:78b46c0d5246 65 /* few useful utilities that may be missing */
murilopontes 0:78b46c0d5246 66
murilopontes 0:78b46c0d5246 67 static int strlen(uchar *s)
murilopontes 0:78b46c0d5246 68 {
murilopontes 0:78b46c0d5246 69 int i;
murilopontes 0:78b46c0d5246 70 for(i=0;*s;s++,i++);
murilopontes 0:78b46c0d5246 71 return i;
murilopontes 0:78b46c0d5246 72 }
murilopontes 0:78b46c0d5246 73
murilopontes 0:78b46c0d5246 74 static void puts(char *s)
murilopontes 0:78b46c0d5246 75 {
murilopontes 0:78b46c0d5246 76 while(*s)
murilopontes 0:78b46c0d5246 77 putchar(*s++);
murilopontes 0:78b46c0d5246 78 }
murilopontes 0:78b46c0d5246 79
murilopontes 0:78b46c0d5246 80 /* callback for help function
murilopontes 0:78b46c0d5246 81 */
murilopontes 0:78b46c0d5246 82 static void help_fnt(int argc, char **argv)
murilopontes 0:78b46c0d5246 83 {
murilopontes 0:78b46c0d5246 84 puts("? display help on given or available commands\r\n");
murilopontes 0:78b46c0d5246 85 puts("<TAB> auto-completion\r\n");
murilopontes 0:78b46c0d5246 86 puts("<cr> execute command line\r\n");
murilopontes 0:78b46c0d5246 87 puts("CTRL-P recall previous input line\r\n");
murilopontes 0:78b46c0d5246 88 puts("CTRL-N recall next input line\r\n");
murilopontes 0:78b46c0d5246 89 puts("<any> treat as input character\r\n");
murilopontes 0:78b46c0d5246 90 }
murilopontes 0:78b46c0d5246 91
murilopontes 0:78b46c0d5246 92 /*
murilopontes 0:78b46c0d5246 93 */
murilopontes 0:78b46c0d5246 94
murilopontes 0:78b46c0d5246 95 enum { NULLMATCH,FULLMATCH,PARTMATCH,UNMATCH,MATCH,AMBIG };
murilopontes 0:78b46c0d5246 96
murilopontes 0:78b46c0d5246 97 /* verify if the non-spaced part of s2 is included at the begining
murilopontes 0:78b46c0d5246 98 * of s1.
murilopontes 0:78b46c0d5246 99 * return FULLMATCH if s2 equal to s1, PARTMATCH if s1 starts with s2
murilopontes 0:78b46c0d5246 100 * but there are remaining chars in s1, UNMATCH if s1 does not start with
murilopontes 0:78b46c0d5246 101 * s2
murilopontes 0:78b46c0d5246 102 */
murilopontes 0:78b46c0d5246 103 int strstart(uchar *s1, uchar *s2)
murilopontes 0:78b46c0d5246 104 {
murilopontes 0:78b46c0d5246 105 while(*s1 && *s1==*s2) { s1++; s2++; }
murilopontes 0:78b46c0d5246 106
murilopontes 0:78b46c0d5246 107 if(*s2==' ' || *s2==0)
murilopontes 0:78b46c0d5246 108 {
murilopontes 0:78b46c0d5246 109 if(*s1==0)
murilopontes 0:78b46c0d5246 110 return FULLMATCH; /* full match */
murilopontes 0:78b46c0d5246 111 else
murilopontes 0:78b46c0d5246 112 return PARTMATCH; /* partial match */
murilopontes 0:78b46c0d5246 113 }
murilopontes 0:78b46c0d5246 114 else
murilopontes 0:78b46c0d5246 115 return UNMATCH; /* no match */
murilopontes 0:78b46c0d5246 116 }
murilopontes 0:78b46c0d5246 117
murilopontes 0:78b46c0d5246 118 /*
murilopontes 0:78b46c0d5246 119 * check commands at given level with input string.
murilopontes 0:78b46c0d5246 120 * _cmd: point to first command at this level, return matched cmd
murilopontes 0:78b46c0d5246 121 * _str: point to current unprocessed input, return next unprocessed
murilopontes 0:78b46c0d5246 122 */
murilopontes 0:78b46c0d5246 123 static int parse_command(tinysh_cmd_t **_cmd, uchar **_str)
murilopontes 0:78b46c0d5246 124 {
murilopontes 0:78b46c0d5246 125 uchar *str=*_str;
murilopontes 0:78b46c0d5246 126 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 127 int matched_len=0;
murilopontes 0:78b46c0d5246 128 tinysh_cmd_t *matched_cmd=0;
murilopontes 0:78b46c0d5246 129
murilopontes 0:78b46c0d5246 130 /* first eliminate first blanks */
murilopontes 0:78b46c0d5246 131 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 132 if(!*str)
murilopontes 0:78b46c0d5246 133 {
murilopontes 0:78b46c0d5246 134 *_str=str;
murilopontes 0:78b46c0d5246 135 return NULLMATCH; /* end of input */
murilopontes 0:78b46c0d5246 136 }
murilopontes 0:78b46c0d5246 137
murilopontes 0:78b46c0d5246 138 /* first pass: count matches */
murilopontes 0:78b46c0d5246 139 for(cmd=*_cmd;cmd;cmd=cmd->next)
murilopontes 0:78b46c0d5246 140 {
murilopontes 0:78b46c0d5246 141 int ret=strstart(cmd->name,str);
murilopontes 0:78b46c0d5246 142
murilopontes 0:78b46c0d5246 143 if(ret==FULLMATCH)
murilopontes 0:78b46c0d5246 144 {
murilopontes 0:78b46c0d5246 145 /* found full match */
murilopontes 0:78b46c0d5246 146 while(*str && *str!=' ') str++;
murilopontes 0:78b46c0d5246 147 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 148 *_str=str;
murilopontes 0:78b46c0d5246 149 *_cmd=cmd;
murilopontes 0:78b46c0d5246 150 return MATCH;
murilopontes 0:78b46c0d5246 151 }
murilopontes 0:78b46c0d5246 152 else if (ret==PARTMATCH)
murilopontes 0:78b46c0d5246 153 {
murilopontes 0:78b46c0d5246 154 if(matched_cmd)
murilopontes 0:78b46c0d5246 155 {
murilopontes 0:78b46c0d5246 156 *_cmd=matched_cmd;
murilopontes 0:78b46c0d5246 157 return AMBIG;
murilopontes 0:78b46c0d5246 158 }
murilopontes 0:78b46c0d5246 159 else
murilopontes 0:78b46c0d5246 160 {
murilopontes 0:78b46c0d5246 161 matched_cmd=cmd;
murilopontes 0:78b46c0d5246 162 }
murilopontes 0:78b46c0d5246 163 }
murilopontes 0:78b46c0d5246 164 else /* UNMATCH */
murilopontes 0:78b46c0d5246 165 {
murilopontes 0:78b46c0d5246 166 }
murilopontes 0:78b46c0d5246 167 }
murilopontes 0:78b46c0d5246 168 if(matched_cmd)
murilopontes 0:78b46c0d5246 169 {
murilopontes 0:78b46c0d5246 170 while(*str && *str!=' ') str++;
murilopontes 0:78b46c0d5246 171 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 172 *_cmd=matched_cmd;
murilopontes 0:78b46c0d5246 173 *_str=str;
murilopontes 0:78b46c0d5246 174 return MATCH;
murilopontes 0:78b46c0d5246 175 }
murilopontes 0:78b46c0d5246 176 else
murilopontes 0:78b46c0d5246 177 return UNMATCH;
murilopontes 0:78b46c0d5246 178 }
murilopontes 0:78b46c0d5246 179
murilopontes 0:78b46c0d5246 180 /* create a context from current input line
murilopontes 0:78b46c0d5246 181 */
murilopontes 0:78b46c0d5246 182 static void do_context(tinysh_cmd_t *cmd, uchar *str)
murilopontes 0:78b46c0d5246 183 {
murilopontes 0:78b46c0d5246 184 while(*str)
murilopontes 0:78b46c0d5246 185 context_buffer[cur_context++]=*str++;
murilopontes 0:78b46c0d5246 186 context_buffer[cur_context]=0;
murilopontes 0:78b46c0d5246 187 cur_cmd_ctx=cmd;
murilopontes 0:78b46c0d5246 188 }
murilopontes 0:78b46c0d5246 189
murilopontes 0:78b46c0d5246 190 /* execute the given command by calling callback with appropriate
murilopontes 0:78b46c0d5246 191 * arguments
murilopontes 0:78b46c0d5246 192 */
murilopontes 0:78b46c0d5246 193 static void exec_command(tinysh_cmd_t *cmd, uchar *str)
murilopontes 0:78b46c0d5246 194 {
murilopontes 0:78b46c0d5246 195 char *argv[MAX_ARGS];
murilopontes 0:78b46c0d5246 196 int argc=0;
murilopontes 0:78b46c0d5246 197 int i;
murilopontes 0:78b46c0d5246 198
murilopontes 0:78b46c0d5246 199 /* copy command line to preserve it for history */
murilopontes 0:78b46c0d5246 200 for(i=0;i<BUFFER_SIZE;i++)
murilopontes 0:78b46c0d5246 201 trash_buffer[i]=str[i];
murilopontes 0:78b46c0d5246 202 str=trash_buffer;
murilopontes 0:78b46c0d5246 203
murilopontes 0:78b46c0d5246 204 /* cut into arguments */
murilopontes 0:78b46c0d5246 205 argv[argc++]=cmd->name;
murilopontes 0:78b46c0d5246 206 while(*str && argc<MAX_ARGS)
murilopontes 0:78b46c0d5246 207 {
murilopontes 0:78b46c0d5246 208 while(*str==' ') str++;
murilopontes 0:78b46c0d5246 209 if(*str==0)
murilopontes 0:78b46c0d5246 210 break;
murilopontes 0:78b46c0d5246 211 argv[argc++]=str;
murilopontes 0:78b46c0d5246 212 while(*str!=' ' && *str) str++;
murilopontes 0:78b46c0d5246 213 if(!*str) break;
murilopontes 0:78b46c0d5246 214 *str++=0;
murilopontes 0:78b46c0d5246 215 }
murilopontes 0:78b46c0d5246 216 /* call command function if present */
murilopontes 0:78b46c0d5246 217 if(cmd->function)
murilopontes 0:78b46c0d5246 218 {
murilopontes 0:78b46c0d5246 219 tinysh_arg=cmd->arg;
murilopontes 0:78b46c0d5246 220 cmd->function(argc,&argv[0]);
murilopontes 0:78b46c0d5246 221 }
murilopontes 0:78b46c0d5246 222 }
murilopontes 0:78b46c0d5246 223
murilopontes 0:78b46c0d5246 224 /* try to execute the current command line
murilopontes 0:78b46c0d5246 225 */
murilopontes 0:78b46c0d5246 226 static int exec_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 227 {
murilopontes 0:78b46c0d5246 228 uchar *str=_str;
murilopontes 0:78b46c0d5246 229
murilopontes 0:78b46c0d5246 230 while(1)
murilopontes 0:78b46c0d5246 231 {
murilopontes 0:78b46c0d5246 232 int ret;
murilopontes 0:78b46c0d5246 233 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 234 if(ret==MATCH) /* found unique match */
murilopontes 0:78b46c0d5246 235 {
murilopontes 0:78b46c0d5246 236 if(cmd)
murilopontes 0:78b46c0d5246 237 {
murilopontes 0:78b46c0d5246 238 if(!cmd->child) /* no sub-command, execute */
murilopontes 0:78b46c0d5246 239 {
murilopontes 0:78b46c0d5246 240 exec_command(cmd,str);
murilopontes 0:78b46c0d5246 241 return 0;
murilopontes 0:78b46c0d5246 242 }
murilopontes 0:78b46c0d5246 243 else
murilopontes 0:78b46c0d5246 244 {
murilopontes 0:78b46c0d5246 245 if(*str==0) /* no more input, this is a context */
murilopontes 0:78b46c0d5246 246 {
murilopontes 0:78b46c0d5246 247 do_context(cmd,_str);
murilopontes 0:78b46c0d5246 248 return 0;
murilopontes 0:78b46c0d5246 249 }
murilopontes 0:78b46c0d5246 250 else /* process next command word */
murilopontes 0:78b46c0d5246 251 {
murilopontes 0:78b46c0d5246 252 cmd=cmd->child;
murilopontes 0:78b46c0d5246 253 }
murilopontes 0:78b46c0d5246 254 }
murilopontes 0:78b46c0d5246 255 }
murilopontes 0:78b46c0d5246 256 else /* cmd == 0 */
murilopontes 0:78b46c0d5246 257 {
murilopontes 0:78b46c0d5246 258 return 0;
murilopontes 0:78b46c0d5246 259 }
murilopontes 0:78b46c0d5246 260 }
murilopontes 0:78b46c0d5246 261 else if(ret==AMBIG)
murilopontes 0:78b46c0d5246 262 {
murilopontes 0:78b46c0d5246 263 puts("ambiguity: ");
murilopontes 0:78b46c0d5246 264 puts(str);
murilopontes 0:78b46c0d5246 265 puts("\r\n");
murilopontes 0:78b46c0d5246 266 return 0;
murilopontes 0:78b46c0d5246 267 }
murilopontes 0:78b46c0d5246 268 else if(ret==UNMATCH) /* UNMATCH */
murilopontes 0:78b46c0d5246 269 {
murilopontes 0:78b46c0d5246 270 puts("no match: ");
murilopontes 0:78b46c0d5246 271 puts(str);
murilopontes 0:78b46c0d5246 272 puts("\r\n");
murilopontes 0:78b46c0d5246 273 return 0;
murilopontes 0:78b46c0d5246 274 }
murilopontes 0:78b46c0d5246 275 else /* NULLMATCH */
murilopontes 0:78b46c0d5246 276 return 0;
murilopontes 0:78b46c0d5246 277 }
murilopontes 0:78b46c0d5246 278 }
murilopontes 0:78b46c0d5246 279
murilopontes 0:78b46c0d5246 280 /* display help for list of commands
murilopontes 0:78b46c0d5246 281 */
murilopontes 0:78b46c0d5246 282 static void display_child_help(tinysh_cmd_t *cmd)
murilopontes 0:78b46c0d5246 283 {
murilopontes 0:78b46c0d5246 284 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 285 int len=0;
murilopontes 0:78b46c0d5246 286
murilopontes 0:78b46c0d5246 287 puts("\r\n");
murilopontes 0:78b46c0d5246 288 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 289 if(len<strlen(cm->name))
murilopontes 0:78b46c0d5246 290 len=strlen(cm->name);
murilopontes 0:78b46c0d5246 291 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 292 if(cm->help)
murilopontes 0:78b46c0d5246 293 {
murilopontes 0:78b46c0d5246 294 int i;
murilopontes 0:78b46c0d5246 295 puts(cm->name);
murilopontes 0:78b46c0d5246 296 for(i=strlen(cm->name);i<len+2;i++)
murilopontes 0:78b46c0d5246 297 putchar(' ');
murilopontes 0:78b46c0d5246 298 puts(cm->help);
murilopontes 0:78b46c0d5246 299 puts("\r\n");
murilopontes 0:78b46c0d5246 300 }
murilopontes 0:78b46c0d5246 301 }
murilopontes 0:78b46c0d5246 302
murilopontes 0:78b46c0d5246 303 /* try to display help for current comand line
murilopontes 0:78b46c0d5246 304 */
murilopontes 0:78b46c0d5246 305 static int help_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 306 {
murilopontes 0:78b46c0d5246 307 uchar *str=_str;
murilopontes 0:78b46c0d5246 308
murilopontes 0:78b46c0d5246 309 while(1)
murilopontes 0:78b46c0d5246 310 {
murilopontes 0:78b46c0d5246 311 int ret;
murilopontes 0:78b46c0d5246 312 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 313 if(ret==MATCH && *str==0) /* found unique match or empty line */
murilopontes 0:78b46c0d5246 314 {
murilopontes 0:78b46c0d5246 315 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 316 int len=0;
murilopontes 0:78b46c0d5246 317
murilopontes 0:78b46c0d5246 318 if(cmd->child) /* display sub-commands help */
murilopontes 0:78b46c0d5246 319 {
murilopontes 0:78b46c0d5246 320 display_child_help(cmd->child);
murilopontes 0:78b46c0d5246 321 return 0;
murilopontes 0:78b46c0d5246 322 }
murilopontes 0:78b46c0d5246 323 else /* no sub-command, show single help */
murilopontes 0:78b46c0d5246 324 {
murilopontes 0:78b46c0d5246 325 if(*(str-1)!=' ')
murilopontes 0:78b46c0d5246 326 putchar(' ');
murilopontes 0:78b46c0d5246 327 if(cmd->usage)
murilopontes 0:78b46c0d5246 328 puts(cmd->usage);
murilopontes 0:78b46c0d5246 329 puts(": ");
murilopontes 0:78b46c0d5246 330 if(cmd->help)
murilopontes 0:78b46c0d5246 331 puts(cmd->help);
murilopontes 0:78b46c0d5246 332 else
murilopontes 0:78b46c0d5246 333 puts("no help available");
murilopontes 0:78b46c0d5246 334 puts("\r\n");
murilopontes 0:78b46c0d5246 335 }
murilopontes 0:78b46c0d5246 336 return 0;
murilopontes 0:78b46c0d5246 337 }
murilopontes 0:78b46c0d5246 338 else if(ret==MATCH && *str)
murilopontes 0:78b46c0d5246 339 { /* continue processing the line */
murilopontes 0:78b46c0d5246 340 cmd=cmd->child;
murilopontes 0:78b46c0d5246 341 }
murilopontes 0:78b46c0d5246 342 else if(ret==AMBIG)
murilopontes 0:78b46c0d5246 343 {
murilopontes 0:78b46c0d5246 344 puts("\r\nambiguity: ");
murilopontes 0:78b46c0d5246 345 puts(str);
murilopontes 0:78b46c0d5246 346 puts("\r\n");
murilopontes 0:78b46c0d5246 347 return 0;
murilopontes 0:78b46c0d5246 348 }
murilopontes 0:78b46c0d5246 349 else if(ret==UNMATCH)
murilopontes 0:78b46c0d5246 350 {
murilopontes 0:78b46c0d5246 351 puts("\r\nno match: ");
murilopontes 0:78b46c0d5246 352 puts(str);
murilopontes 0:78b46c0d5246 353 puts("\r\n");
murilopontes 0:78b46c0d5246 354 return 0;
murilopontes 0:78b46c0d5246 355 }
murilopontes 0:78b46c0d5246 356 else /* NULLMATCH */
murilopontes 0:78b46c0d5246 357 {
murilopontes 0:78b46c0d5246 358 if(cur_cmd_ctx)
murilopontes 0:78b46c0d5246 359 display_child_help(cur_cmd_ctx->child);
murilopontes 0:78b46c0d5246 360 else
murilopontes 0:78b46c0d5246 361 display_child_help(root_cmd);
murilopontes 0:78b46c0d5246 362 return 0;
murilopontes 0:78b46c0d5246 363 }
murilopontes 0:78b46c0d5246 364 }
murilopontes 0:78b46c0d5246 365 }
murilopontes 0:78b46c0d5246 366
murilopontes 0:78b46c0d5246 367 /* try to complete current command line
murilopontes 0:78b46c0d5246 368 */
murilopontes 0:78b46c0d5246 369 static int complete_command_line(tinysh_cmd_t *cmd, uchar *_str)
murilopontes 0:78b46c0d5246 370 {
murilopontes 0:78b46c0d5246 371 uchar *str=_str;
murilopontes 0:78b46c0d5246 372
murilopontes 0:78b46c0d5246 373 while(1)
murilopontes 0:78b46c0d5246 374 {
murilopontes 0:78b46c0d5246 375 int ret;
murilopontes 0:78b46c0d5246 376 int common_len=BUFFER_SIZE;
murilopontes 0:78b46c0d5246 377 int _str_len;
murilopontes 0:78b46c0d5246 378 int i;
murilopontes 0:78b46c0d5246 379 uchar *__str=str;
murilopontes 0:78b46c0d5246 380
murilopontes 0:78b46c0d5246 381 tinysh_cmd_t *_cmd=cmd;
murilopontes 0:78b46c0d5246 382 ret=parse_command(&cmd,&str);
murilopontes 0:78b46c0d5246 383 for(_str_len=0;__str[_str_len]&&__str[_str_len]!=' ';_str_len++);
murilopontes 0:78b46c0d5246 384 if(ret==MATCH && *str)
murilopontes 0:78b46c0d5246 385 {
murilopontes 0:78b46c0d5246 386 cmd=cmd->child;
murilopontes 0:78b46c0d5246 387 }
murilopontes 0:78b46c0d5246 388 else if(ret==AMBIG || ret==MATCH || ret==NULLMATCH)
murilopontes 0:78b46c0d5246 389 {
murilopontes 0:78b46c0d5246 390 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 391 tinysh_cmd_t *matched_cmd=0;
murilopontes 0:78b46c0d5246 392 int nb_match=0;
murilopontes 0:78b46c0d5246 393
murilopontes 0:78b46c0d5246 394 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 395 {
murilopontes 0:78b46c0d5246 396 int r=strstart(cm->name,__str);
murilopontes 0:78b46c0d5246 397 if(r==FULLMATCH)
murilopontes 0:78b46c0d5246 398 {
murilopontes 0:78b46c0d5246 399 for(i=_str_len;cmd->name[i];i++)
murilopontes 0:78b46c0d5246 400 tinysh_char_in(cmd->name[i]);
murilopontes 0:78b46c0d5246 401 if(*(str-1)!=' ')
murilopontes 0:78b46c0d5246 402 tinysh_char_in(' ');
murilopontes 0:78b46c0d5246 403 if(!cmd->child)
murilopontes 0:78b46c0d5246 404 {
murilopontes 0:78b46c0d5246 405 if(cmd->usage)
murilopontes 0:78b46c0d5246 406 {
murilopontes 0:78b46c0d5246 407 puts(cmd->usage);
murilopontes 0:78b46c0d5246 408 putchar('\n');
murilopontes 0:78b46c0d5246 409 return 1;
murilopontes 0:78b46c0d5246 410 }
murilopontes 0:78b46c0d5246 411 else
murilopontes 0:78b46c0d5246 412 return 0;
murilopontes 0:78b46c0d5246 413 }
murilopontes 0:78b46c0d5246 414 else
murilopontes 0:78b46c0d5246 415 {
murilopontes 0:78b46c0d5246 416 cmd=cmd->child;
murilopontes 0:78b46c0d5246 417 break;
murilopontes 0:78b46c0d5246 418 }
murilopontes 0:78b46c0d5246 419 }
murilopontes 0:78b46c0d5246 420 else if(r==PARTMATCH)
murilopontes 0:78b46c0d5246 421 {
murilopontes 0:78b46c0d5246 422 nb_match++;
murilopontes 0:78b46c0d5246 423 if(!matched_cmd)
murilopontes 0:78b46c0d5246 424 {
murilopontes 0:78b46c0d5246 425 matched_cmd=cm;
murilopontes 0:78b46c0d5246 426 common_len=strlen(cm->name);
murilopontes 0:78b46c0d5246 427 }
murilopontes 0:78b46c0d5246 428 else
murilopontes 0:78b46c0d5246 429 {
murilopontes 0:78b46c0d5246 430 for(i=_str_len;cm->name[i] && i<common_len &&
murilopontes 0:78b46c0d5246 431 cm->name[i]==matched_cmd->name[i];i++);
murilopontes 0:78b46c0d5246 432 if(i<common_len)
murilopontes 0:78b46c0d5246 433 common_len=i;
murilopontes 0:78b46c0d5246 434 }
murilopontes 0:78b46c0d5246 435 }
murilopontes 0:78b46c0d5246 436 }
murilopontes 0:78b46c0d5246 437 if(cm)
murilopontes 0:78b46c0d5246 438 continue;
murilopontes 0:78b46c0d5246 439 if(matched_cmd)
murilopontes 0:78b46c0d5246 440 {
murilopontes 0:78b46c0d5246 441 if(_str_len==common_len)
murilopontes 0:78b46c0d5246 442 {
murilopontes 1:71580bf962fe 443 puts("\r\n");
murilopontes 0:78b46c0d5246 444 for(cm=cmd;cm;cm=cm->next)
murilopontes 0:78b46c0d5246 445 {
murilopontes 0:78b46c0d5246 446 int r=strstart(cm->name,__str);
murilopontes 0:78b46c0d5246 447 if(r==FULLMATCH || r==PARTMATCH)
murilopontes 0:78b46c0d5246 448 {
murilopontes 0:78b46c0d5246 449 puts(cm->name);
murilopontes 1:71580bf962fe 450 puts("\r\n");
murilopontes 0:78b46c0d5246 451 }
murilopontes 0:78b46c0d5246 452 }
murilopontes 0:78b46c0d5246 453 return 1;
murilopontes 0:78b46c0d5246 454 }
murilopontes 0:78b46c0d5246 455 else
murilopontes 0:78b46c0d5246 456 {
murilopontes 0:78b46c0d5246 457 for(i=_str_len;i<common_len;i++)
murilopontes 0:78b46c0d5246 458 tinysh_char_in(matched_cmd->name[i]);
murilopontes 0:78b46c0d5246 459 if(nb_match==1)
murilopontes 0:78b46c0d5246 460 tinysh_char_in(' ');
murilopontes 0:78b46c0d5246 461 }
murilopontes 0:78b46c0d5246 462 }
murilopontes 0:78b46c0d5246 463 return 0;
murilopontes 0:78b46c0d5246 464 }
murilopontes 0:78b46c0d5246 465 else /* UNMATCH */
murilopontes 0:78b46c0d5246 466 {
murilopontes 0:78b46c0d5246 467 return 0;
murilopontes 0:78b46c0d5246 468 }
murilopontes 0:78b46c0d5246 469 }
murilopontes 0:78b46c0d5246 470 }
murilopontes 0:78b46c0d5246 471
murilopontes 0:78b46c0d5246 472 /* start a new line
murilopontes 0:78b46c0d5246 473 */
murilopontes 0:78b46c0d5246 474 static void start_of_line()
murilopontes 0:78b46c0d5246 475 {
murilopontes 0:78b46c0d5246 476 /* display start of new line */
murilopontes 0:78b46c0d5246 477 puts(prompt);
murilopontes 0:78b46c0d5246 478 if(cur_context)
murilopontes 0:78b46c0d5246 479 {
murilopontes 0:78b46c0d5246 480 puts(context_buffer);
murilopontes 0:78b46c0d5246 481 puts("> ");
murilopontes 0:78b46c0d5246 482 }
murilopontes 0:78b46c0d5246 483 cur_index=0;
murilopontes 0:78b46c0d5246 484 }
murilopontes 0:78b46c0d5246 485
murilopontes 0:78b46c0d5246 486 /* character input
murilopontes 0:78b46c0d5246 487 */
murilopontes 0:78b46c0d5246 488 static void _tinysh_char_in(uchar c)
murilopontes 0:78b46c0d5246 489 {
murilopontes 0:78b46c0d5246 490 uchar *line=input_buffers[cur_buf_index];
murilopontes 0:78b46c0d5246 491
murilopontes 0:78b46c0d5246 492 if(c=='\n' || c=='\r') /* validate command */
murilopontes 0:78b46c0d5246 493 {
murilopontes 0:78b46c0d5246 494 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 495 int context=0;
murilopontes 0:78b46c0d5246 496
murilopontes 0:78b46c0d5246 497 /* first, echo the newline */
murilopontes 0:78b46c0d5246 498 if(echo)
murilopontes 0:78b46c0d5246 499 putchar(c);
murilopontes 0:78b46c0d5246 500
murilopontes 0:78b46c0d5246 501 while(*line && *line==' ') line++;
murilopontes 0:78b46c0d5246 502 if(*line) /* not empty line */
murilopontes 0:78b46c0d5246 503 {
murilopontes 0:78b46c0d5246 504 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 505 exec_command_line(cmd,line);
murilopontes 0:78b46c0d5246 506 cur_buf_index=(cur_buf_index+1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 507 cur_index=0;
murilopontes 0:78b46c0d5246 508 input_buffers[cur_buf_index][0]=0;
murilopontes 0:78b46c0d5246 509 }
murilopontes 0:78b46c0d5246 510 start_of_line();
murilopontes 0:78b46c0d5246 511 }
murilopontes 0:78b46c0d5246 512 else if(c==TOPCHAR) /* return to top level */
murilopontes 0:78b46c0d5246 513 {
murilopontes 0:78b46c0d5246 514 if(echo)
murilopontes 0:78b46c0d5246 515 putchar(c);
murilopontes 0:78b46c0d5246 516
murilopontes 0:78b46c0d5246 517 cur_context=0;
murilopontes 0:78b46c0d5246 518 cur_cmd_ctx=0;
murilopontes 0:78b46c0d5246 519 }
murilopontes 0:78b46c0d5246 520 else if(c==8 || c==127) /* backspace */
murilopontes 0:78b46c0d5246 521 {
murilopontes 0:78b46c0d5246 522 if(cur_index>0)
murilopontes 0:78b46c0d5246 523 {
murilopontes 0:78b46c0d5246 524 puts("\b \b");
murilopontes 0:78b46c0d5246 525 cur_index--;
murilopontes 0:78b46c0d5246 526 line[cur_index]=0;
murilopontes 0:78b46c0d5246 527 }
murilopontes 0:78b46c0d5246 528 }
murilopontes 0:78b46c0d5246 529 else if(c==16) /* CTRL-P: back in history */
murilopontes 0:78b46c0d5246 530 {
murilopontes 0:78b46c0d5246 531 int prevline=(cur_buf_index+HISTORY_DEPTH-1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 532
murilopontes 0:78b46c0d5246 533 if(input_buffers[prevline][0])
murilopontes 0:78b46c0d5246 534 {
murilopontes 0:78b46c0d5246 535 line=input_buffers[prevline];
murilopontes 0:78b46c0d5246 536 /* fill the rest of the line with spaces */
murilopontes 0:78b46c0d5246 537 while(cur_index-->strlen(line))
murilopontes 0:78b46c0d5246 538 puts("\b \b");
murilopontes 0:78b46c0d5246 539 putchar('\r');
murilopontes 0:78b46c0d5246 540 start_of_line();
murilopontes 0:78b46c0d5246 541 puts(line);
murilopontes 0:78b46c0d5246 542 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 543 cur_buf_index=prevline;
murilopontes 0:78b46c0d5246 544 }
murilopontes 0:78b46c0d5246 545 }
murilopontes 0:78b46c0d5246 546 else if(c==14) /* CTRL-N: next in history */
murilopontes 0:78b46c0d5246 547 {
murilopontes 0:78b46c0d5246 548 int nextline=(cur_buf_index+1)%HISTORY_DEPTH;
murilopontes 0:78b46c0d5246 549
murilopontes 0:78b46c0d5246 550 if(input_buffers[nextline][0])
murilopontes 0:78b46c0d5246 551 {
murilopontes 0:78b46c0d5246 552 line=input_buffers[nextline];
murilopontes 0:78b46c0d5246 553 /* fill the rest of the line with spaces */
murilopontes 0:78b46c0d5246 554 while(cur_index-->strlen(line))
murilopontes 0:78b46c0d5246 555 puts("\b \b");
murilopontes 0:78b46c0d5246 556 putchar('\r');
murilopontes 0:78b46c0d5246 557 start_of_line();
murilopontes 0:78b46c0d5246 558 puts(line);
murilopontes 0:78b46c0d5246 559 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 560 cur_buf_index=nextline;
murilopontes 0:78b46c0d5246 561 }
murilopontes 0:78b46c0d5246 562 }
murilopontes 0:78b46c0d5246 563 else if(c=='?') /* display help */
murilopontes 0:78b46c0d5246 564 {
murilopontes 0:78b46c0d5246 565 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 566 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 567 help_command_line(cmd,line);
murilopontes 0:78b46c0d5246 568 start_of_line();
murilopontes 0:78b46c0d5246 569 puts(line);
murilopontes 0:78b46c0d5246 570 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 571 }
murilopontes 0:78b46c0d5246 572 else if(c==9 || c=='!') /* TAB: autocompletion */
murilopontes 0:78b46c0d5246 573 {
murilopontes 0:78b46c0d5246 574 tinysh_cmd_t *cmd;
murilopontes 0:78b46c0d5246 575 cmd=cur_cmd_ctx?cur_cmd_ctx->child:root_cmd;
murilopontes 0:78b46c0d5246 576 if(complete_command_line(cmd,line))
murilopontes 0:78b46c0d5246 577 {
murilopontes 0:78b46c0d5246 578 start_of_line();
murilopontes 0:78b46c0d5246 579 puts(line);
murilopontes 0:78b46c0d5246 580 }
murilopontes 0:78b46c0d5246 581 cur_index=strlen(line);
murilopontes 0:78b46c0d5246 582 }
murilopontes 0:78b46c0d5246 583 else /* any input character */
murilopontes 0:78b46c0d5246 584 {
murilopontes 0:78b46c0d5246 585 if(cur_index<BUFFER_SIZE)
murilopontes 0:78b46c0d5246 586 {
murilopontes 0:78b46c0d5246 587 if(echo)
murilopontes 0:78b46c0d5246 588 putchar(c);
murilopontes 0:78b46c0d5246 589 line[cur_index++]=c;
murilopontes 0:78b46c0d5246 590 line[cur_index]=0;
murilopontes 0:78b46c0d5246 591 }
murilopontes 0:78b46c0d5246 592 }
murilopontes 0:78b46c0d5246 593 }
murilopontes 0:78b46c0d5246 594
murilopontes 0:78b46c0d5246 595 /* new character input */
murilopontes 0:78b46c0d5246 596 void tinysh_char_in(uchar c)
murilopontes 0:78b46c0d5246 597 {
murilopontes 0:78b46c0d5246 598 /*
murilopontes 0:78b46c0d5246 599 * filter characters here
murilopontes 0:78b46c0d5246 600 */
murilopontes 0:78b46c0d5246 601 _tinysh_char_in(c);
murilopontes 0:78b46c0d5246 602 }
murilopontes 0:78b46c0d5246 603
murilopontes 0:78b46c0d5246 604 /* add a new command */
murilopontes 0:78b46c0d5246 605 void tinysh_add_command(tinysh_cmd_t *cmd)
murilopontes 0:78b46c0d5246 606 {
murilopontes 0:78b46c0d5246 607 tinysh_cmd_t *cm;
murilopontes 0:78b46c0d5246 608
murilopontes 0:78b46c0d5246 609 if(cmd->parent)
murilopontes 0:78b46c0d5246 610 {
murilopontes 0:78b46c0d5246 611 cm=cmd->parent->child;
murilopontes 0:78b46c0d5246 612 if(!cm)
murilopontes 0:78b46c0d5246 613 {
murilopontes 0:78b46c0d5246 614 cmd->parent->child=cmd;
murilopontes 0:78b46c0d5246 615 }
murilopontes 0:78b46c0d5246 616 else
murilopontes 0:78b46c0d5246 617 {
murilopontes 0:78b46c0d5246 618 while(cm->next) cm=cm->next;
murilopontes 0:78b46c0d5246 619 cm->next=cmd;
murilopontes 0:78b46c0d5246 620 }
murilopontes 0:78b46c0d5246 621 }
murilopontes 0:78b46c0d5246 622 else if(!root_cmd)
murilopontes 0:78b46c0d5246 623 {
murilopontes 0:78b46c0d5246 624 root_cmd=cmd;
murilopontes 0:78b46c0d5246 625 }
murilopontes 0:78b46c0d5246 626 else
murilopontes 0:78b46c0d5246 627 {
murilopontes 0:78b46c0d5246 628 cm=root_cmd;
murilopontes 0:78b46c0d5246 629 while(cm->next) cm=cm->next;
murilopontes 0:78b46c0d5246 630 cm->next=cmd;
murilopontes 0:78b46c0d5246 631 }
murilopontes 0:78b46c0d5246 632 }
murilopontes 0:78b46c0d5246 633
murilopontes 0:78b46c0d5246 634 /* modify shell prompt
murilopontes 0:78b46c0d5246 635 */
murilopontes 0:78b46c0d5246 636 void tinysh_set_prompt(char *str)
murilopontes 0:78b46c0d5246 637 {
murilopontes 0:78b46c0d5246 638 int i;
murilopontes 0:78b46c0d5246 639 for(i=0;str[i] && i<PROMPT_SIZE;i++)
murilopontes 0:78b46c0d5246 640 prompt[i]=str[i];
murilopontes 0:78b46c0d5246 641 prompt[i]=0;
murilopontes 0:78b46c0d5246 642 /* force prompt display by generating empty command */
murilopontes 0:78b46c0d5246 643 tinysh_char_in('\r');
murilopontes 0:78b46c0d5246 644 }
murilopontes 0:78b46c0d5246 645
murilopontes 0:78b46c0d5246 646 /* return current command argument
murilopontes 0:78b46c0d5246 647 */
murilopontes 0:78b46c0d5246 648 void *tinysh_get_arg()
murilopontes 0:78b46c0d5246 649 {
murilopontes 0:78b46c0d5246 650 return tinysh_arg;
murilopontes 0:78b46c0d5246 651 }
murilopontes 0:78b46c0d5246 652
murilopontes 0:78b46c0d5246 653 /* string to decimal/hexadecimal conversion
murilopontes 0:78b46c0d5246 654 */
murilopontes 0:78b46c0d5246 655 unsigned long tinysh_atoxi(char *s)
murilopontes 0:78b46c0d5246 656 {
murilopontes 0:78b46c0d5246 657 int ishex=0;
murilopontes 0:78b46c0d5246 658 unsigned long res=0;
murilopontes 0:78b46c0d5246 659
murilopontes 0:78b46c0d5246 660 if(*s==0) return 0;
murilopontes 0:78b46c0d5246 661
murilopontes 0:78b46c0d5246 662 if(*s=='0' && *(s+1)=='x')
murilopontes 0:78b46c0d5246 663 {
murilopontes 0:78b46c0d5246 664 ishex=1;
murilopontes 0:78b46c0d5246 665 s+=2;
murilopontes 0:78b46c0d5246 666 }
murilopontes 0:78b46c0d5246 667
murilopontes 0:78b46c0d5246 668 while(*s)
murilopontes 0:78b46c0d5246 669 {
murilopontes 0:78b46c0d5246 670 if(ishex)
murilopontes 0:78b46c0d5246 671 res*=16;
murilopontes 0:78b46c0d5246 672 else
murilopontes 0:78b46c0d5246 673 res*=10;
murilopontes 0:78b46c0d5246 674
murilopontes 0:78b46c0d5246 675 if(*s>='0' && *s<='9')
murilopontes 0:78b46c0d5246 676 res+=*s-'0';
murilopontes 0:78b46c0d5246 677 else if(ishex && *s>='a' && *s<='f')
murilopontes 0:78b46c0d5246 678 res+=*s+10-'a';
murilopontes 0:78b46c0d5246 679 else if(ishex && *s>='A' && *s<='F')
murilopontes 0:78b46c0d5246 680 res+=*s+10-'A';
murilopontes 0:78b46c0d5246 681 else
murilopontes 0:78b46c0d5246 682 break;
murilopontes 0:78b46c0d5246 683
murilopontes 0:78b46c0d5246 684 s++;
murilopontes 0:78b46c0d5246 685 }
murilopontes 0:78b46c0d5246 686
murilopontes 0:78b46c0d5246 687 return res;
murilopontes 0:78b46c0d5246 688 }
murilopontes 0:78b46c0d5246 689