250 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			250 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Copyright (c) 2006-2021, RT-Thread Development Team | ||
|  |  * | ||
|  |  * SPDX-License-Identifier: Apache-2.0 | ||
|  |  * | ||
|  |  * Change Logs: | ||
|  |  * Date           Author       Notes | ||
|  |  * 2010-03-22     Bernard      first version | ||
|  |  */ | ||
|  | #ifndef __FINSH_H__
 | ||
|  | #define __FINSH_H__
 | ||
|  | 
 | ||
|  | #include <rtthread.h>
 | ||
|  | #include "finsh_api.h"
 | ||
|  | 
 | ||
|  | /* -- the beginning of option -- */ | ||
|  | #define FINSH_NAME_MAX          16      /* max length of identifier */
 | ||
|  | #define FINSH_NODE_MAX          16      /* max number of node */
 | ||
|  | 
 | ||
|  | #define FINSH_HEAP_MAX          128     /* max length of heap */
 | ||
|  | #define FINSH_STRING_MAX        128     /* max length of string */
 | ||
|  | #define FINSH_VARIABLE_MAX      8       /* max number of variable */
 | ||
|  | 
 | ||
|  | #define FINSH_STACK_MAX         64      /* max stack size */
 | ||
|  | #define FINSH_TEXT_MAX          128     /* max text segment size */
 | ||
|  | 
 | ||
|  | #define HEAP_ALIGNMENT          4       /* heap alignment */
 | ||
|  | 
 | ||
|  | #define FINSH_GET16(x)    (*(x)) | (*((x)+1) << 8)
 | ||
|  | #define FINSH_GET32(x)    (rt_uint32_t)(*(x)) | ((rt_uint32_t)*((x)+1) << 8) | \
 | ||
|  |     ((rt_uint32_t)*((x)+2) << 16) | ((rt_uint32_t)*((x)+3) << 24) | ||
|  | 
 | ||
|  | #define FINSH_SET16(x, v)           \
 | ||
|  |     do                              \ | ||
|  |     {                               \ | ||
|  |         *(x)     = (v) & 0x00ff;    \ | ||
|  |         (*((x)+1)) = (v) >> 8;      \ | ||
|  |     } while ( 0 ) | ||
|  | 
 | ||
|  | #define FINSH_SET32(x, v)                                       \
 | ||
|  |     do                                                          \ | ||
|  |     {                                                           \ | ||
|  |         *(x)     = (rt_uint32_t)(v)  & 0x000000ff;              \ | ||
|  |         (*((x)+1)) = ((rt_uint32_t)(v) >> 8) & 0x000000ff;      \ | ||
|  |         (*((x)+2)) = ((rt_uint32_t)(v) >> 16) & 0x000000ff;     \ | ||
|  |         (*((x)+3)) = ((rt_uint32_t)(v) >> 24);                  \ | ||
|  |     } while ( 0 ) | ||
|  | 
 | ||
|  | /* -- the end of option -- */ | ||
|  | 
 | ||
|  | /* std header file */ | ||
|  | #include <stdio.h>
 | ||
|  | #include <ctype.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <stdint.h>
 | ||
|  | #include <string.h>
 | ||
|  | 
 | ||
|  | #define FINSH_VERSION_MAJOR         1
 | ||
|  | #define FINSH_VERSION_MINOR         0
 | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @addtogroup finsh | ||
|  |  */ | ||
|  | /*@{*/ | ||
|  | #define FINSH_ERROR_OK              0   /**< No error           */
 | ||
|  | #define FINSH_ERROR_INVALID_TOKEN   1   /**< Invalid token      */
 | ||
|  | #define FINSH_ERROR_EXPECT_TYPE     2   /**< Expect a type      */
 | ||
|  | #define FINSH_ERROR_UNKNOWN_TYPE    3   /**< Unknown type       */
 | ||
|  | #define FINSH_ERROR_VARIABLE_EXIST  4   /**< Variable exist     */
 | ||
|  | #define FINSH_ERROR_EXPECT_OPERATOR 5   /**< Expect a operator  */
 | ||
|  | #define FINSH_ERROR_MEMORY_FULL     6   /**< Memory full        */
 | ||
|  | #define FINSH_ERROR_UNKNOWN_OP      7   /**< Unknown operator   */
 | ||
