Comment: | add a bunch of code, port the header mechanism to gpp; add a fuckton of definitions and compatibility header code; notably, add core function kstop and x86.lin.{32,64} impl. update docs accordingly |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e794c5edef00e56053792a71a97b4e5b |
User & Date: | lexi on 2019-06-29 09:31:50 |
Other Links: | manifest | tags |
2019-07-26
| ||
09:51 | major update. fix ridiculous old type size determination mechanism. mmap is still broken and i'm not sure why; the syscall does not appear to be going through correctly - see posix_mmap, kmheapa, and kcore/testbin.exe.fn check-in: 6479e060a3 user: lexi tags: trunk | |
2019-06-29
| ||
09:31 | add a bunch of code, port the header mechanism to gpp; add a fuckton of definitions and compatibility header code; notably, add core function kstop and x86.lin.{32,64} impl. update docs accordingly check-in: e794c5edef user: lexi tags: trunk | |
2019-06-28
| ||
04:52 | fix stupid bullshit that was including boot.o in libk.a which already HAS the runtime shit ohmyGOD check-in: de8e1eb5d2 user: lexi tags: trunk | |
Added grammar/grammar.gpp version [89005aac7c].
1 +#define flag -#1 2 +#define exec x 3 +#define mode flag(#1)#2 4 +#define user U 5 +#define meta M 6 +#define add +#1 7 +#define del -#1 8 +#define unix_lf z 9 +#define keepnl n 10 +#define tri #1#2#3 11 +#define comment c 12 +#define string s 13 +#define quote q 14 +#define eval S 15 +#define evalquote Q 16 +#define stack bal_stack bal_unstack 17 +#define meta_grammar meta_start meta_end meta_arg_start meta_sep meta_arg_end stack 18 +#define user_grammar call_start call_end arg_start arg_sep arg_end stack arg_num_char quote_char
Added grammar/makefile version [8c2d1af7ce].
1 +${TMP}/%: %.gpp grammar.gpp 2 + ${gpp} $< | tr "\n" ' ' > $@
Added grammar/precomp.g.gpp version [d33952f39e].
1 +#include grammar.gpp 2 +#mode comment "//" "\n" 3 +// this file defines the "precomp" grammar, the grammar 4 +// that's used to process C code templates 5 +// vim: ft=c 6 +#define call_start "[" 7 +#define call_end "]" 8 +#define arg_start " " 9 +#define arg_sep ",\\w" 10 +#define arg_end "]" 11 +#define bal_stack "\([" 12 +#define bal_unstack "\)]" 13 +#define arg_num_char "\\$" 14 +#define quote_char "|" 15 +#define meta_start "\\w[" 16 +#define meta_end "]\\w" 17 +#define meta_arg_start " " 18 +#define meta_sep "\\w:\\w" 19 +#define meta_arg_end "]\\W" 20 +add(unix_lf) 21 +add(comment "---" "\\n") 22 +add(comment "(*" "*)") 23 +flag(exec) 24 +mode(user, user_grammar) 25 +mode(meta, meta_grammar)
Added kcore/__stack_chk_fail.fn.c version [7f5547f66a].
1 +#include <k/core.h> 2 + 3 +void __stack_chk_fail(void) { kstop(-1); }
Modified kcore/boot.rt.x86.lin.64.s from [2671a43f32] to [22c891476d].
1 1 ; vim: ft=nasm 2 2 bits 64 3 3 %include "../arch/x86.lin.64.s" 4 4 global _start:function 5 5 extern _boot 6 -extern entry; 6 +extern entry 7 7 8 8 _start: 9 9 mov rbp, rsp 10 10 mov rdi, [rbp + 0] ; argc 11 11 lea rsi, [rbp + 8] ; argv 12 12 13 13 call _boot 14 14 15 15 mov sys.reg.1, sys.reg.ret 16 16 mov sys.reg.0, sys.exit 17 17 sys.call
Modified kcore/core.h from [cb5067b74b] to [ded1289884].
1 1 #ifndef KIcore 2 2 #define KIcore 3 3 #include <k/type.h> 4 4 #include <k/io.h> 5 5 #include <k/str.h> 6 6 7 -static void* const null = (void*)0; 8 - 9 7 typedef struct kvar { 10 8 ksraw name; 11 9 ksraw val; 12 10 char* platform; 13 11 } kvar; 14 12 15 13 typedef struct kenv { 16 14 kiochan std; 17 15 kiochan err; 18 16 sz argc; char** argv; 19 17 kvar* vars; 20 18 } kenv; 21 19 20 + 21 +/* i'm really sorry okay */ 22 +typedef 23 +#if (__STDC_VERSION__ >= 199901L) 24 + _Bool bool; 25 +#endif 26 +enum 27 +#if !(__STDC_VERSION__ >= 199901L) 28 + bool /* enum bool { */ 29 +#endif 30 +{ 31 + false = 0, no = 0, 32 + true = 1, yes = 1 33 +} 34 +#if !(__STDC_VERSION__ >= 199901L) 35 + bool /* } bool ; */ 36 +#endif 37 +; 38 + 39 +#ifndef KFclean 40 +# if (__STDC_VERSION__ >= 199901L) ||\ 41 + (__cplusplus >= 201103L) 42 +# define KVvm_args __VA_ARGS__ 43 +# define KVvm_spec ... 44 +# define KFfeat_variadic_macro 45 +# else 46 +# define KVvm_args K_TEMP_M2QD52 47 +# define KVvm_spec K_TEMP_M2QD52 48 +# endif 49 +# if defined(__GNUC__) || defined(__clang__) 50 +# define KA(KVvm_spec) __attribute__((KVvm_args)) 51 +# else 52 +# define KA(KVvm_spec) 53 +# endif 54 +# define KAformat(KVvm_spec) KA(format(KVvm_args)) 55 +# define KAexport(KVvm_spec) KA(visibility(KVvm_args)) 56 + 57 +# define KAunused KA(unused) 58 +# define KAnoreturn KA(noreturn) 59 +# define KApure KA(const) 60 +# define KAinline KA(always_inline) 61 +# define KAflatten KA(flatten) 62 +# define KAexport_none KAexport("hidden") 63 +# define KAexport_force KAexport("default") 64 +/* now we define standard version flags, 65 + * to make it easy for the user to write 66 + * more portable code. */ 67 +# if (__STDC_VERSION__ >= 199901L) 68 +# define KFstd_c89 69 +# define KFstd_c99 70 +# define KVstd c99 71 +# else 72 +# ifdef __STDC__ 73 +# define KFstd_c89 74 +# define KVstd c89 75 +# else 76 +# define KVstd K&R /* UH OH */ 77 +# endif 78 +# endif 79 +# if (__STDC_VERSION__ >= 201103L) 80 +# define KFstd_c11 81 +# define KVstd c11 82 +# endif 83 +# ifdef __cplusplus 84 +# define KFstd_cpp 85 +# define KVstd c++ 86 +# if (__cplusplus >= 201103L) 87 +# define KFstd_cpp11 88 +# define KVstd c++11 89 +# endif /* TODO: add more */ 90 +# endif 91 +#endif 92 + 93 +/* hooo boy. null. that one's got a storied 94 + * history across the versions and dialects. 95 + * below, we try to find the ideal way to 96 + * offer a "null" "keyword" depending on 97 + * dialect, version, and whether the user 98 + * has asked for macros to be suspended. 99 + * note that this may result in no "null" 100 + * being defined in C++ or K&R C. */ 101 +#if defined (__cplusplus) && ! defined(KFclean) 102 +# if __cplusplus >= 201103L 103 +# define null nullptr 104 +# else 105 +# define null ((void*)0) 106 +# endif 107 +#elif defined __STDC__ 108 + enum { null = 0 }; 109 + /* believe it or not, this is actually 110 + * completely legal. doesn't even raise 111 + * a single warning. i was surprised too. */ 112 +#elif ! defined(KFclean) 113 +# define null ((void*)0) 114 +#endif 115 + 116 +#ifdef __cplusplus 117 +# define noreturn [[ noreturn ]] 118 +#elif __STDC_VERSION__ >= 201103L 119 +# define noreturn _Noreturn 120 +#else 121 +# define noreturn 122 +#endif 123 + 124 +noreturn void kstop(longstat code); 125 + 126 +#ifdef KFclean 127 +# undef noreturn 128 +#endif 129 + 22 130 #endif
Deleted kcore/def.fbsd.i version [4373f0187e].
1 -#define KVos fbsd 2 -typedef unsigned char stat;
Deleted kcore/def.h version [5f84d85008].
1 -#include <k/type.h> 2 -/* <k/def.h> 3 - * ~ lexi hale <lexi@hale.su> 4 - * define flags so we can reason about 5 - * our environment. */ 6 - 7 -#if (KVos == lin) ||\ 8 - (KVos == fbsd) ||\ 9 - (KVos == obsd) ||\ 10 - (KVos == nbsd) ||\ 11 - (KVos == dar) ||\ 12 - (KVos == and) 13 -# define KFenv_unix 14 -#endif 15 - 16 -#if defined(KFenv_unix) ||\ 17 - (KVos == hai) ||\ 18 - (KVos == mgw) 19 -# define KFenv_posix 20 -#endif 21 -
Added kcore/def.h.m version [9abe158651].
1 +--- kcore/def.h.m → <k/def.h> 2 +--- ~ lexi hale <lexi@hale.su> 3 +--- this file gathers information on the environment it's 4 +--- being compiled in, setting macros that other headers 5 +--- need. it will be emitted as <k/def.h>. 6 +--- vim: ft=c 7 + 8 +[ifdef atom_target_bits] 9 + [define target: [atom_target_arch].[atom_target_os].[atom_target_bits]] 10 + #define KVbits [atom_target_bits] 11 +[else] 12 + [define target: [atom_target_arch].[atom_target_os]] 13 +[endif] 14 +#define KVtarget [target] 15 +#define KVos [atom_target_os] 16 +#define KVarch [atom_target_arch] 17 +[if [target_unix] == yes] 18 + #define KFenv_unix 19 + #define KFenv_posix 20 +[else] 21 + [if [target_posix] == yes] 22 + #define KFenv_posix 23 + [endif] 24 +[endif] 25 + 26 +#define Kpragma(p) _Pragma(#p) 27 +#if defined(__GNUC__) || defined(__clang__) 28 +# define Kerror(msg) Kpragma(GCC error #msg) 29 +#else 30 +# define Kerror(msg) Kpragma(message #msg) 31 +#endif 32 +#define Knoimpl(fn) Kerror(no implementation of fn for platform [target])
Deleted kcore/def.lin.i version [0178d496a4].
1 -#define KVos lin 2 -typedef unsigned char stat;
Deleted kcore/def.win.i version [11ccc3c2e7].
1 -#define KVos win 2 -typedef u32 stat;
Added kcore/exit.fn.x86.lin.32.s version [4c4a17d7b6].
1 +bits 32 2 +%include "../arch/x86.lin.32.s" 3 +; vim: ft=nasm 4 +global kio_posix_exit 5 + 6 +kio_posix_exit: 7 + mov sys.reg.0, sys.call.exit 8 + mov sys.reg.1, [esp + 4] ; first C int argument 9 + sys.call 10 + ; does not return
Added kcore/exit.fn.x86.lin.64.s version [4c49f79d26].
1 +bits 64 2 +%include "../arch/x86.lin.64.s" 3 +%include "../arch/x86.cdecl.64.s" 4 +; vim: ft=nasm 5 + 6 +global kio_posix_exit 7 +kio_posix_exit: 8 + mov sys.reg.1, ccall.reg.0 ;nop - rdi → rdi 9 + mov sys.reg.0, sys.exit 10 + sys.call 11 + ; no return
Modified kcore/kcore.md from [d664110812] to [28cd81b166].
1 1 # kcore 2 -**kcore** is the foundation for the rest of libk. it defines types and structs that are needed by every program, and provides the stub that launches a program's "entry" function. 2 +**kcore** is the foundation for the rest of libk. it defines types and structs that are needed by every program, and provides the stub that launches a program's "entry" function. unlike the non-core modules, kcore definitions simply use the prefix `k-`. 3 3 4 4 ## entry 5 5 when using libk, your program's entry point will not be the `int main(int,char**)` function that libc opens into. libk will call the function `stat entry(kenv)` instead. like libc, the value returned by `entry` will be returned to the host platform. 6 6 7 7 ## types 8 8 kcore contains fixed-width integer types (in <k/type.h>). note that the availability of each depends on your platform; compilation will fail if e.g. you try to use a u64 or a u128 on a 32-bit platform, so where exact lengths are not required, you may wish to use the built-in C types instead. 9 9 ................................................................................ 28 28 * `kvar* vars` - a pointer into the program's environment 29 29 30 30 ### struct kvar 31 31 `kvar` is a struct that abstracts over platform environment variables. 32 32 * `kstr name` - the name of an environment variable 33 33 * `kstr val` - the value of an environment variable 34 34 * `char* platform` - a pointer into the platform's underlying representation 35 + 36 +## functions 37 + 38 +### kstop() 39 + 40 +`noreturn void kstop(stat)` terminates the program immediately, returning the specified integer to the OS as an exit status. the type of integer it takes depends on your operating system. consider using the `enum kbad` defines in `<k/magic.h>`, which are designed to standardize exit statuses across different software and are synchronized with a FreeBSD effort to do the same (`<sysexit.h`). 41 + 42 +## definitions 43 + 44 +kcore is the only module that defines any terms outside the k- namespace. the only terms it so defines are native C terms like `noreturn`, which are implemented as keywords in a reserved namespace (`_` followed by an uppercase letter; in this case, `_Noreturn`). macros are then defined in new headers for the "natural" version of the term in order to avoid breaking older code. examples of this technique are `<stdbool.h>` and `<stdnoreturn.h>`. since libk is designed for new, modern code, breaking old code isn't a concern, and we turn on all these new keywords as soon as you load `<k/core.h>`. 45 + 46 +libk attempts to find the best possible definition and implementation for these various types and keywords, abstracting across different C versions and dialects. you can go ahead and use the normal version of the keywords (e.g. `noreturn`, `bool`) no matter what kind of compiler you're using and you're guaranteed that as long as you don't go fiddling with undefined- or implementation behavior, your code will behave the same every time. at worst, it may lack a few optimizations or warnings. 47 + 48 +(the one minor exception is `null`, a new keyword which libk uses in preference to the ugly, hard-to-type C macro `NULL`.) 49 + 50 +`bool` is implemented as a `_Bool` typedef if `_Bool` is available, and as an enum typedef otherwise. either way, and regardless of whether `KFclean` has been defined, booleans can be used and set to the values `true`, `false`, `yes`, or `no`. `yes` and `true` are synonyms, as are `false` and `no`. 51 + 52 +### macros 53 + 54 +if the flag `KFclean` has not been defined, kcore defines a number of macros to abstract over nonstandard C features. for instance, the `KA*` macros can be used to specify GNU/clang attributes without worrying about compatibility, as they'll automatically be blanked under an incompatible compiler. the KA series includes: 55 + 56 + * `KApure` - marks a "pure" function that changes no state and only takes purely numeric arguments, allowing the compiler to avoid repetetive calls to it or even evaluate it at runtime. 57 + * `KAnoreturn` - the GNU/clang-specific version of `noreturn`. 58 + * `KAunused` - acknowledges that a variable is unused and tells the compiler to shut up about it. 59 + * `KAinline` - forces the compiler to inline a function whether it likes it or not. 60 + * `KAflatten` - placed on a function, will force-inline all function calls *made by* that function — sort of like `KAinline` in reverse. 61 + * `KAformat()` - specifies that the function has printf-style syntax for error-checking purposes. worst hack in history. 62 + 63 +if you wish to add more (there are like, hundreds) please consider making a merge request. however, the generic macro KA() is also available in the interim: `KA(unused)`. 64 + 65 +however, unlike C++ attributes, GNU-style attributes can only be placed on a function declaration, *not* its definition.
Added kcore/magic.h version [1f7f63c3e2].
1 +/* <k/magic.h> 2 + * ~ lexi hale <lexi@hale.su> 3 + * one of libk's biggest goals is standardization across 4 + * software. for this reason, we define here a variety 5 + * of "magical numbers" used to signal or describe 6 + * various states, messages, and errors. suggestions are 7 + * welcome. 8 + */ 9 +#include <k/type.h> 10 + 11 +typedef enum kbad { 12 + // values to be returned by an entry function 13 + kbad_ok = 0, 14 + /* the requested operation completed 15 + * successfully */ 16 + 17 + /* these are synchronized with freebsd's existing 18 + * sysexit.h conventions. */ 19 + kbad_usage = 64, 20 + /* # fbsd EX_USAGE 21 + * a usage screen was displayed to the user 22 + * on request or due to improperly formed call */ 23 + kbad_data = 65, 24 + /* # fbsd EX_DATAERR 25 + * data supplied by the user was incorrect in 26 + * some way */ 27 + kbad_no_input = 66, 28 + /* # fbsd EX_NOINPUT 29 + * input to the program is absent */ 30 + kbad_user = 67, 31 + /* # fbsd EX_NOUSER 32 + * these aren't the droids you're looking for */ 33 + kbad_host = 68, 34 + /* # fbsd EX_NOHOST 35 + * that host doesn't exist */ 36 + kbad_avail = 69, 37 + /* # fbsd EX_UNAVAILABLE 38 + * a necessary resource or support system isn't 39 + * available, or something else went wrong */ 40 + kbad_internal = 70, 41 + /* # fbsd EX_SOFTWARE 42 + * "my bad" */ 43 + kbad_os = 71, 44 + /* # fbsd EX_OSERR 45 + * the OS did a fucksy-wucksy */ 46 + kbad_osfile = 72, 47 + /* # fbsd EX_OSFILE 48 + * a system file is fucked up or gone */ 49 + kbad_creat = 73, 50 + /* # fbsd EX_CANTCREAT */ 51 + kbad_io = 74, 52 + /* # fbsd EX_IOERR */ 53 + kbad_try = 75, 54 + /* # fbsd EX_TEMPFAIL 55 + * something went wrong this time. try again 56 + * some other time */ 57 + kbad_proto = 76, 58 + /* # fbsd EX_PROTOCOL 59 + * failure to speak a protocol correctly */ 60 + kbad_perm = 77, 61 + /* # fbsd EX_NOPERM 62 + * you or the program do not have permissions 63 + * to do the thing requested */ 64 + kbad_conf = 78, 65 + /* # fbsd EX_CONFIG 66 + * your configuration is fucked */ 67 +} kbad;
Modified kcore/makefile from [121a62ca71] to [c01fcd380e].
1 1 ## kcore/makefile 2 2 # kcore has to include, among other things, a replacement 3 -# for stddef.h, and that can't be written in portable C, 3 +# for stddef.h, and that can't be written in portable C. 4 4 # so we're generating it at build time. 5 + 6 +# gen-headers = type.h 7 + 8 +include ../modmake 9 + 10 +## the below code predates the introduction of gpp 11 +## to generate these headers from templates instead 12 +## of trying to write one for everypossible arch 13 +## tuple. it is left as a monument to a terrible 14 +## and now blissfully forgotten past. 5 15 # 6 16 # look, imma just be straight with you. the mechanism we're 7 17 # using to generate these headers is unbelievably heinous. 8 18 # it's inelegant, it's gross, and it's horrible. in the long 9 19 # term this NEEDS to be replaced with a bespoke solution 10 20 # instead of makefile gibberish. hopefully tho this will be 11 21 # enough in the short term for libk to get going, enough that 12 22 # someone more competent than me will someday be interested 13 23 # in fixing this horrorshow. 14 24 # 15 25 # until them: i'm sorry. 16 26 # very sincerely yours, lexi hale 17 - 18 -gen-headers = type.h 19 - 20 -include ../modmake 21 - 22 -${OUT}/k/type.h: ${TMP}/type.${TARGET}.i 23 - cp $< $@ 24 - 25 -# generating C source in make… yaaay 26 -define arch = 27 -${TMP}/type.$(1).%.$(2).i: type.$(1).$(2).i def.%.i ${TMP} 28 - echo '#ifndef KItype' > $$@ 29 - echo '#define KItype' >> $$@ 30 - cat $$< >> $$@ 31 - cat def.$$*.i >> $$@ 32 - echo '#endif' >> $$@ 33 -endef 34 - 35 -$(eval $(call arch,x86,32)) 36 -$(eval $(call arch,x86,64)) 37 - 27 +# ${OUT}/k/type.h: ${TMP}/type.${TARGET}.i 28 +# cp $< $@ 29 +# 30 +# # generating C source in make… yaaay 31 +# define arch = 32 +# ${TMP}/type.$(1).%.$(2).i: type.$(1).$(2).i def.%.i ${TMP} 33 +# echo '#ifndef KItype' > $$@ 34 +# echo '#define KItype' >> $$@ 35 +# cat $$< >> $$@ 36 +# cat def.$$*.i >> $$@ 37 +# echo '#endif' >> $$@ 38 +# endef 39 +# 40 +# $(eval $(call arch,x86,32)) 41 +# $(eval $(call arch,x86,64)) 42 +#
Added kcore/old/def.fbsd.i version [4373f0187e].
1 +#define KVos fbsd 2 +typedef unsigned char stat;
Added kcore/old/def.h version [074eb1cc6b].
1 +#include <k/type.h> 2 +/* <k/def.h> 3 + * ~ lexi hale <lexi@hale.su> 4 + * define flags so we can reason about 5 + * our environment. */ 6 + 7 +#if (KVos == lin) ||\ 8 + (KVos == fbsd) ||\ 9 + (KVos == obsd) ||\ 10 + (KVos == nbsd) ||\ 11 + (KVos == dar) ||\ 12 + (KVos == and) 13 +# define KFenv_unix 14 +#endif 15 + 16 +#if defined(KFenv_unix) ||\ 17 + (KVos == hai) ||\ 18 + (KVos == mgw) 19 +# define KFenv_posix 20 +#endif 21 + 22 +#define Kpragma(p) _Pragma(#p) 23 +#if defined(__GNUC__) || defined(__clang__) 24 +# define Kerror(msg) Kpragma(GCC error #msg) 25 +#else 26 +# define Kerror(msg) Kpragma(message #msg) 27 +#endif 28 +#define Knoimpl(fn,p) Kerror(no implementation of fn for platform p)
Added kcore/old/def.lin.i version [0178d496a4].
1 +#define KVos lin 2 +typedef unsigned char stat;
Added kcore/old/def.win.i version [11ccc3c2e7].
1 +#define KVos win 2 +typedef u32 stat;
Added kcore/old/type.x86.32.i version [fe891b76db].
1 +#define KVarch x86 2 +#define KVbits 32 3 + 4 +typedef unsigned long sz; 5 + 6 +typedef unsigned char u8; 7 +typedef signed char s8; 8 +typedef unsigned short u16; 9 +typedef signed short s16; 10 +typedef unsigned long u32; 11 +typedef signed long s32; 12 + 13 +typedef u32 word; 14 +typedef s32 sword;
Added kcore/old/type.x86.64.i version [03a8b8f372].
1 +#define KVarch x86 2 +#define KVbits 64 3 + 4 +typedef unsigned long long sz; 5 + 6 +typedef unsigned char u8; 7 +typedef signed char s8; 8 +typedef unsigned short u16; 9 +typedef signed short s16; 10 +typedef unsigned long u32; 11 +typedef signed long s32; 12 +typedef unsigned long long u64; 13 +typedef signed long long s64; 14 +typedef __uint128_t u128; 15 +typedef __int128_t s128; 16 + 17 +typedef u64 word; 18 +typedef s64 sword;
Added kcore/stop.fn.c version [c4373dead4].
1 +/* kcore/stop.fn.c - kstop() 2 + * ~ lexi hale <lexi@hale.su> 3 + * this file defines a function that prematurely exits from 4 + * a running libk program with an appropriate exit status. */ 5 + 6 +#include <k/core.h> 7 +#include <k/def.h> // so we know what system this is 8 +#include <k/type.h> 9 + 10 +#ifdef KFenv_posix 11 +# define STOPFN kio_posix_exit 12 + extern void STOPFN(int); 13 +#else 14 + Knoimpl(kstop) 15 +#endif 16 + 17 +noreturn void kstop (longstat code) { STOPFN(code); }
Added kcore/testbin.exe.c version [f1bdb07ea2].
1 +#include <k/core.h> 2 +#include <k/mem.h> 3 +#include <k/io.h> 4 +#include <k/magic.h> 5 + 6 +kbad entry(kenv e) { 7 + const char msg[] = "hello from libk\n"; 8 + ksraw ptr = { Kmsz(msg), msg }; 9 + 10 + bool maybe = true; 11 + maybe = no; 12 + 13 + if (kiosend(e.std, ptr, null) == kiocond_ok) { 14 + return kbad_ok; 15 + } else { 16 + return kbad_io; 17 + } 18 +}
Added kcore/type.h.m version [8b1f2e0cb2].
1 +--- kcore/type.h.m → <k/def.h> 2 +--- ~ lexi hale <lexi@hale.su> 3 +--- this file gathers information on the environment it's 4 +--- being compiled in, defining types that our code 5 +--- needs. it will be emitted as <k/type.h>. 6 +--- vim: ft=c 7 + 8 +// arch bit length [atom_target_bits] 9 +--- make some gigantic fucking assumptions 10 +[if [atom_target_bits] >= 8] 11 + typedef unsigned char u8; 12 + typedef signed char s8; 13 + [if [atom_target_bits] >= 16] 14 + typedef unsigned short u16; 15 + typedef signed short s16; 16 + [if [atom_target_bits] >= 32] 17 + typedef unsigned long u32; 18 + typedef signed long s32; 19 + [if [atom_target_bits] >= 64] 20 + typedef unsigned long long u64; 21 + typedef signed long long s64; 22 + [if [atom_target_arch] == x86] 23 + #if defined(__GNUC__) || defined(__clang__) 24 + typedef __uint128_t u128; 25 + typedef __int128_t s128; 26 + #endif 27 + [endif] 28 + [endif] 29 + [endif] 30 + [endif] 31 +[endif] 32 + 33 +typedef u[atom_target_bits] sz; 34 +typedef s[atom_target_bits] ssz; 35 + 36 +--- make sure something unlikely doesn't happen 37 +[define [maxtype name, n]: 38 + [if [n] > [atom_target_bits]] 39 + typedef u[atom_target_bits] [name] 40 + [else] 41 + typedef u[n] [name] 42 + [endif]] 43 + 44 +// exit status integer types - pls use kbad in <k/magic.h> instead 45 +[if [target_posix] == yes] 46 + /* by convention, posix return values are 8-bit, 47 + * but note that many modern UNIXes do technically 48 + * support higher-bit values. for this reason, 49 + * longstat is defined differently under posix. */ 50 + typedef u8 stat; 51 + [maxtype longstat, 32]; 52 +[else] 53 + [if ([atom_target_os] == win) || 54 + ([atom_target_os] == vms)] 55 + [maxtype stat, 32] 56 + [else] 57 + typedef u8 stat; 58 + /* we don't know a specific exit status type 59 + * for your arch so we're going with a sane 60 + * default. if this is wrong, help us fix it! */ 61 + [endif] 62 + typedef stat longstat; 63 +[endif]
Deleted kcore/type.x86.32.i version [fe891b76db].
1 -#define KVarch x86 2 -#define KVbits 32 3 - 4 -typedef unsigned long sz; 5 - 6 -typedef unsigned char u8; 7 -typedef signed char s8; 8 -typedef unsigned short u16; 9 -typedef signed short s16; 10 -typedef unsigned long u32; 11 -typedef signed long s32; 12 - 13 -typedef u32 word; 14 -typedef s32 sword;
Deleted kcore/type.x86.64.i version [03a8b8f372].
1 -#define KVarch x86 2 -#define KVbits 64 3 - 4 -typedef unsigned long long sz; 5 - 6 -typedef unsigned char u8; 7 -typedef signed char s8; 8 -typedef unsigned short u16; 9 -typedef signed short s16; 10 -typedef unsigned long u32; 11 -typedef signed long s32; 12 -typedef unsigned long long u64; 13 -typedef signed long long s64; 14 -typedef __uint128_t u128; 15 -typedef __int128_t s128; 16 - 17 -typedef u64 word; 18 -typedef s64 sword;
Added kio/send.c version [d88d1642fe].
1 +#include <k/io.h> 2 +#include <k/core.h> 3 +#include <k/def.h> 4 +/* send.c - kiosend() 5 + * ~ lexi hale <lexi@hale.su> 6 + * kiosend() writes to a channel with an open out stream 7 + */ 8 + 9 +// we define all platform functions here, 10 +// whether or not they're for the correct 11 +// platform - only the ones actually called 12 +// by the generated code will be linked 13 +extern sz kio_posix_fd_write(int fd, const char* buf, sz len); 14 + 15 +kiocond kiosend(kiochan target, ksraw string, sz* len) { 16 +# ifdef KFenv_posix 17 + sz size = kio_posix_fd_write(target.out.platform_fd, string.ptr, string.size); 18 + if (size == -1) return kiocond_fail; //TODO: retrieve errno and offer more specific errors 19 +# else 20 +# if KVos == win 21 +# error windows IO send function not yet defined 22 +# else 23 + Knoimpl(kiosend,KVos); 24 +# error missing implementation // boring error for plebs 25 +# endif 26 +# endif 27 + 28 + if (len != null) *len = size; 29 + return kiocond_ok; 30 +}
Modified libk.md from [3c28c4d693] to [65938a7892].
25 25 5. **intrinsic reentrancy.** because *jesus christ,* libc. 26 26 6. **interprocess communication.** libc offers no useful IPC abstractions over the paltry array of tools POSIX &co. give us to work with. we can do better. 27 27 7. **tooling.** libk is intended as more than just a library. it's also intended to work with some basic tooling to automate tasks that current binary tooling is inadequate for -- for instance, embedding binary data into a program binary. (see module [kgraft](kgraft)) 28 28 8. **modularity.** libk is not part of the C specification and it isn't always going to be practical for developers to expect the entire library to be present on the end-user's computer. so libk is designed to be usable in many different ways -- as a traditional library, as a static library, in full form or with only components needed by the developer, to be distributed either on its own or as part of a binary. 29 29 9. **compatibility.** code that links against libk should be able to compile and run on any operating system. in the ideal case (Linux or FreeBSD) it will be able to do so without touching any other system libraries; for less ideal environments like Windows, libk will when necessary abstract over system libraries or libc itself. 30 30 10. **sane error-handling.** every time you type `errno` god murders a puppy. 31 31 32 +## dependencies 33 + 34 +libk is designed to be as portable and depedency-free as possible. ideally, it will be possible to compile code against libk using nothing but libk itself. 35 + 36 +compiling libk is also designed to be as easy as possible. it has only two external dependencies, the macro processor [gpp], needed for compile-time header generation , and the [GNU make] utility, whose advanced features are needed to perform the relatively complex task of building all of libk from the ground up. 37 + 38 + [gpp]: http://en.nothingisreal.com/wiki/GPP 39 + [GNU make]: http://www.gnu.org/software/make 40 + 41 +while gpp is a very small program that builds quickly and has no major dependencies of its own, it is an obscure program not likely to be found in any repositories and with an uncertain future. for these reasons, adding m4 translations of the gpp headers should be a long-term priority. being able to be built with both a very small, easily built macro processor, and a very large but extremely well-supported processor, should make libk maximally buildable and future-proof. 42 + 43 +while this project will include gpp tooling and GNU makefiles designed to ease the task of writing and building libk code (as well as tools in many other languages, including native binaries that compile against libk), none of them are required for the task. 44 + 32 45 ## naming conventions 33 46 34 47 one of the most frustrating things about libc is its complete and total *lack* of a naming convention. in C, every function and global is injected into a single global namespace, including macros. this means that every libc header you include scatters words all over that namespace, potentially clobbering your function with a macro! 35 48 36 49 libk is designed to fix this (in hindsight) glaring error. 37 50 38 51 however, a common problem with libraries is the proliferation of inordinately long and hard-to-type function names such as `SuperWidget_Widget_Label_Font_Size_Set()`. this may be tolerable in IDEs with robust auto-complete or when referencing a highly-specific, sparsely-used library; it is however completely intolerable in the case of a core library with heavily used functionality.
Modified makefile from [ac03aab83b] to [d63468c69f].
1 1 export OUT = $(PWD)/out 2 2 3 +# TODO: calculate these using $(MAKE_HOST) 3 4 export ARCH = x86 4 5 export OS = lin 5 6 export BITS = 64 6 7 export TMP = $(PWD)/tmp 7 8 8 -export TARGET = $(ARCH).$(OS).$(BITS) 9 +ifneq ($(BITS),) 10 + export TARGET = $(ARCH).$(OS).$(BITS) 11 +else 12 + export TARGET = $(ARCH).$(OS) 13 +endif 9 14 15 +export gpp = gpp 10 16 export lin-headers = /usr/include/asm 11 17 export fbsd-headers = /usr/include/sys 12 18 13 19 moddirs = $(wildcard k*) 14 20 binaries = $(wildcard k*/*.exe.c) 15 21 functions = $(wildcard k*/*.fn.c) 16 -assemblies = $(wildcard k*/*.fn.${TARGET}.s) 22 +assemblies = $(wildcard k*/*.fn.$(TARGET).s) 17 23 binmods = $(sort $(dir $(binaries))) 18 24 19 25 # i'm sorry 20 -collect = $(strip $(foreach dir,$(moddirs),$(addprefix $(OUT)/$(dir).,$(notdir $(wildcard $(dir)/$1))))) 26 +collect = $(strip $(foreach dir,$(moddirs),$(wildcard $(dir)/*.$1))) 27 +transform = $(strip $(foreach dir,$(moddirs),$(patsubst $(dir)/%.$1,$(subst @,$(dir),$2),$(wildcard $(dir)/*.$1)))) 21 28 22 -cfnsources = $(call collect,*.fn.c) 23 -sfnsources = $(call collect,*.fn.${TARGET}.s) 24 -crtsources = $(call collect,*.rt.c) 25 -srtsources = $(call collect,*.rt.${TARGET}.s) 26 -fnsources = $(cfnsources) $(sfnsources) 27 -rtsources = $(crtsources) $(srtsources) 28 -sources = $(fnsources) $(rtsources) 29 +m-hdr-macs = $(call collect,h.m) 30 +m-c-src-macs = $(call collect,c.m) 31 +m-s-src-macs = $(call collect,$(TARGET).s.m) 29 32 30 -cfnobjects = $(cfnsources:%.c=%.o) 31 -sfnobjects = $(sfnsources:%.s=%.o) 32 -crtobjects = $(crtsources:%.c=%.o) 33 -srtobjects = $(srtsources:%.s=%.o) 34 -fnobjects = $(cfnobjects) $(sfnobjects) 35 -rtobjects = $(crtobjects) $(srtobjects) 33 +m-c-sources = $(call transform,c.m,$(TMP)/@.%.c) 34 +m-s-sources = $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s) 35 + 36 +m-headers = $(call transform,h.m,$(OUT)/k/%.h) 37 +m-c-objects = $(call transform,c.m,$(OUT)/@.%.o) 38 +m-s-objects = $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o) 39 + 40 +fnobjects = $(call transform,fn.c,$(OUT)/@.%.fn.o) \ 41 + $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \ 42 + $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \ 43 + $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o) 44 + 45 +rtobjects = $(call transform,rt.c,$(OUT)/@.%.rt.o) \ 46 + $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \ 47 + $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \ 48 + $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o) 49 + 36 50 objects = $(fnobjects) $(rtobjects) 37 51 38 52 header-dir = /usr/include 39 53 lib-dir = /usr/lib 40 54 55 +unix-oses = lin fbsd dar and 41 56 posix-oses = lin fbsd dar and hai mgw 42 57 43 -ifeq ($(findstring $(OS),$(posix-oses)),$(OS)) 44 -export POSIX = yes 58 +ifeq ($(findstring $(OS),$(unix-oses)),$(OS)) 59 + export UNIX = yes 60 + export POSIX = yes 45 61 else 46 -export POSIX = no 62 + export UNIX = no 63 + ifeq ($(findstring $(OS),$(posix-oses)),$(OS)) 64 + export POSIX = yes 65 + else 66 + export POSIX = no 67 + endif 47 68 endif 48 69 49 70 # include libgcc.a in gcc builds, just in case 50 71 ifeq ($(CC),gcc) 51 72 export COMPLIB = -lgcc 52 73 endif 53 74 54 75 all: $(OUT) defs obj tool lib.static $(OUT)/boot.o lib.shared 55 76 lib.static: defs obj $(OUT)/libk.a 56 77 lib.shared: defs obj $(OUT)/libk.so 57 -obj: $(moddirs:%=%.obj) 58 -defs: $(moddirs:%=%.def) 59 -tool: $(OUT)/libk.a $(binmods:%=%.tool) 78 +obj: $(moddirs:%=%.obj) 79 +defs: $(moddirs:%=%.def) 80 +tool: $(OUT)/boot.o $(OUT)/libk.a $(binmods:%=%.tool) 60 81 clean: 61 82 rm -rf $(TMP) $(OUT) 62 83 63 84 install: all 64 85 install -d $(header-dir)/k -o root -g wheel 65 86 install $(OUT)/k/* $(header-dir)/k/ -o root -g wheel -m 0644 66 87 install -d $(lib-dir)/k -o root -g wheel 67 88 install $(OUT)/libk.a $(OUT)/libk.so $(OUT)/boot.o \ 68 89 $(lib-dir)/k/ -o root -g wheel -m 0644 69 90 70 91 uninstall: $(header-dir)/k $(lib-dir)/k 71 92 rm -rf $^ 72 93 73 -lists = moddirs functions assemblies cfnobjects sfnobjects crtobjects srtobjects rtobjects binaries binmods POSIX 94 +lists = moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX 74 95 dbg: 75 96 @echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))") 76 97 77 -%.obj: %/makefile ${TARGET}.calls $(OUT) 98 +%.obj: %/makefile $(TMP)/precomp.g $(TARGET).calls $(OUT) 78 99 cd $* && $(MAKE) obj 79 100 80 -%.tool: %/makefile $(OUT) 101 +%.tool: %/makefile $(TMP)/precomp.g $(OUT) 81 102 cd $* && $(MAKE) tool 82 103 83 104 %.dbg: %/makefile $(OUT) 84 105 cd $* && $(MAKE) dbg 85 106 86 -%.def: %/makefile $(OUT) $(OUT)/k 107 +%.def: %/makefile $(TMP)/precomp.g $(OUT) $(OUT)/k 87 108 cd $* && $(MAKE) def 88 109 89 110 %.calls: arch/makefile 90 111 cd arch && $(MAKE) $(TMP)/calls.$*.s 112 + 113 +$(TMP)/precomp.g: grammar/precomp.g.gpp $(TMP) 114 + cd grammar && $(MAKE) $@ 91 115 92 116 $(OUT)/libk.so: $(fnobjects) 93 117 ld -shared $(COMPLIB) -o $@ $^ 94 118 @# $(CC) -shared -fPIC -nostdlib $(COMPLIB) -o $@ $(OUT)/*.o 95 119 96 120 $(OUT)/boot.o: $(rtobjects) 97 121 ld -r $^ -o $(OUT)/boot.o ................................................................................ 98 122 99 123 $(OUT)/libk.a: $(fnobjects) $(rtobjects) 100 124 @# using `ar rc` and ranlib here instead of 101 125 @# `ar rcs` in case `ar` isn't the GNU version 102 126 ar rc $@ $^ 103 127 ranlib $@ 104 128 105 -$(OUT) $(OUT)/k: 129 +$(OUT) $(OUT)/k $(TMP): 106 130 mkdir -p $@
Modified modmake from [3c50b488d5] to [eb2aedd9b1].
1 1 #- modmake 2 2 # this is the master makefile that controls the building of each 3 3 # libk module. it is included from each k*/makefile. 4 4 # vim: ft=make 5 5 6 6 mod = $(notdir $(PWD)) 7 -src = $(wildcard *.c) $(wildcard *.s) 7 +src = $(wildcard *.c) $(wildcard *.s) $(filter-out %.h,$(patsubst %.m,%,$(wildcard *.m))) 8 8 bare = $(mod:k%=%) 9 -headers = $(wildcard *.h) $(gen-headers) 9 +headers = $(wildcard *.h) $(gen-headers) $(patsubst %.m,%,$(wildcard *.h.m)) 10 10 11 11 tools = $(filter %.exe.c, $(src)) 12 12 nontools = $(filter-out %.exe.c, $(src)) 13 13 cobjects = $(filter %.c, $(nontools)) 14 14 sobjects = $(filter %.${TARGET}.s, $(nontools)) 15 15 16 -cflags = -isystem ${OUT} -fPIC -nostdlib ${COMPLIB} -L${OUT} -lk 16 +gpp = gpp 17 +cflags = -std=c11 -isystem ${OUT} -fPIC -nostdlib ${COMPLIB} -L${OUT} 18 + 19 +m-env = atom_target_arch=${ARCH} 20 +m-env += atom_target_os=${OS} 21 +ifneq (${BITS},) #!!! ifdef does NOT work with environment variables 22 + m-env += atom_target_bits=${BITS} 23 +endif 24 +m-env += target_posix=${POSIX} 25 +m-env += target_unix=${UNIX} 26 + 27 +m-grammar = $(file < ${TMP}/precomp.g) 28 +m-comp = $(gpp) $(m-grammar) $(m-env:%=-D%) 17 29 18 30 obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \ 19 31 $(sobjects:%.s=${OUT}/$(mod).%.o) 20 32 tool: $(tools:%.exe.c=${OUT}/$(mod).%) \ 21 33 ${OUT}/libk.a 22 34 23 35 def: $(headers:%=${OUT}/k/%) 24 36 25 37 dbg: 38 + @echo src = $(src) 26 39 @echo tools = $(tools) 27 40 @echo TARGET = ${TARGET} 28 41 @echo cobjects = $(cobjects) 29 42 @echo sobjects = $(sobjects) 30 43 @echo headers = $(headers) 44 + @echo m-comp = $(m-comp) 45 + @echo m-grammar = $(m-grammar) 46 + @echo m-env = $(m-env) "$(m-env:%=-D%)" 31 47 @echo mod = $(mod) 32 48 33 -${OUT}/$(mod).%.o: %.c 49 +${OUT}/k/%.h: %.h.m 50 + $(m-comp) $< > $@ 51 + 52 +.PRECIOUS: ${TMP}/$(mod).% 53 +${TMP}/$(mod).%: %.m ${TMP} 54 + $(m-comp) $< > $@ 55 + 56 +${OUT}/$(mod).%.o: ${TMP}/$(mod).%.c 57 + $(CC) $(cflags) -c $< -o $@ 58 + 59 +${OUT}/$(mod).%.o: %.c $(bare).h 34 60 $(CC) $(cflags) -c $< -o $@ 35 61 36 62 ${OUT}/k/%.h: %.h 37 63 cp $< $@ 38 64 39 65 ${OUT}/$(mod).%: %.exe.c 40 - $(CC) $(cflags) $< -o $@ 66 + $(CC) $(cflags) $< ${OUT}/libk.a -o $@ 41 67 42 68 ${TMP}: 43 69 mkdir -p ${TMP} 44 70 45 71 #- assembly 46 72 # compiling the assembly code will be faster but a lot more 47 73 # complex, given the nature of assembly and the large number of ................................................................................ 50 76 # that requires ugly make rules, we're just going to use a 51 77 # function to generate these. 52 78 53 79 # ${OUT} = ultimate build directory 54 80 # $(mod) = module name 55 81 # % = function name 56 82 # $(1) = arch tuple 57 -arch = ${OUT}/$(mod).%.$(1).o: %.$(1).s 83 +arch = ${OUT}/$(mod).%.$(1).o: $2%.$(1).s 58 84 # invoke with $(call arch,tuple). do not 59 85 # put spaces between either term though! 60 86 61 87 ifeq ($(debug),yes) 62 88 yasm-flags = -gdwarf2 63 89 endif 64 90 91 +yasm = yasm $(yasm-flags) -f$1 -i${TMP} $< -o $@ 92 + 65 93 #-- linux 66 94 # linux uses the ELF{32,64} binary format, and generating these 67 95 # from yasm is trivial. linux only supports one ABI per format, 68 96 # at least with ELF, so that's all we need to do. 69 97 70 -#${OUT}/$(mod).%.x86.lin.32.o: %.x86.lin.32.s 71 -$(call arch,x86.lin.32) 72 - yasm $(yasm-flags) -felf32 -i${TMP} $< -o $@ 98 + 99 +$(call arch,x86.lin.32,) 100 + $(call yasm,elf32) 101 + 102 +$(call arch,x86.lin.64,) 103 + $(call yasm,elf64) 104 + 105 +$(call arch,x86.lin.32,${TMP}/$(mod).) 106 + $(call yasm,elf32) 73 107 74 -#${OUT}/$(mod).%.x86.lin.64.o: %.x86.lin.64.s 75 -$(call arch,x86.lin.64) 76 - yasm $(yasm-flags) -felf64 -i${TMP} $< -o $@ 108 +$(call arch,x86.lin.64,${TMP}/$(mod).) 109 + $(call yasm,elf64) 77 110 78 111 #-- freebsd 79 112 # the freebsd ABI is different, so it will require different code 80 113 # (though there might be ways to minimize that). freebsd uses the 81 114 # same binary format as Linux (though it also supports a.out and 82 115 # COFF) but because freebsd can interpret multiple different ABIs 83 116 # the object files need to be "branded" with the correct one 84 117 # using the tool brandelf (`brandelf -t [ABI]`) 85 118 86 -$(call arch,x86.fbsd.32) 87 - yasm -felf32 $< -o $@ 119 +$(call arch,x86.fbsd.32,) 120 + $(call yasm,elf32) 121 + brandelf -t FreeBSD $@ 122 + 123 +$(call arch,x86.fbsd.64,) 124 + $(call yasm,elf64) 88 125 brandelf -t FreeBSD $@ 89 126 90 -$(call arch,x86.fbsd.64) 91 - yasm -felf64 $< -o $@ 127 +$(call arch,x86.fbsd.32,${TMP}/$(mod).) 128 + $(call yasm,elf32) 92 129 brandelf -t FreeBSD $@ 93 130 131 +$(call arch,x86.fbsd.64,${TMP}/$(mod).) 132 + $(call yasm,elf64) 133 + brandelf -t FreeBSD $@