From 208c831c79043d319c542eb8cf73538779849605 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Sun, 25 Jan 2015 22:05:28 -0800 Subject: [PATCH] Refactored the C files out into libraries, started work on the BASIC repl (it can sorta do math!) --- .gitignore | 1 + src/basic.c | 153 +++++++++++++++++++++++++++++++++ src/basic.h | 39 +++++++++ src/conio.c | 90 +++++++++++++++++++ src/conio.h | 8 ++ src/kernel.c | 238 +-------------------------------------------------- src/screen.c | 58 +++++++++++++ src/screen.h | 12 +++ src/stdlib.c | 81 ++++++++++++++++++ src/stdlib.h | 12 +++ src/string.c | 83 ++++++++++++++++++ src/string.h | 12 +++ src/types.h | 7 ++ 13 files changed, 560 insertions(+), 234 deletions(-) create mode 100644 .gitignore create mode 100644 src/basic.c create mode 100644 src/basic.h create mode 100644 src/conio.c create mode 100644 src/conio.h create mode 100644 src/screen.c create mode 100644 src/screen.h create mode 100644 src/stdlib.c create mode 100644 src/stdlib.h create mode 100644 src/string.c create mode 100644 src/string.h create mode 100644 src/types.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31d19ab --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +src/*o diff --git a/src/basic.c b/src/basic.c new file mode 100644 index 0000000..35a5f60 --- /dev/null +++ b/src/basic.c @@ -0,0 +1,153 @@ +#include "basic.h" +#include "screen.h" +#include "conio.h" +#include "string.h" +#include "stdlib.h" + +struct basic_math_expr math_expressions[8]; +int basic_errno; + +char _tokenizer_value[BASIC_TOKENIZER_MAX_LENGTH]; +char *_tokenizer_prev; +char *_tokenizer_prev_next; + +void _tokenizer_init(void) +{ + _tokenizer_prev = NULL; + _tokenizer_prev_next = NULL; +} + +char *_tokenize(char *ptr, char token) +{ + char *orig = NULL; + int len = 0; + + if ( ptr == NULL ) { + return NULL; + } + if ( _tokenizer_prev == ptr ) { + ptr = _tokenizer_prev_next; + } + orig = ptr; + + memset(&_tokenizer_value, 0x00, BASIC_TOKENIZER_MAX_LENGTH); + while ( *ptr != token ) { + if ( *ptr == '\0' ) { + ptr -= sizeof(char); + break; + } + ptr += sizeof(char); + len += 1; + } + if ( len > BASIC_TOKENIZER_MAX_LENGTH ) { + basic_errno = BASIC_ERR_SYNTAX_TOKEN_LENGTH; + return NULL; + } else if ( len == 0 ) { + return NULL; + } + memcpy((void *)&_tokenizer_value, (void *)orig, len); + _tokenizer_prev_next = (ptr + 1); + return &_tokenizer_value; +} + +struct basic_math_expr *basic_parse_expr(char *expbuf) +{ + struct basic_math_expr *ret = &math_expressions[0]; + char flags = 0; + char *subptr = 0; + + _tokenizer_init(); + memset(ret, 0x0, sizeof(struct basic_math_expr)); + + while ( *expbuf != '\0' ) { + if ( *expbuf == ' ' ) { + expbuf += sizeof(char); + continue; + } else if ( isdigit(*expbuf) == 1 ) { + if ( (ret->type == 0) && (flags & BASIC_FOUND_LVAL) == BASIC_FOUND_LVAL ) { + basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_LVALUES; + return NULL; + } else if ( ret->type == 0x0 ) { + ret->lval = atoi(_tokenize(expbuf, ' ')); + flags = (flags + BASIC_FOUND_LVAL); + } else if ( ret->type != 0x0 && ((flags & BASIC_FOUND_RVAL) == BASIC_FOUND_RVAL)) { + basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES; + return NULL; + } else if ( ret->type != 0x0 ) { + ret->rval = atoi(_tokenize(expbuf, ' ')); + } + } else if ( ret->type == 0x0 ) { + if ( *expbuf == '+' ) { + ret->type = BASIC_MATH_ADD; + } else if ( *expbuf == '*' ) { + ret->type = BASIC_MATH_MUL; + } else if ( *expbuf == '-' ) { + ret->type = BASIC_MATH_SUB; + } else if ( *expbuf == '/' ) { + ret->type = BASIC_MATH_DIV; + } else if ( *expbuf == '%' ) { + ret->type = BASIC_MATH_MOD; + } else { + basic_errno = BASIC_ERR_SYNTAX_GENERAL; + return NULL; + } + } else { + basic_errno = BASIC_ERR_SYNTAX_GENERAL; + return NULL; + } + expbuf += sizeof(char); + } + return ret; +} + +void basic_run(void) +{ + char keybuff[512]; + char outbuff[128]; + char decimal; + + struct basic_math_expr *expr; + + blankScreen(); + setCursorPosition(0, 0); + _cputs("Piquant Basic v0.1\n\n"); + + while ( 1 ) { + _cputs("> "); + memset((void *)&keybuff, 0x00, 512); + memset((void *)&outbuff, 0x00, 128); + if ( _cgets((char *)&keybuff) != NULL ) { + _cputs("\n"); + _cputs("Analyzing "); + _cputs((char *)&keybuff); + _cputs("\n"); + + expr = basic_parse_expr((char *)&keybuff); + if ( expr == NULL ) { + _cputs("Syntax Error: "); + decimal = dtoa(basic_errno); + _cputs(&decimal); + _cputs("\n"); + continue; + } + + decimal = dtoa(expr->type); + memcpy(&outbuff, "Expression type: \0", strlen("Expression type: \0")); + strncat(&outbuff, &decimal, 1); + _cputs(&outbuff); + _cputs("\n"); + + decimal = dtoa(expr->lval); + memcpy(&outbuff, "Expression lval: \0", strlen("Expression lval: \0")); + strncat(&outbuff, &decimal, 1); + _cputs(&outbuff); + _cputs("\n"); + + decimal = dtoa(expr->rval); + memcpy(&outbuff, "Expression rval: \0", strlen("Expression rval: \0")); + strncat(&outbuff, &decimal, 1); + _cputs(&outbuff); + _cputs("\n"); + } + } +} diff --git a/src/basic.h b/src/basic.h new file mode 100644 index 0000000..9ee8bae --- /dev/null +++ b/src/basic.h @@ -0,0 +1,39 @@ +#ifndef _BASIC_H_ +#define _BASIC_H_ + +#define BASIC_MATH_ADD 1 +#define BASIC_MATH_SUB 2 +#define BASIC_MATH_MUL 3 +#define BASIC_MATH_DIV 4 +#define BASIC_MATH_MOD 5 + +#define BASIC_LVAL_EXPR 0 +#define BASIC_LVAL_VAR 1 +#define BASIC_RVAL_EXPR 2 +#define BASIC_RVAL_VAR 3 +#define BASIC_RVAL_CONST 4 + +#define BASIC_FOUND_LVAL 0x0001 +#define BASIC_FOUND_RVAL 0x0002 + +#define BASIC_ERR_SYNTAX_MULTIPLE_LVALUES 1 +#define BASIC_ERR_SYNTAX_TOKEN_LENGTH 2 +#define BASIC_ERR_SYNTAX_GENERAL 3 +#define BASIC_ERR_SYNTAX_MULTIPLE_RVALUES 4 + +#define BASIC_TOKENIZER_MAX_LENGTH 512 + +struct basic_math_expr { + char type; + char lval_type; + char rval_type; + char pad; + void *lval; + void *rval; +}; + +extern int basic_errno; + +void run_basic(void); + +#endif /* _BASIC_H_ */ diff --git a/src/conio.c b/src/conio.c new file mode 100644 index 0000000..ce54002 --- /dev/null +++ b/src/conio.c @@ -0,0 +1,90 @@ +#include "types.h" +#include "conio.h" +#include "screen.h" + +void _putch(char c) +{ +#asm + push bx; + push ax; + mov bx, sp; + mov al, [bx+6]; + mov ah, #0x0e; + mov bh, #0x00; + mov bl, #0x07; + int 0x10; + pop ax; + pop bx; +#endasm + return; +} + +void _cputs(char *ptr) +{ + if ( ptr == NULL ) { + return; + } + while ((char)*ptr != 0x0) { + _putch((char)*ptr); + if (*ptr == '\n') { + _cursor_y += 1; + _cursor_x = 0; + setCursorPosition(_cursor_x, _cursor_y); + } else { + advanceCursor(); + } + ptr += 1; + } + return; +} + +char _getkey(char *dest) +{ + char echo; + char scancode; +#asm + push ax; + mov ah, #0x10; + int 0x16; + mov [bp-6], ah; + mov [bp-5], al; + pop ax; +#endasm + *dest = echo; + return scancode; +} + +char *_cgets(char *d) +{ + char *orig = d; + char scancode; + char printable; + + if ( d == NULL ) { + return NULL; + } + + scancode = _getkey(&printable); + + while ( scancode != NULL ) { + if ( scancode == 0x0e ) { + if ( d > orig ) { + backupCursor(); + setCursorPosition(_cursor_x, _cursor_y); + d -= 1; + _putch(0x0); + } + } else if ( scancode == 0x1c ) { + break; + } else { + *(d++) = printable; + _putch(printable); + advanceCursor(); + } + scancode = _getkey(&printable); + } + + __cgets_finish_loop: + *d = NULL; + return orig; +} diff --git a/src/conio.h b/src/conio.h new file mode 100644 index 0000000..4cefb96 --- /dev/null +++ b/src/conio.h @@ -0,0 +1,8 @@ +#ifndef _CONIO_H_ +#define _CONIO_H_ + +void _putch(char _c); +char *_cgets(void); +char _getkey(char *dest); + +#endif /* _CONIO_H_ */ diff --git a/src/kernel.c b/src/kernel.c index d3b2628..7e70076 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1,238 +1,8 @@ -char _cursor_x = 0; -char _cursor_y = 0; - -#define NULL 0x0 -typedef int size_t; - -void setCursorPosition(char x, char y) -{ -#asm - push bx; - mov bx, sp; - mov dl, [bx+4]; - mov dh, [bx+6]; - pop bx; - push ax; - push bx; - mov ah, #0x02; - mov bx, #0x0; - int 0x10; - pop bx; - pop ax; -#endasm - return; -} - -void backupCursor() -{ - - if ( _cursor_x == 0 && _cursor_y > 0 ) { - _cursor_x = 80; - _cursor_y -= 1; - } else if ( _cursor_x > 0 ) { - _cursor_x -= 1; - } - setCursorPosition(_cursor_x, _cursor_y); -} - -void advanceCursor() -{ - _cursor_x += 1; - if ( _cursor_x > 79 ) { - _cursor_x = 0; - _cursor_y += 1; - } - setCursorPosition(_cursor_x, _cursor_y); -} - -void putc(char c) -{ -#asm - push bx; - push ax; - mov bx, sp; - mov al, [bx+6]; - mov ah, #0x0e; - mov bh, #0x00; - mov bl, #0x07; - int 0x10; - pop ax; - pop bx; -#endasm - return; -} - -int strlen(char *ptr) -{ - char *ptr2 = ptr; - if ( ptr == NULL ) { - return 0; - } - - while (*ptr2 != 0x0 ) { - ptr2 += 1; - } - - return ptr2 - ptr; -} - -void puts(char *ptr, char x, char y) -{ - if ( ptr == NULL ) { - return; - } - while ((char)*ptr != 0x0) { - putc((char)*ptr); - if (*ptr == '\n') { - _cursor_y += 1; - _cursor_x = 0; - setCursorPosition(_cursor_x, _cursor_y); - } else { - advanceCursor(); - } - ptr += 1; - } - return; -} - -char getkey(char *dest) -{ - char echo; - char scancode; -#asm - push ax; - mov ah, 0x10; - int 0x16; - mov [bp-6], ah; - mov [bp-5], al; - pop ax; -#endasm - *dest = echo; - return scancode; -} - -char *gets(char *d) -{ - char *orig = d; - char scancode; - char printable; - - if ( d == NULL ) { - return NULL; - } - - scancode = getkey(&printable); - - while ( scancode != NULL ) { - if ( scancode == 0x0e ) { - if ( d > orig ) { - backupCursor(); - setCursorPosition(_cursor_x, _cursor_y); - d -= 1; - putc(0x0); - } - } else if ( scancode == 0x1c ) { - break; - } else { - *(d++) = printable; - putc(printable); - advanceCursor(); - } - scancode = getkey(&printable); - } - - _gets_finish_loop: - *d = NULL; - return orig; -} - -void memset(void *s, int c, size_t n) -{ - int *d = (int *)s; - if ( s == NULL ) { - return; - } - while ( ((int)d - (int)s) <= n ) { - *d = c; - d += sizeof(int); - } -} - -signed int strcmp(char *s1, char *s2) -{ - int d = 0; - int s1len = 0; - - if ( s1 == NULL || s2 == NULL ) { - return 1; - } - - s1len = strlen(s1); - if ( s1len != strlen(s2) ) { - return 1; - } - - while ( *s1 != '\0' ) { - if ( *s1 != *s2 ) { - return 1; - } - s1 += sizeof(char); - s2 += sizeof(char); - } - - return 0; -} - -void repl(void) -{ - char keybuff[512]; - - while ( 1 ) { - puts("> "); - memset((void *)&keybuff, 0x00, 512); - if ( gets((char *)&keybuff) != NULL ) { - puts("\n"); - if ( strcmp(&keybuff, "quit") == 0 ) { - puts("You asked for it\n"); - #asm - hlt; - #endasm - - } else if ( strcmp(&keybuff, "reset") == 0 ) { - puts("Resetting PC ... "); - #asm - jmp 0xf000:0xfff0; - #endasm - - } else if ( strcmp(&keybuff, "help") == 0 ) { - puts("help : Show this help message\n"); - puts("quit : Halt the computer\n"); - puts("reset : Reset the PC\n"); - puts("\n"); - } else { - puts("Wat?\n"); - } - } - } -} - -void blankScreen(void) -{ - char i = 0; - char j = 0; - for ( i = 0 ; i < 26 ; i++ ) { - for ( j = 0; j < 81 ; j++ ) { - setCursorPosition(j, i); - putc(' '); - } - } -} +#include "screen.h" +#include "string.h" +#include "conio.h" void main(void) { - blankScreen(); - setCursorPosition(0, 0); - puts("Piquant Kernel v0.1\n"); - puts("\n"); - repl(); + basic_run(); } diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..acb76ec --- /dev/null +++ b/src/screen.c @@ -0,0 +1,58 @@ +#include "types.h" +#include "screen.h" + +char _cursor_x = 0; +char _cursor_y = 0; + +void blankScreen(void) +{ + char i = 0; + char j = 0; + for ( i = 0 ; i < 26 ; i++ ) { + for ( j = 0; j < 81 ; j++ ) { + setCursorPosition(j, i); + _putch(0x0); + } + } +} + +void setCursorPosition(char x, char y) +{ +#asm + push bx; + mov bx, sp; + mov dl, [bx+4]; + mov dh, [bx+6]; + pop bx; + push ax; + push bx; + mov ah, #0x02; + mov bx, #0x0; + int 0x10; + pop bx; + pop ax; +#endasm + return; +} + +void backupCursor() +{ + + if ( _cursor_x == 0 && _cursor_y > 0 ) { + _cursor_x = 80; + _cursor_y -= 1; + } else if ( _cursor_x > 0 ) { + _cursor_x -= 1; + } + setCursorPosition(_cursor_x, _cursor_y); +} + +void advanceCursor() +{ + _cursor_x += 1; + if ( _cursor_x > 79 ) { + _cursor_x = 0; + _cursor_y += 1; + } + setCursorPosition(_cursor_x, _cursor_y); +} diff --git a/src/screen.h b/src/screen.h new file mode 100644 index 0000000..7b169d6 --- /dev/null +++ b/src/screen.h @@ -0,0 +1,12 @@ +#ifndef _SCREEN_H_ +#define _SCREEN_H_ + +extern char _cursor_x; +extern char _cursor_y; + +void setCursorPosition(char x, char y); +void backupCursor(); +void advanceCursor(); +void blankScreen(); + +#endif /* _SCREEN_H_ */ diff --git a/src/stdlib.c b/src/stdlib.c new file mode 100644 index 0000000..6cdc75d --- /dev/null +++ b/src/stdlib.c @@ -0,0 +1,81 @@ +#include "types.h" +#include "stdlib.h" + +char dtoa(int d) +{ + switch (d) { + case 0: return '0'; break; + case 1: return '1'; break; + case 2: return '2'; break; + case 3: return '3'; break; + case 4: return '4'; break; + case 5: return '5'; break; + case 6: return '6'; break; + case 7: return '7'; break; + case 8: return '8'; break; + case 9: return '9'; break; + } +} + +int atoi(char *nptr) +{ + int value = 0; + char *ptr = nptr; + int multiplier = 1; + + if ( nptr == NULL ) { + return 0; + } + while ( isdigit(*ptr) == 1 ) { + ptr += 1; + } + ptr -= 1; + while ( ptr >= nptr) { + value += (((int)(*ptr--) - 0x30) * multiplier); + multiplier *= 10; + } + return value; +} + +int isdigit(int c) +{ + if (c >= 0x30 && c <= 0x39) { + return 1; + } + return 0; +} + +int isupper(int c) +{ + if (c >= 0x41 && c <= 0x5A) { + return 1; + } + return 0; +} + +int islower(int c) +{ + if (c >= 0x61 && c <= 0x7A) { + return 1; + } + return 0; +} + +int isalnum(int c) +{ + if ( isupper(c) || islower(c) || isdigit(c) ) { + return 1; + } + return 0; +} + +int isxdigit(int c) +{ + if ( isdigit(c) || + (c >= 0x41 && c <= 0x46) || + (c >= 0x61 && c <= 0x66) + ) { + return 1; + } + return 0; +} diff --git a/src/stdlib.h b/src/stdlib.h new file mode 100644 index 0000000..0ace533 --- /dev/null +++ b/src/stdlib.h @@ -0,0 +1,12 @@ +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +char dtoa(int d); +int atoi(char *nptr); +int isdigit(int c); +int isupper(int c); +int islower(int c); +int isalnum(int c); +int isxdigit(int c); + +#endif /* _STDLIB_H_ */ diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000..4121acf --- /dev/null +++ b/src/string.c @@ -0,0 +1,83 @@ +#include "types.h" +#include "string.h" + +size_t strlen(char *ptr) +{ + char *ptr2 = ptr; + if ( ptr == NULL ) { + return 0; + } + + while (*ptr2 != 0x0 ) { + ptr2 += 1; + } + + return ptr2 - ptr; +} + +void *memset(void *s, int c, size_t n) +{ + int *d = (int *)s; + if ( s == NULL ) { + return NULL; + } + while ( ((int)d - (int)s) <= n ) { + *d = c; + d += sizeof(int); + } + return s; +} + +void *memcpy(void *dest, void *src, size_t n) +{ + int i = 0; + char *d = dest; + char *s = src; + + if ( d == NULL || s == NULL ) { + return NULL; + } + for ( i = 0 ; i < n ; i++ ) { + *d++ = *s++; + } + *d = '\0'; + return dest; +} + +int strncat(char *dest, char *src, size_t n) +{ + int c = 0; + if ( dest == NULL || src == NULL ) { + return 0; + } + dest = (dest + strlen(dest)); + while ( c++ < n ) { + *dest++ = *src++; + } + return c; +} + +int strcmp(char *s1, char *s2) +{ + int d = 0; + int s1len = 0; + + if ( s1 == NULL || s2 == NULL ) { + return 1; + } + + s1len = strlen(s1); + if ( s1len != strlen(s2) ) { + return 1; + } + + while ( *s1 != '\0' ) { + if ( *s1 != *s2 ) { + return 1; + } + s1 += sizeof(char); + s2 += sizeof(char); + } + + return 0; +} diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000..c1d06ca --- /dev/null +++ b/src/string.h @@ -0,0 +1,12 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#include "types.h" + +size_t strlen(char *ptr); +int strncat(char *dest, char *src, size_t n); +void *memset(void *s, int c, size_t n); +void *memcpy(void *dest, void *src, size_t n); +int strcmp(const char *s1, const char *s2); + +#endif /* _STRING_H_ */ diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..8d2cf30 --- /dev/null +++ b/src/types.h @@ -0,0 +1,7 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#define NULL 0x0 +typedef int size_t; + +#endif /* _TYPES_H_ */