From 444bfa2f41143aff7490e4fa21565947565b7d30 Mon Sep 17 00:00:00 2001 From: nasr Date: Fri, 13 Mar 2026 22:31:21 +0100 Subject: cleanup: generalisation --- .clang-format | 104 ------------ .clangd | 57 ------- base/base.c | 69 -------- base/base.h | 85 ---------- base/base_arena.c | 86 ---------- base/base_arena.h | 49 ------ build.sh | 54 +++---- build/app | Bin 0 -> 73432 bytes build/libcore.so | Bin 0 -> 69888 bytes library/arena.c | 81 ---------- library/arena.h | 69 -------- library/base.h | 42 ----- library/clang-format | 104 ------------ library/clangd | 59 ------- main | Bin 85960 -> 0 bytes main.c | 257 ------------------------------ run.sh | 8 + source/base/base.h | 77 +++++++++ source/base/base_arena.c | 142 +++++++++++++++++ source/base/base_arena.h | 41 +++++ source/base/base_hash.c | 18 +++ source/base/base_include.h | 30 ++++ source/base/base_mem.c | 17 ++ source/base/base_mem.h | 8 + source/base/base_parse.c | 98 ++++++++++++ source/base/base_parse.h | 28 ++++ source/base/base_stack.c | 187 ++++++++++++++++++++++ source/base/base_stack.h | 20 +++ source/base/base_string.c | 73 +++++++++ source/base/base_string.h | 17 ++ source/base/base_test.c | 14 ++ source/base/base_test.h | 61 +++++++ source/base/bash_hash.h | 15 ++ source/core/core.c | 126 +++++++++++++++ source/core/core.h | 5 + source/platform/platform.c | 12 ++ source/platform/platform.h | 56 +++++++ source/platform/platform_include.h | 7 + xlib-tutorial/2nd-program-anatomy.html | 282 --------------------------------- xlib-tutorial/Xlib.pdf | Bin 357941 -> 0 bytes xlib-tutorial/index.html | 116 -------------- xlib-tutorial/prog-1.cc | 29 ---- xlib-tutorial/prog-2.cc | 74 --------- xlib-tutorial/server.html | 89 ----------- 44 files changed, 1086 insertions(+), 1680 deletions(-) delete mode 100644 .clang-format delete mode 100644 .clangd delete mode 100644 base/base.c delete mode 100644 base/base.h delete mode 100644 base/base_arena.c delete mode 100644 base/base_arena.h create mode 100755 build/app create mode 100755 build/libcore.so delete mode 100644 library/arena.c delete mode 100644 library/arena.h delete mode 100644 library/base.h delete mode 100644 library/clang-format delete mode 100644 library/clangd delete mode 100755 main delete mode 100644 main.c create mode 100755 run.sh create mode 100755 source/base/base.h create mode 100755 source/base/base_arena.c create mode 100755 source/base/base_arena.h create mode 100644 source/base/base_hash.c create mode 100755 source/base/base_include.h create mode 100644 source/base/base_mem.c create mode 100644 source/base/base_mem.h create mode 100755 source/base/base_parse.c create mode 100755 source/base/base_parse.h create mode 100755 source/base/base_stack.c create mode 100755 source/base/base_stack.h create mode 100644 source/base/base_string.c create mode 100644 source/base/base_string.h create mode 100644 source/base/base_test.c create mode 100644 source/base/base_test.h create mode 100644 source/base/bash_hash.h create mode 100644 source/core/core.c create mode 100644 source/core/core.h create mode 100644 source/platform/platform.c create mode 100644 source/platform/platform.h create mode 100644 source/platform/platform_include.h delete mode 100644 xlib-tutorial/2nd-program-anatomy.html delete mode 100644 xlib-tutorial/Xlib.pdf delete mode 100644 xlib-tutorial/index.html delete mode 100644 xlib-tutorial/prog-1.cc delete mode 100644 xlib-tutorial/prog-2.cc delete mode 100644 xlib-tutorial/server.html diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 0929f7f..0000000 --- a/.clang-format +++ /dev/null @@ -1,104 +0,0 @@ -BasedOnStyle: LLVM -Language: Cpp - -# ------------------------------------------------------------------- -# Indentation & layout -# ------------------------------------------------------------------- -IndentWidth: 2 -TabWidth: 2 -UseTab: Never -ContinuationIndentWidth: 2 - -IndentCaseLabels: true -IndentGotoLabels: true -IndentPPDirectives: None -IndentExternBlock: NoIndent - -# ------------------------------------------------------------------- -# Line breaking -# ------------------------------------------------------------------- -ColumnLimit: 0 - -AllowAllParametersOfDeclarationOnNextLine: false -AllowAllArgumentsOnNextLine: false - -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false - -AlwaysBreakAfterReturnType: All -AlwaysBreakTemplateDeclarations: No # harmless for C - -BreakBeforeBinaryOperators: None - -# ------------------------------------------------------------------- -# Braces (Allman style) -# ------------------------------------------------------------------- -BreakBeforeBraces: Allman - -BraceWrapping: - AfterCaseLabel: true - BeforeElse: true - BeforeCatch: true - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true - -# NOTE: -# AfterControlStatement / AfterFunction / AfterStruct / AfterEnum / AfterUnion -# are IMPLIED by Allman and must NOT be redundantly specified. - -# ------------------------------------------------------------------- -# Spacing -# ------------------------------------------------------------------- -SpaceBeforeParens: ControlStatements -SpaceBeforeAssignmentOperators: true -SpaceBeforeRangeBasedForLoopColon: true # ignored in C, harmless - -SpacesInParentheses: false -SpacesInSquareBrackets: false -SpacesInAngles: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 - -PointerAlignment: Right -DerivePointerAlignment: false - -# ------------------------------------------------------------------- -# Alignment (explicitly disabled) -# ------------------------------------------------------------------- -AlignAfterOpenBracket: DontAlign -AlignOperands: false -AlignTrailingComments: false -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: DontAlign - -# ------------------------------------------------------------------- -# Comments -# ------------------------------------------------------------------- -ReflowComments: Never -CommentPragmas: '^ dont touch:' -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 - -# ------------------------------------------------------------------- -# Includes -# ------------------------------------------------------------------- -SortIncludes: Never -IncludeBlocks: Preserve - -# ------------------------------------------------------------------- -# Macros & preprocessor -# ------------------------------------------------------------------- -MacroBlockBegin: '' -MacroBlockEnd: '' -SpaceAfterCStyleCast: false - -# ------------------------------------------------------------------- -# C-specific -# ------------------------------------------------------------------- -Cpp11BracedListStyle: false -DisableFormat: false diff --git a/.clangd b/.clangd deleted file mode 100644 index 759ad19..0000000 --- a/.clangd +++ /dev/null @@ -1,57 +0,0 @@ -CompileFlags: - # Add: - # - -std=c99 - # - -xc - # - # - -Iinclude - # - -Wall - # - -Wextra - # - -Wpedantic - # - -Wshadow - # - -Wconversion - # - -Wsign-conversion - # - -Wmissing-declarations - # - -Wundef - # - -Wpointer-arith - # - -Wcast-align - # - -Wcast-qual - # - -Wwrite-strings - # - -Wswitch-enum - # - -Wformat=2 - # - -Wstrict-aliasing=2 - # - -Werror=implicit-function-declaration - # - -Werror=implicit-int - # - -Werror=incompatible-pointer-types - # - -Werror=return-type - # - -Wformat-security - # - -Wnull-dereference - # - -Wmisleading-indentation - # - # - -Wuninitialized - # - -Werror - # - -Wdouble-promotion - # - -Wstrict-overflow=2 - # - # - -D_POSIX_C_SOURCE=200809L - # - "-I/include" - - Remove: - - -std=* - - -O* - - -march=* - - -mtune=* - - -Hover: - ShowAKA: true - -InlayHints: - Enabled: true - ParameterNames: true - DeducedTypes: true - -Completion: - AllScopes: true - -Index: - Background: Build diff --git a/base/base.c b/base/base.c deleted file mode 100644 index ba8ba32..0000000 --- a/base/base.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "base/base.h" -#include "stddef.h" - -/** - * Helper function to parse strings to int using ascii codes - * */ -local_internal u64 -parse_u64(char *buf, size_t len) -{ - u64 value = 0; - - for ( - size_t buffer_idx = 0; - buffer_idx < len; - ++buffer_idx) - { - char c = buf[buffer_idx]; - if (c < '0' || c > '9') - { - break; - } - value = value * 10 + (c - '0'); - } - - return value; -} - -/* - * is_numeric - Check if a string contains only digits - * @s: String to check - * - * Return: 1 if string contains only numeric characters, 0 otherwise - */ -local_internal b8 -is_numeric(char *s) -{ - for (; *s; ++s) - { - if (*s < '0' || *s > '9') - { - return 0; - } - } - return 1; -} - -local_internal b8 -compare_string(const char *c1, const char *c2) -{ - if (sizeof(c1) != sizeof(c2)) - { - return -1; - } - - for ( - u64 word_idx = 0; - word_idx <= sizeof(*c1); - ++word_idx) - { - if (*c1 != *c2) - { - return -1; - } - ++c1; - ++c2; - } - - return 0; -} diff --git a/base/base.h b/base/base.h deleted file mode 100644 index 8ce6cba..0000000 --- a/base/base.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef BASE_H -#define BASE_H - -#include -#include - -/* assert an expression and output the file and the line */ - -#define RED "\x1b[31m" -#define GREEN "\x1b[32m" -#define RESET "\x1b[0m" - -#define test_assert(expr) \ - do \ - { \ - if (!(expr)) \ - { \ - fprintf(stderr, RED " [FAILED] %s:%d: expr:%s test:%s\n" RESET, __FILE__, __LINE__, #expr, __func__); \ - abort(); \ - } \ - else\ - { \ - fprintf(stdout, GREEN "[PASSED] %s\n" RESET, __func__); \ - }\ - } while (0) - -#define global_variable static -#define local_persist static -#define local_internal static - -#define ERR_OK 0 -#define ERR_IO 1 -#define ERR_PARSE 2 -#define ERR_PERM 3 -#define ERR_INVALID 4 - -#define KiB(n) (((u64)(n)) << 10) -#define MiB(n) (((u64)(n)) << 20) -#define GiB(n) (((u64)(n)) << 30) - -#define BUFFER_SIZE_SMALL 128 -#define BUFFER_SIZE_DEFAULT 256 -#define BUFFER_SIZE_LARGE 512 -#define PATH_MAX_LEN 4096 - -#define DEPRECATED __attribute__((__deprecated__)) - -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -typedef float f32; -typedef double f64; - -typedef i32 b32; -typedef i16 b16; -typedef u8 b8; - -typedef uintptr_t umm; -typedef intptr_t smm; - -#define TRUE 1 -#define FALSE 0 - -local_internal u64 -parse_u64(char *buf, size_t len); - -local_internal b8 -is_numeric(char *s); - -local_internal b8 -compare_string(const char *c1, const char *c2); - -/* - * TODO(nasr): macro for verbose assertions - * - * */ - -#endif diff --git a/base/base_arena.c b/base/base_arena.c deleted file mode 100644 index 16997b2..0000000 --- a/base/base_arena.c +++ /dev/null @@ -1,86 +0,0 @@ -/** - * TODO(nasr): remove stdlib - * */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base_arena.h" - -/* TODO(nasr): reserve pages support */ -/* TODO(nasr): check if an arena has been used before */ - -local_internal mem_arena * -arena_create(u64 capacity) -{ - mem_arena *arena = (mem_arena *)mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (arena == MAP_FAILED) - { - return NULL; - } - - arena->capacity = capacity; - arena->pos = ARENA_BASE_POS; - - return arena; -} - -/* - * make it a void pointer to allow implicit conversion - * */ -local_internal void -arena_destroy(mem_arena *arena) -{ - munmap(arena, arena->capacity); -} - -local_internal void * -arena_push(mem_arena *arena, u64 size, b32 non_zero) -{ - u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN); - u64 new_pos = pos_aligned + size; - - if (new_pos > arena->capacity) - { - assert(0); - return NULL; - } - - arena->pos = new_pos; - /* - * cast to u8 to be able to do pointer arithemtic - * */ - u8 *out = (u8 *)arena + pos_aligned; - - if (!non_zero) - { - memset(out, 0, size); - } - return out; -} - -local_internal void -arena_pop(mem_arena *arena, u64 size) -{ - size = MIN(size, arena->pos - ARENA_BASE_POS); - arena->pos -= size; -} - -local_internal void -arena_pop_to(mem_arena *arena, u64 pos) -{ - u64 size = pos < arena->pos ? arena->pos - pos : 0; - arena_pop(arena, size); -} - -local_internal void -arena_clear(mem_arena *arena) -{ - arena_pop_to(arena, ARENA_BASE_POS); -} diff --git a/base/base_arena.h b/base/base_arena.h deleted file mode 100644 index 19c4f3d..0000000 --- a/base/base_arena.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef ARENA_H -#define ARENA_H - -#include "base.h" - -/** - * Arena Helper macro's - * */ - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1))) - -#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0) -#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1) -#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0) -#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1) - -#define ARENA_BASE_POS (sizeof(mem_arena)) -#define ARENA_ALIGN (sizeof(void *)) - -typedef struct mem_arena mem_arena; - -struct mem_arena -{ - u64 capacity; - u64 pos; -}; - -local_internal mem_arena * -arena_create(u64 capacity); - -local_internal void -arena_destroy(mem_arena *arena); - -local_internal void * -arena_push(mem_arena *arena, u64 size, b32 non_zero); - -local_internal void -arena_pop(mem_arena *arena, u64 size); - -local_internal void -arena_pop_to(mem_arena *arena, u64 pos); - -local_internal void -arena_clear(mem_arena *arena); - - -#endif diff --git a/build.sh b/build.sh index 80f3d5a..e602edb 100755 --- a/build.sh +++ b/build.sh @@ -1,31 +1,29 @@ #!/bin/sh set -eu -# Toolchain -CC=clang - -# Files -SRC=main.c -OUT=main - -# Include paths -INCLUDES="-I." - -# Compiler flags -CFLAGS=" --g --O0 -" - -# Linker flags -LDFLAGS=" --lX11 --I. --lm -" - -echo "==> Building $OUT" -$CC $CFLAGS $INCLUDES "$SRC" -o "$OUT" $LDFLAGS - -echo "==> Running $OUT" -./"$OUT" +script_dir="$(dirname "$(readlink -f "$0")")" +cd "$script_dir" + +build_dir="build" +mkdir -p "$build_dir" + +compile() +{ + source="$1" + out="$2" + flags="${3:-}" + + common_flags="-I. -Wall -Wextra -Wno-unused-function -Wno-unused-variable" + linker_flags="-lX11 -lm" + + flags="$common_flags $flags $linker_flags" + + gcc $flags "$(readlink -f "$source")" -o "$build_dir"/"$out" +} + +# Build core shared lib +compile "source/core/core.h" "libcore.so" "-fPIC -shared -DCORE_UNITY" + +# Build app +compile "source/core/core.c" "app" "-L$build_dir -lcore" + diff --git a/build/app b/build/app new file mode 100755 index 0000000..5220177 Binary files /dev/null and b/build/app differ diff --git a/build/libcore.so b/build/libcore.so new file mode 100755 index 0000000..1026809 Binary files /dev/null and b/build/libcore.so differ diff --git a/library/arena.c b/library/arena.c deleted file mode 100644 index 39711d5..0000000 --- a/library/arena.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "arena.h" - -mem_arena * -arena_create(u64 capacity) -{ - mem_arena *arena = mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (arena == MAP_FAILED) - { - assert(0); - } - - arena->capacity = capacity; - arena->pos = ARENA_BASE_POS; - - return arena; -} - -// make it a void pointer to allow implicit conversion -void -arena_destroy(mem_arena *arena) -{ - munmap(arena, arena->capacity); -} - -void * -arena_push(mem_arena *arena, u64 size, b32 non_zero) -{ - u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN); - u64 new_pos = pos_aligned + size; - - if (new_pos > arena->capacity) - { - assert(0); - return NULL; - } - - arena->pos = new_pos; - // cast to u8 to be able to do pointer arithemtic - u8 *out = (u8 *)arena + pos_aligned; - - if (!non_zero) - { - memset(out, 0, size); - } - return out; -} -void -arena_pop(mem_arena *arena, u64 size) -{ - size = MIN(size, arena->pos - ARENA_BASE_POS); - arena->pos -= size; -} - -void -arena_pop_to(mem_arena *arena, u64 pos) -{ - u64 size = pos < arena->pos ? arena->pos - pos : 0; - arena_pop(arena, size); -} - -void -arena_clear(mem_arena *arena) -{ - arena_pop_to(arena, ARENA_BASE_POS); -} - -#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0) -#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1) -#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0) -#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1) - diff --git a/library/arena.h b/library/arena.h deleted file mode 100644 index 330023e..0000000 --- a/library/arena.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef ARENA_H -#define ARENA_H - -#include "base.h" - -/** - * Arena Helper macro's - * */ - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1))) - - - -/* - * Represents a disk partition with major/minor device numbers and block count. - */ - -/** - * replacing malloc/free with arena allocaters - * - * */ - -#define ARENA_BASE_POS (sizeof(mem_arena)) -// void * for the size of a pointer on the machine, 64/32bit comp -#define ARENA_ALIGN (sizeof(void *)) - - -static inline u64 KiB(u64 n) { return n << 10; } -static inline u64 MiB(u64 n) { return n << 20; } -static inline u64 GiB(u64 n) { return n << 30; } - -typedef struct mem_arena mem_arena; - - -struct mem_arena -{ - u64 capacity; - u64 pos; -} ; - -// arena prototypes -mem_arena * -arena_create(u64 capacity); -// make it a void pointer to allow implicit conversion -void -arena_destroy(mem_arena *arena); - -void * -arena_push(mem_arena *arena, u64 size, b32 non_zero); - -void -arena_pop(mem_arena *arena, u64 size); - -void -arena_pop_to(mem_arena *arena, u64 pos); - -void -arena_clear(mem_arena *arena); - - -#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0) -#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1) -#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0) -#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1) - - -#endif diff --git a/library/base.h b/library/base.h deleted file mode 100644 index 74b6303..0000000 --- a/library/base.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef BASE_H -#define BASE_H - -#include -#include - -#define OK 0 -#define ERR_IO 1 -#define ERR_PARSE 2 -#define ERR_PERM 3 -#define ERR_INVALID 4 - -enum { - BUFFER_SIZE_SMALL = 128, - BUFFER_SIZE_DEFAULT = 256, - BUFFER_SIZE_LARGE = 512, - PATH_MAX_LEN = 4096 -}; - -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -typedef float f32; -typedef double f64; - -typedef i32 b32; -typedef i16 b16; -typedef u8 b8; - -#define TRUE 1 -#define FALSE 0 - - - -#endif diff --git a/library/clang-format b/library/clang-format deleted file mode 100644 index 3c61d5e..0000000 --- a/library/clang-format +++ /dev/null @@ -1,104 +0,0 @@ -BasedOnStyle: LLVM -Language: C - -# ------------------------------------------------------------------- -# Indentation & layout -# ------------------------------------------------------------------- -IndentWidth: 2 -TabWidth: 2 -UseTab: Never -ContinuationIndentWidth: 2 - -IndentCaseLabels: true -IndentGotoLabels: true -IndentPPDirectives: None -IndentExternBlock: NoIndent - -# ------------------------------------------------------------------- -# Line breaking -# ------------------------------------------------------------------- -ColumnLimit: 0 - -AllowAllParametersOfDeclarationOnNextLine: false -AllowAllArgumentsOnNextLine: false - -AllowShortFunctionsOnASingleLine: false -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false - -AlwaysBreakAfterReturnType: All -AlwaysBreakTemplateDeclarations: No # harmless for C - -BreakBeforeBinaryOperators: None - -# ------------------------------------------------------------------- -# Braces (Allman style) -# ------------------------------------------------------------------- -BreakBeforeBraces: Allman - -BraceWrapping: - AfterCaseLabel: true - BeforeElse: true - BeforeCatch: true - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true - -# NOTE: -# AfterControlStatement / AfterFunction / AfterStruct / AfterEnum / AfterUnion -# are IMPLIED by Allman and must NOT be redundantly specified. - -# ------------------------------------------------------------------- -# Spacing -# ------------------------------------------------------------------- -SpaceBeforeParens: ControlStatements -SpaceBeforeAssignmentOperators: true -SpaceBeforeRangeBasedForLoopColon: true # ignored in C, harmless - -SpacesInParentheses: false -SpacesInSquareBrackets: false -SpacesInAngles: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 - -PointerAlignment: Right -DerivePointerAlignment: false - -# ------------------------------------------------------------------- -# Alignment (explicitly disabled) -# ------------------------------------------------------------------- -AlignAfterOpenBracket: DontAlign -AlignOperands: false -AlignTrailingComments: false -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: DontAlign - -# ------------------------------------------------------------------- -# Comments -# ------------------------------------------------------------------- -ReflowComments: false -CommentPragmas: '^ dont touch:' -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 - -# ------------------------------------------------------------------- -# Includes -# ------------------------------------------------------------------- -SortIncludes: Never -IncludeBlocks: Preserve - -# ------------------------------------------------------------------- -# Macros & preprocessor -# ------------------------------------------------------------------- -MacroBlockBegin: '' -MacroBlockEnd: '' -SpaceAfterCStyleCast: false - -# ------------------------------------------------------------------- -# C-specific -# ------------------------------------------------------------------- -Cpp11BracedListStyle: false -DisableFormat: false diff --git a/library/clangd b/library/clangd deleted file mode 100644 index 624678a..0000000 --- a/library/clangd +++ /dev/null @@ -1,59 +0,0 @@ -CompileFlags: - Add: - - -std=c99 - - -xc - - - -Iinclude - - - -Wall - - -Wextra - - -Wpedantic - - -Wshadow - - -Wconversion - - -Wsign-conversion - - -Wmissing-declarations - - -Wundef - - -Wpointer-arith - - -Wcast-align - - -Wcast-qual - - -Wwrite-strings - - -Wswitch-enum - - -Wformat=2 - - -Wstrict-aliasing=2 - - -Werror=implicit-function-declaration - - -Werror=implicit-int - - -Werror=incompatible-pointer-types - - -Werror=return-type - - -Wformat-security - - -Wnull-dereference - - -Wmisleading-indentation - - - -Wunused - - -Wuninitialized - - -Werror - - -Wdouble-promotion - - -Wstrict-overflow=2 - - - -D_POSIX_C_SOURCE=200809L - - "-I/include" - - Remove: - - -std=* - - -O* - - -march=* - - -mtune=* - - -Hover: - ShowAKA: true - -InlayHints: - Enabled: true - ParameterNames: true - DeducedTypes: true - -Completion: - AllScopes: true - -Index: - Background: Build diff --git a/main b/main deleted file mode 100755 index 28736dd..0000000 Binary files a/main and /dev/null differ diff --git a/main.c b/main.c deleted file mode 100644 index 4c43245..0000000 --- a/main.c +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "base/base.h" -#include "base/base_arena.h" - -#include "base/base.c" -#include "base/base_arena.c" - - -#define NIL 0 - -typedef struct -{ -i32 x; -i32 y; -u32 height; -u32 width; -u32 border_width; -i32 window_depth; -u32 window_class; -u64 value_mask; - -} WindowProperties; - -typedef struct -{ -i32 x; -i32 y; -i32 z; - -} vertex; - -void -sleep_ms(long ms) -{ -struct timespec ts; -ts.tv_sec = ms / 1000; -ts.tv_nsec = (ms % 1000) * 1000000L; - -while (nanosleep(&ts, &ts)) -{ -NULL; -} -} - -void -move_down(double *y) -{ -++*y; -} - -void -move_up(double *y) -{ ---*y; -} - -void -move_left(double *x) -{ ---*x; -} - -void -move_right(double *x) -{ -++*x; -} - - - -typedef struct -{ -void (*move)(double *a); -} movement; - -void -handle_destroy(Display *display, GC *gc) -{ -XFreeGC(display, *gc); -XCloseDisplay(display); -} - -typedef struct -{ -i32 x; -i32 y; - -} display_pos; - -typedef struct -{ -i32 x; -i32 y; -i32 z; - -} pos; - - -int -main() -{ -Display *MainDisplay = XOpenDisplay(0); -mem_arena *arena = arena_create(MiB(8)); - -Window root = XDefaultRootWindow(MainDisplay); -int screen = DefaultScreen(MainDisplay); - -Visual *v = DefaultVisual(MainDisplay, screen); - -XSetWindowAttributes wa = { -.background_pixmap = None, -.background_pixel = BlackPixel(MainDisplay, DefaultScreen(MainDisplay)), -.border_pixmap = CopyFromParent, -.border_pixel = 0, -.bit_gravity = ForgetGravity, -.win_gravity = NorthWestGravity, -.backing_store = NotUseful, -.backing_planes = 1, -.backing_pixel = 0, -.save_under = False, -.event_mask = {}, -.do_not_propagate_mask = {}, -.override_redirect = False, -.colormap = CopyFromParent, -.cursor = None -}; - -i32 dp_heigth = DisplayHeight(MainDisplay, screen); -i32 dp_width = DisplayWidth(MainDisplay, screen); - -WindowProperties p = { - -.x = dp_width / 2, -.y = dp_heigth / 2, -.height = (u32)800, -.width = (u32)1200, -.border_width = 0, -.window_depth = CopyFromParent, -.window_class = CopyFromParent, -.value_mask = CWBackPixel, - -}; - - -Window window = -XCreateWindow( -MainDisplay, -root, -p.x, -p.y, -p.width, -p.height, -p.border_width, -p.window_depth, -p.window_class, -v, -p.value_mask, -&wa); - -Pixmap pixmap = XCreatePixmap(MainDisplay, window, dp_width, dp_heigth, 1); - -XSetWindowBorder(MainDisplay, window, 60); -XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask); -XMapWindow(MainDisplay, window); - - -double x = p.width / 2; -double y = p.height / 2; - -u32 rect_width = 50; -u32 rect_height = 50; - -u64 color = 0x0000ff00; - -GC gc = XCreateGC(MainDisplay, window, 0, NIL); -XSetForeground(MainDisplay, gc, color); - - -double *pX = &x; -double *pY = &y; - -movement m = { -.move = move_down -}; - -XEvent event; -XNextEvent(MainDisplay, &event); - -for (;;) -{ -switch (event.type) -case KeyPress: -case KeyRelease: -{ - - -} -default: -{ -if (*pX + rect_width >= p.width) -{ -m.move = move_left; -} -else if (*pX <= 0) -{ -m.move = move_right; -} - -char words[] = "working"; - -XTextItem ti = { -.chars = words, -.nchars = (int)strlen(words), -.delta = 0, -.font = None -}; - -XClearWindow(MainDisplay, window); - -pos *p = arena_push(arena, sizeof(*p), 0); - -p->z = 10; -p->x = ((i32)*pX * 10) / p->z; -p->y = ((i32)*pY * 10) / p->z; - -XFillRectangle( -MainDisplay, -window, -gc, -(i32)p->x, -(i32)p->y, -rect_height, -rect_width); - -m.move(&x); - -sleep_ms(1); - -XFlush(MainDisplay); -} - -case DestroyNotify: -{ -// handle_destroy(MainDisplay, &gc); -} -} - -arena_clear(arena); -return 0; -} diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..a113e23 --- /dev/null +++ b/run.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -eu + +build_dir=~/projects/tb/build + +# Run +export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}:$build_dir" +"$build_dir/app" diff --git a/source/base/base.h b/source/base/base.h new file mode 100755 index 0000000..5fcf9e2 --- /dev/null +++ b/source/base/base.h @@ -0,0 +1,77 @@ +#ifndef BASE_H +#define BASE_H + +#include +#include +#include +#include + +/* assert an expression and output the file and the line */ + +#define internal static +#define global_variable static +#define local_persist static + +#define ERR_OK 0 +#define ERR_IO 1 +#define ERR_PARSE 2 +#define ERR_PERM 3 +#define ERR_INVALID 4 + +#define KiB(n) (((u64)(n)) << 10) +#define MiB(n) (((u64)(n)) << 20) +#define GiB(n) (((u64)(n)) << 30) + +#define unused(x) (void)(x) + +#define PATH_MAX_LEN 128 +#define BUFF_SMALL 128 +#define BUFF_DEFAULT 256 +#define BUFF_LARGE 512 + +#define NIL 0 + +#define DEPRECATED __attribute__((__deprecated__)) + +#if defined(__arm__) || defined(__aarch64__) +#define breakpoint __asm__ volatile("brk #0"); +#define temp_breakpoint __asm__ volatile("udf #0"); +#elif defined(__i386__) || defined(__x86_64__) +#define breakpoint __asm__ volatile("int3"); +#endif + +#define MemCpy(dest, src, len) memcpy((dest), (src), (len)) +#define MemSet(dest, len) memset((dest), (0), (len)) + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +typedef i32 b32; +typedef i16 b16; +typedef u8 b8; + +typedef uintptr_t umm; +typedef intptr_t smm; + +#define TRUE (0 == 0) +#define FALSE (0 != 0) + +typedef struct s8 s8; + +struct s8 +{ + char *data; + umm size; +}; + +#endif diff --git a/source/base/base_arena.c b/source/base/base_arena.c new file mode 100755 index 0000000..76938bd --- /dev/null +++ b/source/base/base_arena.c @@ -0,0 +1,142 @@ +internal mem_arena * +arena_create(u64 capacity) +{ + mem_arena *arena = (mem_arena *)mmap( + /* kernel decides where to throw the arena */ + NULL, + capacity + sizeof(mem_arena), + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + -1, + 0); + + if (arena == MAP_FAILED) + { + return NULL; + } + + arena->capacity = capacity; + arena->base_position = (u8 *)arena + sizeof(mem_arena); + arena->current_position = 0; + arena->previous_position = 0; + + return arena; +} + +internal void +arena_destroy(mem_arena *arena) +{ + if (!arena) + { + return; + } + + int code = munmap(arena, arena->capacity + sizeof(mem_arena)); +} + +internal void * +arena_alloc(mem_arena *arena, u64 size) +{ + if (!arena) + { + return NULL; + } + + u64 aligned = Align(arena->current_position, ARENA_ALIGN); + u64 new_pos = aligned + size; + + if (new_pos > arena->capacity) + { + return NULL; + } + + void *out = arena->base_position + aligned; + + arena->previous_position = arena->current_position; + arena->current_position = aligned + size; + + MemSet(out, size); + + return out; +} + +internal void +arena_pop(mem_arena *arena, u64 size) +{ + size = MIN(size, arena->current_position); + arena->current_position -= size; +} + +internal void +arena_pop_to(mem_arena *arena, u64 pos) +{ + u64 size = pos < arena->current_position ? arena->current_position - pos : 0; + arena_pop(arena, size); +} + +internal void +arena_clear(mem_arena *arena) +{ + arena->current_position = 0; +} + +internal mem_arena * +arena_resize_align(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size, umm alignment) +{ + u8 *old_mem = (u8 *)old_memory; + + if (!is_pow(alignment)) + { + Align(arena->current_position, alignment); + } + + if (old_memory == NULL || old_size == 0) + { + return (mem_arena *)arena_alloc(arena, new_size); + } + else if ((old_mem >= arena->base_position && old_mem < arena->base_position + arena->capacity)) + { + if ((arena->base_position + arena->previous_position) == old_memory) + { + arena->current_position = arena->previous_position + new_size; + if (new_size > old_size) + { + MemSet(&arena->current_position, new_size - old_size); + } + return (mem_arena *)old_memory; + } + else + { + void *new_memory = arena_alloc(arena, new_size); + umm copy_size = old_size < new_size ? old_size : new_size; + memmove(new_memory, old_mem, copy_size); + } + } + else + { + check(0); + } + return NULL; +} + +internal mem_arena * +arena_resize(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size) +{ + return arena_resize_align(arena, old_memory, new_size, old_size, ARENA_ALIGN); +} + +internal temp_arena +temp_arena_begin(mem_arena *arena) +{ + temp_arena t; + t.arena = arena; + t.start_position = arena->current_position; + + return t; +} + +internal void +temp_arena_end(temp_arena temp) +{ + temp.arena->current_position = temp.start_position; +} diff --git a/source/base/base_arena.h b/source/base/base_arena.h new file mode 100755 index 0000000..71d9e69 --- /dev/null +++ b/source/base/base_arena.h @@ -0,0 +1,41 @@ +#ifndef ARENA_H +#define ARENA_H + +#define Align(pointer, alignment) align((u64)(pointer), (umm)(alignment)) +#define PushStruct(arena, type) (type *)arena_alloc((arena), sizeof(type)) +#define PushArray(arena, type, len) (type *)arena_alloc((arena), sizeof(type) * (len)) +#define PushString(arena, len) (s8 *)arena_alloc((arena), sizeof(s8)*len)) + +typedef struct mem_arena mem_arena; +typedef struct temp_arena temp_arena; + +struct mem_arena +{ + u64 current_position; + u64 previous_position; + u64 capacity; + u8 *base_position; +}; + +struct temp_arena +{ + mem_arena *arena; + u64 start_position; +}; + +internal mem_arena * +arena_resize_align( + mem_arena *arena, + void *old_memory, + u64 new_size, + u64 old_size, + umm alignment); + +internal mem_arena * +arena_resize( + mem_arena *arena, + void *old_memory, + u64 new_size, + u64 old_size); + +#endif diff --git a/source/base/base_hash.c b/source/base/base_hash.c new file mode 100644 index 0000000..c309a9a --- /dev/null +++ b/source/base/base_hash.c @@ -0,0 +1,18 @@ + +internal u64 +generate_hash() +{ + // TODO(nasr): + return 0; +} + +internal hash_map +make_hash_map +{ + + // TODO(nasr): + + return {0}; + +} + diff --git a/source/base/base_include.h b/source/base/base_include.h new file mode 100755 index 0000000..3f83fd7 --- /dev/null +++ b/source/base/base_include.h @@ -0,0 +1,30 @@ +#ifndef BASE_INCLUDE_H +#define BASE_INCLUDE_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "base.h" +#include "base_mem.h" +#include "base_arena.h" +#include "base_parse.h" +#include "base_stack.h" +#include "base_test.h" + +#if defined(TB_IMPLEMENTATION) + +#include "base_mem.c" +#include "base_arena.c" +#include "base_parse.c" +#include "base_stack.c" +#include "base_test.c" + +#endif + +#endif diff --git a/source/base/base_mem.c b/source/base/base_mem.c new file mode 100644 index 0000000..f20ba39 --- /dev/null +++ b/source/base/base_mem.c @@ -0,0 +1,17 @@ +internal inline b8 +is_pow(umm x) +{ + return (x & (x - 1)) == 0; +} + +internal inline u64 +align(u64 pointer, umm alignment) +{ + if ((alignment & (alignment - 1)) == 0) + { + return pointer; + } + + return (pointer + alignment - 1) & ~(alignment - 1); +} + diff --git a/source/base/base_mem.h b/source/base/base_mem.h new file mode 100644 index 0000000..945f0ce --- /dev/null +++ b/source/base/base_mem.h @@ -0,0 +1,8 @@ +#ifndef BASE_MEM_H +#define BASE_MEM_H + +#define ARENA_ALIGN (2 * sizeof(void *)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#endif diff --git a/source/base/base_parse.c b/source/base/base_parse.c new file mode 100755 index 0000000..4f216bf --- /dev/null +++ b/source/base/base_parse.c @@ -0,0 +1,98 @@ +/* + * is_numeric - Check if a string contains only digits + * @s: String to check + * + * Return: 1 if string contains only numeric characters, 0 otherwise + */ +internal b8 +is_numeric(char *s) +{ + for (; *s; ++s) + { + if (*s < '0' || *s > '9') + { + return 0; + } + } + return 1; +} + +/* + * TODO(nasr): checkout i think there is a buffer overflow happening somewhere + * */ +internal proc_file * +parse_proc_files(char *path, mem_arena *arena) +{ + if (!path || !arena) + { + return NULL; + } + + i32 fd = open(path, O_RDONLY); + if (fd < 0) + { + return NULL; + } + + char *buffer = PushArray(arena, char, KiB(4)); + u64 bytes = read(fd, buffer, KiB(4)); + close(fd); + + if (bytes == 0) + { + return NULL; + } + + /* guessing the count to 256 because i dont want to do a double pass of the buffer */ + proc_file *pf = PushStruct(arena, proc_file); + pf->entries = PushArray(arena, proc_entry, 256); + + u64 line_start = 0; + u64 delim = -1; + u64 entry_index = 0; + + for (u64 index = 0; index < bytes; ++index) + { + if (buffer[index] == ':' && delim == (u64)-1) + { + delim = index; + } + else if (buffer[index] == '\n') + { + if (delim != (-1.f)) + { + u64 key_len = delim - line_start; + if (key_len >= sizeof(pf->entries[entry_index].key)) + { + key_len = sizeof(pf->entries[entry_index].key) - 1; + } + + u64 val_start = delim + 1; + while (val_start < index && (buffer[val_start] == ' ' || buffer[val_start] == '\t')) + { + val_start++; + } + + u64 val_len = index - val_start; + if (val_len >= sizeof(pf->entries[entry_index].value)) + { + val_len = sizeof(pf->entries[entry_index].value) - 1; + } + + MemCpy(pf->entries[entry_index].key, buffer + line_start, key_len - 1); + MemCpy(pf->entries[entry_index].value, buffer + val_start, val_len); + + pf->entries[entry_index].key[key_len] = '\0'; + pf->entries[entry_index].value[val_len] = '\0'; + + ++pf->count; + ++entry_index; + } + + line_start = index + 1; + delim = (u64)-1; + } + } + + return (pf); +} diff --git a/source/base/base_parse.h b/source/base/base_parse.h new file mode 100755 index 0000000..d66fd04 --- /dev/null +++ b/source/base/base_parse.h @@ -0,0 +1,28 @@ +#ifndef BASE_PARSE_H +#define BASE_PARSE_H + +#define COMPARE_STRING(c1, c2) compare_string((char *)c1, (char *)c2) + +typedef struct proc_entry proc_entry; +typedef struct proc_file proc_file; + +struct proc_file +{ + i32 count; + proc_entry *entries; +}; + +struct proc_entry +{ + char value[16]; + char key[16]; +}; + +typedef struct +{ + i8 *start; + i8 *end; + umm len; +} Line; + +#endif diff --git a/source/base/base_stack.c b/source/base/base_stack.c new file mode 100755 index 0000000..7cf0570 --- /dev/null +++ b/source/base/base_stack.c @@ -0,0 +1,187 @@ +internal mem_stack * +stack_create(u64 capacity) +{ + mem_stack *stack = (mem_stack *)mmap( + 0, + capacity + sizeof(mem_stack), + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + -1, + 0); + + if (stack == MAP_FAILED) + { + return NULL; + } + + stack->capacity = capacity; + stack->base_position = (u8 *)stack + sizeof(mem_stack); + stack->current_offset = 0; + + return stack; +} + +internal umm +calculate_padding(umm pointer, umm alignment, umm header_size) +{ + umm modulo, padding; + + if (!is_pow(alignment)) + { + return 0; + } + + modulo = pointer & (alignment - 1); + + padding = 0; + + if (0 == modulo) + { + padding = alignment - modulo; + } + + if (padding < header_size) + { + header_size -= padding; + + if ((header_size & (alignment - 1)) != 0) + { + padding += alignment * (1 + (header_size / alignment)); + } + else + { + padding += alignment * (header_size / alignment); + } + } + + return padding; +} + +internal mem_stack * +stack_push_align(mem_stack *stack, u64 size, umm alignment) +{ + umm padding = 0; + + if (!is_pow(alignment)) + { + return (0); + } + + if (alignment > 128) + { + alignment = 128; + } + + umm current_address = (umm)stack->base_position + stack->current_offset; + padding = calculate_padding(current_address, alignment, sizeof(mem_stack_header)); + + if (stack->current_offset + padding + size > stack->capacity) + { + return 0; + } + + stack->current_offset += padding; + + umm next_address = current_address + (umm)padding; + mem_stack_header *header = (mem_stack_header *)(next_address - sizeof(mem_stack_header)); + header->padding = padding; + + stack->current_offset += size; + + return MemSet((void *)next_address, size); +} +internal void * +stack_push(mem_stack *stack, umm size) +{ + return stack_push_align(stack, size, ARENA_ALIGN); +} + +internal void +stack_pop(mem_stack *stack, void *pointer) +{ + if (pointer != NULL) + { + umm start, end, current_address; + mem_stack_header *header; + umm prev_offset; + + start = (umm)stack->base_position; + end = start + (umm)stack->capacity; + current_address = (umm)pointer; + + if (!(start <= current_address && current_address < end)) + { + if (0 && "Out of bounds memory address passed to stack allocator (free)") + { + return; + } + return; + } + + if (current_address >= start + (umm)stack->base_position) + { + return; + } + + header = (mem_stack_header *)(current_address - sizeof(mem_stack_header)); + prev_offset = (size_t)(current_address - (umm)header->padding - start); + stack->current_offset = prev_offset; + } +} + +internal mem_stack * +stack_resize_align(mem_stack *stack, void *pointer, u64 old_size, u64 new_size, u64 alignment) +{ + if (pointer == NULL) + { + return stack_push_align(stack, new_size, alignment); + } + else if (new_size == 0) + { + stack_pop(stack, pointer); + return NULL; + } + + umm start, end, current_address; + umm min_size = old_size < new_size ? old_size : new_size; + void *new_pointer; + + start = (umm)stack->base_position; + end = start + (umm)stack->capacity; + current_address = (umm)pointer; + if (!(start <= current_address && current_address < end)) + { + return NULL; + } + + if (current_address >= start + (umm)stack->current_offset) + { + return NULL; + } + + if (old_size == new_size) + { + return pointer; + } + + new_pointer = stack_push_align(stack, new_size, alignment); + memmove(new_pointer, pointer, min_size); + return new_pointer; +} + +internal void +stack_pop_all(mem_stack *stack) +{ + stack->current_offset = 0; +} + +internal void +stack_destroy(mem_stack *stack) +{ + if (!stack) + { + return; + } + + munmap(stack, stack->capacity + sizeof(mem_stack)); +} diff --git a/source/base/base_stack.h b/source/base/base_stack.h new file mode 100755 index 0000000..fc80b20 --- /dev/null +++ b/source/base/base_stack.h @@ -0,0 +1,20 @@ +#ifndef STACK_H +#define STACK_H + +typedef struct mem_stack mem_stack; +typedef struct mem_stack_header mem_stack_header; + +struct mem_stack +{ + u8 *base_position; + umm current_offset; + umm capacity; +}; + +struct mem_stack_header +{ + u8 padding; + u8 previous_offset; +}; + +#endif diff --git a/source/base/base_string.c b/source/base/base_string.c new file mode 100644 index 0000000..cb2d71d --- /dev/null +++ b/source/base/base_string.c @@ -0,0 +1,73 @@ +internal umm +skip_whitespaces(string *buffer) +{ + s32 index = 0; + while (buffer->size > index) + { + ++index; + } +} + +internal b8 +compare_string_struct(string c1, string c2) +{ + if (c1.size != c2.size) + { + return -1; + } + + for (s32 index = 0; + index < c1.size; + ++index) + { + if (c1.Data[index] != c2.Data[index]) + { + return -1; + } + } + + return 0; +} + +internal b8 +compare_string(char *c1, char *c2) +{ + if (sizeof(*c1) != sizeof(*c2)) + { + return -1; + } + + for ( + u64 word_idx = 0; + word_idx <= sizeof(*c1); + ++word_idx) + { + if (*c1 != *c2) + { + return -1; + } + ++c1; + ++c2; + } + + return 0; +} + +/** NOTE(nasr): Helper function to parse strings to int using ascii codes **/ +internal u64 +parse_u64(char *buf, umm len) +{ + u64 value = 0; + + for (umm buffer_idx = 0; buffer_idx < len; ++buffer_idx) + { + char c = buf[buffer_idx]; + if (c < '0' || c > '9') + { + break; + } + value = value * 10 + (c - '0'); + } + + return value; +} diff --git a/source/base/base_string.h b/source/base/base_string.h new file mode 100644 index 0000000..d879450 --- /dev/null +++ b/source/base/base_string.h @@ -0,0 +1,17 @@ +#ifndef BASE_STRING_H +#define BASE_STRING_H + +// let's use this for strings +// to better differentiate between stuff +typedef u8 s8; +typedef struct string string ; + +struct string +{ + s8 *data; + umm size; +}; + +// TODO(nasr): helper functions for string + +#endif /* BASE_STRING_H */ diff --git a/source/base/base_test.c b/source/base/base_test.c new file mode 100644 index 0000000..e44aa69 --- /dev/null +++ b/source/base/base_test.c @@ -0,0 +1,14 @@ +void +write_int(i32 num) +{ + if (num < 0) + { + write(STDERR_FILENO, "-", 1); + num = -num; + } + if (num >= 10) + write_int(num / 10); + char digit = '0' + (num % 10); + + write(STDERR_FILENO, &digit, 1); +} diff --git a/source/base/base_test.h b/source/base/base_test.h new file mode 100644 index 0000000..11028f4 --- /dev/null +++ b/source/base/base_test.h @@ -0,0 +1,61 @@ +#ifndef BASE_TEST_H +#define BASE_TEST_H + +void +write_int(i32 num); + +#define RED "\x1b[31m" +#define GREEN "\x1b[32m" +#define RESET "\x1b[0m" +#define BLUE "\x1b[34m" + +#define LEN(s) (sizeof(s) - 1) + +#define show \ + do \ + { \ + write(STDOUT_FILENO, __FILE__, sizeof(__FILE__) - 1); \ + write(STDOUT_FILENO, ":", 1); \ + write(STDOUT_FILENO, __func__, sizeof(__func__) - 1); \ + write(STDOUT_FILENO, ":", 1); \ + write_int(__LINE__); \ + write(STDOUT_FILENO, "\n", 1); \ + } while (0) + +#define test(expr) \ + { \ + if ((expr) != 0) \ + { \ + write(STDERR_FILENO, "[FAILED] ", LEN("[FAILED] ")); \ + show; \ + _exit(1); \ + } \ + } + +#define check(expr) \ + { \ + if ((expr) != 0) \ + { \ + write(STDERR_FILENO, RED "[ERROR] ", LEN(RED "[ERROR] ")); \ + show; \ + write(STDERR_FILENO, RESET, LEN(RESET)); \ + _exit(1); \ + } \ + else \ + { \ + write(STDERR_FILENO, GREEN "[SUCCESS] ", LEN(GREEN "[SUCCESS] ")); \ + show; \ + write(STDERR_FILENO, RESET, LEN(RESET)); \ + } \ + } + +#define checkpoint_output "<>\n" +#define checkpoint_end_output "^^^^^^^^^^^^^^\n\n\n" +#define checkpoint \ + { \ + write(STDERR_FILENO, BLUE checkpoint_output, LEN(BLUE checkpoint_output)); \ + show; \ + write(STDERR_FILENO, BLUE checkpoint_end_output, LEN(BLUE checkpoint_end_output)); \ + } + +#endif /* BASE_TEST_H */ diff --git a/source/base/bash_hash.h b/source/base/bash_hash.h new file mode 100644 index 0000000..2c286a2 --- /dev/null +++ b/source/base/bash_hash.h @@ -0,0 +1,15 @@ +##ifndef HEADER_H +#define HEADER_H + +typedef struct hash_map hash_map; +typedef struct hash hash; + + +struct hash_map +{ + + +}; + + +#endif /* HEADER_H */ diff --git a/source/core/core.c b/source/core/core.c new file mode 100644 index 0000000..43322de --- /dev/null +++ b/source/core/core.c @@ -0,0 +1,126 @@ +#define TB_IMPLEMENTATION +#include "core.h" +#include "../base/base_include.h" +#include "../platform/platform_include.h" + +int main() +{ + b32 running = 1; + + Display *MainDisplay = XOpenDisplay(0); + mem_arena *arena = arena_create(MiB(8)); + + Window root = XDefaultRootWindow(MainDisplay); + int screen = DefaultScreen(MainDisplay); + + Visual *v = DefaultVisual(MainDisplay, screen); + + XSetWindowAttributes wa = { + .background_pixmap = None, + .background_pixel = BlackPixel(MainDisplay, DefaultScreen(MainDisplay)), + .border_pixmap = CopyFromParent, + .border_pixel = 0, + .bit_gravity = ForgetGravity, + .win_gravity = NorthWestGravity, + .backing_store = NotUseful, + .backing_planes = 1, + .backing_pixel = 0, + .save_under = False, + .event_mask = 0, + .do_not_propagate_mask = 0, + .override_redirect = False, + .colormap = CopyFromParent, + .cursor = None + }; + + i32 dp_heigth = DisplayHeight(MainDisplay, screen); + i32 dp_width = DisplayWidth(MainDisplay, screen); + + WindowProperties p = { + + .x = dp_width / 2, + .y = dp_heigth / 2, + .height = (u32)800, + .width = (u32)1200, + .border_width = 0, + .window_depth = CopyFromParent, + .window_class = CopyFromParent, + .value_mask = CWBackPixel, + + }; + + Window window = + XCreateWindow( + MainDisplay, + root, + p.x, + p.y, + p.width, + p.height, + p.border_width, + p.window_depth, + p.window_class, + v, + p.value_mask, + &wa); + + Pixmap pixmap = XCreatePixmap(MainDisplay, window, dp_width, dp_heigth, 1); + + XSetWindowBorder(MainDisplay, window, 60); + + // NOTE(nasr): type of input we want to handle + XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask | KeyReleaseMask); + + XMapWindow(MainDisplay, window); + + double x = p.width / 2; + double y = p.height / 2; + + u32 rect_width = 50; + u32 rect_height = 50; + + u64 color = 0x0000ff00; + + GC gc = XCreateGC(MainDisplay, window, 0, NIL); + XSetForeground(MainDisplay, gc, color); + + double *pX = &x; + double *pY = &y; + + XEvent event; + XNextEvent(MainDisplay, &event); + + for (;running;) + { + KeySym keysym = XLookupKeysym(event, 0); + + switch (event.type) + { + case (KeyPress): + { + if (keysym == XK_p || keysym == XK_P) + { + XDrawRectangle(MainDisplay, screen, gc, 50, 50, 50, 50); + } + + break; + } + case (KeyRelease): + { + if (keysym == XK_p || keysym == XK_P) + { + XDrawRectangle(MainDisplay, screen, gc, 50, 50, 50, 50); + } + + break; + } + default: + { + + } + + } + } + arena_clear(arena); + return 0; +} diff --git a/source/core/core.h b/source/core/core.h new file mode 100644 index 0000000..c5821c5 --- /dev/null +++ b/source/core/core.h @@ -0,0 +1,5 @@ +#ifndef CORE_H +#define CORE_H + + + #endif diff --git a/source/platform/platform.c b/source/platform/platform.c new file mode 100644 index 0000000..2e7bbad --- /dev/null +++ b/source/platform/platform.c @@ -0,0 +1,12 @@ +internal inline void +sleep_ms(long ms) +{ + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000L; + + while (nanosleep(&ts, &ts)) + { + NULL; + } +} diff --git a/source/platform/platform.h b/source/platform/platform.h new file mode 100644 index 0000000..da8e065 --- /dev/null +++ b/source/platform/platform.h @@ -0,0 +1,56 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +#define NIL 0 + +#include +#include + #include +#include +#include + +typedef struct WindowProperties WindowProperties; +struct WindowProperties +{ + i32 x; + i32 y; + u32 height; + u32 width; + u32 border_width; + i32 window_depth; + u32 window_class; + u64 value_mask; + +}; + +typedef struct vertex vertex; + +struct vertex +{ + i32 x; + i32 y; + i32 z; +}; + +typedef struct display_pos display_pos; + +struct display_pos +{ + i32 x; + i32 y; + +}; + +typedef struct pos pos; +struct pos +{ + i32 x; + i32 y; + i32 z; + +} ; + + + + +#endif /* PLATFORM_H */ diff --git a/source/platform/platform_include.h b/source/platform/platform_include.h new file mode 100644 index 0000000..886c6b8 --- /dev/null +++ b/source/platform/platform_include.h @@ -0,0 +1,7 @@ +#ifndef PLATFORM_INCLUDE_H +#define PLATFORM_INCLUDE_H + +#include "platform.h" +#include "platform.c" + +#endif /* PLATFORM_INCLUDE_H */ diff --git a/xlib-tutorial/2nd-program-anatomy.html b/xlib-tutorial/2nd-program-anatomy.html deleted file mode 100644 index d156f7a..0000000 --- a/xlib-tutorial/2nd-program-anatomy.html +++ /dev/null @@ -1,282 +0,0 @@ - - -Xlib programming tutorial: anatomy of the most basic Xlib program - - - -

