added stdio functionality
This commit is contained in:
parent
990391144c
commit
78f56d916c
2
limine
2
limine
@ -1 +1 @@
|
|||||||
Subproject commit e0e61c946933696453f591da525ab1f8a66a553d
|
Subproject commit eecf8d682a749701691e31b89f66f330f525c611
|
||||||
BIN
obj/src/int.c.o
BIN
obj/src/int.c.o
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
obj/src/main.c.o: src/main.c src/../include/limine.h src/prompt/lex.h \
|
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/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/../include/limine.h:
|
||||||
src/prompt/lex.h:
|
src/prompt/lex.h:
|
||||||
src/prompt/file.h:
|
src/prompt/file.h:
|
||||||
@ -8,5 +9,11 @@ src/acpi.h:
|
|||||||
src/common.h:
|
src/common.h:
|
||||||
src/alloc.h:
|
src/alloc.h:
|
||||||
src/apic.h:
|
src/apic.h:
|
||||||
|
src/kbd.h:
|
||||||
src/map.h:
|
src/map.h:
|
||||||
src/print.h:
|
src/print.h:
|
||||||
|
src/lib/stdio.h:
|
||||||
|
src/lib/malloc.h:
|
||||||
|
src/lib/../common.h:
|
||||||
|
src/lib/../kbd.h:
|
||||||
|
src/lib/../print.h:
|
||||||
|
|||||||
BIN
obj/src/main.c.o
BIN
obj/src/main.c.o
Binary file not shown.
2
run.sh
2
run.sh
@ -1 +1 @@
|
|||||||
qemu-system-x86_64 image.hdd
|
/mnt/c/'Program Files'/qemu/qemu-system-x86_64.exe image.hdd
|
||||||
|
|||||||
29
src/alloc.c
29
src/alloc.c
@ -3,6 +3,19 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "print.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__((
|
__attribute__((
|
||||||
used,
|
used,
|
||||||
section(".limine_requests"))) static volatile struct limine_memmap_request
|
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) {
|
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);
|
usepage(i + page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,7 +131,7 @@ static void unusepage(size_t page) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void unusepagerange(size_t page, size_t len) {
|
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);
|
unusepage(i + page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,9 +157,10 @@ void *alloc(size_t size) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Attempting to find ");
|
|
||||||
print64(pages);
|
dprint("Attempting to find ");
|
||||||
print(" consecutive pages\n");
|
dprint64(pages);
|
||||||
|
dprint(" consecutive pages.....");
|
||||||
size_t consecutive = 0;
|
size_t consecutive = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < total_pages / 64; i++) {
|
for (size_t i = 0; i < total_pages / 64; i++) {
|
||||||
@ -157,6 +171,7 @@ void *alloc(size_t size) {
|
|||||||
consecutive += 64;
|
consecutive += 64;
|
||||||
if (consecutive >= pages) {
|
if (consecutive >= pages) {
|
||||||
usepagerange(page, pages);
|
usepagerange(page, pages);
|
||||||
|
dprint("succeeded!\n");
|
||||||
return addr(page);
|
return addr(page);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -174,6 +189,7 @@ void *alloc(size_t size) {
|
|||||||
|
|
||||||
if (++consecutive >= pages) {
|
if (++consecutive >= pages) {
|
||||||
usepagerange(page, pages);
|
usepagerange(page, pages);
|
||||||
|
dprint("succeeded!\n");
|
||||||
return addr(page);
|
return addr(page);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -183,5 +199,8 @@ void *alloc(size_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprint("failed :(!\n");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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) {
|
static inline void *phys_to_virt(u64 phys) {
|
||||||
return (void *)(phys + hhdm_offset);
|
return (void *)(phys + hhdm_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
src/kbd.c
37
src/kbd.c
@ -72,6 +72,25 @@ char kbd_buffer_getc() {
|
|||||||
return c;
|
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() {
|
void kbd_handler() {
|
||||||
u8 scancode = inb(PS2_DATA_PORT);
|
u8 scancode = inb(PS2_DATA_PORT);
|
||||||
bool released = (scancode & 0x80);
|
bool released = (scancode & 0x80);
|
||||||
@ -91,6 +110,7 @@ void kbd_handler() {
|
|||||||
if(!released) {
|
if(!released) {
|
||||||
kbd_state.caps = !kbd_state.caps;
|
kbd_state.caps = !kbd_state.caps;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -106,18 +126,29 @@ void kbd_handler() {
|
|||||||
|
|
||||||
|
|
||||||
if(kbd_state.caps && c >= 'a' && c <= 'z') {
|
if(kbd_state.caps && c >= 'a' && c <= 'z') {
|
||||||
|
c = c - 'a' + 'A';
|
||||||
} else if(kbd_state.caps && c >= 'A' && c <= 'Z') {
|
} else if(kbd_state.caps && c >= 'A' && c <= 'Z') {
|
||||||
c = c - 'A' + 'a';
|
c = c - 'A' + 'a';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c != 0) {
|
if(c != 0 && !key_held(scancode)) {
|
||||||
kbd_buffer_putc(c);
|
kbd_buffer_putc(c);
|
||||||
}
|
}
|
||||||
printn(&c, 1);
|
|
||||||
|
hold_key(scancode);
|
||||||
|
} else {
|
||||||
|
release_key(scancode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
send_eoi();
|
send_eoi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kbd_getc_blocking() {
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
while(!(ch =kbd_buffer_getc()))
|
||||||
|
;
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
@ -1,2 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
void kbd_handler();
|
void kbd_handler();
|
||||||
|
int kbd_getc_blocking();
|
||||||
|
char kbd_buffer_getc();
|
||||||
33
src/lib/malloc.c
Normal file
33
src/lib/malloc.c
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
5
src/lib/malloc.h
Normal file
5
src/lib/malloc.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void* malloc(size_t sz);
|
||||||
|
void* calloc(size_t sz, size_t n);
|
||||||
|
void* free(void* ptr);
|
||||||
475
src/lib/stdio.h
Normal file
475
src/lib/stdio.h
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#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<end){*cur++=(char)(c);} written++; } while(0)
|
||||||
|
|
||||||
|
while (*fmt) {
|
||||||
|
if (*fmt != '%') { _SEMIT(*fmt++); continue; }
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
bool left_align=false, zero_pad=false;
|
||||||
|
if (*fmt=='-'){left_align=true;fmt++;}
|
||||||
|
if (*fmt=='0'){zero_pad=true;fmt++;}
|
||||||
|
int width=0;
|
||||||
|
while(*fmt>='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;
|
||||||
|
}
|
||||||
48
src/main.c
48
src/main.c
@ -12,8 +12,10 @@ void print_tok(struct token* tok);
|
|||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "kbd.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
#include "lib/stdio.h"
|
||||||
|
|
||||||
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup
|
// credit owed to https://wiki.osdev.org/Limine_Bare_Bones for the limine setup
|
||||||
// code
|
// code
|
||||||
@ -110,7 +112,8 @@ void draw(u8 vect) {
|
|||||||
for (size_t y = 0; y < fb->height; y++) {
|
for (size_t y = 0; y < fb->height; y++) {
|
||||||
for (size_t x = 0; x < fb->width; x++) {
|
for (size_t x = 0; x < fb->width; x++) {
|
||||||
volatile u32 *fb_ptr = fb->address;
|
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);
|
draw(1);
|
||||||
print_init(fb);
|
print_init(fb);
|
||||||
init_idt();
|
init_idt();
|
||||||
bg = 0xFFFFFF;
|
fg = 0xFFFFFF;
|
||||||
fg = 0x000000;
|
bg = 0x000000;
|
||||||
|
|
||||||
if (!hhdm_req.response) {
|
if (!hhdm_req.response) {
|
||||||
print("Failed to get higher half direct mapping\n.");
|
print("Failed to get higher half direct mapping\n.");
|
||||||
@ -197,19 +200,30 @@ void kmain() {
|
|||||||
apic_enable();
|
apic_enable();
|
||||||
print("APIC Enabled\n");
|
print("APIC Enabled\n");
|
||||||
ioapic_init();
|
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 = {
|
struct file input = {
|
||||||
.row = 0,
|
.row = 0,
|
||||||
.col = 0,
|
.col = 0,
|
||||||
.rows = 4,
|
.rows = n_lines,
|
||||||
.lines = (char**)src,
|
.lines = (char**)lines,
|
||||||
.name = name,
|
.name = name,
|
||||||
.tokens = NULL,
|
.tokens = NULL,
|
||||||
.tail = &input.tokens,
|
.tail = &input.tokens,
|
||||||
@ -217,21 +231,15 @@ void kmain() {
|
|||||||
|
|
||||||
int res = lex(&input);
|
int res = lex(&input);
|
||||||
|
|
||||||
print("Result from lexing: ");
|
print("Number of Errors: ");
|
||||||
print8(res);
|
print8(res);
|
||||||
|
|
||||||
if(res != 0) {
|
printf("\n# of Tokens: %d\n", input.tokens->len);
|
||||||
hang();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct token* token = input.tokens;
|
struct token* token = input.tokens;
|
||||||
|
|
||||||
for(;token; token = token->next) {
|
for(;token; token = token->next) {
|
||||||
print_tok(token);
|
print_tok(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
asm volatile("sti");
|
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/print.c
43
src/print.c
@ -14,20 +14,24 @@ static volatile u32 *fb_scr;
|
|||||||
#define TAB_STOP 4
|
#define TAB_STOP 4
|
||||||
|
|
||||||
// buffer at each edge for readability
|
// buffer at each edge for readability
|
||||||
#define TERM_WIDTH (FONT_WIDTH + 2)
|
#define GLYPH_WIDTH (FONT_WIDTH + 2)
|
||||||
#define TERM_HEIGHT (FONT_HEIGHT + 2)
|
#define GLYPH_HEIGHT (FONT_HEIGHT + 2)
|
||||||
|
|
||||||
void print_init(struct limine_framebuffer *fb) {
|
void print_init(struct limine_framebuffer *fb) {
|
||||||
term_width = fb->width / TERM_WIDTH;
|
term_width = fb->width / GLYPH_WIDTH;
|
||||||
term_height = fb->height / TERM_HEIGHT;
|
term_height = fb->height / GLYPH_HEIGHT;
|
||||||
fb_width = fb->width;
|
fb_width = fb->width;
|
||||||
fb_height = fb->height;
|
fb_height = fb->height;
|
||||||
fb_scr = fb->address;
|
fb_scr = fb->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scrollback() {
|
static void scrollback() {
|
||||||
memmove((void *)fb_scr, (void *)(fb_scr + fb_width * TERM_HEIGHT),
|
memmove((void *)fb_scr, (void *)(fb_scr + fb_width * GLYPH_HEIGHT),
|
||||||
fb_width * (fb_height - TERM_HEIGHT) * sizeof(u32));
|
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) {
|
void put(int ch) {
|
||||||
@ -63,14 +67,14 @@ void put(int ch) {
|
|||||||
size_t idx = ch - ' ';
|
size_t idx = ch - ' ';
|
||||||
u32 glyph = font[idx];
|
u32 glyph = font[idx];
|
||||||
|
|
||||||
size_t px = col * TERM_WIDTH;
|
size_t px = col * GLYPH_WIDTH;
|
||||||
size_t py = row * TERM_HEIGHT;
|
size_t py = row * GLYPH_HEIGHT;
|
||||||
|
|
||||||
for (size_t y = 0; y < TERM_HEIGHT; y++) {
|
for (size_t y = 0; y < GLYPH_HEIGHT; y++) {
|
||||||
for (size_t x = 0; x < TERM_WIDTH; x++) {
|
for (size_t x = 0; x < GLYPH_WIDTH; x++) {
|
||||||
size_t off = (py + y) * fb_width + (px + x);
|
size_t off = (py + y) * fb_width + (px + x);
|
||||||
bool padding =
|
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;
|
fb_scr[off] = ((~glyph & 1) | padding) ? bg : fg;
|
||||||
glyph >>= !padding;
|
glyph >>= !padding;
|
||||||
}
|
}
|
||||||
@ -112,3 +116,20 @@ void print64(u64 n) {
|
|||||||
print32(n >> 32);
|
print32(n >> 32);
|
||||||
print32(n & 0xFFFFFFFF);
|
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;
|
||||||
|
}
|
||||||
@ -13,3 +13,4 @@ void print32(u32 n);
|
|||||||
void print16(u16 n);
|
void print16(u16 n);
|
||||||
void print8(u8 n);
|
void print8(u8 n);
|
||||||
void print_init(struct limine_framebuffer *fb);
|
void print_init(struct limine_framebuffer *fb);
|
||||||
|
void unput(void);
|
||||||
|
|||||||
@ -6,8 +6,11 @@
|
|||||||
|
|
||||||
static int lex_error(struct file* state, const char* err) {
|
static int lex_error(struct file* state, const char* err) {
|
||||||
print(state->name);
|
print(state->name);
|
||||||
|
print("[");
|
||||||
print16(state->row+1);
|
print16(state->row+1);
|
||||||
|
print(":");
|
||||||
print16(state->col+1);
|
print16(state->col+1);
|
||||||
|
print("] ");
|
||||||
print(err);
|
print(err);
|
||||||
print("\n");
|
print("\n");
|
||||||
return 1;
|
return 1;
|
||||||
@ -74,14 +77,12 @@ static struct token* tok(enum tokentype type, struct file* state, int col, void*
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool isdigit(int ch) {
|
static bool isdigit(int ch) {
|
||||||
return (ch <= '9' && ch >= '0');
|
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) {
|
static bool isalpha(int ch) {
|
||||||
return (ch <= 'z' && ch >= 'a')
|
return (ch <= 'z' && ch >= 'a')
|
||||||
|| (ch <= 'Z' && ch >= 'A');
|
|| (ch <= 'Z' && ch >= 'A');
|
||||||
@ -103,6 +104,10 @@ static int tolower(int ch) {
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isxdigit(int ch) {
|
||||||
|
return isdigit(ch) || (isalpha(ch) && tolower(ch) <= 'f');
|
||||||
|
}
|
||||||
|
|
||||||
// cribbed from musl
|
// cribbed from musl
|
||||||
static bool isspace(int ch) {
|
static bool isspace(int ch) {
|
||||||
return ch == ' ' || (unsigned)ch-'\t' < 5;
|
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];
|
int ch = state->lines[state->row][state->col];
|
||||||
if(ch == '0' && state->lines[state->row][state->col+1] == 'x') {
|
if(ch == '0' && state->lines[state->row][state->col+1] == 'x') {
|
||||||
state->col+=2;
|
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");
|
lex_error(state, "expected hexadecimal digits in hex literal");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -155,7 +163,7 @@ int lex(struct file* state) {
|
|||||||
if(state->row >= state->rows)
|
if(state->row >= state->rows)
|
||||||
return 0;
|
return 0;
|
||||||
while(isspace(state->lines[state->row][state->col])) {
|
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->col = 0;
|
||||||
state->row++;
|
state->row++;
|
||||||
if(state->row >= state->rows)
|
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] == '*') {
|
if(state->lines[state->row][state->col] == '/' && state->lines[state->row][state->col+1] == '*') {
|
||||||
state->col += 2;
|
state->col += 2;
|
||||||
while(!(state->lines[state->row][state->col] == '*' && state->lines[state->row][state->col+1] == '/')) {
|
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->col = -1;
|
||||||
state->row++;
|
state->row++;
|
||||||
if(state->row >= state->rows)
|
if(state->row >= state->rows)
|
||||||
@ -177,7 +185,7 @@ int lex(struct file* state) {
|
|||||||
state->col++;
|
state->col++;
|
||||||
}
|
}
|
||||||
state->col += 2;
|
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->row++;
|
||||||
state->col = 0;
|
state->col = 0;
|
||||||
}
|
}
|
||||||
@ -240,7 +248,7 @@ int lex(struct file* state) {
|
|||||||
print8(ch);
|
print8(ch);
|
||||||
print(") '");
|
print(") '");
|
||||||
printn(&ch,1);
|
printn(&ch,1);
|
||||||
print("\n");
|
print("'\n");
|
||||||
state->col++;
|
state->col++;
|
||||||
return 1 + lex(state);
|
return 1 + lex(state);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ static size_t strlen(const char* str) {
|
|||||||
extern u32 fg, bg;
|
extern u32 fg, bg;
|
||||||
|
|
||||||
void print_tok(struct token* tok) {
|
void print_tok(struct token* tok) {
|
||||||
|
u32 savebg = bg, savefg = fg;
|
||||||
/* header: [file:row:col] */
|
/* header: [file:row:col] */
|
||||||
print("[");
|
print("[");
|
||||||
print(tok->file->name);
|
print(tok->file->name);
|
||||||
@ -29,24 +30,28 @@ void print_tok(struct token* tok) {
|
|||||||
}
|
}
|
||||||
print("] ");
|
print("] ");
|
||||||
|
|
||||||
|
u32 color = fg;
|
||||||
switch (tok->type) {
|
switch (tok->type) {
|
||||||
case TOK_KEYWORD:
|
case TOK_KEYWORD:
|
||||||
|
color = 0xFF3322;
|
||||||
print("keyword: ");
|
print("keyword: ");
|
||||||
print(keywords[tok->keyword]);
|
print(keywords[tok->keyword]);
|
||||||
print("\n");
|
print("\n");
|
||||||
break;
|
break;
|
||||||
case TOK_NUM:
|
case TOK_NUM:
|
||||||
|
color = 0x3322FF;
|
||||||
print("number: ");
|
print("number: ");
|
||||||
print(" (");
|
print(" (");
|
||||||
print64((unsigned long)tok->num);
|
print64((unsigned long)tok->num);
|
||||||
print("):\n");
|
print("):\n");
|
||||||
break;
|
break;
|
||||||
case TOK_IDEN: {
|
case TOK_IDEN: {
|
||||||
|
color = 0x137FFF;
|
||||||
struct iden* id = &identbl[tok->iden];
|
struct iden* id = &identbl[tok->iden];
|
||||||
print("iden: { .hash = 0x");
|
print("iden: { .hash = 0x");
|
||||||
print32(id->hash);
|
print32(id->hash);
|
||||||
print(", .data = \"");
|
print(", .data = \"");
|
||||||
print(*id->data);
|
print(id->data);
|
||||||
print("\" (");
|
print("\" (");
|
||||||
/* print pointer value as hex */
|
/* print pointer value as hex */
|
||||||
print("ptr"); /* pointer printing omitted; add if needed */
|
print("ptr"); /* pointer printing omitted; add if needed */
|
||||||
@ -56,6 +61,7 @@ void print_tok(struct token* tok) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOK_OP: {
|
case TOK_OP: {
|
||||||
|
color = 0xBEDEAD;
|
||||||
print("operator: ");
|
print("operator: ");
|
||||||
print(ops[tok->op]);
|
print(ops[tok->op]);
|
||||||
print(" (#");
|
print(" (#");
|
||||||
@ -64,6 +70,7 @@ void print_tok(struct token* tok) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
color = 0x00FF00;
|
||||||
/* print single char and hex */
|
/* print single char and hex */
|
||||||
char c[2] = { (char)tok->type, 0 };
|
char c[2] = { (char)tok->type, 0 };
|
||||||
print(c);
|
print(c);
|
||||||
@ -108,13 +115,15 @@ void print_tok(struct token* tok) {
|
|||||||
printn(tok->file->lines[tok->row], tok->col);
|
printn(tok->file->lines[tok->row], tok->col);
|
||||||
|
|
||||||
/* print token text */
|
/* print token text */
|
||||||
|
fg = color;
|
||||||
if (tok->len > 0)
|
if (tok->len > 0)
|
||||||
printn(tok->file->lines[tok->row] + tok->col, tok->len);
|
printn(tok->file->lines[tok->row] + tok->col, tok->len);
|
||||||
|
fg = savefg;
|
||||||
|
bg = savebg;
|
||||||
|
|
||||||
/* print rest of line after token */
|
/* print rest of line after token */
|
||||||
printn(tok->file->lines[tok->row] + tok->col + tok->len,
|
printn(tok->file->lines[tok->row] + tok->col + tok->len,
|
||||||
strlen(tok->file->lines[tok->row] + tok->col + tok->len));
|
strlen(tok->file->lines[tok->row] + tok->col + tok->len));
|
||||||
print("\n");
|
|
||||||
|
|
||||||
/* caret line */
|
/* caret line */
|
||||||
print("\t | ");
|
print("\t | ");
|
||||||
@ -125,7 +134,7 @@ void print_tok(struct token* tok) {
|
|||||||
print(" ");
|
print(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u32 savebg = bg, savefg = fg;
|
|
||||||
fg = bg;
|
fg = bg;
|
||||||
bg = ~fg;
|
bg = ~fg;
|
||||||
print("^");
|
print("^");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user