feat: Symmetric Multiprocessing, text editor improvements, merge doom libc, implement math functions
This commit is contained in:
@@ -1076,8 +1076,8 @@ static void filemanager_open_entry(FileManagerState* fm, int idx) {
|
||||
montauk::spawn("0:/apps/music/music.elf", fullpath);
|
||||
} else if (str_ends_with(fm->entry_names[idx], ".elf")) {
|
||||
montauk::spawn(fullpath);
|
||||
} else if (fm->desktop) {
|
||||
open_texteditor_with_file(fm->desktop, fullpath);
|
||||
} else {
|
||||
montauk::spawn("0:/apps/texteditor/texteditor.elf", fullpath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@ endif
|
||||
DOOM_SRC := ../../../doomgeneric/doomgeneric
|
||||
LIBC_INC := ../../include/libc
|
||||
PROG_INC := ../../include
|
||||
LIBDIR := ../../lib
|
||||
LINK_LD := ../../link.ld
|
||||
BINDIR := ../../bin
|
||||
OBJDIR := obj
|
||||
@@ -153,7 +154,7 @@ DOOM_SRCS := \
|
||||
z_zone.c
|
||||
|
||||
# Local source files
|
||||
LOCAL_SRCS := doomgeneric_montauk.c libc.c
|
||||
LOCAL_SRCS := doomgeneric_montauk.c
|
||||
|
||||
# ---- Object files ----
|
||||
|
||||
@@ -171,7 +172,7 @@ all: $(TARGET)
|
||||
|
||||
$(TARGET): $(ALL_OBJS) $(LINK_LD) Makefile
|
||||
mkdir -p $(BINDIR)/apps/doom
|
||||
$(LD) $(CFLAGS) $(LDFLAGS) $(ALL_OBJS) -o $@
|
||||
$(LD) $(CFLAGS) $(LDFLAGS) $(ALL_OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||
|
||||
# DOOM source files (from doomgeneric directory)
|
||||
$(OBJDIR)/%.o: $(DOOM_SRC)/%.c Makefile
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
# Makefile for texteditor (standalone Window Server app) on MontaukOS
|
||||
# Copyright (c) 2026 Daniel Hammer
|
||||
|
||||
MAKEFLAGS += -rR
|
||||
.SUFFIXES:
|
||||
|
||||
# ---- Toolchain ----
|
||||
|
||||
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||
else
|
||||
CXX := g++
|
||||
endif
|
||||
|
||||
# ---- Paths ----
|
||||
|
||||
PROG_INC := ../../include
|
||||
LINK_LD := ../../link.ld
|
||||
BINDIR := ../../bin
|
||||
OBJDIR := obj
|
||||
LIBDIR := ../../lib
|
||||
|
||||
# ---- Compiler flags ----
|
||||
|
||||
CXXFLAGS := \
|
||||
-std=gnu++20 \
|
||||
-g -O2 -pipe \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-function \
|
||||
-nostdinc \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
-fno-PIC \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-m64 \
|
||||
-march=x86-64 \
|
||||
-msse \
|
||||
-msse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=small \
|
||||
-I $(PROG_INC) \
|
||||
-isystem $(PROG_INC)/libc \
|
||||
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||
|
||||
# ---- Linker flags ----
|
||||
|
||||
LDFLAGS := \
|
||||
-nostdlib \
|
||||
-static \
|
||||
-Wl,--build-id=none \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,-m,elf_x86_64 \
|
||||
-z max-page-size=0x1000 \
|
||||
-T $(LINK_LD)
|
||||
|
||||
# ---- Source files ----
|
||||
|
||||
SRCS := main.cpp stb_truetype_impl.cpp
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||
|
||||
# ---- Target ----
|
||||
|
||||
TARGET := $(BINDIR)/apps/texteditor/texteditor.elf
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
||||
mkdir -p $(BINDIR)/apps/texteditor
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBDIR)/libc/liblibc.a -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp Makefile
|
||||
mkdir -p $(OBJDIR)
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(TARGET)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* stb_truetype_impl.cpp
|
||||
* Single compilation unit for stb_truetype in MontaukOS freestanding environment
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <montauk/heap.h>
|
||||
#include <montauk/string.h>
|
||||
#include <gui/stb_math.h>
|
||||
|
||||
// Override all stb_truetype dependencies before including the implementation
|
||||
|
||||
#define STBTT_ifloor(x) ((int) stb_floor(x))
|
||||
#define STBTT_iceil(x) ((int) stb_ceil(x))
|
||||
#define STBTT_sqrt(x) stb_sqrt(x)
|
||||
#define STBTT_pow(x,y) stb_pow(x,y)
|
||||
#define STBTT_fmod(x,y) stb_fmod(x,y)
|
||||
#define STBTT_cos(x) stb_cos(x)
|
||||
#define STBTT_acos(x) stb_acos(x)
|
||||
#define STBTT_fabs(x) stb_fabs(x)
|
||||
|
||||
#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x))
|
||||
#define STBTT_free(x,u) ((void)(u), montauk::mfree(x))
|
||||
|
||||
#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n)
|
||||
#define STBTT_memset(d,v,n) montauk::memset(d,v,n)
|
||||
|
||||
#define STBTT_strlen(x) montauk::slen(x)
|
||||
|
||||
#define STBTT_assert(x) ((void)(x))
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <gui/stb_truetype.h>
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* syntax_highlight.hpp
|
||||
* C syntax highlighting for the MontaukOS text editor
|
||||
* Activated for .c and .h files
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gui/gui.hpp>
|
||||
|
||||
using namespace gui;
|
||||
|
||||
// ============================================================================
|
||||
// Token types
|
||||
// ============================================================================
|
||||
|
||||
enum SynToken : uint8_t {
|
||||
SYN_NORMAL,
|
||||
SYN_KEYWORD,
|
||||
SYN_TYPE,
|
||||
SYN_PREPROCESSOR,
|
||||
SYN_STRING,
|
||||
SYN_CHAR,
|
||||
SYN_COMMENT,
|
||||
SYN_NUMBER,
|
||||
SYN_OPERATOR,
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Colors for each token type
|
||||
// ============================================================================
|
||||
|
||||
inline Color syn_color(SynToken tok) {
|
||||
switch (tok) {
|
||||
case SYN_KEYWORD: return Color::from_rgb(0xC5, 0x62, 0x8C); // magenta-pink
|
||||
case SYN_TYPE: return Color::from_rgb(0x2E, 0x86, 0xAB); // teal
|
||||
case SYN_PREPROCESSOR: return Color::from_rgb(0x8B, 0x6E, 0xB5); // purple
|
||||
case SYN_STRING: return Color::from_rgb(0x6A, 0x9F, 0x3A); // green
|
||||
case SYN_CHAR: return Color::from_rgb(0x6A, 0x9F, 0x3A); // green
|
||||
case SYN_COMMENT: return Color::from_rgb(0x7A, 0x7A, 0x7A); // gray
|
||||
case SYN_NUMBER: return Color::from_rgb(0xC9, 0x7E, 0x2A); // orange
|
||||
case SYN_OPERATOR: return Color::from_rgb(0x40, 0x40, 0x40); // dark gray
|
||||
default: return Color::from_rgb(0x1E, 0x1E, 0x1E); // near-black
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Keyword / type lookup
|
||||
// ============================================================================
|
||||
|
||||
inline bool syn_is_alpha(char c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||
}
|
||||
|
||||
inline bool syn_is_alnum(char c) {
|
||||
return syn_is_alpha(c) || (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline bool syn_is_digit(char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
inline bool syn_is_hex(char c) {
|
||||
return syn_is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
inline bool syn_streq(const char* buf, int len, const char* kw) {
|
||||
int i = 0;
|
||||
while (i < len && kw[i]) {
|
||||
if (buf[i] != kw[i]) return false;
|
||||
i++;
|
||||
}
|
||||
return i == len && kw[i] == '\0';
|
||||
}
|
||||
|
||||
inline SynToken syn_classify_word(const char* buf, int len) {
|
||||
// C keywords
|
||||
static const char* keywords[] = {
|
||||
"auto", "break", "case", "const", "continue", "default", "do",
|
||||
"else", "enum", "extern", "for", "goto", "if", "inline",
|
||||
"register", "restrict", "return", "sizeof", "static", "struct",
|
||||
"switch", "typedef", "union", "volatile", "while",
|
||||
"NULL", "true", "false", "nullptr",
|
||||
};
|
||||
// C types
|
||||
static const char* types[] = {
|
||||
"void", "char", "short", "int", "long", "float", "double",
|
||||
"signed", "unsigned", "bool", "_Bool",
|
||||
"int8_t", "int16_t", "int32_t", "int64_t",
|
||||
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
|
||||
"size_t", "ssize_t", "ptrdiff_t", "intptr_t", "uintptr_t",
|
||||
"FILE",
|
||||
};
|
||||
|
||||
for (int i = 0; i < (int)(sizeof(keywords) / sizeof(keywords[0])); i++) {
|
||||
if (syn_streq(buf, len, keywords[i])) return SYN_KEYWORD;
|
||||
}
|
||||
for (int i = 0; i < (int)(sizeof(types) / sizeof(types[0])); i++) {
|
||||
if (syn_streq(buf, len, types[i])) return SYN_TYPE;
|
||||
}
|
||||
return SYN_NORMAL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Per-line highlighter
|
||||
// ============================================================================
|
||||
//
|
||||
// Fills `out[]` with SynToken values for each character in the line.
|
||||
// `in_block_comment` is the multi-line comment state carried across lines:
|
||||
// - pass in the state from the previous line
|
||||
// - on return, updated for the next line
|
||||
//
|
||||
// `line` points to the first char of the line, `len` is its length
|
||||
// (excluding the newline). `out` must have room for `len` entries.
|
||||
|
||||
inline void syn_highlight_line(const char* line, int len, SynToken* out, bool& in_block_comment) {
|
||||
int i = 0;
|
||||
|
||||
while (i < len) {
|
||||
// ---- Block comment continuation ----
|
||||
if (in_block_comment) {
|
||||
while (i < len) {
|
||||
if (i + 1 < len && line[i] == '*' && line[i + 1] == '/') {
|
||||
out[i] = SYN_COMMENT;
|
||||
out[i + 1] = SYN_COMMENT;
|
||||
i += 2;
|
||||
in_block_comment = false;
|
||||
break;
|
||||
}
|
||||
out[i] = SYN_COMMENT;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char c = line[i];
|
||||
|
||||
// ---- Line comment ----
|
||||
if (c == '/' && i + 1 < len && line[i + 1] == '/') {
|
||||
while (i < len) out[i++] = SYN_COMMENT;
|
||||
break;
|
||||
}
|
||||
|
||||
// ---- Block comment start ----
|
||||
if (c == '/' && i + 1 < len && line[i + 1] == '*') {
|
||||
in_block_comment = true;
|
||||
out[i] = SYN_COMMENT;
|
||||
out[i + 1] = SYN_COMMENT;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Preprocessor directive ----
|
||||
if (c == '#') {
|
||||
// Check that only whitespace precedes the #
|
||||
bool is_pp = true;
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (line[j] != ' ' && line[j] != '\t') { is_pp = false; break; }
|
||||
}
|
||||
if (is_pp) {
|
||||
while (i < len) {
|
||||
// Handle line-comment inside preprocessor
|
||||
if (i + 1 < len && line[i] == '/' && line[i + 1] == '/') {
|
||||
while (i < len) out[i++] = SYN_COMMENT;
|
||||
break;
|
||||
}
|
||||
// Handle block comment start inside preprocessor
|
||||
if (i + 1 < len && line[i] == '/' && line[i + 1] == '*') {
|
||||
in_block_comment = true;
|
||||
out[i] = SYN_COMMENT;
|
||||
out[i + 1] = SYN_COMMENT;
|
||||
i += 2;
|
||||
// Continue consuming as comment
|
||||
while (i < len) {
|
||||
if (i + 1 < len && line[i] == '*' && line[i + 1] == '/') {
|
||||
out[i] = SYN_COMMENT;
|
||||
out[i + 1] = SYN_COMMENT;
|
||||
i += 2;
|
||||
in_block_comment = false;
|
||||
break;
|
||||
}
|
||||
out[i] = SYN_COMMENT;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
out[i] = SYN_PREPROCESSOR;
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- String literal ----
|
||||
if (c == '"') {
|
||||
out[i++] = SYN_STRING;
|
||||
while (i < len) {
|
||||
if (line[i] == '\\' && i + 1 < len) {
|
||||
out[i] = SYN_STRING;
|
||||
out[i + 1] = SYN_STRING;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '"') {
|
||||
out[i++] = SYN_STRING;
|
||||
break;
|
||||
}
|
||||
out[i++] = SYN_STRING;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Character literal ----
|
||||
if (c == '\'') {
|
||||
out[i++] = SYN_CHAR;
|
||||
while (i < len) {
|
||||
if (line[i] == '\\' && i + 1 < len) {
|
||||
out[i] = SYN_CHAR;
|
||||
out[i + 1] = SYN_CHAR;
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (line[i] == '\'') {
|
||||
out[i++] = SYN_CHAR;
|
||||
break;
|
||||
}
|
||||
out[i++] = SYN_CHAR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Numbers ----
|
||||
if (syn_is_digit(c) || (c == '.' && i + 1 < len && syn_is_digit(line[i + 1]))) {
|
||||
// Hex
|
||||
if (c == '0' && i + 1 < len && (line[i + 1] == 'x' || line[i + 1] == 'X')) {
|
||||
out[i] = SYN_NUMBER; out[i + 1] = SYN_NUMBER;
|
||||
i += 2;
|
||||
while (i < len && syn_is_hex(line[i])) out[i++] = SYN_NUMBER;
|
||||
} else {
|
||||
// Decimal / float
|
||||
while (i < len && (syn_is_digit(line[i]) || line[i] == '.'))
|
||||
out[i++] = SYN_NUMBER;
|
||||
}
|
||||
// Suffixes: u, l, f, etc.
|
||||
while (i < len && (line[i] == 'u' || line[i] == 'U' ||
|
||||
line[i] == 'l' || line[i] == 'L' ||
|
||||
line[i] == 'f' || line[i] == 'F'))
|
||||
out[i++] = SYN_NUMBER;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Identifiers / keywords / types ----
|
||||
if (syn_is_alpha(c)) {
|
||||
int start = i;
|
||||
while (i < len && syn_is_alnum(line[i])) i++;
|
||||
SynToken tok = syn_classify_word(line + start, i - start);
|
||||
for (int j = start; j < i; j++) out[j] = tok;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Operators ----
|
||||
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '%' ||
|
||||
c == '=' || c == '!' || c == '<' || c == '>' || c == '&' ||
|
||||
c == '|' || c == '^' || c == '~' || c == '?' || c == ':') {
|
||||
out[i++] = SYN_OPERATOR;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ---- Everything else (whitespace, braces, parens, etc.) ----
|
||||
out[i++] = SYN_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Extension check
|
||||
// ============================================================================
|
||||
|
||||
inline bool syn_is_c_file(const char* filepath) {
|
||||
if (!filepath || filepath[0] == '\0') return false;
|
||||
int len = 0;
|
||||
while (filepath[len]) len++;
|
||||
if (len >= 2 && filepath[len - 2] == '.' &&
|
||||
(filepath[len - 1] == 'c' || filepath[len - 1] == 'h'))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user