libk  Check-in [f5b7fa5762]

Overview
Comment:updates
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f5b7fa57628ccb9c61d9729b95f3861eaa0f432ed935140731689c2eff8fba7c
User & Date: lexi on 2019-06-27 05:52:40
Other Links: manifest | tags
Context
2019-06-27
09:57
add in mechanism to generate syscall tables for x86 linux check-in: 860229e8ce user: lexi tags: trunk
05:52
updates check-in: f5b7fa5762 user: lexi tags: trunk
2019-06-26
13:59
fix typo check-in: 4eb81c9227 user: lexi tags: trunk
Changes

Deleted arch/x86.lin.32.inc version [32148439cc].

     1         -; vim: ft=nasm
     2         -%define lin.call.exit 1
     3         -%define lin.call.fork 2
     4         -%define lin.call.read 3
     5         -%define lin.call.write 4
     6         -%define lin.call.open 5
     7         -%define lin.call.close 6
     8         -
     9         -%define lin.call.chdir 12
    10         -
    11         -%define lin.reg.n 6
    12         -%define lin.reg.0 eax
    13         -%define lin.reg.1 ebx
    14         -%define lin.reg.2 ecx
    15         -%define lin.reg.3 edx
    16         -%define lin.reg.4 esi
    17         -%define lin.reg.5 edi
    18         -
    19         -%define lin.call int 0x80 ; sysenter is allegedly the
    20         -  ; politically correct option but it does not actually
    21         -  ; appear to work without a whole lot of extra bullshit
    22         -
    23         -; todo: learn vdsos

Added arch/x86.lin.32.s version [7c5909e17f].

            1  +; vim: ft=nasm
            2  +%define sys.exit 1
            3  +%define sys.fork 2
            4  +%define sys.read 3
            5  +%define sys.write 4
            6  +%define sys.open 5
            7  +%define sys.close 6
            8  +%define sys.chdir 12
            9  +
           10  +%define sys.reg.n 6
           11  +%define sys.reg.0 eax
           12  +%define sys.reg.1 ebx
           13  +%define sys.reg.2 ecx
           14  +%define sys.reg.3 edx
           15  +%define sys.reg.4 esi
           16  +%define sys.reg.5 edi
           17  +
           18  +%define sys.call int 0x80 ; sysenter is allegedly the
           19  +  ; politically correct option but it does not actually
           20  +  ; appear to work without a whole lot of extra bullshit
           21  +
           22  +; todo: learn vdsos

Deleted arch/x86.lin.64.inc version [abfe39789c].

     1         -; vim: ft=nasm
     2         -%define lin.call.exit 60
     3         -%define lin.call.fork 57
     4         -%define lin.call.read 0
     5         -%define lin.call.write 1
     6         -%define lin.call.open 2
     7         -%define lin.call.close 3
     8         -
     9         -%define lin.call.chdir 80
    10         -
    11         -%define lin.reg.n 6
    12         -%define lin.reg.0 rax
    13         -%define lin.reg.1 rdi
    14         -%define lin.reg.2 rsi
    15         -%define lin.reg.3 rdx
    16         -%define lin.reg.4 r10
    17         -%define lin.reg.6 r8
    18         -%define lin.reg.7 r9
    19         -
    20         -%define lin.c.0 rdi
    21         -%define lin.c.1 rsi
    22         -%define lin.c.2 rdx
    23         -%define lin.c.3 rcx
    24         -%define lin.c.4 r8
    25         -%define lin.c.5 r9
    26         -
    27         -%define lin.call syscall
    28         -; todo: learn vdsos