Anatomy of the most basic Xlib program

- -The program starts with the legal stuff: - -

-#include <X11/Xlib.h> // Every Xlib program must include this
-#include <assert.h>   // I include this to test return values the lazy way
-#include <unistd.h>   // So we got the profile for 10 seconds
-
-#define NIL (0)       // A name for the void pointer
-
- -Then the serious thing. First we open a connection to the server. - -

-Display *dpy = XOpenDisplay(NIL);
-assert(dpy);
-
- -If it fails (and it may), XOpenDisplay() will return NIL. - -

- -We gonna create a window, but we need to get the window's background -color first. X uses a quite complex color model in order to accommodate -to every conceivable piece of hardware. Each color is encoded by an integer, -but the integer for a given color may change from a machine to another -one, and even on the same machine, from an execution of the program to -the next. The only "colors" that X guarantees to exist are black and -white. We can get them using the -BlackPixel() -and -WhitePixel() -macros. - -


-      int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
-      int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
-
- -As we yet can see, most of the Xlib calls take the "display" (the -value returned by -XOpenDisplay()) -as their first parameter. You want to know why ? - -

- -There is still someting magic, (the -DefaultScreen() -stuff), but we gonna keep it for a later -explanation. We now can -create our window: - -


-      // Create the window
-
-      Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 
-				     200, 100, 0, blackColor, blackColor);
-
- -Unlike what appears in the dialog, we use the -function -XCreateSimpleWindow() -instead of -XCreateWindow(). -XCreateSimpleWindow() -is not really simpler than -XCreateWindow() -(it takes only a few less parameters), but it uses less concepts, so -we gonna stick to it for now. There are still a bunch of parameters to -explain: - -
    - -
  • dpy is the usual display connection (remember). - -

  • DefaultRootWindow(dpy): yet another parameter that may -seem magic until now. This is the "parent window" of the window we are -creating. The window we create appears inside its parent, and is -bounded by it (the window is said to be "clipped" by its -parent). Those who guess from the name "Default" that they may be -other root windows guess right. More on this later. For now, the default -root window makes appear our window on the screen, and will give the -window manager a chance to decorate -our window. - -

  • 0, 0 These are the coordinates of the upper left -corner of the window (the origin of the coordinates in X is at the -upper left, contrary to most mathematical textbooks). The dimensions, -like every dimensions in X, are in pixels (X does not support -user-defined scales, unlike some other graphical systems like -OpenGL). - -

    - -Contrary to what may seem, there is very little chance for the window -to appear, at 0,0. The reason is that the -window manager will put the window -at its policy-defined position. - -

  • 200, 100: these are the width and height of the -window, in pixels. - -

  • 0: this is the width of the window's border. This -has nothing to do with the border appended by the -window manager, so this is most -often set to zero. - -

  • blackColor, blackColor: these are the colors of the -window's border (NOT the -window manager's border), and the -window's background, respectively. -XCreateSimpleWindow() -clears the window when created, -XCreateWindow() -does not. - -
