summaryrefslogtreecommitdiff
path: root/finsh
diff options
context:
space:
mode:
Diffstat (limited to 'finsh')
-rw-r--r--finsh/cmd.c375
-rw-r--r--finsh/finsh.h303
-rw-r--r--finsh/finsh_compiler.c906
-rw-r--r--finsh/finsh_error.c46
-rw-r--r--finsh/finsh_error.h14
-rw-r--r--finsh/finsh_heap.c269
-rw-r--r--finsh/finsh_heap.h10
-rw-r--r--finsh/finsh_init.c48
-rw-r--r--finsh/finsh_node.c174
-rw-r--r--finsh/finsh_node.h60
-rw-r--r--finsh/finsh_ops.c594
-rw-r--r--finsh/finsh_ops.h107
-rw-r--r--finsh/finsh_parser.c965
-rw-r--r--finsh/finsh_parser.h9
-rw-r--r--finsh/finsh_token.c562
-rw-r--r--finsh/finsh_token.h53
-rw-r--r--finsh/finsh_var.c130
-rw-r--r--finsh/finsh_var.h32
-rw-r--r--finsh/finsh_vm.c356
-rw-r--r--finsh/finsh_vm.h26
-rw-r--r--finsh/shell.c270
-rw-r--r--finsh/symbol.c56
22 files changed, 5365 insertions, 0 deletions
diff --git a/finsh/cmd.c b/finsh/cmd.c
new file mode 100644
index 0000000000..ef2b02d135
--- /dev/null
+++ b/finsh/cmd.c
@@ -0,0 +1,375 @@
+/*
+ * File : cmd.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://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2006-04-30 Bernard first implementation
+ * 2006-05-04 Bernard add list_thread,
+ * list_sem,
+ * list_timer
+ * 2006-05-20 Bernard add list_mutex,
+ * list_mailbox,
+ * list_msgqueue,
+ * list_event,
+ * list_fevent,
+ * list_mempool
+ * 2006-06-03 Bernard display stack information in list_thread
+ * 2006-08-10 Bernard change version to invoke rt_show_version
+ * 2008-09-10 Bernard update the list function for finsh syscall
+ * list and sysvar list
+ * 2009-05-30 Bernard add list_device
+ */
+
+#include <rtthread.h>
+#include "finsh.h"
+
+long hello()
+{
+ rt_kprintf("Hello RT-Thread!\n");
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(hello, say hello world)
+
+extern void rt_show_version(void);
+long version()
+{
+ rt_show_version();
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(version, show RT-Thread version information)
+
+#define rt_list_entry(node, type, member) \
+ ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
+extern struct rt_object_information rt_object_container[];
+
+int list_thread()
+{
+ struct rt_thread *thread;
+ struct rt_list_node *list, *node;
+ rt_uint8_t* ptr;
+
+ list = &rt_object_container[RT_Object_Class_Thread].object_list;
+
+ rt_kprintf(" thread pri status sp stack size max used left tick error\n");
+ rt_kprintf("-------- ---- ------- ---------- ---------- ---------- ---------- ---\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ thread = rt_list_entry(node, struct rt_thread, list);
+ rt_kprintf("%-8s 0x%02x", thread->name, thread->current_priority);
+
+ if (thread->stat == RT_THREAD_READY) rt_kprintf(" ready ");
+ else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+ else if (thread->stat == RT_THREAD_INIT) rt_kprintf(" init ");
+
+ ptr = (rt_uint8_t*)thread->stack_addr;
+ while (*ptr == '#')ptr ++;
+
+ rt_kprintf(" 0x%08x 0x%08x 0x%08x 0x%08x %03d\n",
+ thread->stack_size + ((rt_uint32_t)thread->stack_addr - (rt_uint32_t)thread->sp),
+ thread->stack_size,
+ thread->stack_size - ((rt_uint32_t) ptr - (rt_uint32_t)thread->stack_addr),
+ thread->remaining_tick,
+ thread->error);
+
+ }
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_thread, list thread)
+
+static void show_wait_queue(struct rt_list_node* list)
+{
+ struct rt_thread *thread;
+ struct rt_list_node *node;
+
+ for (node = list->next; node != list; node = node->next)
+ {
+ thread = rt_list_entry(node, struct rt_thread, tlist);
+ rt_kprintf("%s", thread->name);
+ if (node->next != list) rt_kprintf("/");
+ }
+}
+
+#ifdef RT_USING_SEMAPHORE
+int list_sem()
+{
+ struct rt_semaphore *sem;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_Semaphore].object_list;
+
+ rt_kprintf("semaphore v suspend thread\n");
+ rt_kprintf("-------- --- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ sem = (struct rt_semaphore*)(rt_list_entry(node, struct rt_object, list));
+ if (sem->parent.suspend_thread_count != 0)
+ {
+ rt_kprintf("%-8s %03d %d:", sem->parent.parent.name, sem->value, sem->parent.suspend_thread_count);
+ show_wait_queue(&(sem->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-8s %03d %d\n", sem->parent.parent.name, sem->value, sem->parent.suspend_thread_count);
+ }
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_sem, list semaphone in system)
+#endif
+
+#ifdef RT_USING_FASTEVENT
+int list_fevent()
+{
+ struct rt_fast_event *e;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_FastEvent].object_list;
+
+ rt_kprintf("fevent set \n");
+ rt_kprintf("-------- ----------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ e = (struct rt_fast_event*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s 0x%08x\n", e->parent.name, e->set);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_fevent, list fast event in system)
+#endif
+
+#ifdef RT_USING_EVENT
+int list_event()
+{
+ struct rt_event *e;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_Event].object_list;
+
+ rt_kprintf("event set suspend thread\n");
+ rt_kprintf("-------- ---------- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ e = (struct rt_event*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s 0x%08x %03d\n", e->parent.parent.name, e->set, e->parent.suspend_thread_count);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_event, list event in system)
+#endif
+
+#ifdef RT_USING_MUTEX
+int list_mutex()
+{
+ struct rt_mutex *m;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_Mutex].object_list;
+
+ rt_kprintf("mutex owner hold suspend thread\n");
+ rt_kprintf("-------- -------- ---- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ m = (struct rt_mutex*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s %-8s %04d %d\n", m->parent.parent.name, m->owner->name, m->hold, m->parent.suspend_thread_count);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_mutex, list mutex in system)
+#endif
+
+#ifdef RT_USING_MAILBOX
+int list_mailbox()
+{
+ struct rt_mailbox *m;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_MailBox].object_list;
+
+ rt_kprintf("mailbox entry size suspend thread\n");
+ rt_kprintf("-------- ---- ---- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ m = (struct rt_mailbox*)(rt_list_entry(node, struct rt_object, list));
+ if (m->parent.suspend_thread_count != 0)
+ {
+ rt_kprintf("%-8s %04d %04d %d:", m->parent.parent.name, m->entry, m->size, m->parent.suspend_thread_count);
+ show_wait_queue(&(m->parent.suspend_thread));
+ rt_kprintf("\n");
+ }
+ else
+ {
+ rt_kprintf("%-8s %04d %04d %d\n", m->parent.parent.name, m->entry, m->size, m->parent.suspend_thread_count);
+ }
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_mailbox, list mail box in system)
+#endif
+
+#ifdef RT_USING_MESSAGEQUEUE
+int list_msgqueue()
+{
+ struct rt_messagequeue *m;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_MessageQueue].object_list;
+
+ rt_kprintf("msgqueue entry suspend thread\n");
+ rt_kprintf("-------- ---- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ m = (struct rt_messagequeue*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s %04d %d\n", m->parent.parent.name, m->entry, m->parent.suspend_thread_count);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_msgqueue, list message queue in system)
+#endif
+
+#ifdef RT_USING_MEMPOOL
+int list_mempool()
+{
+ struct rt_mempool *mp;
+
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_MemPool].object_list;
+
+ rt_kprintf("mempool block total free suspend thread\n");
+ rt_kprintf("-------- ---- ---- ---- --------------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ mp = (struct rt_mempool*)rt_list_entry(node, struct rt_object, list);
+ rt_kprintf("%-8s %04d %04d %04d %d\n", mp->parent.name,
+ mp->block_size, mp->block_total_count, mp->block_free_count,
+ mp->suspend_thread_count);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_mempool, list memory pool in system)
+#endif
+
+int list_timer()
+{
+ struct rt_timer *timer;
+ struct rt_list_node *list, *node;
+
+ list = &rt_object_container[RT_Object_Class_Timer].object_list;
+
+ rt_kprintf("timer periodic timeout flag\n");
+ rt_kprintf("-------- ---------- ---------- -----------\n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ timer = (struct rt_timer*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s 0x%08x 0x%08x ", timer->parent.name, timer->init_tick, timer->timeout_tick);
+ if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) rt_kprintf("activated\n");
+ else rt_kprintf("deactivated\n");
+ }
+
+ rt_kprintf("current tick:0x%08x\n", rt_tick_get());
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_timer, list timer in system)
+
+#ifdef RT_USING_DEVICE
+int list_device()
+{
+ struct rt_device *device;
+ struct rt_list_node *list, *node;
+ const char *device_type_str[] =
+ {
+ "Character Device",
+ "Block Device",
+ "Network Interface",
+ "MTD Device",
+ "CAN",
+ "RTC",
+ "Unknown"
+ };
+
+ list = &rt_object_container[RT_Object_Class_Device].object_list;
+
+ rt_kprintf("device type \n");
+ rt_kprintf("-------- ---------- \n");
+ for (node = list->next; node != list; node = node->next)
+ {
+ device = (struct rt_device*)(rt_list_entry(node, struct rt_object, list));
+ rt_kprintf("%-8s %-8s \n", device->parent.name, device_type_str[device->type]);
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list_device, list device in system)
+#endif
+
+int list()
+{
+ struct finsh_syscall_item* syscall_item;
+ struct finsh_sysvar_item* sysvar_item;
+
+ rt_kprintf("--Function List:\n");
+ {
+ struct finsh_syscall* index;
+ for (index = _syscall_table_begin; index < _syscall_table_end; index ++)
+ {
+#ifdef FINSH_USING_DESCRIPTION
+ rt_kprintf("%-16s -- %s\n", index->name, index->desc);
+#else
+ rt_kprintf("%s\n", index->name);
+#endif
+ }
+ }
+
+ /* list syscall list */
+ syscall_item = global_syscall_list;
+ while (syscall_item != NULL)
+ {
+ rt_kprintf("[l] %s\n", syscall_item->syscall.name);
+ syscall_item = syscall_item->next;
+ }
+
+ rt_kprintf("--Variable List:\n");
+ {
+ struct finsh_sysvar* index;
+ for (index = _sysvar_table_begin; index < _sysvar_table_end; index ++)
+ {
+#ifdef FINSH_USING_DESCRIPTION
+ rt_kprintf("%-16s -- %s\n", index->name, index->desc);
+#else
+ rt_kprintf("%s\n", index->name);
+#endif
+ }
+ }
+
+ sysvar_item = global_sysvar_list;
+ while (sysvar_item != NULL)
+ {
+ rt_kprintf("[l] %s\n", sysvar_item->sysvar.name);
+ sysvar_item = sysvar_item->next;
+ }
+
+ return 0;
+}
+FINSH_FUNCTION_EXPORT(list, list all symbol in system)
+
+#ifdef FINSH_USING_SYMTAB
+static int dummy = 0;
+FINSH_VAR_EXPORT(dummy, finsh_type_int, dummy variable for finsh)
+#endif
diff --git a/finsh/finsh.h b/finsh/finsh.h
new file mode 100644
index 0000000000..a913588d48
--- /dev/null
+++ b/finsh/finsh.h
@@ -0,0 +1,303 @@
+#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;
+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);
+#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(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
diff --git a/finsh/finsh_compiler.c b/finsh/finsh_compiler.c
new file mode 100644
index 0000000000..b440f0fa4e
--- /dev/null
+++ b/finsh/finsh_compiler.c
@@ -0,0 +1,906 @@
+#include <finsh.h>
+
+#include "finsh_node.h"
+#include "finsh_error.h"
+#include "finsh_var.h"
+#include "finsh_ops.h"
+
+union finsh_value* finsh_compile_sp; /* stack pointer */
+u_char* finsh_compile_pc; /* PC */
+
+#define finsh_code_byte(x) do { *finsh_compile_pc = (x); finsh_compile_pc ++; } while(0)
+#define finsh_code_word(x) do { FINSH_SET16(finsh_compile_pc, x); finsh_compile_pc +=2; } while(0)
+#define finsh_code_dword(x) do { FINSH_SET32(finsh_compile_pc, x); finsh_compile_pc +=4; } while(0)
+
+static int finsh_compile(struct finsh_node* node)
+{
+ if (node != NULL)
+ {
+ /* compile child node */
+ if (finsh_node_child(node) != NULL)
+ finsh_compile(finsh_node_child(node));
+
+ /* compile current node */
+ switch (node->node_type)
+ {
+ case FINSH_NODE_ID:
+ {
+ /* identifier::syscall */
+ if (node->idtype & FINSH_IDTYPE_SYSCALL)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)node->id.syscall->func);
+ }
+ /* identifier::sysvar */
+ else if (node->idtype & FINSH_IDTYPE_SYSVAR)
+ {
+ struct finsh_sysvar* sysvar;
+
+ sysvar = node->id.sysvar;
+ if (sysvar != NULL)
+ {
+ switch (sysvar->type)
+ {
+ case finsh_type_char:
+ case finsh_type_uchar:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ }
+
+ finsh_code_dword((long)(sysvar->var));
+ break;
+
+ case finsh_type_short:
+ case finsh_type_ushort:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ }
+
+ finsh_code_dword((long)(sysvar->var));
+ break;
+
+ case finsh_type_int:
+ case finsh_type_uint:
+ case finsh_type_long:
+ case finsh_type_ulong:
+ case finsh_type_charp:
+ case finsh_type_shortp:
+ case finsh_type_intp:
+ case finsh_type_longp:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ }
+
+ finsh_code_dword((long)(sysvar->var));
+ break;
+ }
+ }
+ }
+ /* identifier::var */
+ else
+ {
+ struct finsh_var* var;
+
+ var = node->id.var;
+ if (var != NULL)
+ {
+ switch (var->type)
+ {
+ case finsh_type_char:
+ case finsh_type_uchar:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ }
+
+ finsh_code_dword((long)&(var->value.char_value));
+ break;
+
+ case finsh_type_short:
+ case finsh_type_ushort:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ }
+
+ finsh_code_dword((long)&(var->value.short_value));
+ break;
+
+ case finsh_type_int:
+ case finsh_type_uint:
+ case finsh_type_long:
+ case finsh_type_ulong:
+ case finsh_type_charp:
+ case finsh_type_shortp:
+ case finsh_type_intp:
+ case finsh_type_longp:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* load address */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ }
+ else
+ {
+ /* load value */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ }
+
+ finsh_code_dword((long)&(var->value.long_value));
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ /* load const */
+ case FINSH_NODE_VALUE_CHAR:
+ finsh_code_byte(FINSH_OP_LD_BYTE);
+ finsh_code_byte(node->value.char_value);
+ break;
+
+ case FINSH_NODE_VALUE_INT:
+ case FINSH_NODE_VALUE_LONG:
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword(node->value.long_value);
+ break;
+
+ case FINSH_NODE_VALUE_NULL:
+ case FINSH_NODE_VALUE_STRING:
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((u_long)node->value.ptr);
+ break;
+
+ /* arithmetic operation */
+ case FINSH_NODE_SYS_ADD:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_ADD_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_ADD_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_ADD_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_SUB:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SUB_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SUB_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SUB_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_MUL:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MUL_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MUL_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MUL_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_DIV:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_DIV_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_DIV_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_DIV_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_MOD:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MOD_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MOD_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MOD_DWORD);
+ break;
+
+ /* bit operation */
+ case FINSH_NODE_SYS_AND:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_AND_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_AND_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_AND_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_OR:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_OR_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_OR_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_OR_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_XOR:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_XOR_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_XOR_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_XOR_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_BITWISE:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_BITWISE_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_BITWISE_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_BITWISE_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_SHL:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHL_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHL_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHL_DWORD);
+ break;
+
+ case FINSH_NODE_SYS_SHR:
+ if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHR_BYTE);
+ else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHR_WORD);
+ else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHR_DWORD);
+ break;
+
+ /* syscall */
+ case FINSH_NODE_SYS_FUNC:
+ {
+ int parameters;
+ struct finsh_node* sibling;
+
+ parameters = 0;
+ sibling = finsh_node_sibling(finsh_node_child(node));
+ while (sibling != NULL)
+ {
+ parameters ++;
+ sibling = finsh_node_sibling(sibling);
+ }
+
+ /* load address of function */
+ // finsh_code_dword((long)&(node->var->value.ptr));
+
+ /* syscall parameters */
+ finsh_code_byte(FINSH_OP_SYSCALL);
+ finsh_code_byte(parameters);
+ }
+ break;
+
+ /* assign expression */
+ case FINSH_NODE_SYS_ASSIGN:
+ if (finsh_node_child(node)->node_type == FINSH_NODE_ID)
+ {
+ switch (finsh_node_child(node)->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
+ }
+ }
+ else if (finsh_node_child(node)->node_type == FINSH_NODE_SYS_GETVALUE)
+ {
+ switch ((finsh_node_child(node)->data_type) & 0x0F)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
+ }
+ }
+ break;
+
+ /* pre-increase */
+ case FINSH_NODE_SYS_PREINC:
+ if (finsh_node_child(node)->node_type == FINSH_NODE_ID)
+ {
+ struct finsh_var* var;
+ var = finsh_node_child(node)->id.var;
+
+ /* ld_dword &id */
+ // finsh_code_byte(FINSH_OP_LD_DWORD);
+
+ switch (node->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ /* address */
+ // finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_value_byte &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_byte 1 */
+ finsh_code_byte(FINSH_OP_LD_BYTE);
+ finsh_code_byte(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_ADD_BYTE);
+ /* st_byte */
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ /* address */
+ // finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_value_word &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_word 1 */
+ finsh_code_byte(FINSH_OP_LD_WORD);
+ finsh_code_word(1);
+
+ /* add_word */
+ finsh_code_byte(FINSH_OP_ADD_WORD);
+ /* st_word */
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ /* address */
+ // finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword 1 */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword(1);
+
+ /* add_dword */
+ finsh_code_byte(FINSH_OP_ADD_DWORD);
+ /* st_dword */
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+ }
+ }
+ break;
+
+ /* pre-decrease */
+ case FINSH_NODE_SYS_PREDEC:
+ if (finsh_node_child(node)->node_type == FINSH_NODE_ID)
+ {
+ struct finsh_var* var;
+ var = finsh_node_child(node)->id.var;
+
+ /* ld_dword &id */
+ // finsh_code_byte(FINSH_OP_LD_DWORD);
+
+ switch (node->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ /* address */
+ // finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_value_byte &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_byte 1 */
+ finsh_code_byte(FINSH_OP_LD_BYTE);
+ finsh_code_byte(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_SUB_BYTE);
+ /* st_byte */
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ /* address */
+ // finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_value_word &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_word 1 */
+ finsh_code_byte(FINSH_OP_LD_WORD);
+ finsh_code_word(1);
+
+ /* add_word */
+ finsh_code_byte(FINSH_OP_SUB_WORD);
+ /* st_word */
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ /* address */
+ // finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword 1 */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword(1);
+
+ /* add_dword */
+ finsh_code_byte(FINSH_OP_SUB_DWORD);
+ /* st_dword */
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* load value again */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+
+ break;
+ }
+ }
+ break;
+
+ /* increase */
+ case FINSH_NODE_SYS_INC:
+ if (finsh_node_child(node)->node_type == FINSH_NODE_ID)
+ {
+ struct finsh_var* var;
+ var = finsh_node_child(node)->id.var;
+
+ switch (node->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ /* ld_value_byte &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ // finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_value_byte &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_byte 1 */
+ finsh_code_byte(FINSH_OP_LD_BYTE);
+ finsh_code_byte(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_ADD_BYTE);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ /* ld_value_word &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ // finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_value_word &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_word 1 */
+ finsh_code_byte(FINSH_OP_LD_WORD);
+ finsh_code_word(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_ADD_WORD);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ /* ld_value_dword &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ // finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_value_dword &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword 1 */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_ADD_DWORD);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+ }
+ }
+ break;
+
+ /* decrease */
+ case FINSH_NODE_SYS_DEC:
+ if (finsh_node_child(node)->node_type == FINSH_NODE_ID)
+ {
+ struct finsh_var* var;
+ var = finsh_node_child(node)->id.var;
+
+ switch (node->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ /* ld_value_byte &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ // finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_value_byte &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
+ finsh_code_dword((long)&(var->value.char_value));
+
+ /* ld_byte 1 */
+ finsh_code_byte(FINSH_OP_LD_BYTE);
+ finsh_code_byte(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_SUB_BYTE);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_BYTE);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+
+ case FINSH_DATA_TYPE_WORD:
+ /* ld_value_word &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ // finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_value_word &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
+ finsh_code_dword((long)&(var->value.short_value));
+
+ /* ld_word 1 */
+ finsh_code_byte(FINSH_OP_LD_WORD);
+ finsh_code_word(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_SUB_WORD);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_WORD);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+
+ case FINSH_DATA_TYPE_DWORD:
+ /* ld_value_dword &id */
+ // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ // finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword &id */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_value_dword &id */
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
+ finsh_code_dword((long)&(var->value.long_value));
+
+ /* ld_dword 1 */
+ finsh_code_byte(FINSH_OP_LD_DWORD);
+ finsh_code_dword(1);
+
+ /* add_byte */
+ finsh_code_byte(FINSH_OP_SUB_DWORD);
+ /* get byte */
+ finsh_code_byte(FINSH_OP_ST_DWORD);
+
+ /* pop */
+ finsh_code_byte(FINSH_OP_POP);
+ break;
+ }
+ }
+ break;
+
+ case FINSH_NODE_SYS_NULL:
+ finsh_code_dword(0);
+ break;
+
+ case FINSH_NODE_SYS_GETVALUE:
+ if (node->idtype & FINSH_IDTYPE_ADDRESS)
+ {
+ /* nothing will be generated */
+ }
+ else
+ {
+ switch (node->data_type)
+ {
+ case FINSH_DATA_TYPE_BYTE:
+ finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
+ break;
+ case FINSH_DATA_TYPE_WORD:
+ finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
+ break;
+ case FINSH_DATA_TYPE_DWORD:
+ finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case FINSH_NODE_SYS_GETADDR:
+ /* nothing will be generated */
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_UNKNOWN_NODE);
+ break;
+ }
+
+ /* compile sibling node */
+ if (finsh_node_sibling(node) != NULL)
+ finsh_compile(finsh_node_sibling(node));
+ }
+
+ return 0;
+}
+
+static int finsh_type_check(struct finsh_node* node, u_char is_addr)
+{
+ if (node != NULL)
+ {
+ /* address & value */
+ if (node->node_type == FINSH_NODE_SYS_ASSIGN ||
+ node->node_type == FINSH_NODE_SYS_PREINC ||
+ node->node_type == FINSH_NODE_SYS_PREDEC ||
+ node->node_type == FINSH_NODE_SYS_GETADDR)
+ {
+ /* address */
+ finsh_type_check(finsh_node_child(node), FINSH_IDTYPE_ADDRESS);
+ }
+ else if (node->node_type == FINSH_NODE_SYS_GETVALUE && is_addr)
+ {
+ /* change the attribute of getvalue in left expr */
+ finsh_type_check(finsh_node_child(node), 0);
+ }
+ else
+ {
+ /* transfer 'av' to child node */
+ finsh_type_check(finsh_node_child(node), is_addr);
+ }
+
+ /* always does not load address in sibling */
+ finsh_type_check(finsh_node_sibling(node), FINSH_NODE_VALUE);
+
+ /** set attribute of current node */
+
+ /* make sure the current node is address or value */
+ if (node->idtype != FINSH_IDTYPE_SYSCALL) node->idtype |= is_addr;
+
+ if (finsh_node_child(node) != NULL)
+ {
+ node->data_type = finsh_node_child(node)->data_type;
+ return 0;
+ }
+
+ if (node->node_type == FINSH_NODE_ID)
+ {
+ if (node->idtype & FINSH_IDTYPE_VAR)
+ {
+ struct finsh_var* var;
+
+ var = node->id.var;
+ if (var != NULL)
+ {
+ switch (var->type)
+ {
+ case finsh_type_void:
+ node->data_type = FINSH_DATA_TYPE_VOID;
+ break;
+
+ case finsh_type_char:
+ case finsh_type_uchar:
+ node->data_type = FINSH_DATA_TYPE_BYTE;
+ break;
+
+ case finsh_type_short:
+ case finsh_type_ushort:
+ node->data_type = FINSH_DATA_TYPE_WORD;
+ break;
+
+ case finsh_type_int:
+ case finsh_type_uint:
+ case finsh_type_long:
+ case finsh_type_ulong:
+ node->data_type = FINSH_DATA_TYPE_DWORD;
+ break;
+
+ case finsh_type_charp:
+ case finsh_type_voidp:
+ case finsh_type_shortp:
+ case finsh_type_intp:
+ case finsh_type_longp:
+ node->data_type = FINSH_DATA_TYPE_DWORD;
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
+ break;
+ }
+ }
+ }
+ else if (node->idtype & FINSH_IDTYPE_SYSVAR)
+ {
+ struct finsh_sysvar *sysvar;
+
+ sysvar = node->id.sysvar;
+ if (sysvar != NULL)
+ {
+ switch (sysvar->type)
+ {
+ case finsh_type_void:
+ node->data_type = FINSH_DATA_TYPE_VOID;
+ break;
+
+ case finsh_type_char:
+ case finsh_type_uchar:
+ node->data_type = FINSH_DATA_TYPE_BYTE;
+ break;
+
+ case finsh_type_short:
+ case finsh_type_ushort:
+ node->data_type = FINSH_DATA_TYPE_WORD;
+ break;
+
+ case finsh_type_int:
+ case finsh_type_uint:
+ case finsh_type_long:
+ case finsh_type_ulong:
+ node->data_type = FINSH_DATA_TYPE_DWORD;
+ break;
+
+ case finsh_type_charp:
+ case finsh_type_voidp:
+ case finsh_type_shortp:
+ case finsh_type_intp:
+ case finsh_type_longp:
+ node->data_type = FINSH_DATA_TYPE_DWORD;
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
+ break;
+ }
+ }
+ }
+ }
+ else if (node->node_type == FINSH_NODE_VALUE_CHAR)
+ {
+ node->data_type = FINSH_DATA_TYPE_BYTE;
+ }
+ else if (node->node_type == FINSH_NODE_VALUE_INT ||
+ node->node_type == FINSH_NODE_VALUE_LONG ||
+ node->node_type == FINSH_NODE_VALUE_STRING ||
+ node->node_type == FINSH_NODE_VALUE_NULL)
+ {
+ node->data_type = FINSH_DATA_TYPE_DWORD;
+ }
+ }
+ return 0;
+}
+
+int finsh_compiler_run(struct finsh_node* node)
+{
+ struct finsh_node* sibling;
+
+ /* type check */
+ finsh_type_check(node, FINSH_NODE_VALUE);
+
+ /* clean text segment and vm stack */
+ memset(&text_segment[0], 0, sizeof(text_segment));
+ memset(&finsh_vm_stack[0], 0, sizeof(finsh_vm_stack[0]));
+
+ /* reset compile stack pointer and pc */
+ finsh_compile_sp = &finsh_vm_stack[0];
+ finsh_compile_pc = &text_segment[0];
+
+ /* compile node */
+ sibling = node;
+ while (sibling != NULL)
+ {
+ struct finsh_node* current_node;
+ current_node = sibling;
+
+ /* get sibling node */
+ sibling = current_node->sibling;
+
+ /* clean sibling node */
+ current_node->sibling = NULL;
+ finsh_compile(current_node);
+
+ /* pop current value */
+ if (sibling != NULL) finsh_code_byte(FINSH_OP_POP);
+ }
+
+ return 0;
+}
diff --git a/finsh/finsh_error.c b/finsh/finsh_error.c
new file mode 100644
index 0000000000..e28223c732
--- /dev/null
+++ b/finsh/finsh_error.c
@@ -0,0 +1,46 @@
+#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];
+}
diff --git a/finsh/finsh_error.h b/finsh/finsh_error.h
new file mode 100644
index 0000000000..725da02a9e
--- /dev/null
+++ b/finsh/finsh_error.h
@@ -0,0 +1,14 @@
+#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
diff --git a/finsh/finsh_heap.c b/finsh/finsh_heap.c
new file mode 100644
index 0000000000..2fc027896f
--- /dev/null
+++ b/finsh/finsh_heap.c
@@ -0,0 +1,269 @@
+#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()
+{
+ /* 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;
+ }
+}
diff --git a/finsh/finsh_heap.h b/finsh/finsh_heap.h
new file mode 100644
index 0000000000..ac9df4f91a
--- /dev/null
+++ b/finsh/finsh_heap.h
@@ -0,0 +1,10 @@
+#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
diff --git a/finsh/finsh_init.c b/finsh/finsh_init.c
new file mode 100644
index 0000000000..e0dce342d3
--- /dev/null
+++ b/finsh/finsh_init.c
@@ -0,0 +1,48 @@
+#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;
+}
diff --git a/finsh/finsh_node.c b/finsh/finsh_node.c
new file mode 100644
index 0000000000..b5d7461adc
--- /dev/null
+++ b/finsh/finsh_node.c
@@ -0,0 +1,174 @@
+#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;
+}
diff --git a/finsh/finsh_node.h b/finsh/finsh_node.h
new file mode 100644
index 0000000000..c26fdea8de
--- /dev/null
+++ b/finsh/finsh_node.h
@@ -0,0 +1,60 @@
+#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
diff --git a/finsh/finsh_ops.c b/finsh/finsh_ops.c
new file mode 100644
index 0000000000..d201397083
--- /dev/null
+++ b/finsh/finsh_ops.c
@@ -0,0 +1,594 @@
+#include "finsh_ops.h"
+#include "finsh_vm.h"
+
+#define OP_BIN_BYTE(x) do {\
+ (finsh_sp - 2)->char_value = (finsh_sp - 2)->char_value x (finsh_sp - 1)->char_value; \
+ finsh_sp--; \
+ }while (0)
+
+#define OP_BIN_WORD(x) do {\
+ (finsh_sp - 2)->short_value = (finsh_sp - 2)->short_value x (finsh_sp - 1)->short_value; \
+ finsh_sp--; \
+ }while (0)
+
+#define OP_BIN_DWORD(x) do {\
+ (finsh_sp - 2)->long_value = (finsh_sp - 2)->long_value x (finsh_sp - 1)->long_value; \
+ finsh_sp--; \
+ }while (0)
+
+/* --- noop --- */
+void OP_no_op()
+{
+ /* none */
+ return ;
+}
+
+/* --- add --- */
+void OP_add_byte()
+{
+ OP_BIN_BYTE(+);
+
+ return ;
+}
+
+void OP_add_word()
+{
+ OP_BIN_WORD(+);
+
+ return ;
+}
+
+void OP_add_dword()
+{
+ OP_BIN_DWORD(+);
+
+ return ;
+}
+
+/* --- sub --- */
+void OP_sub_byte()
+{
+ OP_BIN_BYTE(-);
+
+ return ;
+}
+
+void OP_sub_word()
+{
+ OP_BIN_WORD(-);
+
+ return ;
+}
+
+void OP_sub_dword()
+{
+ OP_BIN_DWORD(-);
+
+ return ;
+}
+
+/* --- div --- */
+void OP_div_byte()
+{
+ OP_BIN_BYTE(/);
+
+ return ;
+}
+
+void OP_div_word()
+{
+ OP_BIN_WORD(/);
+
+ return ;
+}
+
+void OP_div_dword()
+{
+ OP_BIN_DWORD(/);
+
+ return ;
+}
+
+/* --- mod --- */
+void OP_mod_byte()
+{
+ OP_BIN_BYTE(%);
+
+ return ;
+}
+
+void OP_mod_word()
+{
+ OP_BIN_WORD(%);
+
+ return ;
+}
+
+void OP_mod_dword()
+{
+ OP_BIN_DWORD(%);
+
+ return ;
+}
+
+/* --- mul --- */
+void OP_mul_byte()
+{
+ OP_BIN_BYTE(*);
+
+ return ;
+}
+
+void OP_mul_word()
+{
+ OP_BIN_WORD(*);
+
+ return ;
+}
+
+void OP_mul_dword()
+{
+ OP_BIN_DWORD(*);
+
+ return ;
+}
+
+/* --- and --- */
+void OP_and_byte()
+{
+ OP_BIN_BYTE(&);
+
+ return ;
+}
+
+void OP_and_word()
+{
+ OP_BIN_WORD(&);
+
+ return ;
+}
+
+void OP_and_dword()
+{
+ OP_BIN_DWORD(&);
+
+ return ;
+}
+
+/* --- or --- */
+void OP_or_byte()
+{
+ OP_BIN_BYTE(|);
+
+ return ;
+}
+
+void OP_or_word()
+{
+ OP_BIN_WORD(|);
+
+ return ;
+}
+
+void OP_or_dword()
+{
+ OP_BIN_DWORD(|);
+
+ return ;
+}
+
+/* --- xor --- */
+void OP_xor_byte()
+{
+ OP_BIN_BYTE(^);
+
+ return ;
+}
+
+void OP_xor_word()
+{
+ OP_BIN_WORD(^);
+
+ return ;
+}
+
+void OP_xor_dword()
+{
+ OP_BIN_DWORD(^);
+
+ return ;
+}
+
+/* --- bw --- */
+void OP_bw_byte()
+{
+ (finsh_sp - 1)->char_value = ~ ((finsh_sp - 1)->char_value);
+
+ return ;
+}
+
+void OP_bw_word()
+{
+ (finsh_sp - 1)->short_value = ~ ((finsh_sp - 1)->short_value);
+
+ return ;
+}
+
+void OP_bw_dword()
+{
+ (finsh_sp - 1)->long_value = ~ ((finsh_sp - 1)->long_value);
+
+ return ;
+}
+
+/* --- shl --- */
+void OP_shl_byte()
+{
+ OP_BIN_BYTE(<<);
+
+ return ;
+}
+
+void OP_shl_word()
+{
+ OP_BIN_WORD(<<);
+
+ return ;
+}
+
+void OP_shl_dword()
+{
+ OP_BIN_DWORD(<<);
+
+ return ;
+}
+
+/* --- shr --- */
+void OP_shr_byte()
+{
+ OP_BIN_BYTE(>>);
+
+ return ;
+}
+
+void OP_shr_word()
+{
+ OP_BIN_WORD(>>);
+
+ return ;
+}
+
+void OP_shr_dword()
+{
+ OP_BIN_DWORD(>>);
+
+ return ;
+}
+
+/* --- ld --- */
+void OP_ld_byte()
+{
+ finsh_sp->char_value = *finsh_pc;
+
+ finsh_sp++;
+ finsh_pc++;
+
+ return ;
+}
+
+void OP_ld_word()
+{
+ finsh_sp->short_value = FINSH_GET16(finsh_pc);
+
+ finsh_sp ++;
+ finsh_pc += 2;
+
+ return ;
+}
+
+void OP_ld_dword()
+{
+ finsh_sp->long_value = FINSH_GET32(finsh_pc);
+
+ finsh_sp ++;
+ finsh_pc += 4;
+
+ return ;
+}
+
+void OP_ld_value_byte()
+{
+ char* c;
+
+ c = (char*) (FINSH_GET32(finsh_pc));
+
+ finsh_sp->char_value = *c;
+
+ finsh_sp ++;
+ finsh_pc += 4;
+
+ return;
+}
+
+void OP_ld_value_byte_stack()
+{
+ char* c;
+
+ c = (char *)(finsh_sp - 1)->long_value;
+ (finsh_sp - 1)->char_value = *c;
+
+ return;
+}
+
+void OP_ld_value_word()
+{
+ short* s;
+
+ s = (short*) (FINSH_GET32(finsh_pc));
+
+ finsh_sp->short_value = *s;
+
+ finsh_sp ++;
+ finsh_pc += 4;
+
+ return;
+}
+
+void OP_ld_value_word_stack()
+{
+ short* s;
+
+ s = (short *)(finsh_sp - 1)->long_value;
+ (finsh_sp - 1)->short_value = *s;
+
+ return;
+}
+
+void OP_ld_value_dword()
+{
+ long* l;
+
+ l = (long*) (FINSH_GET32(finsh_pc));
+
+ finsh_sp->long_value = *l;
+
+ finsh_sp ++;
+ finsh_pc += 4;
+
+ return;
+}
+
+void OP_ld_value_dword_stack()
+{
+ long* l;
+
+ l = (long *)(finsh_sp - 1)->long_value;
+ (finsh_sp - 1)->long_value = *l;
+
+ return;
+}
+
+/* --- st --- */
+/*
+ * 2006-4-16 bernard
+ * fixed the sp move bug
+ */
+void OP_st_byte()
+{
+ *(char*)((finsh_sp - 2)->long_value) = (finsh_sp - 1)->char_value;
+ finsh_sp --;
+
+ return ;
+}
+
+/*
+ * 2006-4-16 bernard
+ * fixed the sp move bug
+ */
+void OP_st_word()
+{
+ *(short*)((finsh_sp - 2)->long_value) = (finsh_sp - 1)->short_value;
+ finsh_sp --;
+
+ return ;
+}
+
+/*
+ * 2006-4-16 bernard
+ * fixed the sp move bug
+ */
+void OP_st_dword()
+{
+ *(long*)((finsh_sp - 2)->long_value) = (finsh_sp - 1)->long_value;
+ finsh_sp --;
+
+ return ;
+}
+
+/* --- pop --- */
+void OP_pop()
+{
+ finsh_sp --;
+ return ;
+}
+
+/* --- call --- */
+void OP_call()
+{
+ /* the max number of arg*/
+ unsigned long parameterv[16];
+ unsigned int parameters, i;
+
+ typedef unsigned long var_t;
+ typedef var_t (*op_func)();
+ op_func f;
+ var_t r;
+
+ parameters = *finsh_pc ++;
+
+ i = 0; finsh_sp --;
+ while (i < parameters)
+ {
+ parameterv[parameters - 1 - i] = finsh_sp->long_value;
+ finsh_sp --;
+ i++;
+ }
+
+ f = (op_func)(finsh_sp->long_value);
+ switch (parameters)
+ {
+ case 0:
+ r = f();
+ break;
+
+ case 1:
+ r = f(parameterv[0]);
+ break;
+
+ case 2:
+ r = f(parameterv[0], parameterv[1]);
+ break;
+
+ case 3:
+ r = f(parameterv[0], parameterv[1], parameterv[2]);
+ break;
+
+ case 4:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3]);
+ break;
+
+ case 5:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4]);
+ break;
+
+ case 6:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5]);
+ break;
+
+ case 7:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6]);
+ break;
+
+ case 8:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7]);
+ break;
+
+ case 9:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8]);
+ break;
+
+ case 10:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9]);
+ break;
+
+ case 11:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10]);
+ break;
+
+ case 12:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10], parameterv[11]);
+ break;
+
+ case 13:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10], parameterv[11],
+ parameterv[12]);
+ break;
+
+ case 14:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10], parameterv[11],
+ parameterv[12], parameterv[13]);
+ break;
+
+ case 15:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10], parameterv[11],
+ parameterv[12], parameterv[13], parameterv[14]);
+ break;
+
+ case 16:
+ r = f(parameterv[0], parameterv[1], parameterv[2], parameterv[3],
+ parameterv[4], parameterv[5], parameterv[6], parameterv[7],
+ parameterv[8], parameterv[9], parameterv[10], parameterv[11],
+ parameterv[12], parameterv[13], parameterv[14], parameterv[15]);
+ break;
+
+ default:
+ r = 0;
+ break;
+ }
+
+ finsh_sp->long_value = r;
+ finsh_sp ++;
+
+ return ;
+}
+
+op_func op_table[] =
+{
+ /* 00 */ OP_no_op,
+ /* 01 */ OP_add_byte,
+ /* 02 */ OP_add_word,
+ /* 03 */ OP_add_dword,
+ /* 04 */ OP_sub_byte,
+ /* 05 */ OP_sub_word,
+ /* 06 */ OP_sub_dword,
+ /* 07 */ OP_div_byte,
+ /* 08 */ OP_div_word,
+ /* 09 */ OP_div_dword,
+ /* 10 */ OP_mod_byte,
+ /* 11 */ OP_mod_word,
+ /* 12 */ OP_mod_dword,
+ /* 13 */ OP_mul_byte,
+ /* 14 */ OP_mul_word,
+ /* 15 */ OP_mul_dword,
+ /* 16 */ OP_and_byte,
+ /* 17 */ OP_and_word,
+ /* 18 */ OP_and_dword,
+ /* 19 */ OP_or_byte,
+ /* 20 */ OP_or_word,
+ /* 21 */ OP_or_dword,
+ /* 22 */ OP_xor_byte,
+ /* 23 */ OP_xor_word,
+ /* 24 */ OP_xor_dword,
+ /* 25 */ OP_bw_byte,
+ /* 26 */ OP_bw_word,
+ /* 27 */ OP_bw_dword,
+ /* 28 */ OP_shl_byte,
+ /* 29 */ OP_shl_word,
+ /* 30 */ OP_shl_dword,
+ /* 31 */ OP_shr_byte,
+ /* 32 */ OP_shr_word,
+ /* 33 */ OP_shr_dword,
+ /* 34 */ OP_ld_byte,
+ /* 35 */ OP_ld_word,
+ /* 36 */ OP_ld_dword,
+ /* 37 */ OP_ld_value_byte,
+ /* 38 */ OP_ld_value_word,
+ /* 39 */ OP_ld_value_dword,
+ /* 40 */ OP_st_byte,
+ /* 41 */ OP_st_word,
+ /* 42 */ OP_st_dword,
+ /* 43 */ OP_pop,
+ /* 44 */ OP_call,
+ /* 45 */ OP_ld_value_byte_stack,
+ /* 46 */ OP_ld_value_word_stack,
+ /* 47 */ OP_ld_value_dword_stack,
+ NULL
+};
diff --git a/finsh/finsh_ops.h b/finsh/finsh_ops.h
new file mode 100644
index 0000000000..1db5869518
--- /dev/null
+++ b/finsh/finsh_ops.h
@@ -0,0 +1,107 @@
+#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 op_func op_table[];
+
+#endif
diff --git a/finsh/finsh_parser.c b/finsh/finsh_parser.c
new file mode 100644
index 0000000000..b308e6d8f5
--- /dev/null
+++ b/finsh/finsh_parser.c
@@ -0,0 +1,965 @@
+#include <finsh.h>
+
+#include "finsh_token.h"
+#include "finsh_node.h"
+#include "finsh_error.h"
+#include "finsh_parser.h"
+#include "finsh_var.h"
+
+/*
+ * the structure of abstract syntax tree:
+ * root____________
+ * | \
+ * child__ sibling__
+ * | \ | \
+ * child sibling child sibling
+ * ...
+ */
+static enum finsh_type proc_type(struct finsh_parser* self);
+static int proc_identifier(struct finsh_parser* self, char* id);
+static struct finsh_node* proc_variable_decl(struct finsh_parser* self);
+static struct finsh_node* proc_expr(struct finsh_parser* self);
+static struct finsh_node* proc_assign_expr(struct finsh_parser* self);
+static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self);
+static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self);
+static struct finsh_node* proc_and_expr(struct finsh_parser* self);
+static struct finsh_node* proc_shift_expr(struct finsh_parser* self);
+static struct finsh_node* proc_additive_expr(struct finsh_parser* self);
+static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self);
+static struct finsh_node* proc_cast_expr(struct finsh_parser* self);
+static struct finsh_node* proc_unary_expr(struct finsh_parser* self);
+static struct finsh_node* proc_postfix_expr(struct finsh_parser* self);
+static struct finsh_node* proc_primary_expr(struct finsh_parser* self);
+static struct finsh_node* proc_param_list(struct finsh_parser* self);
+static struct finsh_node* proc_expr_statement(struct finsh_parser* self);
+static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1,
+ struct finsh_node* node2);
+
+/* check token */
+#define check_token(token, lex, type) if ( (token) != (type) ) \
+ { \
+ finsh_error_set(FINSH_ERROR_INVALID_TOKEN); \
+ finsh_token_replay(lex); \
+ }
+
+/* is the token a data type? */
+#define is_base_type(token) ((token) == finsh_token_type_void \
+ || (token) == finsh_token_type_char \
+ || (token) == finsh_token_type_short \
+ || (token) == finsh_token_type_int \
+ || (token) == finsh_token_type_long)
+
+/* get the next token */
+#define next_token(token, lex) (token) = finsh_token_token(lex)
+
+/* match a specified token */
+#define match_token(token, lex, type) next_token(token, lex); \
+ check_token(token, lex, type)
+
+/*
+process for function and variable declaration.
+decl_variable -> type declaration_list ';'
+declarator_list -> declarator_list ',' declarator
+ | declarator
+declarator -> identifier
+ | identifier ASSIGN expr_assign
+*/
+static struct finsh_node* proc_variable_decl(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ enum finsh_type type;
+ char id[FINSH_NAME_MAX + 1];
+
+ struct finsh_node *node;
+ struct finsh_node *end;
+ struct finsh_node *assign;
+
+ node = NULL;
+ end = NULL;
+
+ /* get type */
+ type = proc_type(self);
+
+ /*process id.*/
+ if (proc_identifier(self, id) == 0)
+ {
+ /* if add variable failed */
+ if (finsh_var_insert(id, type) < 0)
+ {
+ finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
+ }
+ }
+
+ next_token(token, &(self->token));
+ switch ( token )
+ {
+ case finsh_token_type_comma:/*',', it's a variable_list declaration.*/
+ if (proc_identifier(self, id) == 0)
+ {
+ /* if add variable failed */
+ if (finsh_var_insert(id, type) < 0)
+ {
+ finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
+ }
+ }
+
+ next_token(token, &(self->token));
+ if ( token == finsh_token_type_assign )
+ {
+ /* get the right side of assign expression */
+ assign = proc_assign_expr(self);
+
+ if (assign != NULL)
+ {
+ struct finsh_node* idnode;
+
+ idnode = finsh_node_new_id(id);
+ end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ node = end;
+
+ next_token(token, &(self->token));
+ }
+ }
+
+ while ( token == finsh_token_type_comma )
+ {
+ if (proc_identifier(self, id) == 0)
+ {
+ /* if add variable failed */
+ if (finsh_var_insert(id, type) < 0)
+ {
+ finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
+ }
+ }
+
+ next_token(token, &(self->token));
+ if ( token == finsh_token_type_assign )
+ {
+ /* get the right side of assign expression */
+ assign = proc_assign_expr(self);
+
+ if (assign != NULL)
+ {
+ struct finsh_node* idnode;
+
+ idnode = finsh_node_new_id(id);
+
+ /* make assign expression node */
+ if (node != NULL)
+ {
+ finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ end = finsh_node_sibling(end);
+ }
+ else
+ {
+ end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ node = end;
+ }
+
+ next_token(token, &(self->token));
+ }
+ }
+ }
+
+ check_token(token, &(self->token), finsh_token_type_semicolon);
+ return node;
+
+ case finsh_token_type_assign:/*'=', it's a variable with assign declaration.*/
+ {
+ struct finsh_node *idnode;
+
+ assign = proc_assign_expr(self);
+ if (assign != NULL)
+ {
+ idnode = finsh_node_new_id(id);
+
+ /* make assign expression node */
+ end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ node = end;
+
+ next_token(token, &(self->token));
+ }
+
+ while ( token == finsh_token_type_comma )
+ {
+ if (proc_identifier(self, id) == 0)
+ {
+ /* if add variable failed */
+ if (finsh_var_insert(id, type) < 0)
+ {
+ finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
+ }
+ }
+
+ next_token(token, &(self->token));
+ if (token == finsh_token_type_assign)
+ {
+ /* get the right side of assign expression */
+ assign = proc_assign_expr(self);
+
+ if (assign != NULL)
+ {
+ idnode = finsh_node_new_id(id);
+
+ /* make assign expression node */
+ if (node != NULL)
+ {
+ finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ end = finsh_node_sibling(end);
+ }
+ else
+ {
+ end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
+ node = end;
+ }
+
+ next_token(token, &(self->token));
+ }
+ }
+ }
+
+ check_token(token, &(self->token), finsh_token_type_semicolon);
+ return node;
+ }
+
+ case finsh_token_type_semicolon:/*';', it's a variable declaration.*/
+ return node;
+
+ default:
+ finsh_error_set(FINSH_ERROR_EXPECT_TYPE);
+
+ return NULL;
+ }
+}
+
+/*
+type -> type_prefix type_basic | type_basic
+type_prefix -> UNSIGNED
+type_basic -> VOID
+ | CHAR
+ | SHORT
+ | INT
+ | STRING
+*/
+static enum finsh_type proc_type(struct finsh_parser* self)
+{
+ enum finsh_type type;
+ enum finsh_token_type token;
+
+ /* set init type */
+ type = finsh_type_unknown;
+
+ next_token(token, &(self->token));
+ if ( is_base_type(token) ) /* base_type */
+ {
+ switch (token)
+ {
+ case finsh_token_type_void:
+ type = finsh_type_void;
+ break;
+
+ case finsh_token_type_char:
+ type = finsh_type_char;
+ break;
+
+ case finsh_token_type_short:
+ type = finsh_type_short;
+ break;
+
+ case finsh_token_type_int:
+ type = finsh_type_int;
+ break;
+
+ case finsh_token_type_long:
+ type = finsh_type_long;
+ break;
+
+ default:
+ goto __return;
+ }
+ }
+ else if ( token == finsh_token_type_unsigned ) /* unsigned base_type */
+ {
+ next_token(token, &(self->token));
+ if ( is_base_type(token) )
+ {
+ switch (token)
+ {
+ case finsh_token_type_char:
+ type = finsh_type_uchar;
+ break;
+
+ case finsh_token_type_short:
+ type = finsh_type_ushort;
+ break;
+
+ case finsh_token_type_int:
+ type = finsh_type_uint;
+ break;
+
+ case finsh_token_type_long:
+ type = finsh_type_ulong;
+ break;
+
+ default:
+ goto __return;
+ }
+ }
+ else
+ {
+ finsh_token_replay(&(self->token));
+ finsh_error_set(FINSH_ERROR_EXPECT_TYPE);
+ }
+ }
+ else
+ {
+ goto __return;
+ }
+
+ /* parse for pointer */
+ next_token(token, &(self->token));
+ if (token == finsh_token_type_mul)
+ {
+ switch (type)
+ {
+ case finsh_type_void:
+ type = finsh_type_voidp;
+ break;
+
+ case finsh_type_char:
+ case finsh_type_uchar:
+ type = finsh_type_charp;
+ break;
+
+ case finsh_type_short:
+ case finsh_type_ushort:
+ type = finsh_type_shortp;
+ break;
+
+ case finsh_type_int:
+ case finsh_type_uint:
+ type = finsh_type_intp;
+ break;
+
+ case finsh_type_long:
+ case finsh_type_ulong:
+ type = finsh_type_longp;
+ break;
+
+ default:
+ type = finsh_type_voidp;
+ break;
+ }
+ }
+ else finsh_token_replay(&(self->token));
+
+ return type;
+
+__return:
+ finsh_token_replay(&(self->token));
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
+
+ return type;
+}
+
+/*
+identifier -> IDENTIFIER
+*/
+static int proc_identifier(struct finsh_parser* self, char* id)
+{
+ enum finsh_token_type token;
+
+ match_token(token, &(self->token), finsh_token_type_identifier);
+
+ strncpy(id, (char*)self->token.string, FINSH_NAME_MAX);
+
+ return 0;
+}
+
+/*
+statement_expr -> ';'
+ | expr ';'
+*/
+static struct finsh_node* proc_expr_statement(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* expr;
+
+ expr = NULL;
+ next_token(token, &(self->token));
+ if ( token != finsh_token_type_semicolon )
+ {
+ finsh_token_replay(&(self->token));
+ expr = proc_expr(self);
+
+ match_token(token, &(self->token), finsh_token_type_semicolon);
+ }
+
+ return expr;
+}
+
+/*
+expr -> expr_assign
+*/
+static struct finsh_node* proc_expr(struct finsh_parser* self)
+{
+ return proc_assign_expr(self);
+}
+
+/*
+expr_assign -> expr_inclusive_or
+ | expr_unary ASSIGN expr_assign
+*/
+static struct finsh_node* proc_assign_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* or;
+ struct finsh_node* assign;
+
+ or = proc_inclusive_or_expr(self);
+
+ next_token(token, &(self->token));
+
+ if (token == finsh_token_type_assign)
+ {
+ assign = proc_assign_expr(self);
+
+ return make_sys_node(FINSH_NODE_SYS_ASSIGN, or, assign);
+ }
+ else finsh_token_replay(&(self->token));
+
+ return or;
+}
+
+/*
+expr_inclusive_or -> expr_exclusive_or
+ | expr_inclusive_or '|' expr_exclusive_or
+*/
+static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* xor;
+ struct finsh_node* xor_new;
+
+ xor = proc_exclusive_or_expr(self);
+
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_or )
+ {
+ xor_new = proc_exclusive_or_expr(self);
+
+ if (xor_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else xor = make_sys_node(FINSH_NODE_SYS_OR, xor, xor_new);
+
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return xor;
+}
+
+/*
+expr_exclusive_or -> expr_and
+ | expr_exclusive '^' expr_and
+*/
+static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* and;
+ struct finsh_node* and_new;
+
+ and = proc_and_expr(self);
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_xor )
+ {
+ and_new = proc_and_expr(self);
+ if (and_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else and = make_sys_node(FINSH_NODE_SYS_XOR, and, and_new);
+
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return and;
+}
+
+/*
+expr_and -> expr_shift
+ | expr_and '&' expr_shift
+*/
+static struct finsh_node* proc_and_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* shift;
+ struct finsh_node* shift_new;
+
+ shift = proc_shift_expr(self);
+
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_and )
+ {
+ shift_new = proc_shift_expr(self);
+
+ if (shift_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else shift = make_sys_node(FINSH_NODE_SYS_AND, shift, shift_new);
+
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return shift;
+}
+
+/*
+expr_shift -> expr_additive
+ | expr_shift '<<' expr_additive
+ | expr_shift '>>' expr_additive
+*/
+static struct finsh_node* proc_shift_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* add;
+ struct finsh_node* add_new;
+
+ add = proc_additive_expr(self);
+
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_shl || token == finsh_token_type_shr)
+ {
+ add_new = proc_additive_expr(self);
+ if (add_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else
+ {
+ switch (token)
+ {
+ case finsh_token_type_shl:
+ add = make_sys_node(FINSH_NODE_SYS_SHL, add, add_new);
+ break;
+ case finsh_token_type_shr:
+ add = make_sys_node(FINSH_NODE_SYS_SHR, add, add_new);
+ break;
+ default:
+ finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ break;
+ }
+ }
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return add;
+}
+
+/*
+expr_additive -> expr_multiplicative
+ | expr_additive SUB expr_multiplicative
+ | expr_additive ADD expr_multiplicative
+*/
+static struct finsh_node* proc_additive_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* mul;
+ struct finsh_node* mul_new;
+
+ mul = proc_multiplicative_expr(self);
+
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_sub || token == finsh_token_type_add )
+ {
+ mul_new = proc_multiplicative_expr(self);
+ if (mul_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else
+ {
+ switch (token)
+ {
+ case finsh_token_type_sub:
+ mul = make_sys_node(FINSH_NODE_SYS_SUB, mul, mul_new);
+ break;
+ case finsh_token_type_add:
+ mul = make_sys_node(FINSH_NODE_SYS_ADD, mul, mul_new);
+ break;
+ default:
+ finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ break;
+ }
+ }
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return mul;
+}
+
+/*
+expr_multiplicative -> expr_cast
+ | expr_multiplicative '*' expr_cast
+ | expr_multiplicative '/' expr_cast
+ | expr_multiplicative '%' expr_cast
+*/
+static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* cast;
+ struct finsh_node* cast_new;
+
+ cast = proc_cast_expr(self);
+ next_token(token, &(self->token));
+ while (token == finsh_token_type_mul ||
+ token == finsh_token_type_div ||
+ token == finsh_token_type_mod )
+ {
+ cast_new = proc_cast_expr(self);
+ if (cast_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ else
+ {
+ switch (token)
+ {
+ case finsh_token_type_mul:
+ cast = make_sys_node(FINSH_NODE_SYS_MUL, cast, cast_new);
+ break;
+
+ case finsh_token_type_div:
+ cast = make_sys_node(FINSH_NODE_SYS_DIV, cast, cast_new);
+ break;
+
+ case finsh_token_type_mod:
+ cast = make_sys_node(FINSH_NODE_SYS_MOD, cast, cast_new);
+ break;
+
+ default:
+ finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+ break;
+ }
+ }
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return cast;
+}
+
+/*
+20060313, add recast parse
+expr_cast -> expr_unary
+ | '(' type ')' expr_cast
+*/
+static struct finsh_node* proc_cast_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ enum finsh_type type;
+ struct finsh_node* cast;
+
+ next_token(token, &(self->token));
+ if (token == finsh_token_type_left_paren)
+ {
+ type = proc_type(self);
+ match_token(token, &(self->token), finsh_token_type_right_paren);
+
+ cast = proc_cast_expr(self);
+ cast->data_type = type;
+ return cast;
+ }
+
+ finsh_token_replay(&(self->token));
+ return proc_unary_expr(self);
+}
+
+/*
+20050921, add '*' and '&'
+expr_unary -> expr_postfix
+ | ADD expr_cast
+ | INC expr_cast
+ | SUB expr_cast
+ | DEC expr_cast
+ | '~' expr_cast
+ | '*' expr_cast
+ | '&' expr_cast
+*/
+static struct finsh_node* proc_unary_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node *cast;
+
+ next_token(token, &(self->token));
+ switch (token)
+ {
+ case finsh_token_type_add: /* + */
+ cast = proc_cast_expr(self);
+ return cast;
+
+ case finsh_token_type_inc: /* ++ */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_PREINC, cast, NULL);
+
+ case finsh_token_type_sub: /* - */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_SUB, finsh_node_new_long(0), cast);
+
+ case finsh_token_type_dec: /* -- */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_PREDEC, cast, NULL);
+
+ case finsh_token_type_bitwise: /* ~ */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_BITWISE, cast, NULL);
+
+ case finsh_token_type_mul: /* * */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_GETVALUE, cast, NULL);
+
+ case finsh_token_type_and: /* & */
+ cast = proc_cast_expr(self);
+ return make_sys_node(FINSH_NODE_SYS_GETADDR, cast, NULL);
+
+ default:
+ finsh_token_replay(&(self->token));
+ return proc_postfix_expr(self);
+ }
+}
+
+/*
+expr_postfix -> expr_primary
+ | expr_postfix INC
+ | expr_postfix DEC
+ | expr_postfix '(' param_list ')'
+*/
+static struct finsh_node* proc_postfix_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* postfix;
+
+ postfix = proc_primary_expr(self);
+
+ next_token(token, &(self->token));
+ while ( token == finsh_token_type_inc ||
+ token == finsh_token_type_dec ||
+ token == finsh_token_type_left_paren )
+ {
+ switch (token)
+ {
+ case finsh_token_type_inc :/* '++' */
+ postfix = make_sys_node(FINSH_NODE_SYS_INC, postfix, NULL);
+ break;
+
+ case finsh_token_type_dec :/* '--' */
+ postfix = make_sys_node(FINSH_NODE_SYS_DEC, postfix, NULL);
+ break;
+
+ case finsh_token_type_left_paren :/* '(' */
+ {
+ struct finsh_node* param_list;
+
+ param_list = NULL;
+ next_token(token, &(self->token));
+ if (token != finsh_token_type_right_paren)
+ {
+ finsh_token_replay(&(self->token));
+ param_list = proc_param_list(self);
+
+ match_token(token, &(self->token), finsh_token_type_right_paren);
+ }
+
+ postfix = make_sys_node(FINSH_NODE_SYS_FUNC, postfix, param_list);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+ return postfix;
+}
+
+/*
+expr_primary -> literal
+ | '(' expr ')'
+ | identifier
+*/
+static struct finsh_node* proc_primary_expr(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node* expr;
+
+ next_token(token, &(self->token));
+ switch ( token )
+ {
+ case finsh_token_type_identifier:
+ {
+ char id[FINSH_NAME_MAX + 1];
+
+ finsh_token_replay(&(self->token));
+ proc_identifier(self, id);
+ return finsh_node_new_id(id);
+ }
+
+ case finsh_token_type_left_paren:
+ expr = proc_expr(self);
+ match_token(token, &(self->token), finsh_token_type_right_paren);
+ return expr;
+
+ case finsh_token_type_value_int:
+ return finsh_node_new_int(self->token.value.int_value);
+
+ case finsh_token_type_value_long:
+ return finsh_node_new_long(self->token.value.long_value);
+
+ case finsh_token_type_value_char:
+ return finsh_node_new_char(self->token.value.char_value);
+
+ case finsh_token_type_value_string:
+ return finsh_node_new_string((char*)self->token.string);
+
+ case finsh_token_type_value_null:
+ return finsh_node_new_ptr(NULL);
+
+ default:
+ finsh_error_set(FINSH_ERROR_INVALID_TOKEN);
+ break;
+ }
+
+ return NULL;
+}
+
+/*
+param_list -> empty
+ | expr_assign
+ | param_list ',' expr_assign
+*/
+static struct finsh_node* proc_param_list(struct finsh_parser* self)
+{
+ enum finsh_token_type token;
+ struct finsh_node *node, *assign;
+
+ assign = proc_assign_expr(self);
+ node = assign;
+
+ next_token(token, &(self->token));
+ while (token == finsh_token_type_comma )
+ {
+ finsh_node_sibling(assign) = proc_assign_expr(self);
+
+ if (finsh_node_sibling(assign) != NULL) assign = finsh_node_sibling(assign);
+ else finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
+
+ next_token(token, &(self->token));
+ }
+
+ finsh_token_replay(&(self->token));
+
+ return node;
+}
+
+/*
+make a new node as following tree:
+new_node
+|
+node1__
+ \
+ node2
+*/
+static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1, struct finsh_node* node2)
+{
+ struct finsh_node* node;
+
+ node = finsh_node_allocate(type);
+
+ finsh_node_child(node) = node1;
+ if (node1 != NULL) finsh_node_sibling(node1) = node2;
+ else finsh_error_set(FINSH_ERROR_NULL_NODE);
+
+ return node;
+}
+
+/*
+start -> statement_expr | decl_variable
+*/
+void finsh_parser_run(struct finsh_parser* self, const u_char* string)
+{
+ enum finsh_token_type token;
+ struct finsh_node *node;
+
+ node = NULL;
+
+ /* init parser */
+ self->parser_string = (u_char*)string;
+
+ /* init token */
+ finsh_token_init(&(self->token), self->parser_string);
+
+ /* get next token */
+ next_token(token, &(self->token));
+ while (token != finsh_token_type_eof && token != finsh_token_type_bad)
+ {
+ switch (token)
+ {
+ case finsh_token_type_identifier:
+ /* process expr_statement */
+ finsh_token_replay(&(self->token));
+
+ if (self->root != NULL)
+ {
+ finsh_node_sibling(node) = proc_expr_statement(self);
+ if (finsh_node_sibling(node) != NULL)
+ node = finsh_node_sibling(node);
+ }
+ else
+ {
+ node = proc_expr_statement(self);
+ self->root = node;
+ }
+ break;
+
+ default:
+ if (is_base_type(token) || token == finsh_token_type_unsigned)
+ {
+ /* variable decl */
+ finsh_token_replay(&(self->token));
+
+ if (self->root != NULL)
+ {
+ finsh_node_sibling(node) = proc_variable_decl(self);
+ if (finsh_node_sibling(node) != NULL)
+ node = finsh_node_sibling(node);
+ }
+ else
+ {
+ node = proc_variable_decl(self);
+ self->root = node;
+ }
+ }
+ else
+ {
+ /* process expr_statement */
+ finsh_token_replay(&(self->token));
+
+ if (self->root != NULL)
+ {
+ finsh_node_sibling(node) = proc_expr_statement(self);
+ if (finsh_node_sibling(node) != NULL)
+ node = finsh_node_sibling(node);
+ else next_token(token, &(self->token));
+ }
+ else
+ {
+ node = proc_expr_statement(self);
+ self->root = node;
+ }
+ }
+
+ break;
+ }
+ /* get next token */
+ next_token(token, &(self->token));
+ }
+}
+
+int finsh_parser_init(struct finsh_parser* self)
+{
+ memset(self, 0, sizeof(struct finsh_parser));
+
+ return 0;
+}
diff --git a/finsh/finsh_parser.h b/finsh/finsh_parser.h
new file mode 100644
index 0000000000..a8339062e7
--- /dev/null
+++ b/finsh/finsh_parser.h
@@ -0,0 +1,9 @@
+#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
diff --git a/finsh/finsh_token.c b/finsh/finsh_token.c
new file mode 100644
index 0000000000..7002ca27f4
--- /dev/null
+++ b/finsh/finsh_token.c
@@ -0,0 +1,562 @@
+#include <finsh.h>
+
+#include "finsh_token.h"
+#include "finsh_error.h"
+
+#define is_digit(ch) ((ch) >= '0' && (ch) <= '9')
+#define is_separator(ch) !(((ch) >= 'a' && (ch) <= 'z') \
+ || ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= '0' && (ch) <= '9') || ((ch) == '_'))
+#define is_eof(self) (self)->eof
+
+struct name_table
+{
+ char* name;
+ enum finsh_token_type type;
+};
+
+/* keyword */
+static struct name_table finsh_name_table[] =
+{
+ {"void", finsh_token_type_void},
+ {"char", finsh_token_type_char},
+ {"short", finsh_token_type_short},
+ {"int", finsh_token_type_int},
+ {"long", finsh_token_type_long},
+ {"unsigned", finsh_token_type_unsigned},
+
+ {"NULL", finsh_token_type_value_null},
+ {"null", finsh_token_type_value_null}
+};
+
+static char token_next_char(struct finsh_token* self);
+static void token_prev_char(struct finsh_token* self);
+static long token_spec_number(char* string, int length, int b);
+static void token_run(struct finsh_token* self);
+static int token_match_name(struct finsh_token* self, const char* str);
+static void token_proc_number(struct finsh_token* self);
+static u_char* token_proc_string(struct finsh_token* self);
+static void token_trim_space(struct finsh_token* self);
+static char token_proc_char(struct finsh_token* self);
+static int token_proc_escape(struct finsh_token* self);
+
+void finsh_token_init(struct finsh_token* self, u_char* line)
+{
+ memset(self, 0, sizeof(struct finsh_token));
+
+ self->line = line;
+}
+
+enum finsh_token_type finsh_token_token(struct finsh_token* self)
+{
+ if ( self->replay ) self->replay = 0;
+ else token_run(self);
+
+ return (enum finsh_token_type)self->current_token;
+}
+
+void finsh_token_get_token(struct finsh_token* self, u_char* token)
+{
+ strncpy((char*)token, (char*)self->string, FINSH_NAME_MAX);
+}
+
+int token_get_string(struct finsh_token* self, u_char* str)
+{
+ unsigned char *p=str;
+ char ch;
+
+ ch = token_next_char(self);
+ if (is_eof(self)) return -1;
+
+ str[0] = '\0';
+
+ if ( is_digit(ch) )/*the first character of identifier is not a digit.*/
+ {
+ token_prev_char(self);
+ return -1;
+ }
+
+ while (!is_separator(ch) && !is_eof(self))
+ {
+ *p++ = ch;
+
+ ch = token_next_char(self);
+ }
+ self->eof = 0;
+
+ token_prev_char(self);
+ *p = '\0';
+
+ return 0;
+}
+
+/*
+get next character.
+*/
+static char token_next_char(struct finsh_token* self)
+{
+ if (self->eof) return '\0';
+
+ if (self->position == (int)strlen((char*)self->line) || self->line[self->position] =='\n')
+ {
+ self->eof = 1;
+ self->position = 0;
+ return '\0';
+ }
+
+ return self->line[self->position++];
+}
+
+static void token_prev_char(struct finsh_token* self)
+{
+ if ( self->eof ) return;
+
+ if ( self->position == 0 ) return;
+ else self->position--;
+}
+
+static void token_run(struct finsh_token* self)
+{
+ char ch;
+
+ token_trim_space(self); /* first trim space and tab. */
+ token_get_string(self, &(self->string[0]));
+
+ if ( is_eof(self) ) /*if it is eof, break;*/
+ {
+ self->current_token = finsh_token_type_eof;
+ return ;
+ }
+
+ if (self->string[0] != '\0') /*It is a key word or a identifier.*/
+ {
+ if ( !token_match_name(self, (char*)self->string) )
+ {
+ self->current_token = finsh_token_type_identifier;
+ }
+ return;
+ }
+ else/*It is a operator character.*/
+ {
+ ch = token_next_char(self);
+
+ switch ( ch )
+ {
+ case '(':
+ self->current_token = finsh_token_type_left_paren;
+ break;
+
+ case ')':
+ self->current_token = finsh_token_type_right_paren;
+ break;
+
+ case ',':
+ self->current_token = finsh_token_type_comma;
+ break;
+
+ case ';':
+ self->current_token = finsh_token_type_semicolon;
+ break;
+
+ case '&':
+ self->current_token = finsh_token_type_and;
+ break;
+
+ case '*':
+ self->current_token = finsh_token_type_mul;
+ break;
+
+ case '+':
+ ch = token_next_char(self);
+
+ if ( ch == '+' )
+ {
+ self->current_token = finsh_token_type_inc;
+ }
+ else
+ {
+ token_prev_char(self);
+ self->current_token = finsh_token_type_add;
+ }
+ break;
+
+ case '-':
+ ch = token_next_char(self);
+
+ if ( ch == '-' )
+ {
+ self->current_token = finsh_token_type_dec;
+ }
+ else
+ {
+ token_prev_char(self);
+ self->current_token = finsh_token_type_sub;
+ }
+ break;
+
+ case '/':
+ self->current_token = finsh_token_type_div;
+ break;
+
+ case '<':
+ ch = token_next_char(self);
+
+ if ( ch == '<' )
+ {
+ self->current_token = finsh_token_type_shl;
+ }
+ else
+ {
+ token_prev_char(self);
+ self->current_token = finsh_token_type_bad;
+ }
+ break;
+
+ case '>':
+ ch = token_next_char(self);
+
+ if ( ch == '>' )
+ {
+ self->current_token = finsh_token_type_shr;
+ }
+ else
+ {
+ token_prev_char(self);
+ self->current_token = finsh_token_type_bad;
+ }
+ break;
+
+ case '|':
+ self->current_token = finsh_token_type_or;
+ break;
+
+ case '%':
+ self->current_token = finsh_token_type_mod;
+ break;
+
+ case '~':
+ self->current_token = finsh_token_type_bitwise;
+ break;
+
+ case '^':
+ self->current_token = finsh_token_type_xor;
+ break;
+
+ case '=':
+ self->current_token = finsh_token_type_assign;
+ break;
+
+ case '\'':
+ self->value.char_value = token_proc_char(self);
+ self->current_token = finsh_token_type_value_char;
+ break;
+
+ case '"':
+ token_proc_string(self);
+ self->current_token = finsh_token_type_value_string;
+ break;
+
+ default:
+ if ( is_digit(ch) )
+ {
+ token_prev_char(self);
+ token_proc_number(self);
+ break;
+ }
+
+ finsh_error_set(FINSH_ERROR_UNKNOWN_TOKEN);
+ self->current_token = finsh_token_type_bad;
+
+ break;
+ }
+ }
+}
+
+static int token_match_name(struct finsh_token* self, const char* str)
+{
+ int i;
+
+ for (i = 0; i < sizeof(finsh_name_table)/sizeof(struct name_table); i++)
+ {
+ if ( strcmp(finsh_name_table[i].name, str)==0 )
+ {
+ self->current_token = finsh_name_table[i].type;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void token_trim_space(struct finsh_token* self)
+{
+ char ch;
+ while ( (ch = token_next_char(self)) ==' ' || ch == '\t');
+
+ token_prev_char(self);
+}
+
+static char token_proc_char(struct finsh_token* self)
+{
+ char ch;
+ char buf[4], *p;
+
+ p = buf;
+ ch = token_next_char(self);
+
+ if ( ch == '\\' )
+ {
+ ch = token_next_char(self);
+ switch ( ch )
+ {
+ case 'n': ch = '\n'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ case 'b': ch = '\b'; break;
+ case 'r': ch = '\r'; break;
+ case '\\': ch = '\\'; break;
+ case '\'': ch = '\''; break;
+ default :
+ while ( is_digit(ch) )/*for '\113' char*/
+ {
+ ch = token_next_char(self);
+ *p++ = ch;
+ }
+
+ token_prev_char(self);
+ *p = '\0';
+ ch = atoi(p);
+ break;
+ }
+ }
+
+ if ( token_next_char(self) != '\'' )
+ {
+ token_prev_char(self);
+ finsh_error_set(FINSH_ERROR_EXPECT_CHAR);
+ return ch;
+ }
+
+ return ch;
+}
+
+static u_char* token_proc_string(struct finsh_token* self)
+{
+ u_char* p;
+
+ for ( p = &self->string[0]; p - &(self->string[0]) < FINSH_STRING_MAX; )
+ {
+ char ch = token_next_char(self);
+
+ if ( is_eof(self) )
+ {
+ finsh_error_set(FINSH_ERROR_UNEXPECT_END);
+ return NULL;;
+ }
+ if ( ch == '\\' )
+ {
+ ch = token_proc_escape(self);
+ }
+ else if ( ch == '"' )/*end of string.*/
+ {
+ *p = '\0';
+ return self->string;
+ }
+
+ *p++ = ch;
+ }
+
+ return NULL;
+}
+
+static int token_proc_escape(struct finsh_token* self)
+{
+ char ch;
+ int result=0;
+
+ ch = token_next_char(self);
+ switch (ch)
+ {
+ case 'n':
+ result = '\n';
+ break;
+ case 't':
+ result = '\t';
+ break;
+ case 'v':
+ result = '\v';
+ break;
+ case 'b':
+ result = '\b';
+ break;
+ case 'r':
+ result = '\r';
+ break;
+ case 'f':
+ result = '\f';
+ break;
+ case 'a':
+ result = '\007';
+ break;
+ case 'x':
+ result = 0;
+ ch = token_next_char(self);
+ while ( (ch - '0')<16u )
+ {
+ result = result*16 + ch - '0';
+ ch = token_next_char(self);
+ }
+ token_prev_char(self);
+ break;
+ default:
+ if ( (ch - '0') < 8u)
+ {
+ result = 0;
+ while ( (ch - '0') < 8u )
+ {
+ result = result*8 + ch - '0';
+ ch = token_next_char(self);
+ }
+
+ token_prev_char(self);
+ }
+ break;
+ }
+
+ return result;
+}
+
+/*
+(0|0x|0X|0b|0B)number+(l|L)
+*/
+static void token_proc_number(struct finsh_token* self)
+{
+ char ch;
+ int b;
+ char *p, buf[128];
+ long value;
+
+ value = 0;
+ p = buf;
+ b = 10;
+
+ ch = token_next_char(self);
+ if ( ch == '0' )
+ {
+ ch = token_next_char(self);
+ if ( ch == 'x' || ch == 'X' )/*it's a hex number*/
+ {
+ b = 16;
+ ch = token_next_char(self);
+ while ( is_digit(ch) || isalpha(ch) )
+ {
+ *p++ = ch;
+ ch = token_next_char(self);
+ }
+
+ *p = '\0';
+ }
+ else if ( ch == 'b' || ch == 'B' )
+ {
+ b = 2;
+ ch = token_next_char(self);
+ while ( (ch=='0')||(ch=='1') )
+ {
+ *p++ = ch;
+ ch = token_next_char(self);
+ }
+
+ *p = '\0';
+ }
+ else
+ {
+ b = 8;
+ while ( is_digit(ch) )
+ {
+ *p++ = ch;
+ ch = token_next_char(self);
+ }
+
+ *p = '\0';
+ }
+
+ self->value.int_value = token_spec_number(buf, strlen(buf), b);
+ self->current_token = finsh_token_type_value_int;
+ }
+ else
+ {
+ while ( is_digit(ch) )
+ {
+ value = value*10 + ( ch - '0' );
+ ch = token_next_char(self);
+ }
+
+ self->value.int_value = value;
+ self->current_token = finsh_token_type_value_int;
+ }
+
+ switch ( ch )
+ {
+ case 'l':
+ case 'L':
+ self->current_token = finsh_token_type_value_long;
+ break;
+
+ default:
+ token_prev_char(self);
+ break;
+ }
+}
+
+/*use 64 bit number*/
+#define BN_SIZE 2
+
+static long token_spec_number(char* string, int length, int b)
+{
+ char* p;
+ int t;
+ int i, j, shift=1;
+ unsigned int bn[BN_SIZE], v;
+ long d;
+
+ p = string;
+ i = 0;
+
+ switch ( b )
+ {
+ case 16: shift = 4;
+ break;
+ case 8: shift = 3;
+ break;
+ case 2: shift = 1;
+ break;
+ default: break;
+ }
+
+ for ( j=0; j<BN_SIZE ; j++) bn[j] = 0;
+
+ while ( i<length )
+ {
+ t = *p++;
+ if ( t>='a' && t <='f' )
+ {
+ t = t - 'a' +10;
+ }
+ else if ( t >='A' && t <='F' )
+ {
+ t = t - 'A' +10;
+ }
+ else t = t - '0';
+
+ for ( j=0; j<BN_SIZE ; j++)
+ {
+ v = bn[j];
+ bn[j] = (v<<shift) | t;
+ t = v >> (32 - shift);
+ }
+ i++;
+ }
+
+ d = (long)bn[0];
+
+ return d;
+}
diff --git a/finsh/finsh_token.h b/finsh/finsh_token.h
new file mode 100644
index 0000000000..2224f003a1
--- /dev/null
+++ b/finsh/finsh_token.h
@@ -0,0 +1,53 @@
+#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
diff --git a/finsh/finsh_var.c b/finsh/finsh_var.c
new file mode 100644
index 0000000000..5b6d6ac3ea
--- /dev/null
+++ b/finsh/finsh_var.c
@@ -0,0 +1,130 @@
+#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;
+}
diff --git a/finsh/finsh_var.h b/finsh/finsh_var.h
new file mode 100644
index 0000000000..fa7df0ff1f
--- /dev/null
+++ b/finsh/finsh_var.h
@@ -0,0 +1,32 @@
+#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
diff --git a/finsh/finsh_vm.c b/finsh/finsh_vm.c
new file mode 100644
index 0000000000..e51e4de022
--- /dev/null
+++ b/finsh/finsh_vm.c
@@ -0,0 +1,356 @@
+#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
+#include <stdio.h>
+void finsh_disassemble()
+{
+ u_char *pc, op;
+
+ pc = &text_segment[0];
+ while (*pc != 0)
+ {
+ op = *pc;
+ switch (op)
+ {
+ case FINSH_OP_ADD_BYTE:
+ pc ++;
+ printf("addb\n");
+ break;
+
+ case FINSH_OP_SUB_BYTE:
+ pc ++;
+ printf("subb\n");
+ break;
+
+ case FINSH_OP_DIV_BYTE:
+ pc ++;
+ printf("divb\n");
+ break;
+
+ case FINSH_OP_MOD_BYTE:
+ pc ++;
+ printf("modb\n");
+ break;
+
+ case FINSH_OP_MUL_BYTE:
+ pc ++;
+ printf("mulb\n");
+ break;
+
+ case FINSH_OP_AND_BYTE:
+ pc ++;
+ printf("andb\n");
+ break;
+
+ case FINSH_OP_OR_BYTE:
+ pc ++;
+ printf("orb\n");
+ break;
+
+ case FINSH_OP_XOR_BYTE:
+ pc ++;
+ printf("xorb\n");
+ break;
+
+ case FINSH_OP_BITWISE_BYTE:
+ pc ++;
+ printf("bwb\n");
+ break;
+
+ case FINSH_OP_SHL_BYTE:
+ pc ++;
+ printf("shlb\n");
+ break;
+
+ case FINSH_OP_SHR_BYTE:
+ pc ++;
+ printf("shrb\n");
+ break;
+
+ case FINSH_OP_LD_BYTE:
+ pc ++;
+ printf("ldb %d\n", *pc++);
+ break;
+
+ case FINSH_OP_LD_VALUE_BYTE:
+ pc ++;
+ printf("ldb [0x%x]\n", FINSH_GET32(pc));
+ pc += 4;
+ break;
+
+ case FINSH_OP_ST_BYTE:
+ pc ++;
+ printf("stb\n");
+ break;
+
+ case FINSH_OP_ADD_WORD:
+ pc ++;
+ printf("addw\n");
+ break;
+
+ case FINSH_OP_SUB_WORD:
+ pc ++;
+ printf("subw\n");
+ break;
+
+ case FINSH_OP_DIV_WORD:
+ pc ++;
+ printf("divw\n");
+ break;
+
+ case FINSH_OP_MOD_WORD:
+ pc ++;
+ printf("modw\n");
+ break;
+
+ case FINSH_OP_MUL_WORD:
+ pc ++;
+ printf("mulw\n");
+ break;
+
+ case FINSH_OP_AND_WORD:
+ pc ++;
+ printf("andw\n");
+ break;
+
+ case FINSH_OP_OR_WORD:
+ pc ++;
+ printf("orw\n");
+ break;
+
+ case FINSH_OP_XOR_WORD:
+ pc ++;
+ printf("xorw\n");
+ break;
+
+ case FINSH_OP_BITWISE_WORD:
+ pc ++;
+ printf("bww\n");
+ break;
+
+ case FINSH_OP_SHL_WORD:
+ pc ++;
+ printf("shlw\n");
+ break;
+
+ case FINSH_OP_SHR_WORD:
+ pc ++;
+ printf("shrw\n");
+ break;
+
+ case FINSH_OP_LD_WORD:
+ pc ++;
+ printf("ldw %d\n", FINSH_GET16(pc));
+ pc += 2;
+ break;
+
+ case FINSH_OP_LD_VALUE_WORD:
+ pc ++;
+ printf("ldw [0x%x]\n", FINSH_GET32(pc));
+ pc += 4;
+ break;
+
+ case FINSH_OP_ST_WORD:
+ pc ++;
+ printf("stw\n");
+ break;
+
+ case FINSH_OP_ADD_DWORD:
+ pc ++;
+ printf("addd\n");
+ break;
+
+ case FINSH_OP_SUB_DWORD:
+ pc ++;
+ printf("subd\n");
+ break;
+
+ case FINSH_OP_DIV_DWORD:
+ pc ++;
+ printf("divd\n");
+ break;
+
+ case FINSH_OP_MOD_DWORD:
+ pc ++;
+ printf("modd\n");
+ break;
+
+ case FINSH_OP_MUL_DWORD:
+ pc ++;
+ printf("muld\n");
+ break;
+
+ case FINSH_OP_AND_DWORD:
+ pc ++;
+ printf("andd\n");
+ break;
+
+ case FINSH_OP_OR_DWORD:
+ pc ++;
+ printf("ord\n");
+ break;
+
+ case FINSH_OP_XOR_DWORD:
+ pc ++;
+ printf("xord\n");
+ break;
+
+ case FINSH_OP_BITWISE_DWORD:
+ pc ++;
+ printf("bwd\n");
+ break;
+
+ case FINSH_OP_SHL_DWORD:
+ pc ++;
+ printf("shld\n");
+ break;
+
+ case FINSH_OP_SHR_DWORD:
+ pc ++;
+ printf("shrd\n");
+ break;
+
+ case FINSH_OP_LD_DWORD:
+ pc ++;
+ printf("ldd 0x%x\n", FINSH_GET32(pc));
+ pc += 4;
+ break;
+
+ case FINSH_OP_LD_VALUE_DWORD:
+ pc ++;
+ printf("ldd [0x%x]\n", FINSH_GET32(pc));
+ pc += 4;
+ break;
+
+ case FINSH_OP_ST_DWORD:
+ pc ++;
+ printf("std\n");
+ break;
+
+ case FINSH_OP_POP:
+ printf("pop\n");
+ pc ++;
+ break;
+
+ case FINSH_OP_SYSCALL:
+ pc ++;
+ printf("syscall %d\n", *pc++);
+ break;
+
+ case FINSH_OP_LD_VALUE_BYTE_STACK:
+ pc ++;
+ printf("ldb [sp]\n");
+ break;
+
+ case FINSH_OP_LD_VALUE_WORD_STACK:
+ pc ++;
+ printf("ldw [sp]\n");
+ break;
+
+ case FINSH_OP_LD_VALUE_DWORD_STACK:
+ pc ++;
+ printf("ldd [sp]\n");
+ break;
+
+ default:
+ return;
+ }
+ }
+}
+#endif
diff --git a/finsh/finsh_vm.h b/finsh/finsh_vm.h
new file mode 100644
index 0000000000..1e453776ed
--- /dev/null
+++ b/finsh/finsh_vm.h
@@ -0,0 +1,26 @@
+#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
diff --git a/finsh/shell.c b/finsh/shell.c
new file mode 100644
index 0000000000..f38d745a9c
--- /dev/null
+++ b/finsh/shell.c
@@ -0,0 +1,270 @@
+/*
+ * 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://openlab.rt-thread.com/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
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+
+#include "finsh.h"
+
+#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
+#endif
+
+/* finsh thread */
+struct rt_thread finsh_thread;
+char finsh_thread_stack[2048];
+struct rt_semaphore uart_sem;
+#ifdef RT_USING_DEVICE
+rt_device_t finsh_device;
+#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
+
+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
+
+#ifdef RT_USING_DEVICE
+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(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);
+ }
+}
+#else
+void finsh_notify()
+{
+ rt_sem_release(&uart_sem);
+}
+#endif
+
+void finsh_thread_entry(void* parameter)
+{
+ struct finsh_parser parser;
+ char line[256];
+ int pos ;
+
+ finsh_init(&parser);
+
+ while (1)
+ {
+ rt_kprintf("finsh>>");
+
+ memset(line, 0, sizeof(line));
+ pos = 0;
+ while (1)
+ {
+ if (rt_sem_take(&uart_sem, -1) == RT_EOK)
+ {
+ /* read one character from serial */
+ char ch;
+
+#ifndef RT_USING_DEVICE
+ ch = rt_serial_getc();
+ if (ch != 0)
+#else
+ rt_err_t rx_result;
+ rx_result = rt_device_read(finsh_device, 0, &ch, 1);
+ if (ch != 0 && rx_result == 1)
+#endif
+ {
+ line[pos] = ch;
+
+ rt_kprintf("%c", line[pos]);
+
+ /* if it's the end of line, break */
+ if (line[pos] == 0xd || line[pos] == 0xa)
+ {
+ /* change to ';' and break */
+ line[pos] = ';';
+ break;
+ }
+ pos ++;
+ }
+ }
+ }
+
+ rt_kprintf("\n");
+ finsh_parser_run(&parser, (unsigned char*)&line[0]);
+
+ /* 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)
+ {
+ finsh_vm_run();
+
+ if (isprint((unsigned char)finsh_stack_bottom()))
+ {
+ 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%04x\n",
+ (unsigned int)finsh_stack_bottom(),
+ (unsigned int)finsh_stack_bottom());
+ }
+ }
+
+ finsh_flush(&parser);
+ }
+}
+
+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()
+{
+ 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 */
+#endif
+#endif
+
+ rt_thread_init(&finsh_thread,
+ "tshell",
+ finsh_thread_entry, RT_NULL,
+ &finsh_thread_stack[0], sizeof(finsh_thread_stack),
+ 20, 100);
+ rt_thread_startup(&finsh_thread);
+}
diff --git a/finsh/symbol.c b/finsh/symbol.c
new file mode 100644
index 0000000000..a94ec64009
--- /dev/null
+++ b/finsh/symbol.c
@@ -0,0 +1,56 @@
+#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