libk  Check-in [b5f6f19923]

Overview
Comment:updates, begin putting together error-handling mechanism
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: b5f6f199234d0ec07678fe8e9a8b102e289e1266c3e54b934fce5a73c38537e0
User & Date: lexi on 2019-08-19 01:46:21
Other Links: manifest | tags
Context
2019-08-19
02:04
add makerule, add include mode to typesize check-in: 8b84a67d85 user: lexi tags: trunk
01:46
updates, begin putting together error-handling mechanism check-in: b5f6f19923 user: lexi tags: trunk
2019-08-18
18:29
add error reporting to kiosend() check-in: b2f129d7b9 user: lexi tags: trunk
Changes

Modified arch/x86.lin.32.s from [d3081be9ee] to [a7ffc6f8bf].

     1         -;; abi definition file for x86 linux 32-bit
     2         -; vim: ft=nasm
     3         -
     4         -; syscall32 numbers - syscall table must be created first!
     5         -%include "system_calls.s"
     6         -
     7         -; syscall32 registers
     8         -%define sys.reg.n 6
     9         -%define sys.reg.0 eax
    10         -%define sys.reg.1 ebx
    11         -%define sys.reg.2 ecx
    12         -%define sys.reg.3 edx
    13         -%define sys.reg.4 esi
    14         -%define sys.reg.5 edi
    15         -
    16         -%macro sys 1-6
    17         -	%assign i 0
    18         -	%rep %0
    19         -		mov sys.reg. %+ i, %1 ; i'm actually shocked this worked
    20         -		%rotate 1
    21         -		%assign i i+1
    22         -	%endrep 
    23         -	syscall
    24         -%endmacro
    25         -
    26         -%define sys.call int 0x80 ; sysenter is allegedly the
    27         -  ; politically correct option but it does not actually
    28         -  ; appear to work without a whole lot of extra bullshit
    29         -
    30         -; todo: learn vdsos

Added global/build-id.sh version [5d0ff4e06b].

            1  +#!/usr/bin/env sh
            2  +. global/common.sh
            3  +
            4  +origin=1566169297
            5  +now=$(date +%s)
            6  +delta=$(expr $now - $origin)
            7  +
            8  +
            9  +if test "$1" = "private"; then
           10  +	# for privacy's sake, we're not to show
           11  +	# the hostname. instead, we calculate a
           12  +	# hash based on the  time delta and the
           13  +	# output of uname -a for extra entropy
           14  +	if has "$HASH"; then
           15  +		hash="$HASH"
           16  +	elif has sha1; then
           17  +		hash=sha1
           18  +	elif has sha1sum; then
           19  +		hash=sha1sum
           20  +	else
           21  +		say "cannot find a hashing function; privacy mode cannot be used"
           22  +		exit 1
           23  +	fi
           24  +
           25  +	h=$(printf "%x%s" "$delta" "$(uname -a)" | $hash)
           26  +	echo ${h:1:7}
           27  +else
           28  +	printf "%x:%s" $delta $(uname -n)
           29  +fi

Added global/common.sh version [4d96b9fc79].

            1  +me=$0
            2  +say() { echo >&2 "($me) $1";      }
            3  +has() { which $1 >/dev/null 2>&1; return $?; }
            4  +check() {
            5  +	var=$1
            6  +	test "${!var}" == "" || return 0
            7  +	say "we were not able to detect a default value for the configuration variable \$$var. please set this variable to $2 and try again."
            8  +	exit 1
            9  +}

