diff --git a/bin/os b/bin/os index 4fc001b..7cb4a65 100755 Binary files a/bin/os and b/bin/os differ diff --git a/image.hdd b/image.hdd index 1dee7b3..b8afcb8 100644 Binary files a/image.hdd and b/image.hdd differ diff --git a/limine b/limine index e0e61c9..eecf8d6 160000 --- a/limine +++ b/limine @@ -1 +1 @@ -Subproject commit e0e61c946933696453f591da525ab1f8a66a553d +Subproject commit eecf8d682a749701691e31b89f66f330f525c611 diff --git a/obj/src/int.c.o b/obj/src/int.c.o index 850fc4e..22cdad4 100644 Binary files a/obj/src/int.c.o and b/obj/src/int.c.o differ diff --git a/obj/src/main.c.d b/obj/src/main.c.d index a5046c3..1efc91c 100644 --- a/obj/src/main.c.d +++ b/obj/src/main.c.d @@ -1,6 +1,7 @@ obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \ src/prompt/file.h src/acpi.h src/common.h src/alloc.h src/apic.h \ - src/map.h src/print.h + src/kbd.h src/map.h src/print.h src/lib/stdio.h src/lib/malloc.h \ + src/lib/../common.h src/lib/../kbd.h src/lib/../print.h src/../include/limine.h: src/prompt/lex.h: src/prompt/file.h: @@ -8,5 +9,11 @@ src/acpi.h: src/common.h: src/alloc.h: src/apic.h: +src/kbd.h: src/map.h: src/print.h: +src/lib/stdio.h: +src/lib/malloc.h: +src/lib/../common.h: +src/lib/../kbd.h: +src/lib/../print.h: diff --git a/obj/src/main.c.o b/obj/src/main.c.o index 182c1b5..c48e610 100644 Binary files a/obj/src/main.c.o and b/obj/src/main.c.o differ diff --git a/run.sh b/run.sh index dbed59c..9b1bb9d 100644 --- a/run.sh +++ b/run.sh @@ -1 +1 @@ -qemu-system-x86_64 image.hdd +/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd diff --git a/src/alloc.c b/src/alloc.c index 8b67de3..0deb914 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3,6 +3,19 @@ #include "common.h" #include "print.h" +#ifdef DBG + #define dprint(x) print(x) + #define dprint8(x) print8(x) + #define dprint16(x) print16(x) + #define dprint32(x) print32(x) + #define dprint64(x) print64(x) +#else + #define dprint(x) + #define dprint8(x) + #define dprint16(x) + #define dprint32(x) + #define dprint64(x) +#endif __attribute__(( used, section(".limine_requests"))) static volatile struct limine_memmap_request @@ -106,7 +119,7 @@ static void usepage(size_t page) { } static void usepagerange(size_t page, size_t len) { - for (size_t i = 0; i < len; len++) { + for (size_t i = 0; i < len; i++) { usepage(i + page); } } @@ -118,7 +131,7 @@ static void unusepage(size_t page) { } static void unusepagerange(size_t page, size_t len) { - for (size_t i = 0; i < len; len++) { + for (size_t i = 0; i < len; i++) { unusepage(i + page); } } @@ -144,9 +157,10 @@ void *alloc(size_t size) { return NULL; } - print("Attempting to find "); - print64(pages); - print(" consecutive pages\n"); + + dprint("Attempting to find "); + dprint64(pages); + dprint(" consecutive pages....."); size_t consecutive = 0; for (size_t i = 0; i < total_pages / 64; i++) { @@ -157,6 +171,7 @@ void *alloc(size_t size) { consecutive += 64; if (consecutive >= pages) { usepagerange(page, pages); + dprint("succeeded!\n"); return addr(page); } continue; @@ -173,7 +188,8 @@ void *alloc(size_t size) { page = i * 64 + bit; if (++consecutive >= pages) { - usepagerange(page, pages); + usepagerange(page, pages); + dprint("succeeded!\n"); return addr(page); } } else { @@ -183,5 +199,8 @@ void *alloc(size_t size) { } } + dprint("failed :(!\n"); + return NULL; } + diff --git a/src/alloc.h b/src/alloc.h index b841650..bdb6449 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -11,3 +11,4 @@ static inline u64 virt_to_phys(void *virt) { return (u64)virt - hhdm_offset; } static inline void *phys_to_virt(u64 phys) { return (void *)(phys + hhdm_offset); } + diff --git a/src/kbd.c b/src/kbd.c index 2417eeb..c3375fa 100644 --- a/src/kbd.c +++ b/src/kbd.c @@ -72,6 +72,25 @@ char kbd_buffer_getc() { return c; } +static u8 held_map[0x100/16]; +static void hold_key(u8 key) { + key &= (0x100/2)-1; + + held_map[key>>3] |= (1 << (key & 7)); +} + +static void release_key(u8 key) { + key &= (0x100/2)-1; + + held_map[key>>3] &= ~(1 << (key & 7)); +} + +static bool key_held(u8 key) { + key &= (0x100/2)-1; + + return (held_map[key>>3] & (1 << (key & 7))); +} + void kbd_handler() { u8 scancode = inb(PS2_DATA_PORT); bool released = (scancode & 0x80); @@ -91,6 +110,7 @@ void kbd_handler() { if(!released) { kbd_state.caps = !kbd_state.caps; } + break; default: break; } @@ -106,18 +126,29 @@ void kbd_handler() { if(kbd_state.caps && c >= 'a' && c <= 'z') { - + c = c - 'a' + 'A'; } else if(kbd_state.caps && c >= 'A' && c <= 'Z') { c = c - 'A' + 'a'; } - if(c != 0) { + if(c != 0 && !key_held(scancode)) { kbd_buffer_putc(c); } - printn(&c, 1); + + hold_key(scancode); + } else { + release_key(scancode); } send_eoi(); } +int kbd_getc_blocking() { + int ch; + + while(!(ch =kbd_buffer_getc())) + ; + + return ch; +} \ No newline at end of file diff --git a/src/kbd.h b/src/kbd.h index 8f981e7..68918ee 100644 --- a/src/kbd.h +++ b/src/kbd.h @@ -1,2 +1,4 @@ #pragma once void kbd_handler(); +int kbd_getc_blocking(); +char kbd_buffer_getc(); \ No newline at end of file diff --git a/src/lib/malloc.c b/src/lib/malloc.c new file mode 100644 index 0000000..fc58b75 --- /dev/null +++ b/src/lib/malloc.c @@ -0,0 +1,33 @@ +#include +#include "../alloc.h" + +struct malloc_header { + size_t size; +}; + +void* malloc(size_t sz) { + size_t total = sz + sizeof(struct malloc_header); + + struct malloc_header* mh = alloc(total); + if(!mh) + return mh; + mh->size = total; + return (void*)(&mh[1]); +} + +void* calloc(size_t sz, size_t n) { + // for now ignore the case of sz * n > 1 << 64 + size_t N = sz * n; + u8* ptr = malloc(N); + for(size_t i = 0; i < N; i++) + ptr[i] = 0; +} + +void free(void* ptr) { + if(!ptr) { + return; + } + size_t sz = ((struct malloc_header*)ptr)[-1].size; + + dealloc(ptr, sz); +} \ No newline at end of file diff --git a/src/lib/malloc.h b/src/lib/malloc.h new file mode 100644 index 0000000..a2f1b7f --- /dev/null +++ b/src/lib/malloc.h @@ -0,0 +1,5 @@ +#pragma once + +void* malloc(size_t sz); +void* calloc(size_t sz, size_t n); +void* free(void* ptr); \ No newline at end of file diff --git a/src/lib/stdio.h b/src/lib/stdio.h new file mode 100644 index 0000000..1339fb2 --- /dev/null +++ b/src/lib/stdio.h @@ -0,0 +1,475 @@ +#pragma once + + +#include +#include "malloc.h" +#include "../common.h" +#include "../kbd.h" +#include "../print.h" + +#define MAX_LINE_LEN 256 + +static inline int puts(const char *s) { + print(s); + put('\n'); + return 0; +} + +#define _STDIO_PEEK_BUFF_EMPTY -1 +static int _stdio_peek_buf = _STDIO_PEEK_BUFF_EMPTY; +/* getc – blocking, consumes one character */ +static inline int getc(void) { + if (_stdio_peek_buf >= 0) { + int c = _stdio_peek_buf; + _stdio_peek_buf = -1; + return c; + } + return kbd_getc_blocking(); +} + +/* peek – blocking, returns next char WITHOUT consuming it */ +static inline int peek(void) { + if (_stdio_peek_buf < 0) + _stdio_peek_buf = kbd_getc_blocking(); + return _stdio_peek_buf; +} + +/* getc_nb – non-blocking version; returns -1 if no char ready */ +static inline int getc_nb(void) { + if (_stdio_peek_buf >= 0) { + int c = _stdio_peek_buf; + _stdio_peek_buf = _STDIO_PEEK_BUFF_EMPTY; + return c; + } + int c = kbd_buffer_getc(); + return c ? c : _STDIO_PEEK_BUFF_EMPTY; +} + +/* peek_nb – non-blocking peek; returns -1 if no char ready */ +static inline int peek_nb(void) { + if (_stdio_peek_buf < 0) { + int c = kbd_buffer_getc(); + if (!c) return -1; + _stdio_peek_buf = c; + } + return _stdio_peek_buf; +} + +static inline char *getline_alloc(size_t max_hint) { + size_t cap = max_hint > 0 ? max_hint : 128; + char *buf = (char *)malloc(cap); + if (!buf) { + print("getline_alloc failed to alloc! :(\n"); + return NULL; + } + + size_t len = 0; + + for (;;) { + int c = getc(); + + + + if (c == '\b') { /* backspace */ + if (len > 0) { + len--; + unput(); + } + continue; + } + + /* grow buffer if needed (leave room for NUL) */ + if (len + 1 >= cap) { + size_t new_cap = cap * 2; + char *new_buf = (char *)malloc(new_cap); + if (!new_buf) { free(buf); print("getline_alloc failed to alloc! :(\n"); return NULL; } + for (size_t i = 0; i < len; i++) new_buf[i] = buf[i]; + free(buf); + buf = new_buf; + cap = new_cap; + } + + buf[len++] = (char)c; + if (c == '\n' || c == '\r') { + put('\n'); + break; + } else { + put(c); /* echo */ + } + } + + buf[len] = '\0'; + return buf; +} + +static inline int getline_buf(char *buf, size_t n) { + if (!buf || n == 0) return -1; + size_t len = 0; + + for (;;) { + int c = getc(); + + if (c == '\n' || c == '\r') { + put('\n'); + break; + } + + if (c == '\b') { + if (len > 0) { len--; unput(); } + continue; + } + + if (len < n - 1) { + buf[len++] = (char)c; + put(c); + } + /* else: buffer full – keep echoing but discard */ + } + + buf[len] = '\0'; + return (int)len; +} + + +static inline char *_fmt_uint(char *end, u64 val, int base, bool upper) { + static const char lo[] = "0123456789abcdef"; + static const char up[] = "0123456789ABCDEF"; + const char *digs = upper ? up : lo; + *--end = '\0'; + if (val == 0) { *--end = '0'; return end; } + while (val) { *--end = digs[val % (u64)base]; val /= (u64)base; } + return end; +} + +static inline int vprintf(const char *fmt, va_list ap) { + int written = 0; + +#define _EMIT(c) do { put(c); written++; } while(0) +#define _EMITS(s) do { const char *_p=(s); while(*_p){_EMIT(*_p);_p++;} } while(0) + + while (*fmt) { + if (*fmt != '%') { _EMIT(*fmt++); continue; } + fmt++; /* skip '%' */ + + /* flags */ + bool left_align = false; + bool zero_pad = false; + if (*fmt == '-') { left_align = true; fmt++; } + if (*fmt == '0') { zero_pad = true; fmt++; } + + /* width */ + int width = 0; + while (*fmt >= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0'); + + /* length modifier */ + int lng = 0; /* 0=int, 1=long, 2=long long */ + if (*fmt == 'l') { lng=1; fmt++; } + if (*fmt == 'l') { lng=2; fmt++; } + + char tmp[66]; + char *s = NULL; + char cbuf[2] = {0,0}; + bool neg = false; + + switch (*fmt++) { + case '%': + _EMIT('%'); + continue; + + case 'c': + cbuf[0] = (char)va_arg(ap, int); + s = cbuf; + break; + + case 's': + s = va_arg(ap, char *); + if (!s) s = "(null)"; + break; + + case 'd': case 'i': { + i64 v = (lng==2) ? va_arg(ap,long long) : + (lng==1) ? va_arg(ap,long) : + va_arg(ap,int); + if (v < 0) { neg = true; v = -v; } + s = _fmt_uint(tmp+65, (u64)v, 10, false); + break; + } + + case 'u': { + u64 v = (lng==2) ? va_arg(ap,unsigned long long) : + (lng==1) ? va_arg(ap,unsigned long) : + va_arg(ap,unsigned int); + s = _fmt_uint(tmp+65, v, 10, false); + break; + } + + case 'o': { + u64 v = (lng==2) ? va_arg(ap,unsigned long long) : + (lng==1) ? va_arg(ap,unsigned long) : + va_arg(ap,unsigned int); + s = _fmt_uint(tmp+65, v, 8, false); + break; + } + + case 'x': { + u64 v = (lng==2) ? va_arg(ap,unsigned long long) : + (lng==1) ? va_arg(ap,unsigned long) : + va_arg(ap,unsigned int); + s = _fmt_uint(tmp+65, v, 16, false); + break; + } + + case 'X': { + u64 v = (lng==2) ? va_arg(ap,unsigned long long) : + (lng==1) ? va_arg(ap,unsigned long) : + va_arg(ap,unsigned int); + s = _fmt_uint(tmp+65, v, 16, true); + break; + } + + case 'p': { + u64 v = (u64)(uintptr_t)va_arg(ap, void *); + print("0x"); + written += 2; + s = _fmt_uint(tmp+65, v, 16, false); + break; + } + + default: + _EMIT('?'); + continue; + } + + /* padding / output */ + int slen = 0; + for (const char *p = s; *p; p++) slen++; + if (neg) slen++; /* for '-' */ + + int pad = width - slen; + + if (!left_align && pad > 0) { + char pc = zero_pad ? '0' : ' '; + if (neg && zero_pad) { _EMIT('-'); neg=false; written++; } + while (pad-- > 0) { _EMIT(pc); written++; } + } + if (neg) { _EMIT('-'); written++; } + while (*s) { _EMIT(*s++); written++; } + if (left_align && pad > 0) + while (pad-- > 0) { _EMIT(' '); written++; } + } + +#undef _EMIT +#undef _EMITS + return written; +} + +static inline int printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vprintf(fmt, ap); + va_end(ap); + return r; +} + + +typedef struct { char *p; size_t rem; } _sbuf; + +/* We re-implement the inner loop targeting a string buffer instead of the + * screen. Factoring out a shared back-end with a function pointer would be + * cleaner but adds complexity; this keeps it self-contained. */ +static inline int vsnprintf(char *out, size_t size, const char *fmt, va_list ap) { + if (!out || !size) return 0; + char *cur = out; + char *end = out + size - 1; /* leave room for NUL */ + int written = 0; + +#define _SEMIT(c) do { if(cur='0'&&*fmt<='9') width=width*10+(*fmt++-'0'); + int lng=0; + if(*fmt=='l'){lng=1;fmt++;} + if(*fmt=='l'){lng=2;fmt++;} + + char tmp[66]; + char *s=NULL; + char cbuf[2]={0,0}; + bool neg=false; + + switch(*fmt++) { + case '%': _SEMIT('%'); continue; + case 'c': cbuf[0]=(char)va_arg(ap,int); s=cbuf; break; + case 's': s=va_arg(ap,char*); if(!s)s="(null)"; break; + case 'd': case 'i': { + i64 v=(lng==2)?va_arg(ap,long long):(lng==1)?va_arg(ap,long):va_arg(ap,int); + if(v<0){neg=true;v=-v;} + s=_fmt_uint(tmp+65,(u64)v,10,false); break; + } + case 'u': { + u64 v=(lng==2)?va_arg(ap,unsigned long long):(lng==1)?va_arg(ap,unsigned long):va_arg(ap,unsigned int); + s=_fmt_uint(tmp+65,v,10,false); break; + } + case 'o': { + u64 v=(lng==2)?va_arg(ap,unsigned long long):(lng==1)?va_arg(ap,unsigned long):va_arg(ap,unsigned int); + s=_fmt_uint(tmp+65,v,8,false); break; + } + case 'x': { + u64 v=(lng==2)?va_arg(ap,unsigned long long):(lng==1)?va_arg(ap,unsigned long):va_arg(ap,unsigned int); + s=_fmt_uint(tmp+65,v,16,false); break; + } + case 'X': { + u64 v=(lng==2)?va_arg(ap,unsigned long long):(lng==1)?va_arg(ap,unsigned long):va_arg(ap,unsigned int); + s=_fmt_uint(tmp+65,v,16,true); break; + } + case 'p': { + u64 v=(u64)(uintptr_t)va_arg(ap,void*); + _SEMIT('0'); _SEMIT('x'); written+=2; + s=_fmt_uint(tmp+65,v,16,false); break; + } + default: _SEMIT('?'); continue; + } + + int slen=0; for(const char*p=s;*p;p++) slen++; if(neg) slen++; + int pad=width-slen; + if(!left_align&&pad>0){char pc=zero_pad?'0':' '; if(neg&&zero_pad){_SEMIT('-');neg=false;} while(pad-->0){_SEMIT(pc);}} + if(neg){_SEMIT('-');} + while(*s){_SEMIT(*s++);} + if(left_align&&pad>0) while(pad-->0){_SEMIT(' ');} + } +#undef _SEMIT + *cur = '\0'; + return written; +} + +static inline int snprintf(char *out, size_t size, const char *fmt, ...) { + va_list ap; va_start(ap, fmt); + int r = vsnprintf(out, size, fmt, ap); + va_end(ap); return r; +} + +static inline int sprintf(char *out, const char *fmt, ...) { + va_list ap; va_start(ap, fmt); + /* pass a huge size – caller's responsibility to have enough room */ + int r = vsnprintf(out, (size_t)-1, fmt, ap); + va_end(ap); return r; +} + +static inline int _skip_ws(const char **p) { + while (**p==' '||**p=='\t'||**p=='\n'||**p=='\r') (*p)++; + return 0; +} + +static inline int vsscanf(const char *str, const char *fmt, va_list ap) { + const char *s = str; + int matched = 0; + + while (*fmt) { + if (*fmt == ' ') { _skip_ws(&s); fmt++; continue; } + if (*fmt != '%') { + if (*s != *fmt) return matched; + s++; fmt++; continue; + } + fmt++; /* skip '%' */ + if (*fmt == '%') { if (*s=='%') s++; fmt++; continue; } + + int lng = 0; + if (*fmt=='l'){lng=1;fmt++;} + if (*fmt=='l'){lng=2;fmt++;} + + _skip_ws(&s); + + switch (*fmt++) { + case 'c': { + char *out = va_arg(ap, char*); + if (!*s) return matched; + *out = *s++; + matched++; + break; + } + case 's': { + char *out = va_arg(ap, char*); + if (!*s) return matched; + while (*s && *s!=' '&&*s!='\t'&&*s!='\n'&&*s!='\r') + *out++ = *s++; + *out = '\0'; + matched++; + break; + } + case 'd': case 'i': { + bool neg2 = false; + if (*s=='-'){neg2=true;s++;} + else if(*s=='+') s++; + if (*s<'0'||*s>'9') return matched; + i64 v=0; + while(*s>='0'&&*s<='9') v=v*10+(*s++-'0'); + if(neg2) v=-v; + if(lng==2) *va_arg(ap,long long*)=(long long)v; + else if(lng==1) *va_arg(ap,long*)=(long)v; + else *va_arg(ap,int*)=(int)v; + matched++; + break; + } + case 'u': { + if(*s<'0'||*s>'9') return matched; + u64 v=0; + while(*s>='0'&&*s<='9') v=v*10+(*s++-'0'); + if(lng==2) *va_arg(ap,unsigned long long*)=(unsigned long long)v; + else if(lng==1) *va_arg(ap,unsigned long*)=(unsigned long)v; + else *va_arg(ap,unsigned int*)=(unsigned int)v; + matched++; + break; + } + case 'x': case 'X': { + if(*s=='0'&&(*(s+1)=='x'||*(s+1)=='X')) s+=2; + u64 v=0; bool any=false; + while((*s>='0'&&*s<='9')||(*s>='a'&&*s<='f')||(*s>='A'&&*s<='F')){ + u8 d=(*s>='a')?*s-'a'+10:(*s>='A')?*s-'A'+10:*s-'0'; + v=v*16+d; s++; any=true; + } + if(!any) return matched; + if(lng==2) *va_arg(ap,unsigned long long*)=(unsigned long long)v; + else if(lng==1) *va_arg(ap,unsigned long*)=(unsigned long)v; + else *va_arg(ap,unsigned int*)=(unsigned int)v; + matched++; + break; + } + case 'o': { + if(*s<'0'||*s>'7') return matched; + u64 v=0; + while(*s>='0'&&*s<='7') v=v*8+(*s++-'0'); + if(lng==2) *va_arg(ap,unsigned long long*)=(unsigned long long)v; + else if(lng==1) *va_arg(ap,unsigned long*)=(unsigned long)v; + else *va_arg(ap,unsigned int*)=(unsigned int)v; + matched++; + break; + } + default: + return matched; + } + } + return matched; +} + +static inline int sscanf(const char *str, const char *fmt, ...) { + va_list ap; va_start(ap, fmt); + int r = vsscanf(str, fmt, ap); + va_end(ap); return r; +} + + +static inline int scanf(const char *fmt, ...) { + char *line = getline_alloc(MAX_LINE_LEN); + if (!line) return -1; + va_list ap; va_start(ap, fmt); + int r = vsscanf(line, fmt, ap); + va_end(ap); + free(line); + return r; +} diff --git a/src/main.c b/src/main.c index ec65462..8696498 100644 --- a/src/main.c +++ b/src/main.c @@ -12,8 +12,10 @@ void print_tok(struct token* tok); #include "alloc.h" #include "apic.h" #include "common.h" +#include "kbd.h" #include "map.h" #include "print.h" +#include "lib/stdio.h" // credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup // code @@ -110,7 +112,8 @@ void draw(u8 vect) { for (size_t y = 0; y < fb->height; y++) { for (size_t x = 0; x < fb->width; x++) { volatile u32 *fb_ptr = fb->address; - fb_ptr[y * fb->width + x] = (((x ^ y) & 0xff) * 0x0F0003) * vect; + int tone = ((x ^ y) & 0xFF) >> 6; + fb_ptr[y * fb->width + x] = (tone << 16); } } } @@ -153,8 +156,8 @@ void kmain() { draw(1); print_init(fb); init_idt(); - bg = 0xFFFFFF; - fg = 0x000000; + fg = 0xFFFFFF; + bg = 0x000000; if (!hhdm_req.response) { print("Failed to get higher half direct mapping\n."); @@ -197,19 +200,30 @@ void kmain() { apic_enable(); print("APIC Enabled\n"); ioapic_init(); - const char* src[] = { - "u8 main(u32 x) {\n", - " u16 y = x + 16;\n", - " u8 z = x * y;\n", - " return z; }\n" - }; - const char* name = "prompt> "; + asm volatile("sti"); + +#define LINES 40 + size_t max_len = MAX_LINE_LEN; + char* line = getline_alloc(max_len); + char* lines[LINES]; + + size_t n_lines = 0; + for(n_lines = 0; n_lines < LINES; n_lines++) { + line = getline_alloc(max_len); + if(!line) + break; + if(line[0] == 'F' && line[1] == 'I' && line[2] == '\n') + break; + lines[n_lines] = line; + } + + const char* name = "stdin"; struct file input = { .row = 0, .col = 0, - .rows = 4, - .lines = (char**)src, + .rows = n_lines, + .lines = (char**)lines, .name = name, .tokens = NULL, .tail = &input.tokens, @@ -217,21 +231,15 @@ void kmain() { int res = lex(&input); - print("Result from lexing: "); + print("Number of Errors: "); print8(res); - if(res != 0) { - hang(); - } - + printf("\n# of Tokens: %d\n", input.tokens->len); struct token* token = input.tokens; for(;token; token = token->next) { print_tok(token); } - - - asm volatile("sti"); hang(); } diff --git a/src/print.c b/src/print.c index 17ea5a6..13dd1f4 100644 --- a/src/print.c +++ b/src/print.c @@ -14,20 +14,24 @@ static volatile u32 *fb_scr; #define TAB_STOP 4 // buffer at each edge for readability -#define TERM_WIDTH (FONT_WIDTH + 2) -#define TERM_HEIGHT (FONT_HEIGHT + 2) +#define GLYPH_WIDTH (FONT_WIDTH + 2) +#define GLYPH_HEIGHT (FONT_HEIGHT + 2) void print_init(struct limine_framebuffer *fb) { - term_width = fb->width / TERM_WIDTH; - term_height = fb->height / TERM_HEIGHT; + term_width = fb->width / GLYPH_WIDTH; + term_height = fb->height / GLYPH_HEIGHT; fb_width = fb->width; fb_height = fb->height; fb_scr = fb->address; } static void scrollback() { - memmove((void *)fb_scr, (void *)(fb_scr + fb_width * TERM_HEIGHT), - fb_width * (fb_height - TERM_HEIGHT) * sizeof(u32)); + memmove((void *)fb_scr, (void *)(fb_scr + fb_width * GLYPH_HEIGHT), + fb_width * (fb_height - GLYPH_HEIGHT) * sizeof(u32)); + size_t last_row_start = (term_height - 1) * fb_width; + for (size_t i = 0; i < fb_width; i++) { + fb_scr[last_row_start + i] = bg; + } } void put(int ch) { @@ -63,14 +67,14 @@ void put(int ch) { size_t idx = ch - ' '; u32 glyph = font[idx]; - size_t px = col * TERM_WIDTH; - size_t py = row * TERM_HEIGHT; + size_t px = col * GLYPH_WIDTH; + size_t py = row * GLYPH_HEIGHT; - for (size_t y = 0; y < TERM_HEIGHT; y++) { - for (size_t x = 0; x < TERM_WIDTH; x++) { + for (size_t y = 0; y < GLYPH_HEIGHT; y++) { + for (size_t x = 0; x < GLYPH_WIDTH; x++) { size_t off = (py + y) * fb_width + (px + x); bool padding = - (y == 0 || y == TERM_HEIGHT - 1 || x == 0 || x == TERM_WIDTH - 1); + (y == 0 || y == GLYPH_HEIGHT - 1 || x == 0 || x == GLYPH_WIDTH - 1); fb_scr[off] = ((~glyph & 1) | padding) ? bg : fg; glyph >>= !padding; } @@ -112,3 +116,20 @@ void print64(u64 n) { print32(n >> 32); print32(n & 0xFFFFFFFF); } + +void unput(void) { + if (col > 0) { + col--; + } else if (row > 0) { + row--; + col = term_width - 1; + } else { + return; /* already at (0,0), nothing to erase */ + } + + size_t px = col * GLYPH_WIDTH; + size_t py = row * GLYPH_HEIGHT; + for (size_t y = 0; y < GLYPH_HEIGHT; y++) + for (size_t x = 0; x < GLYPH_WIDTH; x++) + fb_scr[(py + y) * fb_width + (px + x)] = bg; +} \ No newline at end of file diff --git a/src/print.h b/src/print.h index 7d4a6d4..e8da0c6 100644 --- a/src/print.h +++ b/src/print.h @@ -13,3 +13,4 @@ void print32(u32 n); void print16(u16 n); void print8(u8 n); void print_init(struct limine_framebuffer *fb); +void unput(void); diff --git a/src/prompt/lex.c b/src/prompt/lex.c index f10abfa..d897c0c 100644 --- a/src/prompt/lex.c +++ b/src/prompt/lex.c @@ -6,8 +6,11 @@ static int lex_error(struct file* state, const char* err) { print(state->name); + print("["); print16(state->row+1); + print(":"); print16(state->col+1); + print("] "); print(err); print("\n"); return 1; @@ -74,14 +77,12 @@ static struct token* tok(enum tokentype type, struct file* state, int col, void* return ret; } + + static bool isdigit(int ch) { return (ch <= '9' && ch >= '0'); } -static bool isxdigit(int ch) { - return ((ch <= '9' && ch >= '0') || (ch <= 'F' && ch >= 'A') || (ch <= 'F' && ch >= 'A')); -} - static bool isalpha(int ch) { return (ch <= 'z' && ch >= 'a') || (ch <= 'Z' && ch >= 'A'); @@ -103,6 +104,10 @@ static int tolower(int ch) { return ch; } +static bool isxdigit(int ch) { + return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f'); +} + // cribbed from musl static bool isspace(int ch) { return ch == ' ' || (unsigned)ch-'\t' < 5; @@ -113,7 +118,10 @@ static int parse_num(struct file* state, int save, int sign) { int ch = state->lines[state->row][state->col]; if(ch == '0' && state->lines[state->row][state->col+1] == 'x') { state->col+=2; - if(!isdigit(state->lines[state->row][state->col])) { + if(!isxdigit(state->lines[state->row][state->col])) { + print("On input: '"); + printn(&state->lines[state->row][state->col], 1); + print("'\n"); lex_error(state, "expected hexadecimal digits in hex literal"); return 1; } @@ -155,7 +163,7 @@ int lex(struct file* state) { if(state->row >= state->rows) return 0; while(isspace(state->lines[state->row][state->col])) { - if(state->lines[state->row][state->col] == '\n') { + if(state->lines[state->row][state->col] == '\n' || !state->lines[state->row][state->col]) { state->col = 0; state->row++; if(state->row >= state->rows) @@ -168,7 +176,7 @@ int lex(struct file* state) { if(state->lines[state->row][state->col] == '/' && state->lines[state->row][state->col+1] == '*') { state->col += 2; while(!(state->lines[state->row][state->col] == '*' && state->lines[state->row][state->col+1] == '/')) { - if(state->lines[state->row][state->col] == '\n') { + if(state->lines[state->row][state->col] == '\n' || !state->lines[state->row][state->col]) { state->col = -1; state->row++; if(state->row >= state->rows) @@ -177,7 +185,7 @@ int lex(struct file* state) { state->col++; } state->col += 2; - if(state->lines[state->row][state->col] == '\n') { + if(state->lines[state->row][state->col] == '\n' || !state->lines[state->row][state->col]) { state->row++; state->col = 0; } @@ -240,7 +248,7 @@ int lex(struct file* state) { print8(ch); print(") '"); printn(&ch,1); - print("\n"); + print("'\n"); state->col++; return 1 + lex(state); } diff --git a/src/prompt/print.c b/src/prompt/print.c index ef4bf1e..b3aea6c 100644 --- a/src/prompt/print.c +++ b/src/prompt/print.c @@ -14,6 +14,7 @@ static size_t strlen(const char* str) { extern u32 fg, bg; void print_tok(struct token* tok) { + u32 savebg = bg, savefg = fg; /* header: [file:row:col] */ print("["); print(tok->file->name); @@ -29,24 +30,28 @@ void print_tok(struct token* tok) { } print("] "); + u32 color = fg; switch (tok->type) { case TOK_KEYWORD: + color = 0xFF3322; print("keyword: "); print(keywords[tok->keyword]); print("\n"); break; case TOK_NUM: + color = 0x3322FF; print("number: "); print(" ("); print64((unsigned long)tok->num); print("):\n"); break; case TOK_IDEN: { + color = 0x137FFF; struct iden* id = &identbl[tok->iden]; print("iden: { .hash = 0x"); print32(id->hash); print(", .data = \""); - print(*id->data); + print(id->data); print("\" ("); /* print pointer value as hex */ print("ptr"); /* pointer printing omitted; add if needed */ @@ -56,6 +61,7 @@ void print_tok(struct token* tok) { break; } case TOK_OP: { + color = 0xBEDEAD; print("operator: "); print(ops[tok->op]); print(" (#"); @@ -64,6 +70,7 @@ void print_tok(struct token* tok) { break; } default: { + color = 0x00FF00; /* print single char and hex */ char c[2] = { (char)tok->type, 0 }; print(c); @@ -108,13 +115,15 @@ void print_tok(struct token* tok) { printn(tok->file->lines[tok->row], tok->col); /* print token text */ + fg = color; if (tok->len > 0) printn(tok->file->lines[tok->row] + tok->col, tok->len); + fg = savefg; + bg = savebg; /* print rest of line after token */ printn(tok->file->lines[tok->row] + tok->col + tok->len, strlen(tok->file->lines[tok->row] + tok->col + tok->len)); - print("\n"); /* caret line */ print("\t | "); @@ -125,7 +134,7 @@ void print_tok(struct token* tok) { print(" "); } } - u32 savebg = bg, savefg = fg; + fg = bg; bg = ~fg; print("^");