Added arch/x86.lin.64.s version [fcbc285104].

            1  +;; abi definition file
            2  +;; macros:
            3  +;; * sys: syscall64 wrapper
            4  +;; * ccall: automatically generate code to call a C function
            5  +;;          with any number of arguments
            6  +
            7  +; syscall ops
            8  +%define sys.call syscall
            9  +; syscall numbers
           10  +%define sys.write 1
           11  +%define sys.brk 12
           12  +%define sys.exit 60
           13  +
           14  +; register order for syscall convention
           15  +%define sys.reg.0 rax
           16  +%define sys.reg.1 rdi
           17  +%define sys.reg.2 rsi
           18  +%define sys.reg.3 rdx
           19  +%define sys.reg.4 r10
           20  +%define sys.reg.5 r8
           21  +%define sys.reg.6 r9
           22  +
           23  +; register order for ccall convention
           24  +%define ccall.reg.ct 6
           25  +%define ccall.reg.0 rdi
           26  +%define ccall.reg.1 rsi
           27  +%define ccall.reg.2 rdx
           28  +%define ccall.reg.3 rcx
           29  +%define ccall.reg.4 r8
           30  +%define ccall.reg.5 r9
           31  +
           32  +%macro sys 1-8
           33  +	%assign i 0
           34  +	%rep %0
           35  +		mov sys.reg. %+ i, %1 ; i'm actually shocked this worked
           36  +		%rotate 1
           37  +		%assign i i+1
           38  +	%endrep 
           39  +	syscall
           40  +%endmacro
           41  +
           42  +%macro sys.prep 1-8
           43  +	; for when we need to modify parameters before we
           44  +	; make the actual call.
           45  +	%assign i 0
           46  +	%rep %0
           47  +		mov sys.reg. %+ i, %1
           48  +		%rotate 1
           49  +		%assign i i+1
           50  +	%endrep
           51  +%endmacro
           52  +
           53  +%macro ccall 1-*
           54  +	%if %0 > ccall.reg.ct
           55  +		%assign ct ccall.reg.ct
           56  +	%else
           57  +		%assign ct %0-1
           58  +	%endif
           59  +	%assign i 0
           60  +	%rotate 1
           61  +	%rep ct
           62  +		; if the function is well-behaved, all its arguments fit
           63  +		; in registers. if not, things get ugly. see below.
           64  +		mov ccall.reg. %+ i, %1
           65  +		%assign i i+1
           66  +		%rotate 1
           67  +	%endrep
           68  +	%if %0 > ccall.reg.ct
           69  +		; if there are more parameters to a C function than the
           70  +		; number of permitted registers, they must be pushed in
           71  +		; reverse order to the stack.
           72  +		; keep your function signatures under control, people.
           73  +		%assign ct (%0-ct)-1
           74  +		%rotate ct
           75  +		%rep ct
           76  +			%rotate -1
           77  +			push %1
           78  +		%endrep
           79  +		%rotate ct
           80  +		push rsp ; it's our responsibility to preserve the stack
           81  +	%endif
           82  +	call %1
           83  +	%if %0 > ccall.reg.ct
           84  +		; the extra arguments are still on the stack; time to
           85  +		; dump them back into the Garbage Zone
           86  +		pop rsp
           87  +	%endif
           88  +%endmacro

Added kfile/file.h version [7ec69a3e9e].

            1  +#ifndef KIfile
            2  +#define KIfile
            3  +
            4  +#endif

Added kfile/kfile.md version [194f78820a].

            1  +# kfile

Added kfile/makefile version [f0df06fe05].

            1  +include ../modmake

Added kgraft/exe.attach.c version [a7ffc6f8bf].


Added kgraft/graft.h version [510bcb01f3].

            1  +#ifndef KIgraft
            2  +#define KIgraft
            3  +
            4  +#endif

Added kgraft/kgraft.md version [74aca3ba50].

            1  +# kgraft

Added kgraft/makefile version [f0df06fe05].

            1  +include ../modmake

Added kio/io.h version [247977844e].

            1  +#ifndef KIio
            2  +#define KIio
            3  +
            4  +#endif

Added kio/kio.md version [947bccad05].

            1  +# kio

Modified kio/kio_posix_fd_write.x86.lin.32.s from [c48aae0264] to [7b77d86bab].

     1      1   bits 32
     2      2   global kio_posix_fd_write
     3      3   
     4         -%include "../arch/x86.lin.32.inc"
            4  +%include "../arch/x86.lin.32.s"
     5      5   ; vim: ft=nasm
     6      6   
     7      7   kio_posix_fd_write:
     8         -	mov lin.reg.0, lin.call.write
     9         -	mov lin.reg.1, [esp + 4] ; holy god but this took the most
    10         -	mov lin.reg.2, [esp + 8] ; stupidly long time to fucking
    11         -	mov lin.reg.3, [esp + 12]; figure out
    12         -	lin.call
            8  +	mov sys.reg.0, sys.call.write
            9  +	mov sys.reg.1, [esp + 4] ; holy god but this took the most
           10  +	mov sys.reg.2, [esp + 8] ; stupidly long time to fucking
           11  +	mov sys.reg.3, [esp + 12]; figure out
           12  +	sys.call
    13     13   	ret
    14     14   

Modified kio/kio_posix_fd_write.x86.lin.64.s from [4a36b27408] to [b72b3eff18].

     1      1   bits 64
     2      2   global kio_posix_fd_write
     3      3   
     4         -%include "../arch/x86.lin.64.inc"
            4  +%include "../arch/x86.lin.64.s"
     5      5   ; vim: ft=nasm
     6      6   
     7      7   kio_posix_fd_write:
     8         -	mov lin.reg.0, lin.call.write
     9         -	; mov lin.reg.1, lin.c.0 - nop
    10         -	; mov lin.reg.2, lin.c.1 - nop
    11         -	; mov lin.reg.3, lin.c.2 - nop
    12         -	lin.call
            8  +	mov sys.reg.0, sys.write
            9  +	; mov sys.reg.1, ccall.reg.0 - nop
           10  +	; mov sys.reg.2, ccall.reg.1 - nop
           11  +	; mov sys.reg.3, ccall.reg.2 - nop
           12  +	sys.call
    13     13   	ret
    14     14   