- -

-      // We want to get MapNotify events
-
-      XSelectInput(dpy, w, StructureNotifyMask);
-
- -As we're starting to know, X is based upon a -client-server architecture. The X server -sends events to the client (the program we're writing), to keep it -informed of the modifications in the server. There are many of them -(each time a window is created, moved, masked, unmasked, and many -other things), so a client must tell the server the events it is -interested in. With this XSelectInput() stuff, we tell the -server we want to be informed of "structural" changes occuring on the -w window. Creation and mapping are such changes. There is no -way to be informed for example of only mapping modification, and not -creations, so we've to take everything. In this particular application -we're interesting in "mapping" events (grosso modo, the window -appears on the screen). - -

-      // "Map" the window (that is, make it appear on the screen)
-
-      XMapWindow(dpy, w);
-
- -And (once again) this is a client-server -system. The map request is asynchronous, meaning that the time this -instruction is executed doesn't tell us when the window is actually -mapped. To be sure, we've to wait for the server to send us a -MapNotify -event (this is why we want to be sensitive to such events). - -

-      // Create a "Graphics Context"
-
-      GC gc = XCreateGC(dpy, w, 0, NIL);
-
- -Yet another magic stuff. But mastering them is the reason of the -existence of this tutorial... - -

- -For several reasons, the graphical model of X is stateless, meaning -that the server doesn't remember (among other things) attributes such -as the drawing color, the thickness of the lines and so on. Thus, -we've to give all these parameters to the server on each -drawing request. To avoid passing two dozens of parameters, many of -them unchanged from one request to the next, X uses an object called -the Graphics Context, or GC for short. We store in the -graphics context all the needed parameters. Here, we want the color -used to draw lines, called the foregound color: - -


