From 787f37aa67e076b6da5b23a6583ebb7d63595811 Mon Sep 17 00:00:00 2001 From: ffashion Date: Wed, 26 Apr 2023 23:27:04 +0800 Subject: [PATCH] feat kmcvm: init commit Signed-off-by: ffashion --- usr/command/Makefile | 1 + usr/command/kmcvm/Makefile | 5 + usr/command/kmcvm/kmcvm.c | 56 ++++ usr/command/kmcvm/mpool.c | 355 ++++++++++++++++++++++ usr/command/kmcvm/mpool.h | 113 +++++++ usr/command/kmcvm/parser.c | 598 +++++++++++++++++++++++++++++++++++++ usr/command/kmcvm/parser.h | 56 ++++ usr/command/kmcvm/token.c | 224 ++++++++++++++ usr/command/kmcvm/token.h | 34 +++ 9 files changed, 1442 insertions(+) create mode 100644 usr/command/kmcvm/Makefile create mode 100644 usr/command/kmcvm/kmcvm.c create mode 100644 usr/command/kmcvm/mpool.c create mode 100644 usr/command/kmcvm/mpool.h create mode 100644 usr/command/kmcvm/parser.c create mode 100644 usr/command/kmcvm/parser.h create mode 100644 usr/command/kmcvm/token.c create mode 100644 usr/command/kmcvm/token.h diff --git a/usr/command/Makefile b/usr/command/Makefile index d7aca6bd..f58df659 100644 --- a/usr/command/Makefile +++ b/usr/command/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later obj-y += arch/ +obj-y += kmcvm/ obj-$(CONFIG_KCMD_ASCII85) += ascii85.o obj-$(CONFIG_KCMD_BASE32) += base32.o obj-$(CONFIG_KCMD_BASE64) += base64.o diff --git a/usr/command/kmcvm/Makefile b/usr/command/kmcvm/Makefile new file mode 100644 index 00000000..68619f23 --- /dev/null +++ b/usr/command/kmcvm/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +obj-y += kmcvm.o +obj-y += parser.o +obj-y += token.o +obj-y += mpool.o diff --git a/usr/command/kmcvm/kmcvm.c b/usr/command/kmcvm/kmcvm.c new file mode 100644 index 00000000..c2fb0781 --- /dev/null +++ b/usr/command/kmcvm/kmcvm.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2022 John Sanpe + */ + +#include +#include +#include "parser.h" +#include "token.h" + +static state kmcvm_main(struct kshell_context *ctx, int argc, char *argv[]) +{ + Token *head; + Node *node; + mpool_t *pool; + const char *token; + + token = kshell_getenv(ctx, "COMPUTE"); + + pool = mpool_create(MPOOL_DEFAULT_SIZE, NULL); + if (pool == NULL) { + return -ENOMEM; + } + + head = tokenize(token, pool); + if (head == NULL) { + mpool_destroy(pool); + return -EINVAL; + } + + //skip head + node = parser(list_next_entry(head, list), pool); + + if (node == NULL) { + mpool_destroy(pool); + return -EINVAL; + } + + kshell_printf(ctx, "%d\n", compute(node)); + + mpool_destroy(pool); + + return -ENOERR; +} + +static struct kshell_command kmcvm_cmd = { + .name = "kmcvm", + .desc = "kernal memory c lang compiler", + .exec = kmcvm_main, +}; + +static state kmcvm_init(void) +{ + return kshell_register(&kmcvm_cmd); +} +kshell_initcall(kmcvm_init); diff --git a/usr/command/kmcvm/mpool.c b/usr/command/kmcvm/mpool.c new file mode 100644 index 00000000..089cacf4 --- /dev/null +++ b/usr/command/kmcvm/mpool.c @@ -0,0 +1,355 @@ +#include "mpool.h" + +#include +#include + +static inline void *mpool_alloc_small(mpool_t *pool, size_t size, + unsigned align); +static void *mpool_alloc_block(mpool_t *pool, size_t size); +static void *mpool_alloc_large(mpool_t *pool, size_t size); + + +unsigned mpool_pagesize = 4096; + + +void * +zhanghan_memalign(size_t alignment, size_t size, mpool_log_t *log) +{ + // void *p; + // int err; + + // p = + + // if (err) { + // // ngx_log_error(NGX_LOG_EMERG, log, err, + // // "posix_memalign(%uz, %uz) failed", alignment, size); + // p = NULL; + // } + + // ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0, + // "posix_memalign: %p:%uz @%uz", p, size, alignment); + + return kmalloc_align(size, GFP_KERNEL, alignment); +} + + +mpool_t * +mpool_create(size_t size, mpool_log_t *log) +{ + mpool_t *p; + + p = zhanghan_memalign(NGX_POOL_ALIGNMENT, size, log); + if (p == NULL) { + return NULL; + } + + p->d.last = (char *) p + sizeof(mpool_t); + p->d.end = (char *) p + size; + p->d.next = NULL; + p->d.failed = 0; + + size = size - sizeof(mpool_t); + p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; + + p->current = p; + p->large = NULL; + p->cleanup = NULL; + p->log = log; + + return p; +} + + +void +mpool_destroy(mpool_t *pool) +{ + mpool_t *p, *n; + ngx_pool_large_t *l; + mpool_cleanup_t *c; + + for (c = pool->cleanup; c; c = c->next) { + if (c->handler) { + // ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, + // "run cleanup: %p", c); + c->handler(c->data); + } + } + +#if (NGX_DEBUG) + + /* + * we could allocate the pool->log from this pool + * so we cannot use this log while kfree()ing the pool + */ + + for (l = pool->large; l; l = l->next) { + ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, "kfree: %p", l->alloc); + } + + for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, pool->log, 0, + "kfree: %p, unused: %uz", p, p->d.end - p->d.last); + + if (n == NULL) { + break; + } + } + +#endif + + for (l = pool->large; l; l = l->next) { + if (l->alloc) { + kfree(l->alloc); + } + } + + for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { + kfree(p); + + if (n == NULL) { + break; + } + } +} + + +void +mpool_reset(mpool_t *pool) +{ + mpool_t *p; + ngx_pool_large_t *l; + + for (l = pool->large; l; l = l->next) { + if (l->alloc) { + kfree(l->alloc); + } + } + + for (p = pool; p; p = p->d.next) { + p->d.last = (char *) p + sizeof(mpool_t); + p->d.failed = 0; + } + + pool->current = pool; + pool->large = NULL; +} + + +void * +mpool_alloc(mpool_t *pool, size_t size) +{ +#if !(NGX_DEBUG_PALLOC) + if (size <= pool->max) { + return mpool_alloc_small(pool, size, 1); + } +#endif + + return mpool_alloc_large(pool, size); +} + + +void * +mpool_nalloc(mpool_t *pool, size_t size) +{ +#if !(NGX_DEBUG_PALLOC) + if (size <= pool->max) { + return mpool_alloc_small(pool, size, 0); + } +#endif + + return mpool_alloc_large(pool, size); +} + + +static inline void * +mpool_alloc_small(mpool_t *pool, size_t size, unsigned align) +{ + char *m; + mpool_t *p; + + p = pool->current; + + do { + m = p->d.last; + + if (align) { + m = mpool_align_ptr(m, MPOOL_ALIGNMENT); + } + + if ((size_t) (p->d.end - m) >= size) { + p->d.last = m + size; + + return m; + } + + p = p->d.next; + + } while (p); + + return mpool_alloc_block(pool, size); +} + + +static void * +mpool_alloc_block(mpool_t *pool, size_t size) +{ + char *m; + size_t psize; + mpool_t *p, *new; + + psize = (size_t) (pool->d.end - (char *) pool); + + m = zhanghan_memalign(NGX_POOL_ALIGNMENT, psize, pool->log); + if (m == NULL) { + return NULL; + } + + new = (mpool_t *) m; + + new->d.end = m + psize; + new->d.next = NULL; + new->d.failed = 0; + + m += sizeof(ngx_pool_data_t); + m = mpool_align_ptr(m, MPOOL_ALIGNMENT); + new->d.last = m + size; + + for (p = pool->current; p->d.next; p = p->d.next) { + if (p->d.failed++ > 4) { + pool->current = p->d.next; + } + } + + p->d.next = new; + + return m; +} + + +static void * +mpool_alloc_large(mpool_t *pool, size_t size) +{ + void *p; + unsigned n; + ngx_pool_large_t *large; + + p = kmalloc(size, GFP_KERNEL); + if (p == NULL) { + return NULL; + } + + n = 0; + + for (large = pool->large; large; large = large->next) { + if (large->alloc == NULL) { + large->alloc = p; + return p; + } + + if (n++ > 3) { + break; + } + } + + large = mpool_alloc_small(pool, sizeof(ngx_pool_large_t), 1); + if (large == NULL) { + kfree(p); + return NULL; + } + + large->alloc = p; + large->next = pool->large; + pool->large = large; + + return p; +} + + +void * +mpool_memalign(mpool_t *pool, size_t size, size_t alignment) +{ + void *p; + ngx_pool_large_t *large; + + p = zhanghan_memalign(alignment, size, pool->log); + if (p == NULL) { + return NULL; + } + + large = mpool_alloc_small(pool, sizeof(ngx_pool_large_t), 1); + if (large == NULL) { + kfree(p); + return NULL; + } + + large->alloc = p; + large->next = pool->large; + pool->large = large; + + return p; +} + + +int +mpool_free(mpool_t *pool, void *p) +{ + ngx_pool_large_t *l; + + for (l = pool->large; l; l = l->next) { + if (p == l->alloc) { + // ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0, + // "kfree: %p", l->alloc); + kfree(l->alloc); + l->alloc = NULL; + + return MPOOL_OK; + } + } + + return MPOOL_DECLINED; +} + + +void * +mpool_calloc(mpool_t *pool, size_t size) +{ + void *p; + + p = mpool_alloc(pool, size); + if (p) { + mpool_memzero(p, size); + } + + return p; +} + + +mpool_cleanup_t * +mpool_cleanup_add(mpool_t *p, size_t size) +{ + mpool_cleanup_t *c; + + c = mpool_alloc(p, sizeof(mpool_cleanup_t)); + if (c == NULL) { + return NULL; + } + + if (size) { + c->data = mpool_alloc(p, size); + if (c->data == NULL) { + return NULL; + } + + } else { + c->data = NULL; + } + + c->handler = NULL; + c->next = p->cleanup; + + p->cleanup = c; + + // ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c); + + return c; +} diff --git a/usr/command/kmcvm/mpool.h b/usr/command/kmcvm/mpool.h new file mode 100644 index 00000000..c69c9eab --- /dev/null +++ b/usr/command/kmcvm/mpool.h @@ -0,0 +1,113 @@ +#ifndef _LOCAL_MPOOL_H_ +#define _LOCAL_MPOOL_H_ + +#ifndef __MPOOL__H__ +#define __MPOOL__H__ + +#include +#include +#include + +typedef struct mpool_pool_s mpool_t; +typedef struct mpool_log_s mpool_log_t; +typedef int mpool_fd_t; + +struct mpool_log_s { +}; + +extern unsigned mpool_pagesize; + +#define mpool_align_ptr(p, a) \ + (char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) + + +#define MPOOL_ALIGNMENT sizeof(unsigned long) /* platform word */ + +#define MPOOL_OK 0 +#define MPOOL_ERROR -1 +#define MPOOL_AGAIN -2 +#define MPOOL_BUSY -3 +#define MPOOL_DONE -4 +#define MPOOL_DECLINED -5 +#define MPOOL_ABORT -6 + + +#define mpool_memzero(buf, n) (void) memset(buf, 0, n) + + +/* + * NGX_MAX_ALLOC_FROM_POOL should be (mpool_pagesize - 1), i.e. 4095 on x86. + * On Windows NT it decreases a number of locked pages in a kernel. + */ +#define NGX_MAX_ALLOC_FROM_POOL (mpool_pagesize - 1) + +#define MPOOL_DEFAULT_SIZE (16 * 1024) + +#define NGX_POOL_ALIGNMENT 16 +#define NGX_MIN_POOL_SIZE \ + ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)), \ + NGX_POOL_ALIGNMENT) + + +typedef void (*mpool_cleanup_pt)(void *data); + +typedef struct mpool_cleanup_s mpool_cleanup_t; + +struct mpool_cleanup_s { + mpool_cleanup_pt handler; + void *data; + mpool_cleanup_t *next; +}; + + +typedef struct ngx_pool_large_s ngx_pool_large_t; + +struct ngx_pool_large_s { + ngx_pool_large_t *next; + void *alloc; +}; + + +typedef struct { + char *last; + char *end; + mpool_t *next; + unsigned failed; +} ngx_pool_data_t; + + +struct mpool_pool_s { + ngx_pool_data_t d; + size_t max; + mpool_t *current; + ngx_pool_large_t *large; + mpool_cleanup_t *cleanup; + mpool_log_t *log; +}; + + +typedef struct { + mpool_fd_t fd; + char *name; + mpool_log_t *log; +} ngx_pool_cleanup_file_t; + + +mpool_t *mpool_create(size_t size, mpool_log_t *log); +void mpool_destroy(mpool_t *pool); +void mpool_reset(mpool_t *pool); + +void *mpool_alloc(mpool_t *pool, size_t size); +void *mpool_nalloc(mpool_t *pool, size_t size); +void *mpool_calloc(mpool_t *pool, size_t size); +void *mpool_pmemalign(mpool_t *pool, size_t size, size_t alignment); +int mpool_free(mpool_t *pool, void *p); + +mpool_cleanup_t *mpool_cleanup_add(mpool_t *p, size_t size); + + +#endif /*__MPOOL__H__*/ + + + +#endif /* _LOCAL_MPOOL_H_ */ diff --git a/usr/command/kmcvm/parser.c b/usr/command/kmcvm/parser.c new file mode 100644 index 00000000..aacb09e5 --- /dev/null +++ b/usr/command/kmcvm/parser.c @@ -0,0 +1,598 @@ +#include "parser.h" +#include "list.h" +#include "token.h" +#include +#include +#include + +static Node *primary(Token **rest, Token *tok, mpool_t *pool); +static Node *mul(Token **rest, Token *tok, mpool_t *pool); +static Node *expr(Token **rest, Token *tok, mpool_t *pool); + + +/* + + - * / ! ~ + + unary + - + + + >= > <= < + + || && + + | & ^ + + shift + << >> + + + // do we need this? + +, += + ++, -- + ? : +*/ +/* + +stmt = ...| ident ":" stmt| "{" compound-stmt | expr-stmt + +compound-stmt = (typedef | declaration | stmt)* "}" + +expr_stmt = expr? ":" + +expr = assign ("," expr)? + +assign = conditional (assign-op assign)? + +assign-op = "=" | "+=" .... + +conditional = logor ("?" expr? ":" conditional)? + +logor = logand ("||" logand)* + +logand = bitor ("&&" bitor)* + +bitor = bitxor ("|" bitxor)* + +bitxor = bitand ("^" bitand)* + +bitand = equality ("&" equality)* + +equality = relational ("==" relational | "!=" relational)* + +relational = shift ("<" shift | "<=" shift | ">" shift | ">=" shift)* + + shift = add ("<<" add | ">>" add)* + +add = mul ("+" mul | "-" mul)* + +mul = cast ("\*" cast | "/" cast | "%" cast)* + +cast = "(" type-name ")" cast | unary + +unary = ("+" | "-" | "*" | "&" | "!" | "~") cast | ("++" | "--") unary | "&&" ident | postfix + +postfix = "(" type-name ")" "{" initializer-list "}" + +​ = ident "(" func-args ")" postfix-tail* | primary postfix-tail* + +postfix-tail = "[" expr "]" | "(" func-args ")"| "." ident| "->" ident| "++"| "--" + +primary "(" "{" stmt+ "}" ")" | "(" expr ")"|| "sizeof" "(" type-name ")"|| "sizeof" unary|"_Alignof" "(" type-name ")"| "_Alignof" unary| ident| str| num + + + +for example +x = 3; +conditional (assign-op assign) ==> primary assign-op primary + + + +*/ + +// static void error(char *fmt, ...) { +// va_list ap; +// va_start(ap, fmt); +// vfprintf(stderr, fmt, ap); +// fprintf(stderr, "\n"); +// exit(1); +// } + +// // Reports an error location and exit. +// static void verror_at(char *loc, char *fmt, va_list ap) { +// int pos = loc - current_input; +// fprintf(stderr, "%s\n", current_input); +// fprintf(stderr, "%*s", pos, ""); // print pos spaces. +// fprintf(stderr, "^ "); +// vfprintf(stderr, fmt, ap); +// fprintf(stderr, "\n"); +// exit(1); +// } + +// static void error_at(char *loc, char *fmt, ...) { +// va_list ap; +// va_start(ap, fmt); +// verror_at(loc, fmt, ap); +// } + +// static void error_tok(Token *tok, char *fmt, ...) { +// va_list ap; +// va_start(ap, fmt); +// verror_at(tok->loc, fmt, ap); +// } + + + +// static void error_log(struct kshell_context *ctx, char *fmt, ...) { +// va_list ap; +// va_start(ap, fmt); + +// vprintk(fmt, ap); + +// exit(-1); +// } + +static bool equal(Token *tok, char *op) { + return memcmp(tok->loc, op, tok->len) == 0 && op[tok->len] == '\0'; +} + +static Token *skip(Token *tok, char *s) { + if (!equal(tok, s)) { + return NULL; + } + return list_next_entry(tok, list); +} + + +static Node *new_node(NodeKind kind, mpool_t *pool) { + Node *node = mpool_alloc(pool, sizeof(Node)); + if (node == NULL) { + return NULL; + } + + node->kind = kind; + return node; +} + +static Node *new_num(int val, mpool_t *pool) { + Node *node = new_node(ND_NUM, pool); + node->val = val; + return node; +} + +static Node *new_unary(NodeKind kind, Node *expr, mpool_t *pool) { + Node *node = new_node(kind, pool); + node->lhs = expr; + return node; +} + +static Node *new_binary(NodeKind kind, Node *lhs, Node *rhs, mpool_t *pool) { + Node *node = new_node(kind, pool); + node->lhs = lhs; + node->rhs = rhs; + return node; +} + +static Node *new_add(Node *lhs, Node *rhs, mpool_t *pool) { + return new_binary(ND_ADD, lhs, rhs, pool); +} + +static Node *new_sub(Node *lhs, Node *rhs, mpool_t *pool) { + return new_binary(ND_SUB, lhs, rhs, pool); +} + +static Node *new_mul(Node *lhs, Node *rhs, mpool_t *pool) { + return new_binary(ND_MUL, lhs, rhs, pool); +} + +static Node *new_div(Node *lhs, Node *rhs, mpool_t *pool) { + return new_binary(ND_DIV, lhs, rhs, pool); +} + +static Node *new_mod(Node *lhs, Node *rhs, mpool_t *pool) { + return new_binary(ND_MOD, lhs, rhs, pool); +} + +//primary is the highest priority +static Node *primary(Token **rest, Token *tok, mpool_t *pool) { + if (equal(tok, "(")) { + Node *node = expr(&tok, list_next_entry(tok, list), pool); + *rest = skip(tok, ")"); + return node; + } + + if (tok->kind == TK_NUM) { + Node *node = new_num(tok->val, pool); + + *rest = list_next_entry(tok, list); + return node; + } + + pr_warn("expected an expression\n"); + return NULL; +} + +static Node *unary(Token **rest, Token *tok, mpool_t *pool) { + Node *node; + if (equal(tok, "+")) { + return mul(rest, tok, pool); + } + + if (equal(tok, "-")) { + node = mul(rest, list_next_entry(tok, list), pool); + return new_unary(ND_NEG, node, pool); + } + + if (equal(tok, "!")) { + node = mul(rest, list_next_entry(tok, list), pool); + return new_unary(ND_NOT, node, pool); + } + + if (equal(tok, "~")) { + node = mul(rest, list_next_entry(tok, list), pool); + return new_unary(ND_BITNOT, node, pool); + } + + return primary(rest, tok, pool); +} + +static Node *mul(Token **rest, Token *tok, mpool_t *pool) { + Node *node = unary(&tok, tok, pool); + + for (;;) { + if (equal(tok, "*")) { + node = new_mul(node, unary(&tok, list_next_entry(tok, list), pool), pool); + continue; + } + + if (equal(tok, "/")) { + node = new_div(node, unary(&tok, list_next_entry(tok, list), pool), pool); + continue; + } + + if (equal(tok, "%")) { + node = new_mod(node, unary(&tok, list_next_entry(tok, list), pool), pool); + continue; + } + + *rest = tok; + return node; + } +} + +static Node *add(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + + node = mul(&tok, tok, pool); + + for (;;) { + + if (equal(tok, "+")) { + rnode = mul(&tok, list_next_entry(tok, list), pool); + + node = new_add(node, rnode, pool); + continue; + } + + if (equal(tok, "-")) { + rnode = mul(&tok, list_next_entry(tok, list), pool); + node = new_sub(node, rnode, pool); + continue; + } + + *rest = tok; + return node; + } +} + +static Node *shift(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = add(&tok, tok, pool); + + for (;;) { + + if (equal(tok, "<<")) { + rnode = add(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_SHL, node, rnode, pool); + } + + if (equal(tok, ">>")) { + rnode = add(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_SHR, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + +static Node *relational(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = shift(&tok, tok, pool); + + for (;;) { + + if (equal(tok, "<")) { + rnode = shift(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LT, node, rnode, pool); + } + + if (equal(tok, "<=")) { + rnode = shift(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LE, node, rnode, pool); + } + + if (equal(tok, ">")) { + rnode = shift(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LT, rnode, node, pool); + } + + if (equal(tok, ">=")) { + rnode = shift(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LE, rnode, node, pool); + } + + *rest = tok; + return node; + } +} + +static Node *equality(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = relational(&tok, tok, pool); + + for (;;) { + + if (equal(tok, "==")) { + rnode = relational(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_EQ, node, rnode, pool); + } + + if (equal(tok, "!=")) { + rnode = relational(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_NE, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + + +static Node *bitand(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = equality(&tok, tok, pool); + + + for (;;) { + if (equal(tok, "&")) { + rnode = equality(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_BITAND, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + +static Node *bitxor(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = bitand(&tok, tok, pool); + + + for (;;) { + if (equal(tok, "^")) { + rnode = bitand(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_BITXOR, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + + +static Node *bitor(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = bitxor(&tok, tok, pool); + + + for (;;) { + if (equal(tok, "|")) { + rnode = bitxor(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_BITOR, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + +static Node *logand(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = bitor(&tok, tok, pool); + + for (;;) { + if (equal(tok, "&&")) { + rnode = bitor(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LOGAND, node, rnode, pool); + } + + *rest = tok; + return node; + } +} + +static Node *logor(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = logand(&tok, tok, pool); + + for (;;) { + if (equal(tok, "||")) { + rnode = logand(&tok, list_next_entry(tok, list), pool); + + node = new_binary(ND_LOGOR, node, rnode, pool); + } + + *rest = tok; + return node; + } + +} + +static Node *conditional(Token **rest, Token *tok, mpool_t *pool) { + Node *cond, *node; + cond = logor(&tok, tok, pool); + + if (!equal(tok, "?")) { + *rest = tok; + return cond; + } + + node = new_node(ND_COND, pool); + + node->cond = cond; + node->then = expr(&tok, list_next_entry(tok, list), pool); + + tok = skip(tok, ":"); + node->els = conditional(rest, tok, pool); + + return node; + +} + +static Node *expr(Token **rest, Token *tok, mpool_t *pool) { + Node *node, *rnode; + node = conditional(&tok, tok, pool); + + if (equal(tok, ",")) { + rnode = expr(rest, list_next_entry(tok, list), pool); + + return new_binary(ND_COMMA, node, rnode, pool); + } + + *rest = tok; + return node; +} + + +Node* parser(Token *tok, mpool_t *pool) { + Node *node; + node = expr(&tok, tok, pool); + + if (tok->kind != TK_EOF) { + pr_warn("expected an eof token\n"); + return NULL; + } + + + return node; +} + + +int compute(Node *node) { + + if (node->kind == ND_NUM) { + return node->val; + } + + if (node->kind == ND_NEG) { + return -compute(node->lhs); + } + + if (node->kind == ND_NOT) { + return !compute(node->lhs); + } + + if (node->kind == ND_BITNOT) { + return ~compute(node->lhs); + } + + if (node->kind == ND_EQ) { + return compute(node->lhs) == compute(node->rhs); + } + + if (node->kind == ND_NE) { + return compute(node->lhs) != compute(node->rhs); + } + + if (node->kind == ND_LE) { + return compute(node->lhs) <= compute(node->rhs); + } + + if (node->kind == ND_LT) { + return compute(node->lhs) < compute(node->rhs); + } + + if (node->kind == ND_SHL) { + return compute(node->lhs) << compute(node->rhs); + } + + if (node->kind == ND_SHR) { + return compute(node->lhs) >> compute(node->rhs); + } + + if (node->kind == ND_MUL) { + return compute(node->lhs) * compute(node->rhs); + } + + if (node->kind == ND_DIV) { + return compute(node->lhs) / compute(node->rhs); + } + + if (node->kind == ND_MOD) { + return compute(node->lhs) % compute(node->rhs); + } + + if (node->kind == ND_ADD) { + return compute(node->lhs) + compute(node->rhs); + } + + if (node->kind == ND_SUB) { + return compute(node->lhs) - compute(node->rhs); + } + + if (node->kind == ND_BITAND) { + return compute(node->lhs) & compute(node->rhs); + } + + if (node->kind == ND_BITXOR) { + return compute(node->lhs) ^ compute(node->rhs); + } + + if (node->kind == ND_BITOR) { + return compute(node->lhs) | compute(node->rhs); + } + + if (node->kind == ND_LOGAND) { + return compute(node->lhs) && compute(node->rhs); + } + + if (node->kind == ND_LOGOR) { + return compute(node->lhs) || compute(node->rhs); + } + + if (node->kind == ND_COMMA) { + return compute(node->rhs); + } + + if (node->kind == ND_COND) { + if (compute(node->cond)) { + return compute(node->then); + } + return compute(node->els); + } + + return 0; +} diff --git a/usr/command/kmcvm/parser.h b/usr/command/kmcvm/parser.h new file mode 100644 index 00000000..8b15a1bc --- /dev/null +++ b/usr/command/kmcvm/parser.h @@ -0,0 +1,56 @@ +#ifndef _LOCAL_PARSER_H_ +#define _LOCAL_PARSER_H_ + + +#include +#include +#include +#include "token.h" +typedef struct ast_node_s Node; + +typedef enum { + ND_NUM, + ND_NEG, // unary - + ND_NOT, // unary ! + ND_EQ, // == + ND_NE, // != + ND_LT, // < + ND_LE, // <= + ND_SHL, // << + ND_SHR, // >> + ND_BITNOT, // unary ~ + ND_MUL, // * + ND_DIV, // / + ND_MOD, // % + ND_ADD, // + + ND_SUB, // - + ND_BITAND, // & + ND_BITXOR, // ^ + ND_BITOR, // | + ND_LOGAND, // && + ND_LOGOR, // || + ND_COMMA, // , + ND_COND, // ?: +}NodeKind; + +struct ast_node_s { + NodeKind kind; + union { + struct { + Node *lhs; + Node *rhs; + }; + struct { + Node *cond; + Node *then; + Node *els; + }; + }; + long val; +}; + +Node* parser(Token *tok, mpool_t *pool); + +int compute(Node *node); + +#endif diff --git a/usr/command/kmcvm/token.c b/usr/command/kmcvm/token.c new file mode 100644 index 00000000..00a0948f --- /dev/null +++ b/usr/command/kmcvm/token.c @@ -0,0 +1,224 @@ +#include "token.h" +#include +#include +#include +#include +#include + +static bool startswith(char *p, char *q) { + return strncmp(p, q, strlen(q)) == 0; +} + +#if 0 +char *token_read_file(char *path) { + FILE *fp; + + if (strcmp(path, "-") == 0) { + // By convention, read from stdin if a given filename is "-". + fp = stdin; + } else { + fp = fopen(path, "r"); + if (!fp) + return NULL; + } + + char *buf; + size_t buflen; + FILE *out = open_memstream(&buf, &buflen); + + // Read the entire file. + for (;;) { + char buf2[4096]; + int n = fread(buf2, 1, sizeof(buf2), fp); + if (n == 0) { + break; + } + + fwrite(buf2, 1, n, out); + } + + if (fp != stdin) + fclose(fp); + + // Make sure that the last line is properly terminated with '\n'. + fflush(out); + if (buflen == 0 || buf[buflen - 1] != '\n') + fputc('\n', out); + fputc('\0', out); + fclose(out); + return buf; +} +#endif + +Token *new_token(tokentype_t type, char *start, char *end, mpool_t *pool) { + Token *t; + t = mpool_alloc(pool, sizeof(Token)); + if (t == NULL) { + return NULL; + } + t->kind = type; + t->loc = start; + t->end = end; + t->len = end - start; + + return t; +} + +Token *new_token_num(char *start, char *end, mpool_t *pool) { + Token *t; + t = new_token(TK_NUM, start, end, pool); + if (t == NULL) { + return NULL; + } + //now we assume is int number + + t->val = atoi(start); + + return t; +} + +Token *new_token_eof(char *end, mpool_t *pool) { + Token *t; + t = new_token(TK_EOF, end , end, pool); + if (t == NULL) { + return NULL; + } + return t; +} + +Token * new_token_punct(char *start, char *end, mpool_t *pool) { + Token *t; + t = new_token(TK_PUNCT, start , end, pool); + if (t == NULL) { + return NULL; + } + + return t; +} + +static int read_punct(char *p) { + static char *kw[] = { + "<<=", ">>=", "...", "==", "!=", "<=", ">=", "->", "+=", + "-=", "*=", "/=", "++", "--", "%=", "&=", "|=", "^=", "&&", + "||", "<<", ">>", "##", + }; + + for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) { + if (startswith(p, kw[i])) { + return strlen(kw[i]); + } + } + + return ispunct(*p) ? 1 : 0; + +} + +Token *tokenize(const char *p, mpool_t *pool) { + Token *head, *t; + int punct_len; + head = new_token(0, NULL, NULL, pool); + if (head == NULL) { + return NULL; + } + + list_head_init(&head->list); + + + for (; *p ;) { + + if (startswith(p, "//")) { + p+=2; + while (*p != '\n') { + p++; + } + continue; + } + + // Skip block comments. + if (startswith(p, "/*")) { + char *q = strstr(p + 2, "*/"); + if (!q) { + pr_warn("unclosed block comment\n"); + goto err; + } + p = q + 2; + continue; + } + + if (*p == '\n') { + p++; + continue; + } + + if (isspace(*p)) { + p++; + continue; + } + + // Numeric literal + if (isdigit(*p) || (*p == '.' && isdigit(p[1]))) { + char *q = p++; + + for (;;) { + + if (p[0] && p[1] && strchr("eEpP", p[0]) && strchr("+-", p[1])) { + p += 2; + } + + else if (isalnum(*p) || *p == '.') { + p++; + }else { + break; + } + } + + t = new_token_num(q, p, pool); + if (t == NULL) { + goto err; + } + + list_add_prev(&head->list, &t->list); + + continue; + } + + //keyword + + //Punctuators + punct_len = read_punct(p); + if (punct_len) { + t = new_token_punct(p, p + punct_len, pool); + if (t == NULL) { + goto err; + } + + p += punct_len; + list_add_prev(&head->list, &t->list); + + continue; + } + + pr_warn("invalid token\n"); + goto err; + } + + t = new_token_eof(p, pool); + if (t == NULL) { + goto err; + } + list_add_prev(&head->list, &t->list); + + return head; +err: + + return NULL; +} + +// Token *tokenize_file(char *file, mpool_t *pool) { +// char *p = token_read_file(file); +// if (p == NULL) { +// return NULL; +// } + +// return tokenize(p, pool); +// } diff --git a/usr/command/kmcvm/token.h b/usr/command/kmcvm/token.h new file mode 100644 index 00000000..605464d2 --- /dev/null +++ b/usr/command/kmcvm/token.h @@ -0,0 +1,34 @@ +#ifndef _LOCAL_TOKEN_H_ +#define _LOCAL_TOKEN_H_ + +#include +#include +#include +#include "mpool.h" + +typedef struct token Token; + +typedef enum tokentype{ + TK_NUM, + TK_NUM_FLOAT, + TK_PUNCT, + TK_KEYWORD, + TK_EOF, +}tokentype_t; + +struct token { + tokentype_t kind; + struct list_head list; + char *loc; + char *end; + size_t len; + int val; + long double fval; +}; + + + +Token *tokenize(const char *p, mpool_t *pool); +// Token *tokenize_file(char *file, mpool_t *pool); + +#endif