Modified kio/makefile from [d6a8fa167d] to [f0df06fe05].

     1         -kio: posix
     2         -
     3         -posix: ${OUT}/kio_posix_fd_write.${TARGET}.o
     4         -
     5         -${OUT}/%.lin.32.o: %.lin.32.s
     6         -	yasm -felf32 $< -o $@
     7         -
     8         -${OUT}/%.lin.64.o: %.lin.64.s
     9         -	yasm -felf64 $< -o $@
    10         -
            1  +include ../modmake

Modified kmem/kmem.md from [e0850f6b30] to [9a7772ee1a].

     4      4   
     5      5   ## module functions
     6      6   
     7      7   **kmem** supplies two module-level functions, used to interact with the `kmptr` container type.
     8      8   
     9      9    * `kmfree(kmptr) → void` - free, downref, or ignore the pasted object as appropriate
    10     10    * `kmshred(kmptr) → void` - free, downref, or ignore the pasted object as appropriate. if deallocating, zero its contents
    11         - * `kmstat(void*) → kmptr` - convenience function to wrap a pointer to a non-managed object in a `kmptr` struct, so it can be passed to functions that accept arbitrary objects. `kmptr p = kmstat(raw)` is equivalent to `kmptr p = { kmptr_kind_static, raw, NULL }`.
           11  + * `kmstat(void*) → kmptr` - convenience function to wrap a pointer to a non-managed object in a `kmptr` struct, so it can be passed to functions that accept arbitrary objects. `kmptr p = kmstat(raw)` is equivalent to `kmptr p = { kmkind_none, raw, NULL }`.
    12     12    * `kmtaint(&kmptr) → void` - "taints" a `kmptr` object by setting it to be shredded when freed. this may be desirable if the object pointed to contains privileged information.
    13     13   
    14     14   ## types
    15     15   
    16     16   kmem defines the following types:
    17     17    
           18  + * `enum kmkind` - enumerates allocation strategies
    18     19    * `struct kmptr` - abstract pointer object
    19         -	* `enum kmptr_kind`
    20     20    * `struct kmcell` - abstract memory cell
    21         -	* `enum kmcell_kind`
    22     21    * `struct kmref` - a reference-counted cell
    23     22    * `struct kmnode` - a node in an allocation tree
    24     23    * `struct kmpool` - a memory pool
    25     24   
    26     25   `kmptr` and `kmcell` are both very similar. the difference is that a kmptr points to a region in memory and can be passed around freely. a `kmcell` is the actual in-memory representation of an allocation cell. a `kmcell` cannot be usefully instantiated; rather, it is downcast from an actual cell type (e.g. `kmnode n; kmcell* s = (kmcell*)(&n)`)
    27     26   
           27  +
           28  +### kmkind
           29  +
           30  +`kmkind` is an enum that specifies an allocation function.
           31  + 
           32  + * `kmkind_none` - no allocation
           33  + * `kmkind_heap` - heap allocation
           34  + * `kmkind_pool` - pool allocation
           35  + * `kmkind_ref` - reference-counting allocation
           36  + * `kmkind_tree` - tree allocation
           37  +
    28     38   ### kmptr
    29     39   
    30     40   kmem functions can operate on both raw pointers and the `kmptr` struct type. `kmptr` is a generic struct that can contain any kind of pointer. this is useful if you wish to allocate different objects in different manners, but pass them on into a single interface.
    31     41   
    32     42   memory pointed at by `kmptr` pointers can be freed either with the usual specialized function, or by passing the `kmptr` structure itself to the generic function `kmfree`, which will handle it appropriately, even if it's a pointer to a garbage-collected object or to a static region of memory.
    33     43   
    34     44   a `kmptr` has the following layout:
    35     45   
    36         - * `kmptr_kind kind` - codes the type of pointer
           46  + * `kmkind kind` - codes the type of pointer; `kmkind_none` indicates a non-allocated pointer to a static (global or on-stack) object.
    37     47    * `kmshred shred` - an enum. if `kmshred_yes`, the value will be zeroed or otherwise made unreadable on free. if no, `kmfree` will consult `src` for shred policy if it is not NULL.
    38     48    * `void* ref` - the raw pointer enclosed by `cell`
    39     49    * `kmcell* cell` - a pointer to an object enclosure, typically either a memory pool or a referencing-counting object. NULL if not needed.
    40     50    
    41     51   the convenience function `kmstat(void*) → kmptr` wraps a pointer to a static object in a `kmptr` struct.
    42     52   
    43         -#### kmptr_kind
    44         -
    45         -`kmptr_kind` is an enum with one of the following values.
    46         -
    47         - * `kmptr_kind_none` - not a valid pointer
    48         - * `kmptr_kind_static` - points to a static region of space. `kmptr` instances with this kind will be ignored by `kmfree`.
    49         - * `kmptr_kind_heap` - a traditional heap pointer.
    50         - * `kmptr_kind_pool` - points to a region stored in a memory pool.
    51         - * `kmptr_kind_ref` - points to a reference-counted object.
    52         - * `kmptr_kind_node` - points to a reference-counted object.
    53         -
    54     53   ### kmcell
    55     54   
    56     55   `kmcell` is a stub struct used to disambiguate between source types.a "source" is an object that can hold an allocated object, such as the heap, a memory pool, a fixed-length array on stack, or a fixed-length global array. all values produced by a kmem allocation function point to within a `kmcell`.
    57     56   
    58     57    * `kmptr_kind kind` - kind of cell
    59     58    * `size_t sz` - kind of cell (data plus all fields)
    60     59    * `kmshred shred` - shredding flag
    61     60   
    62     61   ### kmref
    63     62   
    64     63   `kmref` is a struct that constitutes the in-memory representation of a reference-counted cell.
    65     64   
    66         - * `kmcell_kind kind = ref` - kind of cell
           65  + * `kmkind kind = kmkind_ref` - kind of cell
    67     66    * `size_t sz` - size of cell (data plus all fields)
    68     67    * `kmshred shred` - shredding flag
    69     68    * `size_t refs` - number of active references 
    70     69    * `kmcell* src` - source, if any
    71     70    * `char data[]` - content of cell
    72     71   
    73     72   ### kmnode
    74     73   
    75     74   `kmnode` is a struct that constitutes the in-memory representation of a tree node.
    76     75   
    77         - * `kmcell_kind kind = node` - kind of cell
           76  + * `kmkind kind = kmkind_tree` - kind of cell
    78     77    * `size_t sz` - size of cell (data plus all fields)
    79     78    * `kmshred shred` - shredding flag
    80     79    * `kmnode* parent` - parent node
    81     80    * `kmnode* child` - first child node
    82     81    * `kmnode* lastchild` - last child node
    83     82    * `kmnode* prev` - previous sibling, NULL if first
    84     83    * `kmnode* next` - next sibling, NULL if last
    85     84    * `char data[]` - content of cell
    86     85   
    87     86   ### kmpool
    88     87   
    89         - * `kmcell_kind kind = pool` - indicates the kind of source
           88  + * `kmkind kind = kmkind_pool` - indicates the kind of source
    90     89    * `size_t sz` - size of cell (data plus all fields)
    91     90    * `kmshred shred` - shredding flag
    92     91    * `size_t cellsz` - size of individual pool cells
    93     92    * `kmpoolcell* top` - pointer to most recently allocated pool cell
    94     93    * `kmpoolcell* bottom` - pointer to most recently freed pool cell
    95     94    * `kmpoolcell data[]` - content of cell
    96     95   
    97         -### kmpoolcell
           96  +#### kmpoolcell
    98     97   
    99     98    * `kmpoolcell* last` - pointer to last element allocated before this one
   100     99    * `char data[]` - pool data
   101    100   
   102    101   ### kmshred
   103    102   
   104    103   `kmshred` is an enum used to indicate whether an object should be "shredded" (written over) in memory when it's deleted. this is a useful means to ensure that privileged information is not accidentally left in memory after use. if the shredding mechanism is not useful, compile libk with the flag `KFmem_noshred` to exclude its functions and fields.