-      // Tell the GC we draw using the white color
-
-      XSetForeground(dpy, gc, whiteColor);
-
- -There are many other parameters used to draw a line, but all of them -have reasonable default values. - -

- -That's okay for now. Everything is set up, and we wait for the window -mapping. - -


-      // Wait for the MapNotify event
-
-      for(;;) {
-	    XEvent e;
-	    XNextEvent(dpy, &e);
-	    if (e.type == MapNotify)
-		  break;
-      }
-
- -We loop, taking events as they come and discarding them. When we get a -MapNotify, we exit the loop. We may get events other than -MapNotify for two reasons: - -
    -
  • We have selected StructureNotifyMask to get -MapNotify events, but we could get other events as well (such -as ConfigureNotify, telling the window has changed in position, and/or -size). -
  • Some events can be received, even if we don't have asked for -them, they are called "non-maskable". GraphicsExpose is such an -event. -
- -The non-maskable events are sent only in response to some program -requests (such as copying an area), so they aren't likely to happen in -our context. - -

- -The -XNextEvent() -procedure is blocking, so if there are no event to read, the program -just wait inside the -XNextEvent(). - -

- -When we have exited the loop, we have good confidence that the window -appears on the screen. Actually, this may not be the case since, for -example, the user may have iconified it using the -window manager, but for now, we assume the window -actually appears. We can draw our line: - -