Added global/emit-manpage.sh version [199ffb3202].

            1  +#!/usr/bin/env sh
            2  +(test -d global && test -d $1) || {
            3  +	echo >&2 "($0) run $me from root of libk source directory"
            4  +	exit 1
            5  +}
            6  +
            7  +. global/common.sh
            8  +test "$OUT" = "" && {
            9  +	say "\$OUT environment variable must be set to your build directory - are you running this script by hand? run make doc in the root directory instead!"
           10  +	exit 2
           11  +}
           12  +
           13  +if ! has cmark; then
           14  +	say "to generate documentation for libk, install the cmark package and try again"
           15  +	exit 3
           16  +fi
           17  +
           18  +
           19  +name=$1
           20  +mandest=$OUT/doc/man
           21  +out=$2
           22  +file=$name/$name.md
           23  +desc="$(grep -m1 "^$name:" global/modules | cut -d: -f4)"
           24  +date="$(date -r"$file" "+%d %A %Y")"
           25  +
           26  +mkdir -p $mandest
           27  +
           28  +echo  >$out ".TH ${name^^} \"$section\" \"$date\" \"hale.su libk [r$BUILD]\" \"modules\""
           29  +
           30  +echo >>$out ".SH NAME"
           31  +echo >>$out "$name - $desc"
           32  +echo >>$out ".SH SYNOPSIS" 
           33  +
           34  +dhead=$(grep -m1 -n "^# description$" $file)
           35  +if test $? -eq 0; then
           36  +	descline=$(echo "$dhead" | cut -d: -f1)
           37  +	offset=1
           38  +else
           39  +	descline=$(grep -m2 -n "^#" $file | tail -n1 | cut -d: -f1)
           40  +	offset=0
           41  +fi
           42  +
           43  +tail -n+2 $file | head -n$(expr $descline - 2) | cmark -t man >> $out
           44  +
           45  +echo >>$out ".SH DESCRIPTION"
           46  +
           47  +tail -n+$(expr $descline + $offset) $file  | cmark -t man >> $out
           48  +
           49  +say "wrote manpage for $name to $file"

Added global/genconds.awk version [d4ceed024e].

            1  +BEGIN { FS=":"
            2  +	offset = 0x7F
            3  +
            4  +	print "#ifndef KIglobal_cond"
            5  +	print "#define KIglobal_cond"
            6  +	print "typedef enum kglobal_cond {"
            7  +	printf("kglobal_module_offset = 0x%x,\n", offset)
            8  +}
            9  +
           10  +$2 == "short" { printf("\t%scond_id = 0x%x,\n", $3, offset*NR) }
           11  +$2 == "long" { printf("\t%s_cond_id = 0x%x,\n", $3, offset*NR) }
           12  +
           13  +END {
           14  +	print "} kglobal_cond;"
           15  +	print "extern struct kglobal_module_record"
           16  +	print "\t{ const char* name, * desc, ** error_list }"
           17  +	print "\tkglobal_module_ident[];"
           18  +	print "#endif"
           19  +}

Added global/genident.awk version [730afca5a3].

            1  +BEGIN {
            2  +	defs = ""
            3  +	FS = ":"
            4  +	ORS = ""
            5  +	print "#include <k/internal.egroup.h>\n"
            6  +	print "extern const char"
            7  +}
            8  +
            9  +{
           10  +	if (NR != 1) sep = ","
           11  +	print sep"\n\t*"$1"_error_strings[]"
           12  +	defs = defs "\t{ \""$1"\", \"k "$4"\", "$1"_error_strings },\n"
           13  +}
           14  +
           15  +END {
           16  +	print ";\n"
           17  +	print "struct kglobal_module_record kglobal_module_ident[] = {\n"
           18  +		print defs
           19  +	print "};"
           20  +}

Added global/modules version [4da066f235].

            1  +kbuild:long:kbuild:build tool
            2  +kconf:long:kconf:config parser
            3  +kcli:long:kcli:CLI utilities
            4  +kcore:short:kc:core definitions and routines
            5  +kdb:long:kdb:database
            6  +kdbg:long:kdbg:debug toolkit
            7  +kfile:short:kf:file control
            8  +kgraft:long:kgraft:grafting tool
            9  +kio:short:kio:input/output routines
           10  +kmem:short:km:memory management routines
           11  +kmsg:long:kmsg:IPC routines
           12  +knet:long:knet:network routines
           13  +knum:short:kn:math and number tools
           14  +kproc:short:kp:process control
           15  +kstr:short:ks:string toolkit
           16  +kterm:short:kt:terminal control facility