................................................................................
   151    150    * `tree` [af] - uses a node-child strategy. when a node is freed, all of its children are automatically freed as well.
   152    151      * `kmtreea(kmcell* src, void* parent, size_t) → void*` - create a tree node. if `parent` is NULL, the node will the top of a new tree. if src is null, allocate on-heap.
   153    152      * `kmtreez(kmcell* src, void* parent, size_t) → void*` - like `kmtreea` but zeroed 
   154    153      * `kmtreeao(kmcell* src, void* parent, size_t) → kmptr` - like `kmtreea` but returns a `kmptr` 
   155    154      * `kmtreezo(kmcell* src, void* parent, size_t) → kmptr` - like `kmtreez` but returns a `kmptr` 
   156    155      * `kmtreef(void*) → kmptr` - frees a node and all its children
   157    156   
          157  +## macros
          158  +
          159  +kmem defines the following macros.
          160  +
          161  + * `Kmsz(array)` - a convenience macro to return the number of elements in a static array. inserts the text `( sizeof (array) / sizeof (array) [0] )`

Added kmem/makefile version [f0df06fe05].

            1  +include ../modmake

Added kmem/mem.h version [dc631dc568].

            1  +#ifndef KImem
            2  +#define KImem
            3  +
            4  +#endif

Added kmsg/kmsg.md version [1bf7781e05].

            1  +# kmsg

Added kmsg/makefile version [f0df06fe05].

            1  +include ../modmake

Added kmsg/msg.h version [b69837b00c].

            1  +#ifndef KImsg
            2  +#define KImsg
            3  +
            4  +#endif

Added knet/knet.md version [caaca9de66].

            1  +# knet

Added knet/makefile version [f0df06fe05].

            1  +include ../modmake

Added knet/net.h version [a2f498298b].

            1  +#ifndef KInet
            2  +#define KInet
            3  +
            4  +#endif