|  | #define FINSH_ERROR_UNKNOWN_NODE    8   /**< Unknown node       */
 | ||
|  | #define FINSH_ERROR_EXPECT_CHAR     9   /**< Expect a character */
 | ||
|  | #define FINSH_ERROR_UNEXPECT_END    10  /**< Unexpect end       */
 | ||
|  | #define FINSH_ERROR_UNKNOWN_TOKEN   11  /**< Unknown token      */
 | ||
|  | #define FINSH_ERROR_NO_FLOAT        12  /**< Float not supported */
 | ||
|  | #define FINSH_ERROR_UNKNOWN_SYMBOL  13  /**< Unknown symbol     */
 | ||
|  | #define FINSH_ERROR_NULL_NODE       14  /**< Null node          */
 | ||
|  | /*@}*/ | ||
|  | 
 | ||
|  | /* system call item */ | ||
|  | struct finsh_syscall_item | ||
|  | { | ||
|  |     struct finsh_syscall_item* next;    /* next item */ | ||
|  |     struct finsh_syscall syscall;       /* syscall */ | ||
|  | }; | ||
|  | extern struct finsh_syscall_item *global_syscall_list; | ||
|  | 
 | ||
|  | /* system variable table */ | ||
|  | struct finsh_sysvar | ||
|  | { | ||
|  |     const char*     name;       /* the name of variable */ | ||
|  | #if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
 | ||
|  |     const char*     desc;       /* description of system variable */ | ||
|  | #endif
 | ||
|  |     uint8_t      type;      /* the type of variable */ | ||
|  |     void*        var ;      /* the address of variable */ | ||
|  | }; | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
 | ||
|  | struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call); | ||
|  | struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call); | ||
|  | #define FINSH_NEXT_SYSCALL(index)  index=finsh_syscall_next(index)
 | ||
|  | #define FINSH_NEXT_SYSVAR(index)   index=finsh_sysvar_next(index)
 | ||
|  | #else
 | ||
|  | #define FINSH_NEXT_SYSCALL(index)  index++
 | ||
|  | #define FINSH_NEXT_SYSVAR(index)   index++
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* system variable item */ | ||
|  | struct finsh_sysvar_item | ||
|  | { | ||
|  |     struct finsh_sysvar_item *next;     /* next item */ | ||
|  |     struct finsh_sysvar sysvar;         /* system variable */ | ||
|  | }; | ||
|  | extern struct finsh_sysvar *_sysvar_table_begin, *_sysvar_table_end; | ||
|  | extern struct finsh_sysvar_item* global_sysvar_list; | ||
|  | 
 | ||
|  | /* find out system variable, which should be implemented in user program */ | ||
|  | struct finsh_sysvar* finsh_sysvar_lookup(const char* name); | ||
|  | 
 | ||
|  | 
 | ||
|  | struct finsh_token | ||
|  | { | ||
|  |     char eof; | ||
|  |     char replay; | ||
|  | 
 | ||
|  |     int  position; | ||
|  |     uint8_t current_token; | ||
|  | 
 | ||
|  |     union { | ||
|  |         char char_value; | ||
|  |         int int_value; | ||
|  |         long long_value; | ||
|  |     } value; | ||
|  |     uint8_t string[FINSH_STRING_MAX]; | ||
|  | 
 | ||
|  |     uint8_t* line; | ||
|  | }; | ||
|  | 
 | ||
|  | #define FINSH_IDTYPE_VAR        0x01
 | ||
|  | #define FINSH_IDTYPE_SYSVAR     0x02
 | ||
|  | #define FINSH_IDTYPE_SYSCALL    0x04
 | ||
|  | #define FINSH_IDTYPE_ADDRESS    0x08
 | ||