-      // Draw the line
-      
-      XDrawLine(dpy, w, gc, 10, 60, 180, 20);
-
- -The line is between points (10, 60) and (180, 20). The (0,0) is at the -upper left corner of the window, as usual. If the program just -sleeps here, nothing will happen, because, in case you don't -know, X has a client-server -architecture. Thus the request stays in the client, unless we tell it -to go to the server. This is done by XFlush(): - -

-      // Send the "DrawLine" request to the server
-
-      XFlush(dpy);
-
- -Clever readers may have noticed that we didn't use -XFlush() -before, and it didn't prevent all the requests such as -XMapWindow() -to be sent to the server. The answer is that -XNextEvent() -performs an implicit -XFlush() -before trying to read some events. We have our line now, we just wait -for 10 seconds, so we can make people see how beautiful is our work: - -

-      // Wait for 10 seconds
-
-      sleep(10);
-
- -That's all for now. In next -lesson, we will have a (very) little more interaction. [to be continued] - -
Christophe Tronche, ch.tronche@computer.org
- - diff --git a/xlib-tutorial/Xlib.pdf b/xlib-tutorial/Xlib.pdf deleted file mode 100644 index cef1647..0000000 Binary files a/xlib-tutorial/Xlib.pdf and /dev/null differ diff --git a/xlib-tutorial/index.html b/xlib-tutorial/index.html deleted file mode 100644 index 5e57eaf..0000000 --- a/xlib-tutorial/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - -Xlib programming: a short tutorial - - - - -