Added kproc/kproc.md version [ca8b9fab82].

            1  +# kproc

Added kproc/makefile version [f0df06fe05].

            1  +include ../modmake

Added kproc/proc.h version [8fdd57f87b].

            1  +#ifndef KIproc
            2  +#define KIproc
            3  +
            4  +#endif

Added kstr/kstr.md version [8ba3da6088].

            1  +# kstr
            2  +
            3  +**kstr** is the libk string library. it uses the **short** naming convention with the glyph `s`. **kstr** implies `#include <k/mem.h>`.
            4  +
            5  +## types
            6  +
            7  +### struct kstr
            8  +`struct kstr` is a structure for holding pascal strings (length-prefixed strings). it is the basic libk string type. **note:** if `ptr.ref` ≠ NULL and `sz` = 0, the string's length is unknown and should be calculated by any function that operates on a kstr, storing the result in the object if possible.
            9  + * `size_t sz` - length of string, excluding any null terminator
           10  + * `kmptr ptr` - pointer to string in memory
           11  +
           12  +### struct ksraw
           13  +`struct ksraw` is like `kstr` except it uses raw `char` pointers instead of a `kmptr`.
           14  + * `size_t sz` - length of string, excluding any null terminator
           15  + * `char* ptr` - pointer to string in memory
           16  +
           17  +### struct ksbuf
           18  +`struct ksbuf` is a structure used to hold buffers.
           19  + * `size_t sz` - maximum size of buffer, including any null terminator
           20  + * `char* buf` - region of memory to store buffer in
           21  + * `ksalloc strat` - allocation strategy
           22  + * `kmkind rule` - kind of allocator to use. only needs to be set if `where` is NULL. see [kmem](../kmem/kmem.md).
           23  + * `kmcell* where` - where to allocate the object, in case of pool or tree allocation.
           24  +
           25  +### struct kschain
           26  +`struct kschain` is a structure used for string accumulators that works by aggregating pointers to strings, instead of copying the strings themselves.
           27  + * `kschain_kind kind` - kind of chain
           28  + * `kmkind rule` - kind of allocation to use if `kind` ≠ `kschain_kind_linked`
           29  + * `pstr* ptrs` - pointer to pointer list
           30  + * `size_t ptrc` - number of pointers
           31  + * `size_t sz` - total amount of space in `ptrs`
           32  +
           33  +#### enum kschain_kind
           34  + * `kschain_kind_block` - occupies a single block of memory
           35  + * `kschain_kind_linked` - uses a linked list, allocated and deallocated as necessary
           36  +
           37  +### enum ksalloc
           38  +`enum ksalloc` is an enumerator that tells libk what strategy to use when filling a `ksbuf` or `kschain` struct.
           39  + * `ksalloc_static` - do not allocate memory, fill an already-allocated, statically-sized array.
           40  + * `ksalloc_alloc` - allocate a string in memory using the specified kind of allocator.
           41  + * `ksalloc_dynamic` - fill an already-allocated array if possible, allocate a string in memory if the string length exceeds available space.
           42  +
           43  +## functions
           44  +
           45  +### kssz
           46  +`size_t kssz(char* str, size_t max)` returns the number of characters in a C string, **including** the final null. will count at most `max` characters if `max` > 0.
           47  +
           48  +### kstr
           49  +`kstr kstr(char* str, size_t max)` takes a C string and returns a P-string, calculating the length of `str` and storing it in the return value. `max` works as in `kssz`.
           50  +
           51  +### kstoraw
           52  +`ksraw ksref(kstr)` is a simple convenience function that returns the `ksraw` form of a `kstr`.
           53  +
           54  +### kscomp
           55  +`char* kscomp(size_t ct, ksraw struct[], kmbuf* buf)` is a **string composition** function. it serves as an efficient, generalized replacement for functions like `strcat` and `strdup`.
           56  +
           57  +to use kscomp, create an array of `kstr` and fill it with the strings you wish to concatenate. for example, to programmatically generate an HTML link tag, you might use the following code.
           58  +
           59  +	char mem[512];
           60  +	kmptr text = <...>;
           61  +	char* src = <...>;
           62  +	kmbuf buf = { sizeof mem, &mem, kmkind_none };
           63  +    kstr chain[] = {
           64  +		Kstr("<a href=\""), { 0, src }, Kstr("\">"),
           65  +			ksref(text),
           66  +		Kstr("</a>")
           67  +	};
           68  +	char* html = kscomp([Kmsz(chain)](../kmem/kmem.md), chain, &buf);
           69  +
           70  +kscomp will only calculate the length of individual strings if they are not already known. when it needs to calculate the length of a string, it will store that length in the original array so repeated calls can be made without needing to repeatedly calculate the lengths. this is not always desirable, so the variant `kscompc` exists, which is exactly the same as `kscomp` in every respect except that `chain` is not altered in any way.
           71  +
           72  +### macros
           73  +if `KFclean` is not set when <k/str.h> is included, the following macros are defined.
           74  +
           75  + * `Kstr(string)` - the compile-time equivalent to `kstr()`. `Kstr` takes a literal string and inserts the text `{ sizeof (string), string }` into the document, suitable for initializing a kstr.