|  | struct finsh_node | ||
|  | { | ||
|  |     uint8_t node_type;  /* node node_type */ | ||
|  |     uint8_t data_type;  /* node data node_type */ | ||
|  |     uint8_t idtype;     /* id node information */ | ||
|  | 
 | ||
|  |     union {         /* value node */ | ||
|  |         char    char_value; | ||
|  |         short   short_value; | ||
|  |         int     int_value; | ||
|  |         long    long_value; | ||
|  |         void*   ptr; | ||
|  |     } value; | ||
|  |     union | ||
|  |     { | ||
|  |         /* point to variable identifier or function identifier */ | ||
|  |         struct finsh_var    *var; | ||
|  |         struct finsh_sysvar *sysvar; | ||
|  |         struct finsh_syscall*syscall; | ||
|  |     }id; | ||
|  | 
 | ||
|  |     /* sibling and child node */ | ||
|  |     struct finsh_node *sibling, *child; | ||
|  | }; | ||
|  | 
 | ||
|  | struct finsh_parser | ||
|  | { | ||
|  |     uint8_t* parser_string; | ||
|  | 
 | ||
|  |     struct finsh_token token; | ||
|  |     struct finsh_node* root; | ||
|  | }; | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @ingroup finsh | ||
|  |  * | ||
|  |  * The basic data type in finsh shell | ||
|  |  */ | ||
|  | enum finsh_type { | ||
|  |     finsh_type_unknown = 0, /**< unknown data type */ | ||
|  |     finsh_type_void,        /**< void           */ | ||
|  |     finsh_type_voidp,       /**< void pointer   */ | ||
|  |     finsh_type_char,        /**< char           */ | ||
|  |     finsh_type_uchar,       /**< unsigned char  */ | ||
|  |     finsh_type_charp,       /**< char pointer   */ | ||
|  |     finsh_type_short,       /**< short          */ | ||
|  |     finsh_type_ushort,      /**< unsigned short */ | ||
|  |     finsh_type_shortp,      /**< short pointer  */ | ||
|  |     finsh_type_int,         /**< int            */ | ||
|  |     finsh_type_uint,        /**< unsigned int   */ | ||
|  |     finsh_type_intp,        /**< int pointer    */ | ||
|  |     finsh_type_long,        /**< long           */ | ||
|  |     finsh_type_ulong,       /**< unsigned long  */ | ||
|  |     finsh_type_longp        /**< long pointer   */ | ||
|  | }; | ||
|  | 
 | ||
|  | /* init finsh environment */ | ||
|  | int finsh_init(struct finsh_parser* parser); | ||
|  | /* flush finsh node, text segment */ | ||
|  | int finsh_flush(struct finsh_parser* parser); | ||
|  | /* reset all of finsh */ | ||
|  | int finsh_reset(struct finsh_parser* parser); | ||
|  | #ifdef RT_USING_DEVICE
 | ||
|  | void finsh_set_device(const char* device_name); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* run finsh parser to generate abstract synatx tree */ | ||
|  | void finsh_parser_run (struct finsh_parser* parser, const unsigned char* string); | ||
|  | /* run compiler to compile abstract syntax tree */ | ||
|  | int finsh_compiler_run(struct finsh_node* node); | ||
|  | /* run finsh virtual machine */ | ||
|  | void finsh_vm_run(void); | ||
|  | 
 | ||
|  | /* get variable value */ | ||
|  | struct finsh_var* finsh_var_lookup(const char* name); | ||
|  | /* get bottom value of stack */ | ||
|  | long finsh_stack_bottom(void); | ||
|  | 
 | ||
|  | /* get error number of finsh */ | ||
|  | uint8_t finsh_errno(void); | ||
|  | /* get error string */ | ||
|  | const char* finsh_error_string(uint8_t type); | ||
|  | 
 | ||
|  | #ifdef RT_USING_HEAP
 | ||
|  | /**
 | ||
|  |  * @ingroup finsh | ||
|  |  * | ||
|  |  * This function appends a system call to finsh runtime environment | ||
|  |  * @param name the name of system call | ||
|  |  * @param func the function pointer of system call | ||
|  |  */ | ||
|  | void finsh_syscall_append(const char* name, syscall_func func); | ||
|  | 
 | ||
|  | /**
 | ||
|  |  * @ingroup finsh | ||
|  |  * | ||
|  |  * This function appends a system variable to finsh runtime environment | ||
|  |  * @param name the name of system variable | ||
|  |  * @param type the data type of system variable | ||
|  |  * @param addr the address of system variable | ||
|  |  */ | ||
|  | void finsh_sysvar_append(const char* name, uint8_t type, void* addr); | ||
|  | #endif
 | ||
|  | #endif
 |