Xlib programming: a short tutorial

- -I haven't found anything very satisfying on the Web as an Xlib -tutorial. Many of them are too much Motif-oriented for my -taste. Furthermore, I answer questions about X programming almost -daily, so I've started to put together some small coursewares. - -

Important note:

the example programs are written in C++, but -this is mainly for the ability to declare variables anywhere. - -
- -Let's begin with a short story: the eternal story of the newbie at -Xlib writing his/her first program. - -

- - -"Ok, I've to open a connection to the X server (whatever this means), -with XOpenDisplay, then create a window with XCreateWindow, then draw -a line with XDrawLine. Then, the program sleeps for ten seconds so I -can see the result. Sounds easy." - - -

- -The poor newbie writes the program. And nothing happens. He then -calls his wizard friend. - -

- - --"Did you perform an XFlush after you've done everything ?
-- No, why ?
-- The requests stay in the client,"
wizard doubletalk, thinks the -poor newbie, " if you -don't." - - -

- -The poor newbie changes the program. And nothing happens. He then -calls his wizard friend. - -

- - --"Did you map your window ?
-- Did I do what ???
-- Creating a window doesn't make it appear on the screen. You've to - map it with XMapWindow first. -
- -

- -The poor newbie changes the program. The window appears with nothing -in it (like this). The poor newbie then calls -his wizard friend. - -