Added kstr/makefile version [f0df06fe05].

            1  +include ../modmake

Added kstr/str.h version [21d6720beb].

            1  +#ifndef KIstr
            2  +#define KIstr
            3  +
            4  +#endif

Added kterm/kterm.md version [5df0db1632].

            1  +# kterm

Added kterm/makefile version [f0df06fe05].

            1  +include ../modmake

Added kterm/term.h version [891027d45b].

            1  +#ifndef KIterm
            2  +#define KIterm
            3  +
            4  +#endif

Modified libk.md from [4cea7e271a] to [d44feffbdd].

    31     31   
    32     32   libk is designed to fix this (in hindsight) glaring error.
    33     33   
    34     34   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.
    35     35   
    36     36   therefore, libk uses two slightly different naming conventions: the **short** convention, for core functions the user will call frequently, and the **full** convention, for less-commonly used functions. the inconvenience of remembering which is which will hopefully be outweighed by the keystrokes (and bytes) saved.
    37     37   
    38         -in the **full** convention, a function's name is prefixed with its module name followed by an underscore. thus, `kfile/open.c` will be invoked as `kfile_open()`.
           38  +in the **full** convention, an identifier's name is prefixed with its module name followed by an underscore. thus, `kgraft/list.c` is invoked as `kgraft_list()`.
    39     39   
    40         -in the **short** convention, the function name is prefixed by the letter `k` followed by the module's "glyph" -- a one- or two-letter sequence that represents the module, usually the first one or two characters. therefore, `kio/write.c` is invoked as `kiowrite`.
           40  +in the **short** convention, identifiers are prefixed by the letter `k` followed by the module's "glyph" -- a one- or two-letter sequence that represents the module, usually the first one or two characters. therefore, `kfile/open.c` is invoked as `kfopen`.
    41     41   
    42     42   which naming convention a module uses should be specified at the top of its documentation. if it uses the short convention, its glyph should be specified as well
    43     43   
           44  +in both naming conventions, the following rules apply:
           45  +
           46  + 1. the possible values of enumeration types are always preceded by the name of the enumeration type and an underscore. for instance, the enum `kschain_kind` has a value named `kschain_kind_block`. **exception:** an enum named `<S>_kind`, where `<S>` is a struct type, may simply use the prefix `<S>_`.
           47  + 2. macros begin with the uppercase letter `K` -- e.g. `Kmacro`. macros that can be defined by the user to alter the behavior of the api should begin with `KF` if they are on/off flags, or `KV` otherwise.
           48  + 3. capital letters are only used in macro prefixes.
           49  + 4. low-level function names are prefixed with the API they call into. for example, the function that performs the POSIX syscall `write` is named `kio_posix_fd_write`.a wrapper around the Windows function `CreateProcess()` might be called `kproc_win_createprocess`.
           50  +
    44     51   ### atoms
    45     52   
    46     53   libk uses the concept of "atoms" (small, regular strings of text) to standardize common references, such as operating systems or processor architectures.
    47     54   
    48     55   #### operating systems
    49     56   
    50     57   these atoms will be used to reference operating systems.
................................................................................
    71     78   
    72     79   these atoms will be used to reference particular system architectures. these will mostly be used in the filenames of assembly code.
    73     80   
    74     81   ## macros
    75     82   
    76     83   libk will not in any circumstance use macros to encode magic numbers, instead using typedef'd enums. all libk macros begin with the uppercase letter `K` -- e.g. `Kmacro`. macros that can be defined by the user to alter the behavior of the api should begin with `KF` if they are on/off flags, or `KV` otherwise. **macros should only be defined by the libk headers if the flag `KFclean` is *not* defined at the time of inclusion.**
    77     84   
           85  +include guards take the form of the bare module name prefixed by `KI`. so to test if `k/term.h` has been included, you could write `#ifdef KIterm`.
           86  +
    78     87   ## languages
    79     88   
    80     89   libk uses only three languages: C (\*.c, \*.h), yasm (\*.s), and make (makefile).
    81     90   
    82     91   other assemblers will probably be necessary for the more exotic targets, however.
    83     92   
    84     93   ## repository structure