Deleted kcli/kcli.md version [09b7990027].

     1         -# kcli
     2         -**kcli** is a module that implements common routines used by command-line utilities, such as option parsing, usage display, and more.
     3         -
     4         -## functions
     5         -
     6         -### kcli_usage(kcli_set, kiochan)
     7         -kcli_usage() takes a `kcli_set` and prints a succinct usage summary to a [kiochan](../kio/kio.md).
     8         -
     9         -## types
    10         -
    11         -### struct kcli_set
    12         -`kcli_set` is a struct containing information about your program, such as its name, a synopsis of its function, a pointer to `argv`, and a list of `kcli_opt`s.
    13         -
    14         - * `const char* name` - program name (if null, will be determined from argv instead)
    15         - * `size_t argc` - the number of arguments in the `argv` array.
    16         - * `const char** argv` - the `argv` pointer passed to the `entry` function, representing the command-line arguments passed to the program.
    17         - * `const char* desc` - program description
    18         - * `const kcli_param* params` - a list of options expected by the program.
    19         - * `size_t paramc` - the number of params in the list to process.
    20         - * `const kcli_opt* opts` - a list of options expected by the program.
    21         - * `size_t optc` - the number of options in the list to process.
    22         -
    23         -a kcli_set might be used like so:
    24         -
    25         -    #include <k/core.h>
    26         -    #include <k/io.h>
    27         -    #include <k/cli.h>
    28         -    stat entry(kenv e) {
    29         -    	kcli_flag aardvark;
    30         -    	kcli_flag zebra;
    31         -    	char* user;
    32         -    	char* password;
    33         -		long age;
    34         -		kcli_param params[] = {
    35         -    		{ "user", kcli_param_string, kcli_class_required,
    36         -    		  &user, "the user to log in as" }
    37         -			  // or Kcli_param(user,string,required,"the user to log in as"),
    38         -
    39         -			{ "age", kcli_param_dec, kcli_class_optional,
    40         -    		  &age, "the age of the user" }
    41         -			  // or Kcli_param(age,dec,optional,"the age of the user"),
    42         -		};
    43         -    	kcli_opt options[] = {
    44         -    		{ 'a', "aardvark", kcli_opt_flag, &aardvark,
    45         -    		  "a nocturnal burrowing mammal" },
    46         -			  // or Kcli_opt(aardvark, 'a', flag, "a nocturnal burrowing mammal")
    47         -    		{ 'z', "zebra", kcli_opt_flag, &zebra,
    48         -    		  "a striped equine" },
    49         -    		{ 'p', "password", kcli_opt_string, &password,
    50         -    		  "the password to log in with" }
    51         -    	};
    52         -    	kcli_set argset = {
    53         -    		"demo", e.argc, e.argv,
    54         -    		"a demonstration of the kcli_set type",
    55         -			params, Kmsz(params),
    56         -			options, Kmsz(options)
    57         -    	},
    58         -		size_t args_parsed = kcli_parse(&argset);
    59         -		if (args_parsed == 0) { kcli_usage(&me, e.err); return 1; }
    60         -
    61         -		return 0;
    62         -	}
    63         -
    64         -### struct kcli_opt
    65         -a `kcli_opt` is a representation of a command-line flag and its function. each option must have a unique `id` and/or a unique `name`.
    66         -
    67         - * `char id` - the short single-character form of the flag (or NUL for no short form)
    68         - * `const char* name` - the long string form of the flag (or NULL for no long form)
    69         - * `kcli_opt_kind kind` - enum that describes how the flag will function
    70         - * `void* val` - a pointer to an appropriate type to store the return value in.
    71         - * `const char* desc` - a description of the flag's purpose and function (or NULL for no description)
    72         -
    73         -#### enum kcli_opt_kind
    74         -
    75         - * `kcli_opt_none` - flag is disabled and will not be shown in usage
    76         - * `kcli_opt_string` - flag tells kcli to add a string to the list of expected parameters; appropriate string will be returned
    77         - * `kcli_opt_oct` - flag tells kcli to add an octal number to the list of expected parameters
    78         - * `kcli_opt_dec` - flag tells kcli to add a decimal number to the list of expected parameters
    79         - * `kcli_opt_hex` - flag tells kcli to add a hexdecimal number to the list of expected parameters
    80         - * `kcli_opt_flag` - flag is an option: will return `kcli_flag_on` if entered at least once, `kcli_flag_off` otherwise.
    81         - * `kcli_opt_toggle` - flag toggles value on and off: will return `kcli_flag_on` if entered an odd number of times, `kcli_flag_off` otherwise.
    82         - * `kcli_opt_accumulate` - flag increments a value every time it is entered; often used to implement `-v (--verbose)`-style options (e.g. `-vvvv` would return a value of `4`).
    83         - * `kcli_opt_enum` - flag is one of a series of enumerated values, which will be matched against a table to yield the associated integer.
    84         -
    85         -### struct kcli_param
    86         -`kcli_param` describes a parameter that may be passed to the program whether or not any flags are passed.
    87         -
    88         - * `const char* name` - a short name for the parameter
    89         - * `kcli_param_kind kind` - the kind of parameter passed
    90         - * `kcli_class class` - whether or not the parameter is optional
    91         - * `void* val` - a pointer to an appropriate type of variable to fill
    92         - * `const char* desc` - a description of the parameter's function
    93         -
    94         -#### enum kcli_param_kind
    95         - * `kcli_param_none` - parameter is disabled and will not be expected or accepted
    96         - * `kcli_param_string` - parameter will not be parsed; a raw string will be returned
    97         - * `kcli_param_oct` - parameter will be parsed as an octal number
    98         - * `kcli_param_dec` - parameter will be parsed as a decimal number
    99         - * `kcli_param_hex` - parameter will be parsed as a hexadecimal number
   100         -
   101         -### enum kcli_class
   102         - * `kcli_class_forbidden` - parameter may not be passed
   103         - * `kcli_class_optional` - parameter may or may not be passed
   104         - * `kcli_class_required` - parameter must be passed
   105         -
   106         -### enum kcli_flag
   107         -results that an option of kind `kcli_opt_flag` can return.
   108         -
   109         - * `kcli_flag_off = 0` - flag is off
   110         - * `kcli_flag_on = 1` - flag is on
   111         - 
   112         -## macros
   113         -
   114         -### Kcli_param(field, kind, class, description)
   115         -a convenience macro for filling out parameter lists.
   116         -
   117         -`Kcli_param(field,a,b,"description")` is transformed into:
   118         -
   119         -    { "field", kcli_param_a, kcli_class_b, &field, "description" }
   120         -
   121         -### Kcli_opt(field, kind, class, description)
   122         -a convenience macro for filling out option lists.
   123         -
   124         -`Kcli_opt(name,'n',string,"description")` is transformed into:
   125         -
   126         -    { 'n', "name", kcli_opt_string, &name, "description" }

