mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-23 04:04:15 +08:00
move to components directory
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@635 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
Import('env')
|
||||
Import('RTT_ROOT')
|
||||
|
||||
# The set of source files associated with this SConscript file.
|
||||
src_local = Glob('*.c')
|
||||
|
||||
env.Append(CPPPATH = RTT_ROOT + '/finsh')
|
||||
|
||||
obj = env.Object(src_local)
|
||||
Return('obj')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* File : finsh.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_H__
|
||||
#define __FINSH_H__
|
||||
|
||||
#include <rtthread.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 128 /* 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) (*(x)) | (*((x)+1) << 8) | (*((x)+2) << 16) | (*((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) = (v) & 0x000000ff; \
|
||||
(*((x)+1)) = ((v) >> 8) & 0x000000ff; \
|
||||
(*((x)+2)) = ((v) >> 16) & 0x000000ff; \
|
||||
(*((x)+3)) = ((v) >> 24); \
|
||||
} while ( 0 )
|
||||
|
||||
/* -- the end of option -- */
|
||||
|
||||
/**
|
||||
* @defgroup finsh finsh shell
|
||||
*
|
||||
* finsh is a C-expression shell which gives user access to some symbols present in RT-Thread.
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#if defined(RT_USING_NEWLIB) || defined (RT_USING_MINILIBC)
|
||||
#include <string.h>
|
||||
#else
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned long u_long;
|
||||
|
||||
#if !defined(__CC_ARM) && !defined(__ICCARM__) && !defined(__ICCM16C__)
|
||||
typedef unsigned int size_t;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL RT_NULL
|
||||
#endif
|
||||
|
||||
#define memset rt_memset
|
||||
#define strlen rt_strlen
|
||||
#define strncpy rt_strncpy
|
||||
#define strncmp rt_strncmp
|
||||
|
||||
int strcmp (const char *s1, const char *s2);
|
||||
char *strdup(const char *s);
|
||||
|
||||
int isalpha( int ch );
|
||||
int atoi(const char* s);
|
||||
#else
|
||||
/* use libc of armcc */
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FINSH_VERSION_MAJOR 0
|
||||
#define FINSH_VERSION_MINOR 5
|
||||
|
||||
/* error code */
|
||||
#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 operater */
|
||||
#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 */
|
||||
|
||||
typedef long (*syscall_func)();
|
||||
|
||||
/* system call table */
|
||||
struct finsh_syscall
|
||||
{
|
||||
const char* name; /* the name of system call */
|
||||
#if defined(FINSH_USING_DESCRIPTION) && defined(FINSH_USING_SYMTAB)
|
||||
const char* desc; /* description of system call */
|
||||
#endif
|
||||
syscall_func func; /* the function address of system call */
|
||||
};
|
||||
/* system call item */
|
||||
struct finsh_syscall_item
|
||||
{
|
||||
struct finsh_syscall_item* next; /* next item */
|
||||
struct finsh_syscall syscall; /* syscall */
|
||||
};
|
||||
extern struct finsh_syscall *_syscall_table_begin, *_syscall_table_end;
|
||||
extern struct finsh_syscall_item *global_syscall_list;
|
||||
|
||||
/* find out system call, which should be implemented in user program */
|
||||
struct finsh_syscall* finsh_syscall_lookup(const char* name);
|
||||
|
||||
/* 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
|
||||
u_char type; /* the type of variable */
|
||||
void* var ; /* the address of variable */
|
||||
};
|
||||
/* 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);
|
||||
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
#ifdef FINSH_USING_DESCRIPTION
|
||||
#define FINSH_FUNCTION_EXPORT(name, desc) \
|
||||
const char __fsym_##name##_name[] = #name; \
|
||||
const char __fsym_##name##_desc[] = #desc; \
|
||||
const struct finsh_syscall __fsym_##name SECTION("FSymTab")= \
|
||||
{ \
|
||||
__fsym_##name##_name, \
|
||||
__fsym_##name##_desc, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
const char __vsym_##name##_desc[] = #desc; \
|
||||
const struct finsh_sysvar __vsym_##name SECTION("VSymTab")= \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
__vsym_##name##_desc, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
#else
|
||||
#define FINSH_FUNCTION_EXPORT(name, desc) \
|
||||
const char __fsym_##name##_name[] = #name; \
|
||||
const struct finsh_syscall __fsym_##name SECTION("FSymTab")= \
|
||||
{ \
|
||||
__fsym_##name##_name, \
|
||||
(syscall_func)&name \
|
||||
};
|
||||
|
||||
#define FINSH_VAR_EXPORT(name, type, desc) \
|
||||
const char __vsym_##name##_name[] = #name; \
|
||||
const struct finsh_sysvar __vsym_##name SECTION("VSymTab")= \
|
||||
{ \
|
||||
__vsym_##name##_name, \
|
||||
type, \
|
||||
(void*)&name \
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
#define FINSH_FUNCTION_EXPORT(name, desc)
|
||||
#define FINSH_VAR_EXPORT(name, type, desc)
|
||||
#endif
|
||||
|
||||
struct finsh_token
|
||||
{
|
||||
char eof;
|
||||
char replay;
|
||||
|
||||
int position;
|
||||
u_char current_token;
|
||||
|
||||
union {
|
||||
char char_value;
|
||||
int int_value;
|
||||
long long_value;
|
||||
} value;
|
||||
u_char string[128];
|
||||
|
||||
u_char* line;
|
||||
};
|
||||
|
||||
#define FINSH_IDTYPE_VAR 0x01
|
||||
#define FINSH_IDTYPE_SYSVAR 0x02
|
||||
#define FINSH_IDTYPE_SYSCALL 0x04
|
||||
#define FINSH_IDTYPE_ADDRESS 0x08
|
||||
struct finsh_node
|
||||
{
|
||||
u_char node_type; /* node node_type */
|
||||
u_char data_type; /* node data node_type */
|
||||
u_char 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
|
||||
{
|
||||
u_char* parser_string;
|
||||
|
||||
struct finsh_token token;
|
||||
struct finsh_node* root;
|
||||
};
|
||||
|
||||
/**
|
||||
* finsh basic data type
|
||||
*/
|
||||
enum finsh_type {
|
||||
finsh_type_unknown = 0,
|
||||
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
|
||||
/* set finsh 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 */
|
||||
u_char finsh_errno(void);
|
||||
/* get error string */
|
||||
const char* finsh_error_string(u_char type);
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/**
|
||||
* append 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);
|
||||
/**
|
||||
* append 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, u_char type, void* addr);
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* File : finsh_error.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include "finsh_error.h"
|
||||
|
||||
u_char global_errno;
|
||||
|
||||
const char* finsh_error_string_table[] =
|
||||
{
|
||||
"No error",
|
||||
"Invalid token",
|
||||
"Expect a type",
|
||||
"Unknown type",
|
||||
"Variable exist",
|
||||
"Expect a operater",
|
||||
"Memory full",
|
||||
"Unknown operator",
|
||||
"Unknown node",
|
||||
"Expect a character",
|
||||
"Unexpect end",
|
||||
"Unknown token",
|
||||
"Float not supported",
|
||||
"Unknown symbol",
|
||||
"Null node"
|
||||
};
|
||||
|
||||
int finsh_error_init()
|
||||
{
|
||||
global_errno = FINSH_ERROR_OK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finsh_error_set(u_char type)
|
||||
{
|
||||
global_errno = type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_char finsh_errno()
|
||||
{
|
||||
return global_errno;
|
||||
}
|
||||
|
||||
const char* finsh_error_string(u_char type)
|
||||
{
|
||||
return finsh_error_string_table[type];
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* File : finsh_error.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_ERROR_H__
|
||||
#define __FINSH_ERROR_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
int finsh_error_init(void);
|
||||
|
||||
/* get error number */
|
||||
u_char finsh_errno(void);
|
||||
|
||||
int finsh_error_set(u_char type);
|
||||
const char* finsh_error_string(u_char type);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* File : finsh_heap.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
|
||||
#include "finsh_var.h"
|
||||
|
||||
u_char finsh_heap[FINSH_HEAP_MAX];
|
||||
struct finsh_block_header
|
||||
{
|
||||
u_long length;
|
||||
struct finsh_block_header* next;
|
||||
};
|
||||
#define BLOCK_HEADER(x) (struct finsh_block_header*)(x)
|
||||
#define finsh_block_get_header(data) (struct finsh_block_header*)((u_char*)data - sizeof(struct finsh_block_header))
|
||||
#define finsh_block_get_data(header) (u_char*)((struct finsh_block_header*)header + 1)
|
||||
#define HEAP_ALIGN_SIZE(size) (((size) + HEAP_ALIGNMENT - 1) & ~(HEAP_ALIGNMENT-1))
|
||||
|
||||
static struct finsh_block_header* free_list;
|
||||
static struct finsh_block_header* allocate_list;
|
||||
|
||||
static void finsh_heap_gc(void);
|
||||
|
||||
static void finsh_block_insert(struct finsh_block_header** list, struct finsh_block_header* header);
|
||||
static void finsh_block_remove(struct finsh_block_header** list, struct finsh_block_header* header);
|
||||
static void finsh_block_split(struct finsh_block_header* header, size_t size);
|
||||
static void finsh_block_merge(struct finsh_block_header** list, struct finsh_block_header* header);
|
||||
|
||||
int finsh_heap_init(void)
|
||||
{
|
||||
/* clear heap to zero */
|
||||
memset(&finsh_heap[0], 0, sizeof(finsh_heap));
|
||||
|
||||
/* init free and alloc list */
|
||||
free_list = BLOCK_HEADER(&finsh_heap[0]);
|
||||
free_list->length = FINSH_HEAP_MAX - sizeof(struct finsh_block_header);
|
||||
free_list->next = NULL;
|
||||
|
||||
allocate_list = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate a block from heap
|
||||
*/
|
||||
void* finsh_heap_allocate(size_t size)
|
||||
{
|
||||
struct finsh_block_header* header;
|
||||
|
||||
size = HEAP_ALIGN_SIZE(size);
|
||||
|
||||
/* find the first fit block */
|
||||
for (header = free_list;
|
||||
((header != NULL) && (header->length <= size + sizeof(struct finsh_block_header)));
|
||||
header = header->next) ;
|
||||
|
||||
if (header == NULL)
|
||||
{
|
||||
finsh_heap_gc();
|
||||
|
||||
/* find the first fit block */
|
||||
for (header = free_list;
|
||||
((header != NULL) && (header->length < size + sizeof(struct finsh_block_header)));
|
||||
header = header->next) ;
|
||||
|
||||
/* there is no memory */
|
||||
if (header == NULL) return NULL;
|
||||
}
|
||||
|
||||
/* split block */
|
||||
finsh_block_split(header, size);
|
||||
|
||||
/* remove from free list */
|
||||
finsh_block_remove(&free_list, header);
|
||||
header->next = NULL;
|
||||
|
||||
/* insert to allocate list */
|
||||
finsh_block_insert(&allocate_list, header);
|
||||
|
||||
memset(finsh_block_get_data(header), 0, size);
|
||||
|
||||
return finsh_block_get_data(header);
|
||||
}
|
||||
|
||||
/**
|
||||
* release the allocated block
|
||||
*/
|
||||
void finsh_heap_free(void*ptr)
|
||||
{
|
||||
struct finsh_block_header* header;
|
||||
|
||||
/* get block header */
|
||||
header = finsh_block_get_header(ptr);
|
||||
|
||||
/* remove from allocate list */
|
||||
finsh_block_remove(&allocate_list, header);
|
||||
|
||||
/* insert to free list */
|
||||
finsh_block_insert(&free_list, header);
|
||||
finsh_block_merge(&free_list, header);
|
||||
}
|
||||
|
||||
/**
|
||||
* garbage collector
|
||||
*/
|
||||
static void finsh_heap_gc(void)
|
||||
{
|
||||
int i;
|
||||
struct finsh_block_header *header, *temp;
|
||||
|
||||
temp = NULL;
|
||||
|
||||
/* find the first fit block */
|
||||
for (header = allocate_list; header != NULL; )
|
||||
{
|
||||
for (i = 0; i < FINSH_VARIABLE_MAX; i ++)
|
||||
{
|
||||
if (global_variable[i].type != finsh_type_unknown)
|
||||
{
|
||||
if (global_variable[i].value.ptr == finsh_block_get_data(header))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
temp = header;
|
||||
header = header->next;
|
||||
|
||||
/* this block is an unused block, release it */
|
||||
if (i == FINSH_VARIABLE_MAX)
|
||||
{
|
||||
finsh_heap_free(finsh_block_get_data(temp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* insert a block to list
|
||||
*/
|
||||
void finsh_block_insert(struct finsh_block_header** list, struct finsh_block_header* header)
|
||||
{
|
||||
struct finsh_block_header* node;
|
||||
|
||||
if (*list == NULL)
|
||||
{
|
||||
*list = header;
|
||||
return;
|
||||
}
|
||||
|
||||
/* find out insert point */
|
||||
node = *list;
|
||||
|
||||
if (node > header)
|
||||
{
|
||||
/* insert node in the header of list */
|
||||
header->next = node;
|
||||
*list = header;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (node = *list; node; node = node->next)
|
||||
{
|
||||
if (node->next > header) break;
|
||||
|
||||
if (node->next == NULL) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert node */
|
||||
if (node->next != NULL) header->next = node->next;
|
||||
node->next = header;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove block from list
|
||||
*/
|
||||
void finsh_block_remove(struct finsh_block_header** list, struct finsh_block_header* header)
|
||||
{
|
||||
struct finsh_block_header* node;
|
||||
|
||||
node = *list;
|
||||
if (node == header)
|
||||
{
|
||||
/* remove list header */
|
||||
*list = header->next;
|
||||
header->next = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (node = *list; node != NULL; node = node->next)
|
||||
{
|
||||
if (node->next == header)
|
||||
{
|
||||
node->next = header->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* split block
|
||||
*/
|
||||
void finsh_block_split(struct finsh_block_header* header, size_t size)
|
||||
{
|
||||
struct finsh_block_header* next;
|
||||
|
||||
/*
|
||||
* split header into two node:
|
||||
* header->next->...
|
||||
*/
|
||||
next = BLOCK_HEADER((u_char*)header + sizeof(struct finsh_block_header) + size);
|
||||
next->length = header->length - sizeof(struct finsh_block_header) - size;
|
||||
header->length = size;
|
||||
next->next = header->next;
|
||||
|
||||
header->next = next;
|
||||
}
|
||||
|
||||
void finsh_block_merge(struct finsh_block_header** list, struct finsh_block_header* header)
|
||||
{
|
||||
struct finsh_block_header* prev_node;
|
||||
struct finsh_block_header* next_node;
|
||||
|
||||
next_node = header->next;
|
||||
|
||||
if (*list == header) prev_node = NULL;
|
||||
else
|
||||
{
|
||||
/* find out the previous header */
|
||||
for (prev_node = *list; prev_node; prev_node =prev_node->next)
|
||||
{
|
||||
if (prev_node->next == header)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* try merge node */
|
||||
|
||||
/* merge to previous node */
|
||||
if (prev_node != NULL &&
|
||||
((u_char*)prev_node + prev_node->length + sizeof(struct finsh_block_header)
|
||||
== (u_char*)header))
|
||||
{
|
||||
/* is it close to next node? */
|
||||
if ((next_node != NULL) &&
|
||||
((u_char*)header + header->length + sizeof(struct finsh_block_header)
|
||||
== (u_char*)next_node))
|
||||
{
|
||||
/* merge three node */
|
||||
prev_node->length += header->length + next_node->length +
|
||||
2 * sizeof(struct finsh_block_header);
|
||||
|
||||
prev_node->next = next_node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev_node->length += header->length + sizeof(struct finsh_block_header);
|
||||
prev_node->next = header->next;
|
||||
}
|
||||
}
|
||||
else /* merge to last node */
|
||||
if ( (next_node != NULL) &&
|
||||
((u_char*)header + header->length + sizeof(struct finsh_block_header)
|
||||
== (u_char*)next_node))
|
||||
{
|
||||
header->length += next_node->length + sizeof(struct finsh_block_header);
|
||||
header->next = next_node->next;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* File : finsh_heap.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
|
||||
#ifndef __FINSH_HEAP_H__
|
||||
#define __FINSH_HEAP_H__
|
||||
|
||||
int finsh_heap_init(void);
|
||||
void* finsh_heap_allocate(size_t size);
|
||||
void finsh_heap_free(void*ptr);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* File : finsh_init.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
|
||||
#include "finsh_node.h"
|
||||
#include "finsh_vm.h"
|
||||
#include "finsh_parser.h"
|
||||
#include "finsh_var.h"
|
||||
#include "finsh_error.h"
|
||||
#include "finsh_heap.h"
|
||||
|
||||
int finsh_init(struct finsh_parser* parser)
|
||||
{
|
||||
finsh_parser_init(parser);
|
||||
|
||||
/* finsh init */
|
||||
finsh_node_init();
|
||||
finsh_var_init();
|
||||
finsh_error_init();
|
||||
finsh_heap_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long finsh_stack_bottom()
|
||||
{
|
||||
return finsh_vm_stack[0].long_value;
|
||||
}
|
||||
|
||||
int finsh_flush(struct finsh_parser* parser)
|
||||
{
|
||||
finsh_parser_init(parser);
|
||||
|
||||
/* finsh init */
|
||||
finsh_node_init();
|
||||
finsh_error_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finsh_reset(struct finsh_parser* parser)
|
||||
{
|
||||
/* finsh init */
|
||||
finsh_node_init();
|
||||
finsh_var_init();
|
||||
finsh_error_init();
|
||||
finsh_heap_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* File : finsh_node.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
|
||||
#include "finsh_node.h"
|
||||
#include "finsh_error.h"
|
||||
#include "finsh_var.h"
|
||||
#include "finsh_heap.h"
|
||||
|
||||
struct finsh_node global_node_table[FINSH_NODE_MAX];
|
||||
|
||||
int finsh_node_init()
|
||||
{
|
||||
memset(global_node_table, 0, sizeof(global_node_table));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_allocate(u_char type)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* find an empty entry */
|
||||
for (i = 0; i < FINSH_NODE_MAX; i ++)
|
||||
{
|
||||
if (global_node_table[i].node_type == FINSH_NODE_UNKNOWN) break;
|
||||
}
|
||||
|
||||
if (i == FINSH_NODE_MAX) return NULL;
|
||||
|
||||
/* fill type field */
|
||||
global_node_table[i].node_type = type;
|
||||
|
||||
/* return this allocated node */
|
||||
return &global_node_table[i];
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_id(char* id)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
void* symbol;
|
||||
unsigned char type;
|
||||
|
||||
symbol = NULL;
|
||||
type = 0;
|
||||
node = NULL;
|
||||
|
||||
/* lookup variable firstly */
|
||||
symbol = (void*)finsh_var_lookup(id);
|
||||
if (symbol == NULL)
|
||||
{
|
||||
/* then lookup system variable */
|
||||
symbol = (void*)finsh_sysvar_lookup(id);
|
||||
if (symbol == NULL)
|
||||
{
|
||||
/* then lookup system call */
|
||||
symbol = (void*)finsh_syscall_lookup(id);
|
||||
if (symbol != NULL) type = FINSH_IDTYPE_SYSCALL;
|
||||
}
|
||||
else type = FINSH_IDTYPE_SYSVAR;
|
||||
}
|
||||
else type = FINSH_IDTYPE_VAR;
|
||||
|
||||
if (symbol != NULL)
|
||||
{
|
||||
/* allocate a new node */
|
||||
node = finsh_node_allocate(FINSH_NODE_ID);
|
||||
|
||||
/* allocate node error */
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill node value according type */
|
||||
switch (type)
|
||||
{
|
||||
case FINSH_IDTYPE_VAR:
|
||||
node->id.var = (struct finsh_var*)symbol;
|
||||
break;
|
||||
|
||||
case FINSH_IDTYPE_SYSVAR:
|
||||
node->id.sysvar = (struct finsh_sysvar*)symbol;
|
||||
break;
|
||||
|
||||
case FINSH_IDTYPE_SYSCALL:
|
||||
node->id.syscall = (struct finsh_syscall*)symbol;
|
||||
break;
|
||||
}
|
||||
/* fill identifier type */
|
||||
node->idtype = type;
|
||||
}
|
||||
else finsh_error_set(FINSH_ERROR_UNKNOWN_SYMBOL);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_char(char c)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
|
||||
node = finsh_node_allocate(FINSH_NODE_VALUE_CHAR);
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->value.char_value = c;
|
||||
return node;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_int(int i)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
|
||||
node = finsh_node_allocate(FINSH_NODE_VALUE_INT);
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->value.int_value = i;
|
||||
return node;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_long(long l)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
|
||||
node = finsh_node_allocate(FINSH_NODE_VALUE_LONG);
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->value.long_value = l;
|
||||
return node;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_string(char* s)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
|
||||
node = finsh_node_allocate(FINSH_NODE_VALUE_STRING);
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* make string */
|
||||
node->value.ptr = finsh_heap_allocate(strlen(s) + 1);
|
||||
strncpy(node->value.ptr, s, strlen(s));
|
||||
((u_char*)node->value.ptr)[strlen(s)] = '\0';
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
struct finsh_node* finsh_node_new_ptr(void* ptr)
|
||||
{
|
||||
struct finsh_node* node;
|
||||
|
||||
node = finsh_node_allocate(FINSH_NODE_VALUE_NULL);
|
||||
if (node == NULL)
|
||||
{
|
||||
finsh_error_set(FINSH_ERROR_MEMORY_FULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->value.ptr = ptr;
|
||||
return node;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* File : finsh_node.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_NODE_H__
|
||||
#define __FINSH_NODE_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
#define FINSH_NODE_UNKNOWN 0
|
||||
#define FINSH_NODE_ID 1
|
||||
|
||||
#define FINSH_NODE_VALUE_CHAR 2
|
||||
#define FINSH_NODE_VALUE_INT 3
|
||||
#define FINSH_NODE_VALUE_LONG 4
|
||||
#define FINSH_NODE_VALUE_STRING 5
|
||||
#define FINSH_NODE_VALUE_NULL 6
|
||||
|
||||
#define FINSH_NODE_SYS_ADD 7
|
||||
#define FINSH_NODE_SYS_SUB 8
|
||||
#define FINSH_NODE_SYS_MUL 9
|
||||
#define FINSH_NODE_SYS_DIV 10
|
||||
#define FINSH_NODE_SYS_MOD 11
|
||||
#define FINSH_NODE_SYS_AND 12
|
||||
#define FINSH_NODE_SYS_OR 13
|
||||
#define FINSH_NODE_SYS_XOR 14
|
||||
#define FINSH_NODE_SYS_BITWISE 15
|
||||
#define FINSH_NODE_SYS_SHL 16
|
||||
#define FINSH_NODE_SYS_SHR 17
|
||||
#define FINSH_NODE_SYS_FUNC 18
|
||||
#define FINSH_NODE_SYS_ASSIGN 19
|
||||
#define FINSH_NODE_SYS_CAST 20
|
||||
#define FINSH_NODE_SYS_PREINC 21
|
||||
#define FINSH_NODE_SYS_PREDEC 22
|
||||
#define FINSH_NODE_SYS_INC 23
|
||||
#define FINSH_NODE_SYS_DEC 24
|
||||
#define FINSH_NODE_SYS_GETVALUE 25
|
||||
#define FINSH_NODE_SYS_GETADDR 26
|
||||
#define FINSH_NODE_SYS_NULL 27
|
||||
|
||||
#define FINSH_DATA_TYPE_VOID 0x00
|
||||
#define FINSH_DATA_TYPE_BYTE 0x01
|
||||
#define FINSH_DATA_TYPE_WORD 0x02
|
||||
#define FINSH_DATA_TYPE_DWORD 0x03
|
||||
#define FINSH_DATA_TYPE_PTR 0x10
|
||||
|
||||
#define FINSH_NODE_VALUE 0
|
||||
#define FINSH_NODE_ADDRESS 1
|
||||
#define FINSH_NODE_FUNCTION 2
|
||||
|
||||
int finsh_node_init(void);
|
||||
|
||||
struct finsh_node* finsh_node_allocate(u_char type);
|
||||
struct finsh_node* finsh_node_new_id(char* id);
|
||||
struct finsh_node* finsh_node_new_char(char c);
|
||||
struct finsh_node* finsh_node_new_int(int i);
|
||||
struct finsh_node* finsh_node_new_long(long l);
|
||||
struct finsh_node* finsh_node_new_string(char* s);
|
||||
struct finsh_node* finsh_node_new_ptr(void* ptr);
|
||||
|
||||
#define finsh_node_sibling(node) ((node)->sibling)
|
||||
#define finsh_node_child(node) ((node)->child)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* File : finsh_ops.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_OP_H__
|
||||
#define __FINSH_OP_H__
|
||||
|
||||
#include "finsh_vm.h"
|
||||
|
||||
/*
|
||||
* FinC VM specification
|
||||
* Memory
|
||||
* .VAR
|
||||
*
|
||||
* .STACK
|
||||
*
|
||||
* .HEAP
|
||||
*
|
||||
* .TEXT
|
||||
* OP [op1]
|
||||
*/
|
||||
|
||||
#define FINSH_OP_NOOP 0x00
|
||||
|
||||
/* add @ r1 = r2 + r3 */
|
||||
#define FINSH_OP_ADD_BYTE 0x01
|
||||
#define FINSH_OP_ADD_WORD 0x02
|
||||
#define FINSH_OP_ADD_DWORD 0x03
|
||||
|
||||
/* sub @ r1 = r2 - r3 */
|
||||
#define FINSH_OP_SUB_BYTE 0x04
|
||||
#define FINSH_OP_SUB_WORD 0x05
|
||||
#define FINSH_OP_SUB_DWORD 0x06
|
||||
|
||||
/* div @ r1 = r2 / r3 */
|
||||
#define FINSH_OP_DIV_BYTE 0x07
|
||||
#define FINSH_OP_DIV_WORD 0x08
|
||||
#define FINSH_OP_DIV_DWORD 0x09
|
||||
|
||||
/* mod @ r1 = r2 % r3 */
|
||||
#define FINSH_OP_MOD_BYTE 0x0A
|
||||
#define FINSH_OP_MOD_WORD 0x0B
|
||||
#define FINSH_OP_MOD_DWORD 0x0C
|
||||
|
||||
/* mul @ r1 = r2 * r3 */
|
||||
#define FINSH_OP_MUL_BYTE 0x0D
|
||||
#define FINSH_OP_MUL_WORD 0x0E
|
||||
#define FINSH_OP_MUL_DWORD 0x0F
|
||||
|
||||
/* and @ r1 = r2 & r3 */
|
||||
#define FINSH_OP_AND_BYTE 0x10
|
||||
#define FINSH_OP_AND_WORD 0x11
|
||||
#define FINSH_OP_AND_DWORD 0x12
|
||||
|
||||
/* or @ r1 = r2 | r3 */
|
||||
#define FINSH_OP_OR_BYTE 0x13
|
||||
#define FINSH_OP_OR_WORD 0x14
|
||||
#define FINSH_OP_OR_DWORD 0x15
|
||||
|
||||
/* xor @ r1 = r2 ^ r3 */
|
||||
#define FINSH_OP_XOR_BYTE 0x16
|
||||
#define FINSH_OP_XOR_WORD 0x17
|
||||
#define FINSH_OP_XOR_DWORD 0x18
|
||||
|
||||
/* bw @ r1 = ~r2 */
|
||||
#define FINSH_OP_BITWISE_BYTE 0x19
|
||||
#define FINSH_OP_BITWISE_WORD 0x1A
|
||||
#define FINSH_OP_BITWISE_DWORD 0x1B
|
||||
|
||||
/* shl @ r1 = r2 << r3 */
|
||||
#define FINSH_OP_SHL_BYTE 0x1C
|
||||
#define FINSH_OP_SHL_WORD 0x1D
|
||||
#define FINSH_OP_SHL_DWORD 0x1E
|
||||
|
||||
/* shr @ r1 = r2 >> r3 */
|
||||
#define FINSH_OP_SHR_BYTE 0x1F
|
||||
#define FINSH_OP_SHR_WORD 0x20
|
||||
#define FINSH_OP_SHR_DWORD 0x21
|
||||
|
||||
/* ld @ r1 = [r2] */
|
||||
#define FINSH_OP_LD_BYTE 0x22
|
||||
#define FINSH_OP_LD_WORD 0x23
|
||||
#define FINSH_OP_LD_DWORD 0x24
|
||||
|
||||
#define FINSH_OP_LD_VALUE_BYTE 0x25
|
||||
#define FINSH_OP_LD_VALUE_WORD 0x26
|
||||
#define FINSH_OP_LD_VALUE_DWORD 0x27
|
||||
|
||||
/* st @ [r2] = r1 */
|
||||
#define FINSH_OP_ST_BYTE 0x28
|
||||
#define FINSH_OP_ST_WORD 0x29
|
||||
#define FINSH_OP_ST_DWORD 0x2A
|
||||
|
||||
/* pop */
|
||||
#define FINSH_OP_POP 0x2B
|
||||
|
||||
/* call r1 @ [r1](stack) */
|
||||
#define FINSH_OP_SYSCALL 0x2C
|
||||
|
||||
/* load value from stack */
|
||||
#define FINSH_OP_LD_VALUE_BYTE_STACK 0x2D
|
||||
#define FINSH_OP_LD_VALUE_WORD_STACK 0x2E
|
||||
#define FINSH_OP_LD_VALUE_DWORD_STACK 0x2F
|
||||
|
||||
/* halt */
|
||||
#define FINSH_OP_HALT 0xFF
|
||||
|
||||
typedef void (*op_func)();
|
||||
extern const op_func op_table[];
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* File : finsh_parser.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_PARSER_H__
|
||||
#define __FINSH_PARSER_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
int finsh_parser_init(struct finsh_parser* self);
|
||||
void finsh_parser_run(struct finsh_parser* self, const u_char* string);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* File : finsh_token.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_TOKEN_H__
|
||||
#define __FINSH_TOKEN_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
enum finsh_token_type
|
||||
{
|
||||
finsh_token_type_left_paren = 1, /* ( */
|
||||
finsh_token_type_right_paren , /* ) */
|
||||
finsh_token_type_comma , /* , */
|
||||
finsh_token_type_semicolon , /* ; */
|
||||
finsh_token_type_mul , /* * */
|
||||
finsh_token_type_add , /* + */
|
||||
finsh_token_type_inc , /* ++ */
|
||||
finsh_token_type_sub , /* - */
|
||||
finsh_token_type_dec , /* -- */
|
||||
finsh_token_type_div , /* / */
|
||||
finsh_token_type_mod , /* % */
|
||||
finsh_token_type_assign , /* = */
|
||||
finsh_token_type_and, /* & */
|
||||
finsh_token_type_or, /* | */
|
||||
finsh_token_type_xor, /* ^ */
|
||||
finsh_token_type_bitwise, /* ~ */
|
||||
finsh_token_type_shl, /* << */
|
||||
finsh_token_type_shr, /* >> */
|
||||
/*-- data type --*/
|
||||
finsh_token_type_void, /* void */
|
||||
finsh_token_type_char, /* char */
|
||||
finsh_token_type_short, /* short */
|
||||
finsh_token_type_int, /* int */
|
||||
finsh_token_type_long, /* long */
|
||||
finsh_token_type_unsigned, /* unsigned */
|
||||
/* data value type */
|
||||
finsh_token_type_value_char, /* v:char */
|
||||
finsh_token_type_value_int, /* v:int */
|
||||
finsh_token_type_value_long, /* v:long */
|
||||
finsh_token_type_value_string, /* v:string */
|
||||
finsh_token_type_value_null, /* NULL */
|
||||
/*-- others --*/
|
||||
finsh_token_type_identifier, /* ID */
|
||||
finsh_token_type_bad, /* bad token */
|
||||
finsh_token_type_eof
|
||||
};
|
||||
|
||||
#define finsh_token_position(self) (self)->position
|
||||
#define finsh_token_replay(self) (self)->replay = 1
|
||||
|
||||
void finsh_token_init(struct finsh_token* self, u_char* script);
|
||||
|
||||
enum finsh_token_type finsh_token_token(struct finsh_token* self);
|
||||
void finsh_token_get_token(struct finsh_token* self, u_char* token);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* File : finsh_var.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
#include "finsh_var.h"
|
||||
|
||||
struct finsh_var global_variable[FINSH_VARIABLE_MAX];
|
||||
struct finsh_sysvar_item* global_sysvar_list;
|
||||
|
||||
int finsh_var_init()
|
||||
{
|
||||
memset(global_variable, 0, sizeof(global_variable));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finsh_var_insert(const char* name, int type)
|
||||
{
|
||||
int i, empty;
|
||||
|
||||
empty = -1;
|
||||
for (i = 0; i < FINSH_VARIABLE_MAX; i ++)
|
||||
{
|
||||
/* there is a same name variable exist. */
|
||||
if (strncmp(global_variable[i].name, name, FINSH_NAME_MAX) == 0)
|
||||
return -1;
|
||||
|
||||
if (global_variable[i].type == finsh_type_unknown && empty == -1)
|
||||
{
|
||||
empty = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* there is no empty entry */
|
||||
if (empty == -1) return -1;
|
||||
|
||||
/* insert entry */
|
||||
strncpy(global_variable[empty].name, name, FINSH_NAME_MAX);
|
||||
global_variable[empty].type = type;
|
||||
|
||||
/* return the offset */
|
||||
return empty;
|
||||
}
|
||||
|
||||
int finsh_var_delete(const char* name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FINSH_VARIABLE_MAX; i ++)
|
||||
{
|
||||
if (strncpy(global_variable[i].name, name, FINSH_NAME_MAX) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* can't find variable */
|
||||
if (i == FINSH_VARIABLE_MAX) return -1;
|
||||
|
||||
memset(&global_variable[i], 0, sizeof(struct finsh_var));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct finsh_var* finsh_var_lookup(const char* name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FINSH_VARIABLE_MAX; i ++)
|
||||
{
|
||||
if (strncmp(global_variable[i].name, name, FINSH_NAME_MAX) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* can't find variable */
|
||||
if (i == FINSH_VARIABLE_MAX) return NULL;
|
||||
|
||||
return &global_variable[i];
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
extern char *strdup(const char *s);
|
||||
void finsh_sysvar_append(const char* name, u_char type, void* var_addr)
|
||||
{
|
||||
/* create a sysvar */
|
||||
struct finsh_sysvar_item* item;
|
||||
|
||||
item = (struct finsh_sysvar_item*) rt_malloc (sizeof(struct finsh_sysvar_item));
|
||||
if (item != NULL)
|
||||
{
|
||||
item->next = NULL;
|
||||
item->sysvar.name = strdup(name);
|
||||
item->sysvar.type = type;
|
||||
item->sysvar.var = var_addr;
|
||||
|
||||
if (global_sysvar_list == NULL)
|
||||
{
|
||||
global_sysvar_list = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->next = global_sysvar_list;
|
||||
global_sysvar_list->next = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct finsh_sysvar* finsh_sysvar_lookup(const char* name)
|
||||
{
|
||||
struct finsh_sysvar* index;
|
||||
struct finsh_sysvar_item* item;
|
||||
|
||||
for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
|
||||
{
|
||||
if (strcmp(index->name, name) == 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
/* find in sysvar list */
|
||||
item = global_sysvar_list;
|
||||
while (item != NULL)
|
||||
{
|
||||
if (strncmp(item->sysvar.name, name, strlen(name)) == 0)
|
||||
{
|
||||
return &(item->sysvar);
|
||||
}
|
||||
|
||||
/* move to next item */
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
/* can't find variable */
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* File : finsh_var.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_VAR_H__
|
||||
#define __FINSH_VAR_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
/*
|
||||
* The variable in finsh is put in data segment as a global variable.
|
||||
* The 'finsh_var' structure presents the structure of variable in data segment.
|
||||
*/
|
||||
struct finsh_var
|
||||
{
|
||||
char name[FINSH_NAME_MAX + 1]; /* the name of variable */
|
||||
|
||||
u_char type; /* the type of variable */
|
||||
|
||||
/* variable value */
|
||||
union {
|
||||
char char_value;
|
||||
short short_value;
|
||||
int int_value;
|
||||
long long_value;
|
||||
void* ptr;
|
||||
}value;
|
||||
};
|
||||
extern struct finsh_var global_variable[];
|
||||
|
||||
int finsh_var_init(void);
|
||||
int finsh_var_insert(const char* name, int type);
|
||||
int finsh_var_delete(const char* name);
|
||||
struct finsh_var* finsh_var_lookup(const char* name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* File : finsh_vm.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include <finsh.h>
|
||||
|
||||
#include "finsh_vm.h"
|
||||
#include "finsh_ops.h"
|
||||
#include "finsh_var.h"
|
||||
|
||||
/* stack */
|
||||
union finsh_value finsh_vm_stack[FINSH_STACK_MAX];
|
||||
/* text segment */
|
||||
u_char text_segment[FINSH_TEXT_MAX];
|
||||
|
||||
union finsh_value* finsh_sp; /* stack pointer */
|
||||
u_char* finsh_pc; /* PC */
|
||||
|
||||
/* syscall list, for dynamic system call register */
|
||||
struct finsh_syscall_item* global_syscall_list = NULL;
|
||||
|
||||
// #define VM_DISASSEMBLE
|
||||
void finsh_vm_run()
|
||||
{
|
||||
u_char op;
|
||||
|
||||
/* if want to disassemble the bytecode, please define VM_DISASSEMBLE */
|
||||
#ifdef VM_DISASSEMBLE
|
||||
void finsh_disassemble();
|
||||
finsh_disassemble();
|
||||
#endif
|
||||
|
||||
/* set sp(stack pointer) to the beginning of stack */
|
||||
finsh_sp = &finsh_vm_stack[0];
|
||||
|
||||
/* set pc to the beginning of text segment */
|
||||
finsh_pc = &text_segment[0];
|
||||
|
||||
while ((finsh_pc - &text_segment[0] >= 0) &&
|
||||
(finsh_pc - &text_segment[0] < FINSH_TEXT_MAX))
|
||||
{
|
||||
/* get op */
|
||||
op = *finsh_pc++;
|
||||
|
||||
/* call op function */
|
||||
op_table[op]();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
extern char *strdup(const char *s);
|
||||
void finsh_syscall_append(const char* name, syscall_func func)
|
||||
{
|
||||
/* create the syscall */
|
||||
struct finsh_syscall_item* item;
|
||||
|
||||
item = (struct finsh_syscall_item*)rt_malloc(sizeof(struct finsh_syscall_item));
|
||||
if (item != RT_NULL)
|
||||
{
|
||||
item->next = NULL;
|
||||
item->syscall.name = strdup(name);
|
||||
item->syscall.func = func;
|
||||
|
||||
if (global_syscall_list == NULL)
|
||||
{
|
||||
global_syscall_list = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->next = global_syscall_list;
|
||||
global_syscall_list = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
struct finsh_syscall* finsh_syscall_lookup(const char* name)
|
||||
{
|
||||
struct finsh_syscall* index;
|
||||
struct finsh_syscall_item* item;
|
||||
|
||||
for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
|
||||
{
|
||||
if (strcmp(index->name, name) == 0)
|
||||
return index;
|
||||
}
|
||||
|
||||
/* find on syscall list */
|
||||
item = global_syscall_list;
|
||||
while (item != NULL)
|
||||
{
|
||||
if (strncmp(item->syscall.name, name, strlen(name)) == 0)
|
||||
{
|
||||
return &(item->syscall);
|
||||
}
|
||||
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef VM_DISASSEMBLE
|
||||
void finsh_disassemble()
|
||||
{
|
||||
u_char *pc, op;
|
||||
|
||||
pc = &text_segment[0];
|
||||
while (*pc != 0)
|
||||
{
|
||||
op = *pc;
|
||||
switch (op)
|
||||
{
|
||||
case FINSH_OP_ADD_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("addb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SUB_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("subb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_DIV_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("divb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MOD_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("modb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MUL_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("mulb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_AND_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("andb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_OR_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("orb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_XOR_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("xorb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_BITWISE_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("bwb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHL_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("shlb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHR_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("shrb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("ldb %d\n", *pc++);
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("ldb [0x%x]\n", FINSH_GET32(pc));
|
||||
pc += 4;
|
||||
break;
|
||||
|
||||
case FINSH_OP_ST_BYTE:
|
||||
pc ++;
|
||||
rt_kprintf("stb\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_ADD_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("addw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SUB_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("subw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_DIV_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("divw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MOD_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("modw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MUL_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("mulw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_AND_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("andw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_OR_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("orw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_XOR_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("xorw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_BITWISE_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("bww\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHL_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("shlw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHR_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("shrw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("ldw %d\n", FINSH_GET16(pc));
|
||||
pc += 2;
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("ldw [0x%x]\n", FINSH_GET32(pc));
|
||||
pc += 4;
|
||||
break;
|
||||
|
||||
case FINSH_OP_ST_WORD:
|
||||
pc ++;
|
||||
rt_kprintf("stw\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_ADD_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("addd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SUB_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("subd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_DIV_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("divd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MOD_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("modd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_MUL_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("muld\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_AND_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("andd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_OR_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("ord\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_XOR_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("xord\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_BITWISE_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("bwd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHL_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("shld\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_SHR_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("shrd\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("ldd 0x%x\n", FINSH_GET32(pc));
|
||||
pc += 4;
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("ldd [0x%x]\n", FINSH_GET32(pc));
|
||||
pc += 4;
|
||||
break;
|
||||
|
||||
case FINSH_OP_ST_DWORD:
|
||||
pc ++;
|
||||
rt_kprintf("std\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_POP:
|
||||
rt_kprintf("pop\n");
|
||||
pc ++;
|
||||
break;
|
||||
|
||||
case FINSH_OP_SYSCALL:
|
||||
pc ++;
|
||||
rt_kprintf("syscall %d\n", *pc++);
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_BYTE_STACK:
|
||||
pc ++;
|
||||
rt_kprintf("ldb [sp]\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_WORD_STACK:
|
||||
pc ++;
|
||||
rt_kprintf("ldw [sp]\n");
|
||||
break;
|
||||
|
||||
case FINSH_OP_LD_VALUE_DWORD_STACK:
|
||||
pc ++;
|
||||
rt_kprintf("ldd [sp]\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* File : finsh_vm.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#ifndef __FINSH_VM_H__
|
||||
#define __FINSH_VM_H__
|
||||
|
||||
#include <finsh.h>
|
||||
|
||||
#include "finsh_var.h"
|
||||
|
||||
union finsh_value {
|
||||
char char_value;
|
||||
short short_value;
|
||||
long long_value;
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
extern union finsh_value* finsh_sp; /* stack pointer */
|
||||
extern u_char* finsh_pc; /* PC */
|
||||
|
||||
/* stack */
|
||||
extern union finsh_value finsh_vm_stack[FINSH_STACK_MAX];
|
||||
/* text segment */
|
||||
extern u_char text_segment[FINSH_TEXT_MAX];
|
||||
|
||||
void finsh_vm_run(void);
|
||||
//void finsh_disassemble(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* File : shell.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-04-30 Bernard the first verion for FinSH
|
||||
* 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
|
||||
* 2010-01-18 Bernard fix down then up key bug.
|
||||
* 2010-03-19 Bernard fix backspace issue and fix device read in shell.
|
||||
* 2010-04-01 Bernard add prompt output when start and remove the empty history
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#include "finsh.h"
|
||||
|
||||
/*
|
||||
* Add by caoxl 2009-10-14
|
||||
*
|
||||
*/
|
||||
#ifdef QEMU_CAOXL
|
||||
#define memcpy(a,b,c) rt_memcpy(a,b,c)
|
||||
extern char rt_serial_getc(void);
|
||||
#endif
|
||||
|
||||
#define FINSH_USING_HISTORY
|
||||
|
||||
#if defined(__CC_ARM) /* ARMCC compiler */
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
extern int FSymTab$$Base;
|
||||
extern int FSymTab$$Limit;
|
||||
extern int VSymTab$$Base;
|
||||
extern int VSymTab$$Limit;
|
||||
#endif
|
||||
#elif defined(__ICCARM__) /* for IAR compiler */
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
#pragma section="FSymTab"
|
||||
#pragma section="VSymTab"
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
extern int __fsymtab_start;
|
||||
extern int __fsymtab_end;
|
||||
extern int __vsymtab_start;
|
||||
extern int __vsymtab_end;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* finsh thread */
|
||||
struct rt_thread finsh_thread;
|
||||
char finsh_thread_stack[2048];
|
||||
struct rt_semaphore uart_sem;
|
||||
rt_device_t finsh_device;
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
enum input_stat
|
||||
{
|
||||
WAIT_NORMAL,
|
||||
WAIT_SPEC_KEY,
|
||||
WAIT_FUNC_KEY,
|
||||
};
|
||||
#ifndef FINSH_HISTORY_LINES
|
||||
#define FINSH_HISTORY_LINES 5
|
||||
#endif
|
||||
#ifndef FINSH_CMD_SIZE
|
||||
#define FINSH_CMD_SIZE 80
|
||||
#endif
|
||||
char finsh_cmd_history[FINSH_HISTORY_LINES][FINSH_CMD_SIZE];
|
||||
rt_uint16_t finsh_history_count = 0;
|
||||
#endif
|
||||
|
||||
#if !defined (RT_USING_NEWLIB) && !defined (RT_USING_MINILIBC)
|
||||
void *memccpy(void *dst, const void *src, int c, size_t count)
|
||||
{
|
||||
char *a = dst;
|
||||
const char *b = src;
|
||||
while (count--)
|
||||
{
|
||||
*a++ = *b;
|
||||
if (*b==c)
|
||||
{
|
||||
return (void *)a;
|
||||
}
|
||||
|
||||
b++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strcmp (const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 && *s1 == *s2) s1++, s2++;
|
||||
|
||||
return (*s1 - *s2);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
char *strdup(const char *s)
|
||||
{
|
||||
size_t len = strlen(s) + 1;
|
||||
char *tmp = (char *)rt_malloc(len);
|
||||
|
||||
if(!tmp) return NULL;
|
||||
|
||||
rt_memcpy(tmp, s, len);
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(__CC_ARM) && !defined(__ICCARM__) && !defined(__ICCM16C__)
|
||||
int isalpha( int ch )
|
||||
{
|
||||
return (unsigned int)((ch | 0x20) - 'a') < 26u;
|
||||
}
|
||||
|
||||
int atoi(const char* s)
|
||||
{
|
||||
long int v=0;
|
||||
int sign=1;
|
||||
while ( *s == ' ' || (unsigned int)(*s - 9) < 5u) s++;
|
||||
|
||||
switch (*s)
|
||||
{
|
||||
case '-': sign=-1;
|
||||
case '+': ++s;
|
||||
}
|
||||
|
||||
while ((unsigned int) (*s - '0') < 10u)
|
||||
{
|
||||
v=v*10+*s-'0'; ++s;
|
||||
}
|
||||
|
||||
return sign==-1?-v:v;
|
||||
}
|
||||
|
||||
int isprint(unsigned char ch)
|
||||
{
|
||||
return (unsigned int)(ch - ' ') < 127u - ' ';
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static rt_err_t finsh_rx_ind(rt_device_t dev, rt_size_t size)
|
||||
{
|
||||
/* release semaphore to let finsh thread rx data */
|
||||
rt_sem_release(&uart_sem);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void finsh_set_device(const char* device_name)
|
||||
{
|
||||
rt_device_t dev = RT_NULL;
|
||||
|
||||
dev = rt_device_find(device_name);
|
||||
if (dev != RT_NULL && rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) == RT_EOK)
|
||||
{
|
||||
if (finsh_device != RT_NULL)
|
||||
{
|
||||
/* close old finsh device */
|
||||
rt_device_close(finsh_device);
|
||||
}
|
||||
|
||||
finsh_device = dev;
|
||||
rt_device_set_rx_indicate(dev, finsh_rx_ind);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("finsh: can not find device:%s\n", device_name);
|
||||
}
|
||||
}
|
||||
|
||||
void finsh_auto_complete(char* prefix)
|
||||
{
|
||||
extern void list_prefix(char* prefix);
|
||||
|
||||
rt_kprintf("\n");
|
||||
list_prefix(prefix);
|
||||
rt_kprintf("finsh>>%s", prefix);
|
||||
}
|
||||
|
||||
extern const char* finsh_error_string_table[];
|
||||
void finsh_run_line(struct finsh_parser *parser, const char* line)
|
||||
{
|
||||
rt_kprintf("\n");
|
||||
finsh_parser_run(parser, (unsigned char*)line);
|
||||
|
||||
/* compile node root */
|
||||
if (finsh_errno() == 0)
|
||||
{
|
||||
finsh_compiler_run(parser->root);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("%s\n", finsh_error_string(finsh_errno()));
|
||||
}
|
||||
|
||||
/* 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",
|
||||
(unsigned char)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom());
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("\t%d, 0x%08x\n",
|
||||
(unsigned int)finsh_stack_bottom(),
|
||||
(unsigned int)finsh_stack_bottom());
|
||||
}
|
||||
}
|
||||
|
||||
finsh_flush(parser);
|
||||
}
|
||||
|
||||
void finsh_thread_entry(void* parameter)
|
||||
{
|
||||
struct finsh_parser parser;
|
||||
char line[256], ch;
|
||||
int pos ;
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
enum input_stat stat;
|
||||
unsigned short current_history, use_history;
|
||||
#endif
|
||||
|
||||
pos = 0;
|
||||
stat = WAIT_NORMAL;
|
||||
current_history = 0;
|
||||
use_history = 0;
|
||||
memset(line, 0, sizeof(line));
|
||||
|
||||
finsh_init(&parser);
|
||||
rt_kprintf("finsh>>");
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (rt_sem_take(&uart_sem, RT_WAITING_FOREVER) != RT_EOK) continue;
|
||||
|
||||
/* read one character from device */
|
||||
while (rt_device_read(finsh_device, 0, &ch, 1) == 1)
|
||||
{
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
/*
|
||||
* handle up and down key
|
||||
* up key : 0x1b 0x5b 0x41
|
||||
* down key: 0x1b 0x5b 0x42
|
||||
*/
|
||||
if (ch == 0x1b)
|
||||
{
|
||||
stat = WAIT_SPEC_KEY;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stat == WAIT_SPEC_KEY) && (ch == 0x5b))
|
||||
{
|
||||
if (ch == 0x5b)
|
||||
{
|
||||
stat = WAIT_FUNC_KEY;
|
||||
continue;
|
||||
}
|
||||
stat = WAIT_NORMAL;
|
||||
}
|
||||
|
||||
if (stat == WAIT_FUNC_KEY)
|
||||
{
|
||||
stat = WAIT_NORMAL;
|
||||
|
||||
if (ch == 0x41) /* up key */
|
||||
{
|
||||
/* prev history */
|
||||
if (current_history > 0)current_history --;
|
||||
else
|
||||
{
|
||||
current_history = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the history command */
|
||||
memcpy(line, &finsh_cmd_history[current_history][0],
|
||||
FINSH_CMD_SIZE);
|
||||
pos = strlen(line);
|
||||
use_history = 1;
|
||||
}
|
||||
else if (ch == 0x42) /* down key */
|
||||
{
|
||||
/* next history */
|
||||
if (current_history < finsh_history_count - 1)
|
||||
current_history ++;
|
||||
else
|
||||
{
|
||||
/* set to the end of history */
|
||||
if (finsh_history_count != 0)
|
||||
{
|
||||
current_history = finsh_history_count - 1;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
|
||||
memcpy(line, &finsh_cmd_history[current_history][0],
|
||||
FINSH_CMD_SIZE);
|
||||
pos = strlen(line);
|
||||
use_history = 1;
|
||||
}
|
||||
|
||||
if (use_history)
|
||||
{
|
||||
rt_kprintf("\033[2K\r");
|
||||
rt_kprintf("finsh>>%s", line);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* handle tab key */
|
||||
if (ch == '\t')
|
||||
{
|
||||
/* auto complete */
|
||||
finsh_auto_complete(&line[0]);
|
||||
/* re-calculate position */
|
||||
pos = strlen(line);
|
||||
continue;
|
||||
}
|
||||
/* handle backspace key */
|
||||
else if (ch == 0x7f || ch == 0x08)
|
||||
{
|
||||
if (pos != 0)
|
||||
{
|
||||
rt_kprintf("%c %c", ch, ch);
|
||||
}
|
||||
if (pos <= 0) pos = 0;
|
||||
else pos --;
|
||||
line[pos] = 0;
|
||||
continue;
|
||||
}
|
||||
/* handle end of line, break */
|
||||
else if (ch == 0x0d || ch == 0x0a)
|
||||
{
|
||||
/* change to ';' and break */
|
||||
line[pos] = ';';
|
||||
|
||||
#ifdef FINSH_USING_HISTORY
|
||||
if ((use_history == 0) && (pos != 0))
|
||||
{
|
||||
/* push history */
|
||||
if (finsh_history_count >= FINSH_HISTORY_LINES)
|
||||
{
|
||||
/* move history */
|
||||
int index;
|
||||
for (index = 0; index < FINSH_HISTORY_LINES - 1; index ++)
|
||||
{
|
||||
memcpy(&finsh_cmd_history[index][0],
|
||||
&finsh_cmd_history[index + 1][0], FINSH_CMD_SIZE);
|
||||
}
|
||||
memset(&finsh_cmd_history[index][0], 0, FINSH_CMD_SIZE);
|
||||
memcpy(&finsh_cmd_history[index][0], line, pos);
|
||||
|
||||
/* it's the maximum history */
|
||||
finsh_history_count = FINSH_HISTORY_LINES;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&finsh_cmd_history[finsh_history_count][0], 0, FINSH_CMD_SIZE);
|
||||
memcpy(&finsh_cmd_history[finsh_history_count][0], line, pos);
|
||||
|
||||
/* increase count and set current history position */
|
||||
finsh_history_count ++;
|
||||
}
|
||||
}
|
||||
current_history = finsh_history_count;
|
||||
#endif
|
||||
|
||||
if (pos != 0) finsh_run_line(&parser, line);
|
||||
else rt_kprintf("\n");
|
||||
|
||||
rt_kprintf("finsh>>");
|
||||
memset(line, 0, sizeof(line));
|
||||
pos = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* it's a large line, discard it */
|
||||
if (pos >= 256) pos = 0;
|
||||
|
||||
/* normal character */
|
||||
line[pos] = ch; ch = 0;
|
||||
rt_kprintf("%c", line[pos++]);
|
||||
use_history = 0; /* it's a new command */
|
||||
} /* end of device read */
|
||||
}
|
||||
}
|
||||
|
||||
void finsh_system_function_init(void* begin, void* end)
|
||||
{
|
||||
_syscall_table_begin = (struct finsh_syscall*) begin;
|
||||
_syscall_table_end = (struct finsh_syscall*) end;
|
||||
}
|
||||
|
||||
void finsh_system_var_init(void* begin, void* end)
|
||||
{
|
||||
_sysvar_table_begin = (struct finsh_sysvar*) begin;
|
||||
_sysvar_table_end = (struct finsh_sysvar*) end;
|
||||
}
|
||||
|
||||
/* init finsh */
|
||||
void finsh_system_init(void)
|
||||
{
|
||||
rt_sem_init(&uart_sem, "uart", 0, 0);
|
||||
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
#ifdef __CC_ARM /* ARM C Compiler */
|
||||
finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);
|
||||
finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit);
|
||||
#elif defined (__ICCARM__) /* for IAR Compiler */
|
||||
finsh_system_function_init(__section_begin("FSymTab"),
|
||||
__section_end("FSymTab"));
|
||||
finsh_system_var_init(__section_begin("VSymTab"),
|
||||
__section_end("VSymTab"));
|
||||
#elif defined (__GNUC__) /* GNU GCC Compiler */
|
||||
finsh_system_function_init(&__fsymtab_start, &__fsymtab_end);
|
||||
finsh_system_var_init(&__vsymtab_start, &__vsymtab_start);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if RT_THREAD_PRIORITY_MAX == 8
|
||||
rt_thread_init(&finsh_thread,
|
||||
"tshell",
|
||||
finsh_thread_entry, RT_NULL,
|
||||
&finsh_thread_stack[0], sizeof(finsh_thread_stack),
|
||||
5, 10);
|
||||
#else
|
||||
rt_thread_init(&finsh_thread,
|
||||
"tshell",
|
||||
finsh_thread_entry, RT_NULL,
|
||||
&finsh_thread_stack[0], sizeof(finsh_thread_stack),
|
||||
20, 10);
|
||||
#endif
|
||||
|
||||
rt_thread_startup(&finsh_thread);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* File : symbol.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2010-03-22 Bernard first version
|
||||
*/
|
||||
#include "finsh.h"
|
||||
|
||||
long hello(void);
|
||||
long version(void);
|
||||
long list(void);
|
||||
long list_thread(void);
|
||||
long list_sem(void);
|
||||
long list_mutex(void);
|
||||
long list_fevent(void);
|
||||
long list_event(void);
|
||||
long list_mailbox(void);
|
||||
long list_msgqueue(void);
|
||||
long list_mempool(void);
|
||||
long list_timer(void);
|
||||
|
||||
#ifdef FINSH_USING_SYMTAB
|
||||
struct finsh_syscall *_syscall_table_begin = NULL;
|
||||
struct finsh_syscall *_syscall_table_end = NULL;
|
||||
struct finsh_sysvar *_sysvar_table_begin = NULL;
|
||||
struct finsh_sysvar *_sysvar_table_end = NULL;
|
||||
#else
|
||||
struct finsh_syscall _syscall_table[] =
|
||||
{
|
||||
{"hello", hello},
|
||||
{"version", version},
|
||||
{"list", list},
|
||||
{"list_thread", list_thread},
|
||||
#ifdef RT_USING_SEMAPHORE
|
||||
{"list_sem", list_sem},
|
||||
#endif
|
||||
#ifdef RT_USING_MUTEX
|
||||
{"list_mutex", list_mutex},
|
||||
#endif
|
||||
#ifdef RT_USING_FEVENT
|
||||
{"list_fevent", list_fevent},
|
||||
#endif
|
||||
#ifdef RT_USING_EVENT
|
||||
{"list_event", list_event},
|
||||
#endif
|
||||
#ifdef RT_USING_MAILBOX
|
||||
{"list_mb", list_mailbox},
|
||||
#endif
|
||||
#ifdef RT_USING_MESSAGEQUEUE
|
||||
{"list_mq", list_msgqueue},
|
||||
#endif
|
||||
#ifdef RT_USING_MEMPOOL
|
||||
{"list_memp", list_mempool},
|
||||
#endif
|
||||
{"list_timer", list_timer},
|
||||
};
|
||||
struct finsh_syscall *_syscall_table_begin = &_syscall_table[0];
|
||||
struct finsh_syscall *_syscall_table_end = &_syscall_table[sizeof(_syscall_table) / sizeof(struct finsh_syscall)];
|
||||
|
||||
struct finsh_sysvar *_sysvar_table_begin = NULL;
|
||||
struct finsh_sysvar *_sysvar_table_end = NULL;
|
||||
#endif
|
||||
Reference in New Issue
Block a user