................................................................................
    90     99   each function should be kept in a separate file within its module's directory. when OS or architecture-specific code is needed, the file's name should be a list of one or more of the fields [arch, OS, bits, format] separated by a `.` -- for instance, the 32-bit x86 haiku version of a function called `write` defined in assembly would be named `write.x86.haiku.32.s`. however, if a function has an extraordinarily large number of versions, they may instead be stored in a folder with the same name as the function.
    91    100   
    92    101   each module should have a header named the same thing as the module except without the `k` prefix. (e.g. the header for `kio` is `kio/io.h`) located in its folder. this is the header that the end-user will be importing, and should handle any user-defined flags to present the API the user has selected.
    93    102   
    94    103   each module directory should contain a makefile that can build that module. see **makefiles** below. all makefiles should be named `makefile` (**not** `Makefile`).
    95    104   
    96    105   each module should contain a markdown file. this file's name should be the name of the parent directory suffixed with `.md`; for instance, `kterm` should contain the file `kterm/kterm.md`. this file should document the module as thoroughly as possible 
          106  +
          107  +each module may contain any number of files of the name `exe.*.c`. this files will be treated as *tools* by the build system and compiled as executables, rather than libraries. they should be compiled to `out/$module.$tool`
    97    108   
    98    109   the repository root and each module may also contain the directory `misc`. this directory may be used to store miscellaneous data such as ABI references, developer discussions, and roadmaps. if the `misc` directory is deleted, this must not affect the library or build system's function in any way - that is, nothing outside a `misc` folder may reference a `misc` folder or anything inside it, including documentation. the `misc` directory should be removed when its contents are no longer needed. in most cases, the repository wiki and forum should be used instead of the `misc` folder.
    99    110   
   100    111   the folder `arch` in the root of the repository contains syscall tables and ABI implementations for various architectures.
   101    112   
   102    113   ## makefiles
   103    114   
   104    115   libk uses `make` as its build system. makefiles should be handwritten. there will be one global makefile in the root of the repository, and one makefile for each module.
   105    116   
   106    117   each rule should be prefixed with ${OUT}, to allow retargeting of the build-dir with the OUT environment variable. this is particularly important since the makefiles chain.
   107    118   
   108    119   the rest is TBD.
   109    120   
          121  +## design principles
          122  +
          123  +there are four overriding principles that guide the design of libk.
          124  +
          125  + 1. it should be easy to write code that uses it.
          126  + 2. it should be easy to read code that uses it.
          127  + 3. the simple, obvious way of using libk should produce the most optimal code.
          128  + 4. code that uses libk should be idiomatic C.
          129  +
          130  +for these reasons, the codebase follows a number of strict rules.
          131  + 
          132  +### booleans are banned
          133  +there are a number of reasons for this.
          134  +
          135  +the first is simply that the boolean type in C is a bit messy and libk headers are intended to import as few extra files as possible.
          136  +
          137  +the second is that boolean-using code can be hard to read. consider a struct declaration of the form `rule r = { 10, buf, true, false, true }`: the meaning of this declaration is opaque unless you've memorized the structure's definition.
          138  +
          139  +instead, libk uses enums liberally. so the above might be rewritten as e.g.:
          140  +
          141  +    rule r = { 10, buf,
          142  +		rule_kind_undialectical,
          143  +		rule_action_expropriate,
          144  +		rule_target_bourgeoisie
          145  +	};
          146  +
          147  +this makes code much more legible and has the added benefit of making the definitions easier to expand at a later date if new functionality values is needed without breaking the API or ABI.
          148  + 
   110    149   ## build process
   111    150   
   112    151   libk has a number of targets. all files generated by a `make` invocation will be stored in the folder "out" at the root of the repository. this directory may be deleted entirely to clean the repository.
   113    152   
   114         -**defs** will create the directory `out/k/` and populate it with module header files. the `k/` directory shall be suitable to copy to `/usr/include` or similar. these header files will copied by building the `defs` target of each module's makefile.
          153  +**defs** will create the directory `out/k/` and populate it with module header files. the `k/` directory shall be suitable to copy to `/usr/include` or similar. these header files will copied by building the `${OUT}/$(module).h` target of each module's makefile.
   115    154   
   116    155   **libk.so** will build the dynamically linked form of libk, according to the build variables set
   117    156   
   118    157   **libk.a** will build the statically linked form of libk, according to the build variables set
   119    158   
   120    159   **tool** will build the executables used for modules such as `kgraft`.
   121    160   