Deleted kcli/makefile version [f0df06fe05].

     1         -include ../modmake

Modified kcore/core.h from [7135ae8006] to [632e354c90].

    17     17   typedef struct kenv {
    18     18   	kiochan std;
    19     19   	kiochan err;
    20     20   	sz argc; char** argv;
    21     21   	kvar* vars;
    22     22   } kenv;
    23     23   
    24         -
    25     24   /* i'm really sorry okay */
    26     25   typedef
    27     26   #if (__STDC_VERSION__ >= 199901L)
    28     27   	_Bool bool;
    29     28   #endif
    30     29   enum
    31     30   #if !(__STDC_VERSION__ >= 199901L)
................................................................................
    37     36   }
    38     37   #if !(__STDC_VERSION__ >= 199901L)
    39     38   	bool /* } bool ; */
    40     39   #endif
    41     40   ;
    42     41   
    43     42   #ifndef KFclean
           43  +#	include <k/internal.egroup.h>
           44  +#	define Kokay(cond) (((cond) % kglobal_module_offset) == 0)
    44     45   #	if (__STDC_VERSION__ >= 199901L) ||\
    45     46   	   (__cplusplus      >= 201103L)
    46     47   #		define KVvm_args __VA_ARGS__
    47     48   #		define KVvm_spec ...
    48     49   #		define KFfeat_variadic_macro
    49     50   #	else
    50     51   #		define KVvm_args K_TEMP_M2QD52
................................................................................
   142    143   #ifdef __cplusplus
   143    144   	[[noreturn]] void kstop(stat_long code);
   144    145   #elif __STDC_VERSION__ >= 201103L
   145    146   	_Noreturn void kstop(stat_long code);
   146    147   #else
   147    148   	void kstop(stat_long code);
   148    149   #endif
          150  +
          151  +typedef u16 kcond;
          152  +/* this will probably not need to be altered,
          153  + * as libk sports a modest number of modules,
          154  + * and there are few enough error conditions
          155  + * in each  that 16-bit address space should
          156  + * be more  than enough for the  foreseeable
          157  + * future. however if that changes, altering
          158  + * the  definition here will effect all  the
          159  + * necessary changes throughout the library */
          160  +bool kokay(kcond);
   149    161   
   150    162   #ifdef __cplusplus
   151    163   }
   152    164   #endif
   153    165   
   154    166   #endif

