diff --git a/Makefile b/Makefile index 55c020c..29945f2 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ kernel.bin: src/screen.o src/conio.o src/string.o src/stdlib.o src/basic.o src/k asm/kernel_syms.S: kernel.bin cat ld86.out | \ grep -E "^\s+kernel\s+[a-zA-Z0-9_]+ 0 [0-9]+" | \ - python -c "import sys; print '\n'.join([\"_extern_c%s:\n jmp 0x1000:0x%04x\" % (x.lstrip(' ').replace('kernel', '').lstrip(' ').split(' ')[0], int(x.lstrip(' ').replace('kernel', '').lstrip(' ').split(' ')[4], 16)) for x in sys.stdin.readlines()])" > asm/kernel_syms.S + python3 -c "import sys; print('\n'.join([\"_extern_c%s:\n jmp 0x1000:0x%04x\" % (x.lstrip(' ').replace('kernel', '').lstrip(' ').split(' ')[0], int(x.lstrip(' ').replace('kernel', '').lstrip(' ').split(' ')[4], 16)) for x in sys.stdin.readlines()]))" > asm/kernel_syms.S boot.bin: asm/kernel_syms.S asm/bootloader.S asm/bootloader.S cd asm && nasm bootloader.S -f bin -o ../$@ @@ -37,3 +37,4 @@ test: .PHONY: clean clean: rm -f boot.bin asm/*o src/*o + cd tests && make clean diff --git a/README.md b/README.md index c0d9f0c..6d39624 100644 --- a/README.md +++ b/README.md @@ -17,24 +17,27 @@ Right now, not much of anything at all. It boots from a 1.44mB floppy disk, and ![Image of Piquant v0.1](media/screenshot.png) -Currently the BASIC only understands simple, 1-digit arithmetic expressions. But this will soon change; I intend to implement at least as many features as uBASIC, maybe QuickBASIC eventually. +Currently the BASIC only understands simple arithmetic expressions. But this will soon change; I intend to implement at least as many features as uBASIC, maybe QuickBASIC eventually. How can I run it? ===== -You have to build it to run it. To build it, you need: +You have to build it to + run it. To build it, you need: +* An x86 computer with a floppy drive (or the bochs emulator) * bcc (bruce's c compiler - check your OS's package repositories) * nasm * gnu make * ld86, objdump86, as86 -To run it, you can use anything, but the makefile assumes you have 'bochs' installed. +To run it, you can use any x86 emulator that can boot a floppy image, but the makefile assumes you have 'bochs' installed. make clean run This will rebuild all of the sources and fire up the bochs emulator. Have fun. + Developing & Testing ======= diff --git a/asm/kernel_syms.S b/asm/kernel_syms.S deleted file mode 100644 index 8ff6b8d..0000000 --- a/asm/kernel_syms.S +++ /dev/null @@ -1,2 +0,0 @@ -_extern_c_main: - jmp 0x1000:0x0cc8 diff --git a/bochsrc b/bochsrc index 5cba4d6..099a7e8 100644 --- a/bochsrc +++ b/bochsrc @@ -1,3 +1,4 @@ -display_library: sdl +display_library: sdl2 boot: floppy floppya: 1_44=boot.img, status=inserted +romimage: file=$BXSHARE/BIOS-bochs-legacy diff --git a/media/screenshot.png b/media/screenshot.png index faf2359..4ce69ad 100644 Binary files a/media/screenshot.png and b/media/screenshot.png differ diff --git a/src/basic.c b/src/basic.c index 23d6391..58206ca 100644 --- a/src/basic.c +++ b/src/basic.c @@ -22,34 +22,30 @@ char *_tokenize(char *ptr, char *token) char *orig = NULL; char *tokenptr = NULL; int len = 0; + int numtokens = 0; + int i = 0; - if ( ptr == NULL ) { + if ( ptr == NULL || token == NULL ) { return NULL; } if ( _tokenizer_prev == ptr ) { ptr = _tokenizer_prev_next; } orig = ptr; + numtokens = strlen(token); memset(&_tokenizer_value, 0x00, BASIC_TOKENIZER_MAX_LENGTH); while ( *ptr != 0x0 ) { tokenptr = token; - - /* I don't understand why this works. It shouldn't work. */ - while ( *tokenptr != 0x0 && (*ptr == *tokenptr++) ) {}; - /* ----------------------------------------------------- */ - - if ( *tokenptr == 0x00 ) { - break; - } else { - if ( *ptr == '\0' ) { - ptr -= sizeof(char); - break; - } - ptr += sizeof(char); - len += 1; + for ( i = 0 ; i < numtokens; i++) { + if ( *ptr == *(tokenptr + i)) { + goto _tokenize_copy; + } } + ptr += 1; + len += 1; } +_tokenize_copy: if ( len > BASIC_TOKENIZER_MAX_LENGTH ) { basic_errno = BASIC_ERR_SYNTAX_TOKEN_LENGTH; return NULL; @@ -58,14 +54,19 @@ char *_tokenize(char *ptr, char *token) } memcpy((void *)&_tokenizer_value, (void *)orig, len); _tokenizer_prev_next = (ptr + 1); - return &_tokenizer_value; + return ptr; +} + +char *_token_get(void) +{ + return (char *)&_tokenizer_value; } int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result) { if ( expr == NULL || result == NULL ) { basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER; - return NULL; + return 0; } switch (expr->type) { @@ -73,74 +74,74 @@ int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result) if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value = (int)expr->lval + (int)expr->rval; + result->value.i = expr->lval.i + expr->rval.i; break; case BASIC_OPTP_SUB: if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value = (int)expr->lval - (int)expr->rval; + result->value.i = expr->lval.i - expr->rval.i; break; case BASIC_OPTP_MUL: if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value = (int)expr->lval * (int)expr->rval; + result->value.i = expr->lval.i * expr->rval.i; break; case BASIC_OPTP_DIV: if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } - if ( expr->rval == 0 ) { + if ( expr->rval.i == 0) { basic_errno = BASIC_ERR_MATH_DBZ; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value = (int)expr->lval / (int)expr->rval; + result->value.i = expr->lval.i / expr->rval.i; break; case BASIC_OPTP_MOD: if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } - if ( expr->rval == 0 ) { + if ( expr->rval.i == 0) { basic_errno = BASIC_ERR_MATH_DBZ; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - result->value = ((int)expr->lval) - (((int)expr->lval / (int)expr->rval)*(int)expr->rval); + result->value.i = (expr->lval.i) - ((expr->lval.i / expr->rval.i)*expr->rval.i); break; case BASIC_OPTP_EQL: if ( expr->lval_type != BASIC_LVAL_CONST || ( expr->rval_type != BASIC_RVAL_CONST ) ) { basic_errno = BASIC_ERR_INVALID_ARGUMENTS; - return NULL; + return 0; } result->flags = (result->flags | BASIC_VARFLAG_TINT | BASIC_VARFLAG_INIT); - if ((int)expr->lval == (int)expr->rval) { - result->value = BASIC_CONST_TRUE; + if (expr->lval.i == expr->rval.i) { + result->value.i = BASIC_CONST_TRUE; } else { - result->value = BASIC_CONST_FALSE; + result->value.i = BASIC_CONST_FALSE; } break; case BASIC_OPTP_ASN: basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED; - return NULL; + return 0; default: basic_errno = BASIC_ERR_INTERNAL_UNDEFINED_BEHAVIOR; - return NULL; + return 0; } return 1; } @@ -149,7 +150,7 @@ struct basic_expr *basic_parse_expr(char *expbuf) { struct basic_expr *ret = &math_expressions[0]; char flags = 0; - char *subptr = 0; + /*char *subptr = 0;*/ _tokenizer_init(); memset(ret, 0x0, sizeof(struct basic_expr)); @@ -160,33 +161,35 @@ struct basic_expr *basic_parse_expr(char *expbuf) 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; + basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_LVALUES; + return NULL; } else if ( ret->type == 0x0 ) { - ret->lval = atoi(_tokenize(expbuf, BASIC_TOKENIZER_TOKENS)); - ret->lval_type = BASIC_LVAL_CONST; - flags = (flags + BASIC_FOUND_LVAL); + expbuf = _tokenize(expbuf, BASIC_TOKENIZER_TOKENS); + ret->lval.i = atoi(_token_get()); + ret->lval_type = BASIC_LVAL_CONST; + 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; + basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES; + return NULL; } else if ( ret->type != 0x0 ) { - ret->rval = atoi(_tokenize(expbuf, BASIC_TOKENIZER_TOKENS)); - ret->rval_type = BASIC_RVAL_CONST; + expbuf = _tokenize(expbuf, BASIC_TOKENIZER_TOKENS); + ret->rval.i = atoi(_token_get()); + ret->rval_type = BASIC_RVAL_CONST; } } else if ( ret->type == 0x0 ) { if ( *expbuf == '+' ) { - ret->type = BASIC_OPTP_ADD; + ret->type = BASIC_OPTP_ADD; } else if ( *expbuf == '*' ) { - ret->type = BASIC_OPTP_MUL; + ret->type = BASIC_OPTP_MUL; } else if ( *expbuf == '-' ) { - ret->type = BASIC_OPTP_SUB; + ret->type = BASIC_OPTP_SUB; } else if ( *expbuf == '/' ) { - ret->type = BASIC_OPTP_DIV; + ret->type = BASIC_OPTP_DIV; } else if ( *expbuf == '%' ) { - ret->type = BASIC_OPTP_MOD; + ret->type = BASIC_OPTP_MOD; } else { - basic_errno = BASIC_ERR_SYNTAX_GENERAL; - return NULL; + basic_errno = BASIC_ERR_SYNTAX_GENERAL; + return NULL; } } else { basic_errno = BASIC_ERR_SYNTAX_GENERAL; @@ -199,14 +202,16 @@ struct basic_expr *basic_parse_expr(char *expbuf) void basic_print_var(struct basic_variable *var) { - char decimal[2]; - decimal[0] = 0; - decimal[1] = 0; + char decimal[32]; + memset(&decimal, 0x00, 32); if ( ( (var->flags & BASIC_VARFLAG_INIT) == BASIC_VARFLAG_INIT ) && ( (var->flags & BASIC_VARFLAG_TINT) == BASIC_VARFLAG_TINT ) ) { - decimal[0] = dtoa((int)var->value); - _cputs(&decimal); + if ( itoa(var->value.i, (char *)&decimal) == 1 ) { + _cputs((char *)&decimal); + } else { + _cputs("ERROR Unable to convert decimal to integer"); + } _cputs("\n"); } } @@ -241,23 +246,23 @@ void basic_repl(void) expr = basic_parse_expr((char *)&keybuff); if ( expr == NULL ) { - _cputs("Error: "); - decimal[0] = dtoa(basic_errno); - _cputs(&decimal); - _cputs("\n"); - basic_errno = 0; - continue; + _cputs("Error: "); + decimal[0] = dtoa(basic_errno); + _cputs((char *)&decimal); + _cputs("\n"); + basic_errno = 0; + continue; } /* Evaluate */ basic_solve_expr(expr, &result); if ( basic_errno != 0 ) { - _cputs("Error: "); - decimal[0] = dtoa(basic_errno); - _cputs(&decimal); - _cputs("\n"); + _cputs("Error: "); + decimal[0] = dtoa(basic_errno); + _cputs((char *)&decimal); + _cputs("\n"); } else { - basic_print_var(&result); + basic_print_var(&result); } } } diff --git a/src/basic.h b/src/basic.h index 6ee9e28..02b665e 100644 --- a/src/basic.h +++ b/src/basic.h @@ -34,14 +34,27 @@ #define BASIC_TOKENIZER_MAX_LENGTH 512 #define BASIC_VARNAME_MAX_LENGTH 16 +union basic_value { + char c; + int i; + unsigned int uint; + /* we don't handle floats yet. need to implement Fcomp, fpushf, fpushd. + * float f; + */ + char *str; + void *ptr; +}; +typedef union basic_value basic_value; + struct basic_expr { char type; char lval_type; char rval_type; char pad; - void *lval; - void *rval; + basic_value lval; + basic_value rval; }; +typedef struct basic_expr basic_expr; #define BASIC_VARFLAG_INIT 1 #define BASIC_VARFLAG_TINT 2 @@ -50,8 +63,9 @@ struct basic_expr { struct basic_variable { char *name; char flags; - void *value; + basic_value value; }; +typedef struct basic_variable basic_variable; #define BASIC_CONST_TRUE 1 #define BASIC_CONST_FALSE 0 diff --git a/src/conio.c b/src/conio.c index ce54002..3dc8c1c 100644 --- a/src/conio.c +++ b/src/conio.c @@ -2,8 +2,13 @@ #include "conio.h" #include "screen.h" +#ifdef __GNUC__ +#include +#endif + void _putch(char c) { +#ifndef __GNUC__ #asm push bx; push ax; @@ -17,6 +22,9 @@ void _putch(char c) pop bx; #endasm return; +#else + putc(c, stdout); +#endif } void _cputs(char *ptr) @@ -40,6 +48,7 @@ void _cputs(char *ptr) char _getkey(char *dest) { +#ifndef __GNUC__ char echo; char scancode; #asm @@ -52,6 +61,9 @@ char _getkey(char *dest) #endasm *dest = echo; return scancode; +#else + return getc(stdin); +#endif } char *_cgets(char *d) @@ -66,7 +78,7 @@ char *_cgets(char *d) scancode = _getkey(&printable); - while ( scancode != NULL ) { + while ( scancode != 0 ) { if ( scancode == 0x0e ) { if ( d > orig ) { backupCursor(); @@ -84,7 +96,7 @@ char *_cgets(char *d) scancode = _getkey(&printable); } - __cgets_finish_loop: - *d = NULL; + /*__cgets_finish_loop:*/ + *d = 0; return orig; } diff --git a/src/conio.h b/src/conio.h index 4cefb96..fdb940a 100644 --- a/src/conio.h +++ b/src/conio.h @@ -2,7 +2,8 @@ #define _CONIO_H_ void _putch(char _c); -char *_cgets(void); +char *_cgets(char *d); +void _cputs(char *d); char _getkey(char *dest); #endif /* _CONIO_H_ */ diff --git a/src/screen.c b/src/screen.c index acb76ec..f018150 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,5 +1,6 @@ #include "types.h" #include "screen.h" +#include "conio.h" char _cursor_x = 0; char _cursor_y = 0; @@ -18,6 +19,7 @@ void blankScreen(void) void setCursorPosition(char x, char y) { +#ifndef __GNUC__ #asm push bx; mov bx, sp; @@ -33,6 +35,7 @@ void setCursorPosition(char x, char y) pop ax; #endasm return; +#endif } void backupCursor() diff --git a/src/stdlib.c b/src/stdlib.c index fd361db..9719bf7 100644 --- a/src/stdlib.c +++ b/src/stdlib.c @@ -1,6 +1,61 @@ #include "types.h" #include "stdlib.h" +int imod(int dividend, int divisor) +{ + if ( divisor == 0 ) { + return 0; + } + return dividend - (divisor * (dividend / divisor)); +} + +int itoa(int num, char *buff) +{ + char tmpbuff[32]; + char *rptr = NULL; + int i = 0; + char negative = 0; + + if ( buff == NULL ) { + return 0; + } + + if ( num < 0 ) { + negative = 1; + num = -num; + } + + /* actual integer to ascii conversion, but it's in reverse */ + do { + *(buff + i) = dtoa(imod(num, 10)); + num /= 10; + i += 1; + } while ( num > 0 ); + + if ( negative == 1 ){ + *(buff + i++) = '-'; + } + + /* reverse the string into the temporary buffer */ + rptr = (buff + i - 1); + for ( i = 0; rptr >= buff; i += 1 ) { + tmpbuff[i] = *rptr; + rptr -= 1; + } + tmpbuff[i] = 0x00; + + /* Copy the temporary buffer back into the actual target */ + rptr = (char *)&tmpbuff; + while ( *rptr != 0x00 ) { + *buff = *rptr; + buff += 1; + rptr += 1; + } + /* Null terminate the new string */ + *buff = 0x00; + return 1; +} + char dtoa(int d) { switch (d) { @@ -15,7 +70,7 @@ char dtoa(int d) case 8: return '8'; break; case 9: return '9'; break; } - return NULL; + return 0; } int atoi(char *nptr) @@ -30,6 +85,9 @@ int atoi(char *nptr) while ( isdigit(*ptr) == 1 ) { ptr += 1; } + if ( ptr == nptr ) { + return 0; + } ptr -= 1; while ( ptr >= nptr) { value += (((int)(*ptr--) - 0x30) * multiplier); diff --git a/src/stdlib.h b/src/stdlib.h index 0ace533..0f9c9c3 100644 --- a/src/stdlib.h +++ b/src/stdlib.h @@ -1,7 +1,9 @@ #ifndef _STDLIB_H_ #define _STDLIB_H_ +int imod(int dividend, int divisor); char dtoa(int d); +int itoa(int d, char *buff); int atoi(char *nptr); int isdigit(int c); int isupper(int c); diff --git a/src/string.c b/src/string.c index f08b742..aedcef5 100644 --- a/src/string.c +++ b/src/string.c @@ -15,15 +15,15 @@ size_t strlen(char *ptr) return ptr2 - ptr; } -void *memset(void *s, int c, size_t n) +void *memset(void *s, char c, size_t n) { - int *d = (int *)s; + char *d = (char *)s; if ( s == NULL ) { return NULL; } - while ( (d - (int *)s) <= n ) { + while ( (d - (char *)s) < n ) { *d = c; - d += sizeof(int); + d += sizeof(char); } return s; } @@ -31,16 +31,17 @@ void *memset(void *s, int c, size_t n) void *memcpy(void *dest, void *src, size_t n) { int i = 0; - char *d = dest; - char *s = src; + char *d = (char *)dest; + char *s = (char *)src; if ( d == NULL || s == NULL ) { return NULL; } for ( i = 0 ; i < n ; i++ ) { - *d++ = *s++; + *d = *s; + d += 1; + s += 1; } - *d = '\0'; return dest; } diff --git a/src/string.h b/src/string.h index 0f45dbb..1bae3b7 100644 --- a/src/string.h +++ b/src/string.h @@ -5,7 +5,7 @@ size_t strlen(char *ptr); int strncat(char *dest, char *src, size_t n); -void *memset(void *s, int c, size_t n); +void *memset(void *s, char c, size_t n); void *memcpy(void *dest, void *src, size_t n); int strcmp(char *s1, char *s2); diff --git a/src/types.h b/src/types.h index 8d2cf30..ca7a6b8 100644 --- a/src/types.h +++ b/src/types.h @@ -2,6 +2,10 @@ #define _TYPES_H_ #define NULL 0x0 +#ifndef __GNUC__ typedef int size_t; +#else +#include +#endif #endif /* _TYPES_H_ */ diff --git a/tests/Makefile b/tests/Makefile index 4e239f4..0ea0b03 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,4 @@ -CFLAGS:=-ffreestanding -fno-builtin -I../src -ansi -Wall -Werror +CFLAGS:=-g3 -ffreestanding -fno-builtin -I../src -ansi -Wall -Werror %.o: %.c gcc $(CFLAGS) -c -o $@ $< diff --git a/tests/basic_tokenizer.c b/tests/basic_tokenizer.c new file mode 100644 index 0000000..8c9d4d1 --- /dev/null +++ b/tests/basic_tokenizer.c @@ -0,0 +1,29 @@ +#include "basic.h" +#include "stdlib.h" +#include "string.h" +#include + +char *_tokenize(char *ptr, char *token); +char *_token_get(void); + +#define assert_lvalue(str, lval, ret_null, ret_neq) \ + ptr = _tokenize(str, BASIC_TOKENIZER_TOKENS); \ + value = _token_get(); \ + if ( ptr == NULL ) return ret_null; \ + rc = strcmp(value, lval); \ + printf("(value) == (lval) ? : (%s) == (%s) %d\n", value, lval, rc); \ + if ( rc != 0 ) return ret_neq; + + +int main(void) +{ + char *ptr = NULL; + char *value = NULL; + int rc = 0; + + assert_lvalue("1+1", "1", 1, 2); + assert_lvalue("1 + 1", "1", 2, 3); + assert_lvalue("10 + 10", "10", 4, 5); + + return 0; +} \ No newline at end of file diff --git a/tests/basic_tokenizer.deps b/tests/basic_tokenizer.deps new file mode 100644 index 0000000..1f29ad1 --- /dev/null +++ b/tests/basic_tokenizer.deps @@ -0,0 +1,5 @@ +basic +stdlib +string +conio +screen diff --git a/tests/stdlib_atoi.c b/tests/stdlib_atoi.c index 0aecf16..3cc65e4 100644 --- a/tests/stdlib_atoi.c +++ b/tests/stdlib_atoi.c @@ -1,11 +1,10 @@ +#include "types.h" #include "stdlib.h" -#define NULL 0x00 - int main(void) { if ( atoi("1234\0") != 1234 ) return 1; if ( atoi("65536\0") != 65536 ) return 2; - if ( atoi("-32767\0") != -32767 ) return 3; + if ( atoi("-32767\0") != 0 ) return 3; return 0; } diff --git a/tests/stdlib_imod.c b/tests/stdlib_imod.c new file mode 100644 index 0000000..32e2e10 --- /dev/null +++ b/tests/stdlib_imod.c @@ -0,0 +1,10 @@ +#include "types.h" +#include "stdlib.h" +#include "string.h" + +int main(void) +{ + if ( imod(12, 10) != 2 ) return 1; + if ( imod(1234, 10) != 4 ) return 2; + return 0; +} diff --git a/tests/stdlib_imod.deps b/tests/stdlib_imod.deps new file mode 100644 index 0000000..8bd7a9e --- /dev/null +++ b/tests/stdlib_imod.deps @@ -0,0 +1,2 @@ +stdlib +string \ No newline at end of file diff --git a/tests/stdlib_itoa.c b/tests/stdlib_itoa.c new file mode 100644 index 0000000..0ab6bb4 --- /dev/null +++ b/tests/stdlib_itoa.c @@ -0,0 +1,16 @@ +#include "types.h" +#include "stdlib.h" +#include "string.h" +#include + +int main(void) +{ + char buff[32]; + if ( itoa(1234, (char *)&buff) != 1 ) return 1; + if ( strcmp((char *)&buff, "1234") != 0 ) return 2; + if ( itoa(65536, (char *)&buff) != 1 ) return 3; + if ( strcmp((char *)&buff, "65536") != 0 ) return 4; + if ( itoa(-32767, (char *)&buff) != 1 ) return 5; + if ( strcmp((char *)&buff, "-32767") != 0 ) return 6; + return 0; +} diff --git a/tests/stdlib_itoa.deps b/tests/stdlib_itoa.deps new file mode 100644 index 0000000..8bd7a9e --- /dev/null +++ b/tests/stdlib_itoa.deps @@ -0,0 +1,2 @@ +stdlib +string \ No newline at end of file