Modified makefile from [75ffd11290] to [e2aa0ec204].

     1         -export OUT=$(PWD)/out
     2         -export TARGET=x86.lin.64
            1  +export OUT = $(PWD)/out
            2  +
            3  +export ARCH = x86
            4  +export OS = lin
            5  +export BITS = 64
            6  +
            7  +export TARGET = $(ARCH).$(OS).$(BITS)
            8  +
            9  +moddirs = $(wildcard k*)
           10  +modules = $(moddirs:k%=%)
           11  +headers = $(moddirs:k%=$(OUT)/k/%.h)
           12  +objects = $(modules:%=$(OUT)/k%.o)
           13  +makefiles = $(moddirs:%=%/makefile)
           14  +
           15  +binaries = $(wildcard */exe.*.c)
           16  +binmods = $(sort $(dir $(binaries)))
           17  +
           18  +all: obj defs tool
           19  +obj: $(moddirs:%=%.obj)
           20  +defs: $(headers)
           21  +tool: $(binmods:%=%.tool)
           22  +
           23  +lists = moddirs modules headers objects makefiles binaries binmods
           24  +dbg:
           25  +	@echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))")
           26  +
           27  +%.obj: %/makefile $(OUT)
           28  +	cd $* && $(MAKE) obj
           29  +
           30  +%.tool: %/makefile $(OUT)
           31  +	cd $* && $(MAKE) tool
           32  +
           33  +%.dbg: %/makefile $(OUT)
           34  +	cd $* && $(MAKE) dbg
           35  +
           36  +$(OUT)/libk.so: mods $(OUT)
           37  +	$(CC) -shared -o $@ $(objects)
           38  +
           39  +$(OUT)/libk.a: mods $(OUT)
           40  +	# using `ar c` and ranlib here instead of
           41  +	# `ar cs` in case `ar` isn't the GNU version
           42  +	ar c $@ $(objects)
           43  +	ranlib $@
     3     44   
     4         -all: kio
           45  +$(OUT)/k/%.h: k%/makefile $(OUT)/k
           46  +	cd k$* && $(MAKE) $@
     5     47   
     6         -$(OUT)/kio.o:
     7         -	cd kio && make kio
           48  +$(OUT) $(OUT)/k:
           49  +	mkdir -p $@

Added modmake version [247b2f15bf].

            1  +#- modmake
            2  +# this is the master makefile that controls the building of each
            3  +# libk module. it is included from each k*/makefile.
            4  +# vim: ft=make
            5  +
            6  +mod = $(notdir $(PWD))
            7  +src = $(wildcard *.c) $(wildcard *.s)
            8  +bare = $(mod:k%=%)
            9  +
           10  +tools    = $(filter     exe.%.c,   $(src))
           11  +nontools = $(filter-out exe.%.c,   $(src))
           12  +cobjects = $(filter     %.c,       $(nontools))
           13  +sobjects = $(filter %.${TARGET}.s, $(nontools))
           14  +
           15  +obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \
           16  +	 $(sobjects:%.s=${OUT}/$(mod).%.o)
           17  +tool: $(tools:exe.%.c=${OUT}/$(mod).%)
           18  +
           19  +dbg:
           20  +	@echo tools = $(tools)
           21  +	@echo TARGET = ${TARGET}
           22  +	@echo cobjects = $(cobjects)
           23  +	@echo sobjects = $(sobjects)
           24  +	@echo mod = $(mod)
           25  +
           26  +${OUT}/$(mod).%.o: %.c
           27  +	$(CC) -c $< -o $@
           28  +
           29  +${OUT}/k/$(bare).h: $(bare).h
           30  +	cp $< $@
           31  +
           32  +${OUT}/$(mod).%: exe.%.c
           33  +	$(CC) $< -o $@
           34  +
           35  +#- assembly
           36  +# compiling  the assembly  code will  be  faster but  a lot  more
           37  +# complex, given the  nature of assembly and the  large number of
           38  +# platforms  targeted.  we need  to  add  build rules  for  every
           39  +# arch.OS[.bits] tuple;  since this  is a fairly  repetetive task
           40  +# that  requires ugly  make  rules,  we're just  going  to use  a
           41  +# function to generate these.
           42  +
           43  +# ${OUT} = ultimate build directory
           44  +# $(mod) = module name
           45  +#      % = function name
           46  +#   $(1) = arch tuple
           47  +arch = ${OUT}/$(mod).%.$(1).o: %.$(1).s
           48  +# invoke with $(call arch,tuple). do not
           49  +# put spaces between either term though!
           50  +
           51  +#-- linux
           52  +# linux uses the ELF{32,64} binary format,  and generating these
           53  +# from yasm is trivial.  linux only supports one ABI per format,
           54  +# at least with ELF, so that's all we need to do.
           55  +
           56  +#${OUT}/$(mod).%.x86.lin.32.o: %.x86.lin.32.s
           57  +$(call arch,x86.lin.32)
           58  +	yasm -felf32 $< -o $@
           59  +
           60  +#${OUT}/$(mod).%.x86.lin.64.o: %.x86.lin.64.s
           61  +$(call arch,x86.lin.64)
           62  +	yasm -felf64 $< -o $@
           63  +
           64  +#-- freebsd
           65  +# the freebsd ABI is different, so it will require different code
           66  +# (though there might be ways to minimize that). freebsd uses the
           67  +# same binary format as Linux  (though it also supports a.out and
           68  +# COFF) but because freebsd can interpret multiple different ABIs
           69  +# the  object files  need to  be "branded"  with the  correct one
           70  +# using the tool brandelf (`brandelf -t [ABI]`)
           71  +
           72  +$(call arch,x86.fbsd.32)
           73  +	yasm -felf32 $< -o $@
           74  +	brandelf -t FreeBSD $@
           75  +
           76  +$(call arch,x86.fbsd.64)
           77  +	yasm -felf64 $< -o $@
           78  +	brandelf -t FreeBSD $@
           79  +