- - --"Did you wait for a MapNotify before drawing your line ?" (more wizard doubletalk)
-- "No, why ?
-- X has a stateless drawing model, the content of the window may be lost - when the window isn't on the screen."
(overflow, why can't these - wizard guys speak just like you and me ?) "You've to wait for a MapNotify - before drawing." - - -

- -The poor newbie changes the program. Things are getting more and more -complex. Not as easy as it first seemed. A loop gets the events until a -MapNotify. The window appears with nothing -in it. The poor newbie then calls his wizard friend. - -

- - --"I got it, did you select the StructureNotifyMask on your window ?
-- ???
-- Just do it, and everything'll be fine. -
- -

- -The poor newbie fixes the program. And the miracle happens ! A line in the -window. Until now, the program looks like this -(it is actually slighty more complex than the dialog may let you think). - -

- -Now you've learned at least 2 things: - -

    -
  • How to draw a line in a window with X. -
  • Why some may need an X tutorial. -
- -Now, if you want to learn more and get a deeper understanding of the -program, go to next lesson. - -

More about X.

- - -
Christophe Tronche, ch.tronche@computer.org
- - diff --git a/xlib-tutorial/prog-1.cc b/xlib-tutorial/prog-1.cc deleted file mode 100644 index 3ba596b..0000000 --- a/xlib-tutorial/prog-1.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Written by Ch. Tronche (http://tronche.lri.fr:8000/) -// Copyright by the author. This is unmaintained, no-warranty free software. -// Please use freely. It is appreciated (but by no means mandatory) to -// acknowledge the author's contribution. Thank you. -// Started on Thu Jun 26 23:29:03 1997 - -// -// Xlib tutorial: 1st program -// Make a window appear on the screen. -// - -#include // Every Xlib program must include this -#include // I include this to test return values the lazy way -#include // So we got the profile for 10 seconds - -#define NIL (0) // A name for the void pointer - -main() -{ - Display *dpy = XOpenDisplay(NIL); - assert(dpy); - Window w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, - 200, 100, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - NIL, 0); - XMapWindow(dpy, w); - XFlush(dpy); - sleep(10); -} diff --git a/xlib-tutorial/prog-2.cc b/xlib-tutorial/prog-2.cc deleted file mode 100644 index 51ea0e9..0000000 --- a/xlib-tutorial/prog-2.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Written by Ch. Tronche (http://tronche.lri.fr:8000/) -// Copyright by the author. This is unmaintained, no-warranty free software. -// Please use freely. It is appreciated (but by no means mandatory) to -// acknowledge the author's contribution. Thank you. -// Started on Thu Jun 26 23:29:03 1997 - -// -// Xlib tutorial: 2nd program -// Make a window appear on the screen and draw a line inside. -// If you don't understand this program, go to -// http://tronche.lri.fr:8000/gui/x/xlib-tutorial/2nd-program-anatomy.html -// - -#include // Every Xlib program must include this -#include // I include this to test return values the lazy way -#include // So we got the profile for 10 seconds - -#define NIL (0) // A name for the void pointer - -main() -{ - // Open the display - - Display *dpy = XOpenDisplay(NIL); - assert(dpy); - - // Get some colors - - int blackColor = BlackPixel(dpy, DefaultScreen(dpy)); - int whiteColor = WhitePixel(dpy, DefaultScreen(dpy)); - - // Create the window - - Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, - 200, 100, 0, blackColor, blackColor); - - // We want to get MapNotify events - - XSelectInput(dpy, w, StructureNotifyMask); - - // "Map" the window (that is, make it appear on the screen) - - XMapWindow(dpy, w); - - // Create a "Graphics Context" - - GC gc = XCreateGC(dpy, w, 0, NIL); - - // Tell the GC we draw using the white color - - XSetForeground(dpy, gc, whiteColor); - - // Wait for the MapNotify event - - for(;;) { - XEvent e; - XNextEvent(dpy, &e); - if (e.type == MapNotify) - break; - } - - // Draw the line - - XDrawLine(dpy, w, gc, 10, 60, 180, 20); - - // Send the "DrawLine" request to the server - - XFlush(dpy); - - // Wait for 10 seconds - - sleep(10); -} - diff --git a/xlib-tutorial/server.html b/xlib-tutorial/server.html deleted file mode 100644 index a408834..0000000 --- a/xlib-tutorial/server.html +++ /dev/null @@ -1,89 +0,0 @@ - - -Xlib programming tutorial: What is all this "client-server" stuff ? - - - -

What does all this stuff about "client-server" mean ?

- -Everybody says that X has a "client-server" architecture. So this must -be true, but what does it mean ? - -

- -Well, basically a client-server architecture is conceptually a simple -thing, but the consequences may be a bit subtle, especially the way it -is implemented in the Xlib. - -

What is a client-server architecture ?

- -A client-server architecture is a general mechanism for handling a -shared resource that several programs may want to access -simultaneously. In the case of X, the shared resources are the drawing -area and the input channel. If every process was allowed to write on -it at its will, several processes may want to draw at the same place, -resulting in an unpredictable chaos. Thus, only one process is allowed -to get access to the drawing area: the X server. The processes wanting -to draw stuff or get inputs send requests to the X servers (they are -"clients"). They do this over a communication channel. The X server -performs the requests for its clients, and sends them back replies. It -may also send messages without explicit client's requests to keep them -informed of what is going on. These messages sent by the server on its -own behalf are called "events". - -

Advantages of the client-server architecture

- -The client-server architecture has several advantages, many of them -resulting from the ability to run the server and the clients on -separate machines. Here are some advantages: - -
    - -
  • A client-server architectured system can be very robust: since - the server runs in its own address space, it can protect itself - against poorly written clients. Thus, if a client has a bug, it - will crash alone, the server and the other clients still running - as if nothing has happened. - -
  • The client and the server don't have to run on the same machine, - so we have some communication mechanism here. - -
  • The client and the server may run on separate machines, resulting - in a better load distribution (possibly). - -
  • The client and the server don't have to run on the same hardware, - operating system, etc., giving a better interoperability. - -
- -

Structure of the X client-server architecture

- -As we already mentioned, the server and a client communicates over a -communication channel. This channel is composed of two layers: the -low-level one, which is responsible for carrying bytes in a reliable -way (that is with no loss nor duplication). This link may be among -others a named pipe in the Unix environment, a DECNet link and of -course a TCP/IP connection. - -

- -The upper layer use the byte-transport channel to implement a -higher-level protocol: the X protocol. This protocol says how to tell -the server to request window creation, graphics drawing, and so on, -and how the server answers and sends events. The protocol itself is -separated into different parts: - -

    - -
  • How to connect and how to break a connection, -
  • how to represent the different data types, -
  • what are the requests and what they mean and -
  • what are the replies and what they mean. - -
- -[to be continued]. - -
Christophe Tronche, ch.tronche@computer.org
- - -- cgit v1.3