Modified kcore/kcore.md from [a610cab74a] to [a74f6a9675].

     1      1   # kcore
     2      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         -## entry
     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.
            4  +# description
            5  +**kcore** contains the libk runtime and headers with important typedefs, structures and enumerations.
     6      6   
     7         -## types
     8         -kcore contains fixed-width integer types (in `<k/type.h>`). these types are present on every platform. if a platform has a type with a given bit length, it will be used, otherwise, the type will round to the largest available type (except `u8` and `s8`). 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)`.
            7  +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`.
            8  +
            9  +# program entry point
           10  +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.
           11  +
           12  +# core types
           13  +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)`.
     9     14   
    10     15    * `u8` - an unsigned 8-bit integer, or the smallest available unsigned type
    11     16    * `s8` - a signed 8-bit integer, or the smallest available signed type
    12     17    * `u16` - an unsigned 16-bit integer
    13     18    * `s16` - a signed 16-bit integer
    14     19    * `u32` - an unsigned 32-bit integer
    15     20    * `s32` - a signed 32-bit integer
................................................................................
    21     26    * `sbig` - 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.
    22     27    * `ubyte` - the smallest available unsigned integer type besides \_Bool
    23     28    * `sbyte` - the smallest available signed integer type besides \_Bool
    24     29    * `stat` - the type of process return values expected by the platform (usually u8 on linux)
    25     30    * `sz` - a type large enough to cover a platform's entire address space (libc equivalent size_t)
    26     31    * `offset` - a type that can contain the difference between two pointers (libc equivalent ptrdiff_t)
    27     32   
    28         -## constants
    29         -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`).
    30         -
    31     33    * `byte_bits` - the bit length of ubyte, sbyte, and char; that is, the number of bits in the type `sizeof` measures things in terms of. `sizeof(type) * byte_bits` will always return the number of bits in a type.
    32     34   
    33         -### struct kenv
           35  +**kcore** also defines a number of important structs.
           36  +
           37  +## struct kenv
    34     38   `kenv` is a struct that encompasses the environment the program was launched in.
    35     39    * `kiochan std` - a stereo IO channel for reading and writing to and from stdout.
    36     40    * `kiochan err` - a mono IO channel for writing to stderr.
    37     41    * `kvar* vars` - a pointer into the program's environment
    38     42   
    39         -### struct kvar
           43  +## struct kvar
    40     44   `kvar` is a struct that abstracts over platform environment variables.
    41     45    * `kstr name` - the name of an environment variable
    42     46    * `kstr val` - the value of an environment variable
    43     47    * `char* platform` - a pointer into the platform's underlying representation
    44     48   
    45         -## functions
           49  +# constants
           50  +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`).
           51  +
           52  +# functions
           53  +kcore contains only a handful of primitive functions, most of which provide the C runtime.
    46     54   
    47         -### kstop()
           55  +## kstop()
    48     56   
    49     57   `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>`).
    50     58   
    51         -## definitions
           59  +# definitions
    52     60   
    53     61   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>`.
    54     62   
    55     63   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.
    56     64   
    57     65   (the one minor exception is `null`, a new keyword which libk uses in preference to the ugly, hard-to-type C macro `NULL`.)
    58     66   
    59     67   `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`.
    60     68   
    61         -### macros
           69  +# macros
    62     70   
    63     71   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:
    64     72   
    65         -	* `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.
    66         -	* `KAnoreturn` - the GNU/clang-specific version of `noreturn`.
    67         -	* `KAunused` - acknowledges that a variable is unused and tells the compiler to shut up about it.
    68         -	* `KAinline` - forces the compiler to inline a function whether it likes it or not.
    69         -	* `KAflatten` - placed on a function, will force-inline all function calls *made by* that function — sort of like `KAinline` in reverse.
    70         -	* `KAformat()` - specifies that the function has printf-style syntax for error-checking purposes. worst hack in history.
           73  +  * `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.
           74  +  * `KAnoreturn` - the GNU/clang-specific version of `noreturn`.
           75  +  * `KAunused` - acknowledges that a variable is unused and tells the compiler to shut up about it.
           76  +  * `KAinline` - forces the compiler to inline a function whether it likes it or not.
           77  +  * `KAflatten` - placed on a function, will force-inline all function calls *made by* that function — sort of like `KAinline` in reverse.
           78  +  * `KAformat()` - specifies that the function has printf-style syntax for error-checking purposes. worst hack in history.
    71     79   
    72     80   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)`.
    73     81   
    74     82   however, unlike C++ attributes, GNU-style attributes can only be placed on a function declaration, *not* its definition.

Modified kio/io.h from [d3b54028db] to [2374315a32].

    45     45   typedef struct kiochan {
    46     46   	kiostream in;
    47     47   	  // text can be read from this stream
    48     48   	kiostream out;
    49     49   	  // text can be written to this stream
    50     50   } kiochan;
    51     51   
           52  +#include <k/internal.egroup.h>
    52     53   typedef enum kiocond {
    53     54   	/* to check if a call failed, perform (x >= kiocond_fail) where x
    54     55   	 * is that call's return value. more typically however you should
    55     56   	 * select explicitly against kiocond_ok or kiocond_partial, since
    56     57   	 * those situations will usually need to be handled differently. */
    57     58   
    58         -	kiocond_ok, // success
           59  +	kiocond_ok = kiocond_id, // success
           60  +
    59     61   	kiocond_partial, // partial read or write
    60     62   	kiocond_poll, // call would block
    61     63   	kiocond_interrupt, // call was interrupted by signal
    62     64   
    63     65       kiocond_fail, // action failed - unspecified reason
    64     66   	kiocond_fail_closed_stream, // action failed because stream is closed
    65     67   	kiocond_fail_invalid,

Deleted kmath/kmath.md version [4ac5812f7c].

     1         -# kmath
     2         -kmath contains libk's functions for dealing with numbers. kmath is intended to be much more consistent and generic than libc, with support for arbitrary bases, arbitrarily sized integers, and interfaces at varying levels of abstraction. (for instance, converting numbers to strings will not require invoking a string formatting routine or IO function; string formatting routines will invoke the same conversion functions that users can.) integers larger and smaller than processor types should also be supported, through functions over arrays and bitfield structs.

Deleted kmath/makefile version [f0df06fe05].

     1         -include ../modmake

Modified kmsg/kmsg.md from [1bf7781e05] to [9e287dbaef].

     1      1   # kmsg
            2  +kmsg is libk's inter-process communication library.

Added knum/knum.md version [608a5247b2].

            1  +# knum
            2  +knum contains libk's functions for dealing with numbers. knum is intended to be much more consistent and generic than libc, with support for arbitrary bases, arbitrarily sized integers, and interfaces at varying levels of abstraction. (for instance, converting numbers to strings will not require invoking a string formatting routine or IO function; string formatting routines will invoke the same conversion functions that users can.) integers larger and smaller than processor types should also be supported, through functions over arrays and bitfield structs.

Added knum/makefile version [f0df06fe05].

            1  +include ../modmake

Modified kproc/kproc.md from [ca8b9fab82] to [4efe5a2b89].

     1      1   # kproc
            2  +kproc is libk's library for starting, handling, and controlling userspace processes.

Modified kstr/str.h from [a9e92726f6] to [0c79e2a160].

    18     18   } ksraw;
    19     19   
    20     20   typedef struct ksmut {
    21     21   	sz size;
    22     22   	char* ptr;
    23     23   } ksmut;
    24     24   
           25  +#include <k/internal.egroup.h>
    25     26   typedef enum kscond {
    26         -	kscond_ok,
           27  +	kscond_ok = kscond_id,
    27     28   	kscond_fail,
    28     29   	kscond_unimplemented,
    29     30   	kscond_nonnumeric,
    30     31   } kscond;
    31     32   
    32     33   enum ksconv {
    33     34   	ksconv_default = 0,

Modified makefile from [ed3c61cbaa] to [0343c70b67].

     3      3   # TODO: calculate these using $(MAKE_HOST)
     4      4   export ARCH = x86
     5      5   export OS = lin
     6      6   export BITS = 64
     7      7   export ROOT = $(PWD)
     8      8   export TMP = $(PWD)/gen
     9      9   
           10  +export BUILD = $(shell global/build-id.sh) $(build-host)
           11  +
    10     12   ifneq ($(BITS),)
    11     13       export TARGET = $(ARCH).$(OS).$(BITS)
    12     14   else
    13     15       export TARGET = $(ARCH).$(OS)
    14     16   endif
    15     17   
    16     18   export m4 = m4
    17     19   
    18         -moddirs = $(wildcard k*)
    19         -binaries = $(wildcard k*/*.exe.c)
    20         -functions = $(wildcard k*/*.fn.c) 
    21         -assemblies = $(wildcard k*/*.fn.$(TARGET).s)
    22         -binmods = $(sort $(dir $(binaries)))
           20  +include makerule
           21  +
           22  +moddirs := $(wildcard k*)
           23  +binaries := $(wildcard k*/*.exe.c)
           24  +functions := $(wildcard k*/*.fn.c) 
           25  +assemblies := $(wildcard k*/*.fn.$(TARGET).s)
           26  +binmods := $(sort $(dir $(binaries)))
    23     27   
    24     28   # i'm sorry
    25     29   collect = $(strip $(foreach dir,$(moddirs),$(wildcard $(dir)/*.$1)))
    26     30   transform = $(strip $(foreach dir,$(moddirs),$(patsubst $(dir)/%.$1,$(subst @,$(dir),$2),$(wildcard $(dir)/*.$1))))
    27     31   
    28         -m-hdr-macs = $(call collect,h.m)
    29         -m-c-src-macs = $(call collect,c.m)
    30         -m-s-src-macs = $(call collect,$(TARGET).s.m)
    31         -
    32         -m-c-sources = $(call transform,c.m,$(TMP)/@.%.c)
    33         -m-s-sources = $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s)
    34         -
    35         -m-headers = $(call transform,h.m,$(OUT)/k/%.h)
    36         -m-c-objects = $(call transform,c.m,$(OUT)/@.%.o)
    37         -m-s-objects = $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o)
    38         -
    39         -fnobjects = $(call transform,fn.c,$(OUT)/@.%.fn.o) \
    40         -            $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \
    41         -            $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \
    42         -            $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o)
    43         -
    44         -rtobjects = $(call transform,rt.c,$(OUT)/@.%.rt.o) \
    45         -            $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \
    46         -            $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \
    47         -            $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o)
    48         -
    49         -objects = $(fnobjects) $(rtobjects)
    50         -
    51         -header-dir = /usr/include
    52         -lib-dir = /usr/lib
           32  +m-hdr-macs := $(call collect,h.m)
           33  +m-c-src-macs := $(call collect,c.m)
           34  +m-s-src-macs := $(call collect,$(TARGET).s.m)
           35  +
           36  +m-c-sources := $(call transform,c.m,$(TMP)/@.%.c)
           37  +m-s-sources := $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s)
           38  +
           39  +m-headers := $(call transform,h.m,$(OUT)/k/%.h)
           40  +m-c-objects := $(call transform,c.m,$(OUT)/@.%.o)
           41  +m-s-objects := $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o)
           42  +
           43  +fnobjects := $(call transform,fn.c,$(OUT)/@.%.fn.o) \
           44  +             $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \
           45  +             $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \
           46  +             $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o)
           47  +
           48  +rtobjects := $(call transform,rt.c,$(OUT)/@.%.rt.o) \
           49  +             $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \
           50  +             $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \
           51  +             $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o)
           52  +
           53  +docs := $(wildcard k*/*.md)
           54  +docs-out := $(patsubst %.md,$(OUT)/doc/man/%.4.gz,$(notdir $(docs)))
           55  +objects := $(fnobjects) $(rtobjects)
           56  +
           57  +prefix ?= /usr
           58  +d-header = $(prefix)/include
           59  +d-lib = $(prefix)/lib
           60  +d-share = $(prefix)/share
    53     61   
    54     62   unix-oses = lin fbsd dar and
    55         -posix-oses = lin fbsd dar and hai mgw
           63  +posix-oses = lin fbsd dar and hai mgw cyg
    56     64   
    57     65   ifeq ($(findstring $(OS),$(unix-oses)),$(OS))
    58     66       export UNIX = yes
    59     67       export POSIX = yes
    60     68   else
    61     69       export UNIX = no
    62     70       ifeq ($(findstring $(OS),$(posix-oses)),$(OS))
................................................................................
    64     72   	else
    65     73           export POSIX = no
    66     74   	endif
    67     75   endif
    68     76   
    69     77   # include libgcc.a in gcc builds, just in case
    70     78   ifeq ($(CC),gcc)
    71         -export COMPLIB = -lgcc
           79  +    export COMPLIB = -lgcc
    72     80   endif
    73     81   
    74     82   all: $(OUT) defs obj tool lib.static $(OUT)/boot.o lib.shared
    75     83   lib.static: defs obj $(OUT)/libk.a
    76     84   lib.shared: defs obj $(OUT)/libk.so
    77     85   obj: $(moddirs:%=%.obj) 
    78     86   defs: $(moddirs:%=%.def) 
    79     87   tool: $(OUT)/boot.o $(OUT)/libk.a $(binmods:%=%.tool) 
           88  +doc: $(docs-out)
    80     89   clean:
    81     90   	rm -rf $(TMP) $(OUT)
    82     91   
    83     92   install: all
    84         -	install -d $(header-dir)/k -o root -g wheel
           93  +	install -d $(header-dir)/k $(share-dir)/k -o root -g wheel -m 0755
    85     94   	install $(OUT)/k/* $(header-dir)/k/ -o root -g wheel -m 0644
    86         -	install -d $(lib-dir)/k -o root -g wheel
    87         -	install $(OUT)/libk.a $(OUT)/libk.so $(OUT)/boot.o \
    88         -		$(lib-dir)/k/ -o root -g wheel -m 0644
           95  +	install $(OUT)/libk.a $(OUT)/libk.so \
           96  +		$(lib-dir) -o root -g wheel -m 0644
           97  +	install $(OUT)/boot.o $(share-dir)/k/boot.o -o root -g wheel -m 0644
    89     98   
    90     99   uninstall: $(header-dir)/k $(lib-dir)/k
    91    100   	rm -rf $^
    92    101   
    93         -lists = moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX
          102  +lists = BUILD moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX docs docs-out
    94    103   dbg:
    95    104   	@echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))")
    96    105   
    97         -%.obj: %/makefile  $(OUT)
          106  +%.obj: %/makefile $(OUT)/internal.ident.o $(OUT)
    98    107   	cd $* && $(MAKE) obj
    99    108   
   100    109   %.tool: %/makefile $(OUT)
   101    110   	cd $* && $(MAKE) tool
   102    111   
   103    112   %.dbg: %/makefile $(OUT)
   104    113   	cd $* && $(MAKE) dbg
   105    114   
   106    115   %.def: %/makefile $(TMP)/typesize.def \
          116  +                  $(OUT)/k/internal.egroup.h \
   107    117                     $(TMP)/system_calls.h \
   108    118   				  $(TMP)/system_calls.s \
   109    119   				  $(TMP)/error_table.h \
   110    120   				  $(OUT) $(OUT)/k
   111    121   	cd $* && $(MAKE) def
   112    122   
   113    123   .PRECIOUS: $(TMP)/system_calls.%
................................................................................
   129    139   
   130    140   $(OUT)/libk.a: $(fnobjects) $(rtobjects)
   131    141   	@# using `ar rc` and ranlib here instead of
   132    142   	@# `ar rcs` in case `ar` isn't the GNU version
   133    143   	ar rc $@ $^
   134    144   	ranlib $@
   135    145   
          146  +$(OUT)/man/doc:
          147  +	mkdir -p $@
          148  +
          149  +$(OUT)/k/internal.egroup.h: global/modules global/genconds.awk $(OUT)/k
          150  +	awk -f global/genconds.awk <$< >$@
          151  +$(TMP)/internal.ident.c: global/modules global/genident.awk $(OUT)/k/internal.egroup.h $(TMP)
          152  +	awk -f global/genident.awk <$< >$@
          153  +$(OUT)/%.o: $(TMP)/%.c $(OUT)
          154  +	$(CC) $(cflags) -c $< -o $@
          155  +
   136    156   $(OUT) $(OUT)/k $(TMP):
   137    157   	mkdir -p $@

Modified modmake from [0390aebc43] to [2d5c92fb6a].

     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  +
            6  +include ../makerule
     5      7   
     6      8   mod = $(notdir $(PWD))
     7      9   src = $(wildcard *.c) $(wildcard *.s) $(filter-out %.h,$(patsubst %.m,%,$(wildcard *.m)))
     8     10   bare = $(mod:k%=%)
     9     11   headers = $(wildcard *.h) $(gen-headers) $(patsubst %.m,%,$(wildcard *.h.m))
    10     12   
    11     13   tools    = $(filter     %.exe.c,   $(src))
    12     14   nontools = $(filter-out %.exe.c,   $(src))
    13     15   cobjects = $(filter     %.c,       $(nontools))
    14     16   sobjects = $(filter %.${TARGET}.s, $(nontools))
    15     17   
    16         -cflags = -std=c11 -isystem ${OUT} -isystem ${TMP} -isystem ${ROOT}/arch -fPIC -nostdlib ${COMPLIB} -L${OUT}
    17         -
    18         -m-env = atom_target_arch=${ARCH}
    19         -m-env += atom_target_os=${OS}
    20         -ifneq (${BITS},) #!!! ifdef does NOT work with environment variables
    21         -    m-env += atom_target_bits=${BITS}
    22         -endif
    23         -m-env += target_posix=${POSIX}
    24         -m-env += target_unix=${UNIX}
    25         -
    26         -m-comp = ${m4} $(m-env:%=-D%)
    27         -
    28     18   obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \
    29     19   	 $(sobjects:%.s=${OUT}/$(mod).%.o)
    30     20   tool: $(tools:%.exe.c=${OUT}/$(mod).%) \
    31     21   	  ${OUT}/libk.a
    32     22   
    33     23   def: $(headers:%=${OUT}/k/%)
    34     24