File mod/kcore/kcore.md artifact a74f6a9675 part of check-in 12a51d9c50
kcore
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-
.
description
kcore contains the libk runtime and headers with important typedefs, structures and enumerations.
it also provides boot.o
, the runtime file that must be statically linked into every libk program for it to be able to load. boot.o
is incorporated in the static library libk.a
but for architectural reasons cannot be exported from the dynamic library libk.so
.
program entry point
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. entry may have the return type stat
or stat_long
. on some operating systems, they are the same; on modern versions of UNIX, however, stat_long
will allow you to return a 32-bit exit status. most shells will truncate such statuses, but they can be retrieved be the calling process with the appropriate syscall.
core types
kcore contains fixed-width integer types (in <k/type.h>
). these types are present on every platform, and are not prefixed. if a platform has a type with a given bit length, that type will be used will be used, otherwise, the type will round to the largest available type (except u8
and s8
, which round to the smallest). if you need to be absolutely certain that a type is the appropriate bit length, use sizeof to check its length in a conditional or static assert, for instance if (sizeof(u16) == 16 / kc_byte_bits)
.
u8
- an unsigned 8-bit integer, or the smallest available unsigned types8
- a signed 8-bit integer, or the smallest available signed typeu16
- an unsigned 16-bit integers16
- a signed 16-bit integeru32
- an unsigned 32-bit integers32
- a signed 32-bit integeru64
- an unsigned 64-bit integers64
- a signed 64-bit integeru128
- an unsigned 128-bit integer (uses GCC and clang extensions to offer 128-bit integer support on x86-64)s128
- a signed 128-bit integer (ibid)ubig
- the largest available unsigned integer typesbig
- the largest available signed integer type. note: ubig and sbig really are the largest possible integer types not just the largest native types - if your compiler has extensions for 128-bit types on your arch (as GCC and clang do on x86-64), ubig and sbig will be 128 bits long even if your system word length is less than 128. so only use ubig/sbig if you really, really mean it.ubyte
- the smallest available unsigned integer type besides _Boolsbyte
- the smallest available signed integer type besides _Boolstat
- the type of process return values expected by the platform (usually u8 on linux)sz
- a type large enough to cover a platform's entire address space (libc equivalent size_t)offset
- a type that can contain the difference between two pointers (libc equivalent ptrdiff_t)byte_bits
- the bit length of ubyte, sbyte, and char; that is, the number of bits in the typesizeof
measures things in terms of.sizeof(type) * byte_bits
will always return the number of bits in a type.
kcore also defines a number of important structs.
struct kenv
kenv
is a struct that encompasses the environment the program was launched in.
* kiochan std
- a stereo IO channel for reading and writing to and from stdout.
* kiochan err
- a mono IO channel for writing to stderr.
* kvar* vars
- a pointer into the program's environment
struct kvar
kvar
is a struct that abstracts over platform environment variables.
* kstr name
- the name of an environment variable
* kstr val
- the value of an environment variable
* char* platform
- a pointer into the platform's underlying representation
constants
in <k/type.h>
, every type has an associated min and max constant, containing the smallest and largest value that type can hold on your system. these can be access by suffixing a type with _min
and _max
, respectively. min and max values of native types can be accessed with the kc_[us]
prefix - for instance, the minimum value of signed long
is kc_slong_min
. (long long
can be referenced as llong
).
functions
kcore contains only a handful of primitive functions, most of which provide the C runtime.
kstop()
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>
).
definitions
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>
.
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.
(the one minor exception is null
, a new keyword which libk uses in preference to the ugly, hard-to-type C macro NULL
.)
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
.
macros
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:
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.KAnoreturn
- the GNU/clang-specific version ofnoreturn
.KAunused
- acknowledges that a variable is unused and tells the compiler to shut up about it.KAinline
- forces the compiler to inline a function whether it likes it or not.KAflatten
- placed on a function, will force-inline all function calls made by that function — sort of likeKAinline
in reverse.KAformat()
- specifies that the function has printf-style syntax for error-checking purposes. worst hack in history.
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)
.
however, unlike C++ attributes, GNU-style attributes can only be placed on a function declaration, not its definition.