Index: arch/x86.lin.32.s ================================================================== --- arch/x86.lin.32.s +++ arch/x86.lin.32.s @@ -1,30 +0,0 @@ -;; abi definition file for x86 linux 32-bit -; vim: ft=nasm - -; syscall32 numbers - syscall table must be created first! -%include "system_calls.s" - -; syscall32 registers -%define sys.reg.n 6 -%define sys.reg.0 eax -%define sys.reg.1 ebx -%define sys.reg.2 ecx -%define sys.reg.3 edx -%define sys.reg.4 esi -%define sys.reg.5 edi - -%macro sys 1-6 - %assign i 0 - %rep %0 - mov sys.reg. %+ i, %1 ; i'm actually shocked this worked - %rotate 1 - %assign i i+1 - %endrep - syscall -%endmacro - -%define sys.call int 0x80 ; sysenter is allegedly the - ; politically correct option but it does not actually - ; appear to work without a whole lot of extra bullshit - -; todo: learn vdsos ADDED global/build-id.sh Index: global/build-id.sh ================================================================== --- global/build-id.sh +++ global/build-id.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env sh +. global/common.sh + +origin=1566169297 +now=$(date +%s) +delta=$(expr $now - $origin) + + +if test "$1" = "private"; then + # for privacy's sake, we're not to show + # the hostname. instead, we calculate a + # hash based on the time delta and the + # output of uname -a for extra entropy + if has "$HASH"; then + hash="$HASH" + elif has sha1; then + hash=sha1 + elif has sha1sum; then + hash=sha1sum + else + say "cannot find a hashing function; privacy mode cannot be used" + exit 1 + fi + + h=$(printf "%x%s" "$delta" "$(uname -a)" | $hash) + echo ${h:1:7} +else + printf "%x:%s" $delta $(uname -n) +fi ADDED global/common.sh Index: global/common.sh ================================================================== --- global/common.sh +++ global/common.sh @@ -0,0 +1,9 @@ +me=$0 +say() { echo >&2 "($me) $1"; } +has() { which $1 >/dev/null 2>&1; return $?; } +check() { + var=$1 + test "${!var}" == "" || return 0 + say "we were not able to detect a default value for the configuration variable \$$var. please set this variable to $2 and try again." + exit 1 +} ADDED global/emit-manpage.sh Index: global/emit-manpage.sh ================================================================== --- global/emit-manpage.sh +++ global/emit-manpage.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +(test -d global && test -d $1) || { + echo >&2 "($0) run $me from root of libk source directory" + exit 1 +} + +. global/common.sh +test "$OUT" = "" && { + 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!" + exit 2 +} + +if ! has cmark; then + say "to generate documentation for libk, install the cmark package and try again" + exit 3 +fi + + +name=$1 +mandest=$OUT/doc/man +out=$2 +file=$name/$name.md +desc="$(grep -m1 "^$name:" global/modules | cut -d: -f4)" +date="$(date -r"$file" "+%d %A %Y")" + +mkdir -p $mandest + +echo >$out ".TH ${name^^} \"$section\" \"$date\" \"hale.su libk [r$BUILD]\" \"modules\"" + +echo >>$out ".SH NAME" +echo >>$out "$name - $desc" +echo >>$out ".SH SYNOPSIS" + +dhead=$(grep -m1 -n "^# description$" $file) +if test $? -eq 0; then + descline=$(echo "$dhead" | cut -d: -f1) + offset=1 +else + descline=$(grep -m2 -n "^#" $file | tail -n1 | cut -d: -f1) + offset=0 +fi + +tail -n+2 $file | head -n$(expr $descline - 2) | cmark -t man >> $out + +echo >>$out ".SH DESCRIPTION" + +tail -n+$(expr $descline + $offset) $file | cmark -t man >> $out + +say "wrote manpage for $name to $file" ADDED global/genconds.awk Index: global/genconds.awk ================================================================== --- global/genconds.awk +++ global/genconds.awk @@ -0,0 +1,19 @@ +BEGIN { FS=":" + offset = 0x7F + + print "#ifndef KIglobal_cond" + print "#define KIglobal_cond" + print "typedef enum kglobal_cond {" + printf("kglobal_module_offset = 0x%x,\n", offset) +} + +$2 == "short" { printf("\t%scond_id = 0x%x,\n", $3, offset*NR) } +$2 == "long" { printf("\t%s_cond_id = 0x%x,\n", $3, offset*NR) } + +END { + print "} kglobal_cond;" + print "extern struct kglobal_module_record" + print "\t{ const char* name, * desc, ** error_list }" + print "\tkglobal_module_ident[];" + print "#endif" +} ADDED global/genident.awk Index: global/genident.awk ================================================================== --- global/genident.awk +++ global/genident.awk @@ -0,0 +1,20 @@ +BEGIN { + defs = "" + FS = ":" + ORS = "" + print "#include \n" + print "extern const char" +} + +{ + if (NR != 1) sep = "," + print sep"\n\t*"$1"_error_strings[]" + defs = defs "\t{ \""$1"\", \"k "$4"\", "$1"_error_strings },\n" +} + +END { + print ";\n" + print "struct kglobal_module_record kglobal_module_ident[] = {\n" + print defs + print "};" +} ADDED global/modules Index: global/modules ================================================================== --- global/modules +++ global/modules @@ -0,0 +1,16 @@ +kbuild:long:kbuild:build tool +kconf:long:kconf:config parser +kcli:long:kcli:CLI utilities +kcore:short:kc:core definitions and routines +kdb:long:kdb:database +kdbg:long:kdbg:debug toolkit +kfile:short:kf:file control +kgraft:long:kgraft:grafting tool +kio:short:kio:input/output routines +kmem:short:km:memory management routines +kmsg:long:kmsg:IPC routines +knet:long:knet:network routines +knum:short:kn:math and number tools +kproc:short:kp:process control +kstr:short:ks:string toolkit +kterm:short:kt:terminal control facility DELETED kcli/kcli.md Index: kcli/kcli.md ================================================================== --- kcli/kcli.md +++ kcli/kcli.md @@ -1,126 +0,0 @@ -# kcli -**kcli** is a module that implements common routines used by command-line utilities, such as option parsing, usage display, and more. - -## functions - -### kcli_usage(kcli_set, kiochan) -kcli_usage() takes a `kcli_set` and prints a succinct usage summary to a [kiochan](../kio/kio.md). - -## types - -### struct kcli_set -`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. - - * `const char* name` - program name (if null, will be determined from argv instead) - * `size_t argc` - the number of arguments in the `argv` array. - * `const char** argv` - the `argv` pointer passed to the `entry` function, representing the command-line arguments passed to the program. - * `const char* desc` - program description - * `const kcli_param* params` - a list of options expected by the program. - * `size_t paramc` - the number of params in the list to process. - * `const kcli_opt* opts` - a list of options expected by the program. - * `size_t optc` - the number of options in the list to process. - -a kcli_set might be used like so: - - #include - #include - #include - stat entry(kenv e) { - kcli_flag aardvark; - kcli_flag zebra; - char* user; - char* password; - long age; - kcli_param params[] = { - { "user", kcli_param_string, kcli_class_required, - &user, "the user to log in as" } - // or Kcli_param(user,string,required,"the user to log in as"), - - { "age", kcli_param_dec, kcli_class_optional, - &age, "the age of the user" } - // or Kcli_param(age,dec,optional,"the age of the user"), - }; - kcli_opt options[] = { - { 'a', "aardvark", kcli_opt_flag, &aardvark, - "a nocturnal burrowing mammal" }, - // or Kcli_opt(aardvark, 'a', flag, "a nocturnal burrowing mammal") - { 'z', "zebra", kcli_opt_flag, &zebra, - "a striped equine" }, - { 'p', "password", kcli_opt_string, &password, - "the password to log in with" } - }; - kcli_set argset = { - "demo", e.argc, e.argv, - "a demonstration of the kcli_set type", - params, Kmsz(params), - options, Kmsz(options) - }, - size_t args_parsed = kcli_parse(&argset); - if (args_parsed == 0) { kcli_usage(&me, e.err); return 1; } - - return 0; - } - -### struct kcli_opt -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`. - - * `char id` - the short single-character form of the flag (or NUL for no short form) - * `const char* name` - the long string form of the flag (or NULL for no long form) - * `kcli_opt_kind kind` - enum that describes how the flag will function - * `void* val` - a pointer to an appropriate type to store the return value in. - * `const char* desc` - a description of the flag's purpose and function (or NULL for no description) - -#### enum kcli_opt_kind - - * `kcli_opt_none` - flag is disabled and will not be shown in usage - * `kcli_opt_string` - flag tells kcli to add a string to the list of expected parameters; appropriate string will be returned - * `kcli_opt_oct` - flag tells kcli to add an octal number to the list of expected parameters - * `kcli_opt_dec` - flag tells kcli to add a decimal number to the list of expected parameters - * `kcli_opt_hex` - flag tells kcli to add a hexdecimal number to the list of expected parameters - * `kcli_opt_flag` - flag is an option: will return `kcli_flag_on` if entered at least once, `kcli_flag_off` otherwise. - * `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. - * `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`). - * `kcli_opt_enum` - flag is one of a series of enumerated values, which will be matched against a table to yield the associated integer. - -### struct kcli_param -`kcli_param` describes a parameter that may be passed to the program whether or not any flags are passed. - - * `const char* name` - a short name for the parameter - * `kcli_param_kind kind` - the kind of parameter passed - * `kcli_class class` - whether or not the parameter is optional - * `void* val` - a pointer to an appropriate type of variable to fill - * `const char* desc` - a description of the parameter's function - -#### enum kcli_param_kind - * `kcli_param_none` - parameter is disabled and will not be expected or accepted - * `kcli_param_string` - parameter will not be parsed; a raw string will be returned - * `kcli_param_oct` - parameter will be parsed as an octal number - * `kcli_param_dec` - parameter will be parsed as a decimal number - * `kcli_param_hex` - parameter will be parsed as a hexadecimal number - -### enum kcli_class - * `kcli_class_forbidden` - parameter may not be passed - * `kcli_class_optional` - parameter may or may not be passed - * `kcli_class_required` - parameter must be passed - -### enum kcli_flag -results that an option of kind `kcli_opt_flag` can return. - - * `kcli_flag_off = 0` - flag is off - * `kcli_flag_on = 1` - flag is on - -## macros - -### Kcli_param(field, kind, class, description) -a convenience macro for filling out parameter lists. - -`Kcli_param(field,a,b,"description")` is transformed into: - - { "field", kcli_param_a, kcli_class_b, &field, "description" } - -### Kcli_opt(field, kind, class, description) -a convenience macro for filling out option lists. - -`Kcli_opt(name,'n',string,"description")` is transformed into: - - { 'n', "name", kcli_opt_string, &name, "description" } DELETED kcli/makefile Index: kcli/makefile ================================================================== --- kcli/makefile +++ kcli/makefile @@ -1,1 +0,0 @@ -include ../modmake Index: kcore/core.h ================================================================== --- kcore/core.h +++ kcore/core.h @@ -19,11 +19,10 @@ kiochan err; sz argc; char** argv; kvar* vars; } kenv; - /* i'm really sorry okay */ typedef #if (__STDC_VERSION__ >= 199901L) _Bool bool; #endif @@ -39,10 +38,12 @@ bool /* } bool ; */ #endif ; #ifndef KFclean +# include +# define Kokay(cond) (((cond) % kglobal_module_offset) == 0) # if (__STDC_VERSION__ >= 199901L) ||\ (__cplusplus >= 201103L) # define KVvm_args __VA_ARGS__ # define KVvm_spec ... # define KFfeat_variadic_macro @@ -144,11 +145,22 @@ #elif __STDC_VERSION__ >= 201103L _Noreturn void kstop(stat_long code); #else void kstop(stat_long code); #endif + +typedef u16 kcond; +/* this will probably not need to be altered, + * as libk sports a modest number of modules, + * and there are few enough error conditions + * in each that 16-bit address space should + * be more than enough for the foreseeable + * future. however if that changes, altering + * the definition here will effect all the + * necessary changes throughout the library */ +bool kokay(kcond); #ifdef __cplusplus } #endif #endif Index: kcore/kcore.md ================================================================== --- kcore/kcore.md +++ kcore/kcore.md @@ -1,13 +1,18 @@ # 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-`. -## entry -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. +# description +**kcore** contains the libk runtime and headers with important typedefs, structures and enumerations. -## types -kcore contains fixed-width integer types (in ``). 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)`. +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 ``). 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 type * `s8` - a signed 8-bit integer, or the smallest available signed type * `u16` - an unsigned 16-bit integer * `s16` - a signed 16-bit integer @@ -23,52 +28,55 @@ * `sbyte` - the smallest available signed integer type besides \_Bool * `stat` - 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) -## constants -in ``, 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`). - * `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. -### struct kenv +**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 +## 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 -## functions +# constants +in ``, 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() +## 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 ``, which are designed to standardize exit statuses across different software and are synchronized with a FreeBSD effort to do the same (``). -## definitions +# 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 `` and ``. 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 ``. 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 +# 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 of `noreturn`. - * `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 like `KAinline` in reverse. - * `KAformat()` - specifies that the function has printf-style syntax for error-checking purposes. worst hack in history. + * `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 of `noreturn`. + * `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 like `KAinline` 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. Index: kio/io.h ================================================================== --- kio/io.h +++ kio/io.h @@ -47,17 +47,19 @@ // text can be read from this stream kiostream out; // text can be written to this stream } kiochan; +#include typedef enum kiocond { /* to check if a call failed, perform (x >= kiocond_fail) where x * is that call's return value. more typically however you should * select explicitly against kiocond_ok or kiocond_partial, since * those situations will usually need to be handled differently. */ - kiocond_ok, // success + kiocond_ok = kiocond_id, // success + kiocond_partial, // partial read or write kiocond_poll, // call would block kiocond_interrupt, // call was interrupted by signal kiocond_fail, // action failed - unspecified reason DELETED kmath/kmath.md Index: kmath/kmath.md ================================================================== --- kmath/kmath.md +++ kmath/kmath.md @@ -1,2 +0,0 @@ -# kmath -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 Index: kmath/makefile ================================================================== --- kmath/makefile +++ kmath/makefile @@ -1,1 +0,0 @@ -include ../modmake Index: kmsg/kmsg.md ================================================================== --- kmsg/kmsg.md +++ kmsg/kmsg.md @@ -1,1 +1,2 @@ # kmsg +kmsg is libk's inter-process communication library. ADDED knum/knum.md Index: knum/knum.md ================================================================== --- knum/knum.md +++ knum/knum.md @@ -0,0 +1,2 @@ +# knum +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 Index: knum/makefile ================================================================== --- knum/makefile +++ knum/makefile @@ -0,0 +1,1 @@ +include ../modmake Index: kproc/kproc.md ================================================================== --- kproc/kproc.md +++ kproc/kproc.md @@ -1,1 +1,2 @@ # kproc +kproc is libk's library for starting, handling, and controlling userspace processes. Index: kstr/str.h ================================================================== --- kstr/str.h +++ kstr/str.h @@ -20,12 +20,13 @@ typedef struct ksmut { sz size; char* ptr; } ksmut; +#include typedef enum kscond { - kscond_ok, + kscond_ok = kscond_id, kscond_fail, kscond_unimplemented, kscond_nonnumeric, } kscond; Index: makefile ================================================================== --- makefile +++ makefile @@ -5,56 +5,64 @@ export OS = lin export BITS = 64 export ROOT = $(PWD) export TMP = $(PWD)/gen +export BUILD = $(shell global/build-id.sh) $(build-host) + ifneq ($(BITS),) export TARGET = $(ARCH).$(OS).$(BITS) else export TARGET = $(ARCH).$(OS) endif export m4 = m4 -moddirs = $(wildcard k*) -binaries = $(wildcard k*/*.exe.c) -functions = $(wildcard k*/*.fn.c) -assemblies = $(wildcard k*/*.fn.$(TARGET).s) -binmods = $(sort $(dir $(binaries))) +include makerule + +moddirs := $(wildcard k*) +binaries := $(wildcard k*/*.exe.c) +functions := $(wildcard k*/*.fn.c) +assemblies := $(wildcard k*/*.fn.$(TARGET).s) +binmods := $(sort $(dir $(binaries))) # i'm sorry collect = $(strip $(foreach dir,$(moddirs),$(wildcard $(dir)/*.$1))) transform = $(strip $(foreach dir,$(moddirs),$(patsubst $(dir)/%.$1,$(subst @,$(dir),$2),$(wildcard $(dir)/*.$1)))) -m-hdr-macs = $(call collect,h.m) -m-c-src-macs = $(call collect,c.m) -m-s-src-macs = $(call collect,$(TARGET).s.m) - -m-c-sources = $(call transform,c.m,$(TMP)/@.%.c) -m-s-sources = $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s) - -m-headers = $(call transform,h.m,$(OUT)/k/%.h) -m-c-objects = $(call transform,c.m,$(OUT)/@.%.o) -m-s-objects = $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o) - -fnobjects = $(call transform,fn.c,$(OUT)/@.%.fn.o) \ - $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \ - $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \ - $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o) - -rtobjects = $(call transform,rt.c,$(OUT)/@.%.rt.o) \ - $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \ - $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \ - $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o) - -objects = $(fnobjects) $(rtobjects) - -header-dir = /usr/include -lib-dir = /usr/lib +m-hdr-macs := $(call collect,h.m) +m-c-src-macs := $(call collect,c.m) +m-s-src-macs := $(call collect,$(TARGET).s.m) + +m-c-sources := $(call transform,c.m,$(TMP)/@.%.c) +m-s-sources := $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s) + +m-headers := $(call transform,h.m,$(OUT)/k/%.h) +m-c-objects := $(call transform,c.m,$(OUT)/@.%.o) +m-s-objects := $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o) + +fnobjects := $(call transform,fn.c,$(OUT)/@.%.fn.o) \ + $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \ + $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \ + $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o) + +rtobjects := $(call transform,rt.c,$(OUT)/@.%.rt.o) \ + $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \ + $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \ + $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o) + +docs := $(wildcard k*/*.md) +docs-out := $(patsubst %.md,$(OUT)/doc/man/%.4.gz,$(notdir $(docs))) +objects := $(fnobjects) $(rtobjects) + +prefix ?= /usr +d-header = $(prefix)/include +d-lib = $(prefix)/lib +d-share = $(prefix)/share unix-oses = lin fbsd dar and -posix-oses = lin fbsd dar and hai mgw +posix-oses = lin fbsd dar and hai mgw cyg ifeq ($(findstring $(OS),$(unix-oses)),$(OS)) export UNIX = yes export POSIX = yes else @@ -66,46 +74,48 @@ endif endif # include libgcc.a in gcc builds, just in case ifeq ($(CC),gcc) -export COMPLIB = -lgcc + export COMPLIB = -lgcc endif all: $(OUT) defs obj tool lib.static $(OUT)/boot.o lib.shared lib.static: defs obj $(OUT)/libk.a lib.shared: defs obj $(OUT)/libk.so obj: $(moddirs:%=%.obj) defs: $(moddirs:%=%.def) tool: $(OUT)/boot.o $(OUT)/libk.a $(binmods:%=%.tool) +doc: $(docs-out) clean: rm -rf $(TMP) $(OUT) install: all - install -d $(header-dir)/k -o root -g wheel + install -d $(header-dir)/k $(share-dir)/k -o root -g wheel -m 0755 install $(OUT)/k/* $(header-dir)/k/ -o root -g wheel -m 0644 - install -d $(lib-dir)/k -o root -g wheel - install $(OUT)/libk.a $(OUT)/libk.so $(OUT)/boot.o \ - $(lib-dir)/k/ -o root -g wheel -m 0644 + install $(OUT)/libk.a $(OUT)/libk.so \ + $(lib-dir) -o root -g wheel -m 0644 + install $(OUT)/boot.o $(share-dir)/k/boot.o -o root -g wheel -m 0644 uninstall: $(header-dir)/k $(lib-dir)/k rm -rf $^ -lists = moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX +lists = BUILD moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX docs docs-out dbg: @echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))") -%.obj: %/makefile $(OUT) +%.obj: %/makefile $(OUT)/internal.ident.o $(OUT) cd $* && $(MAKE) obj %.tool: %/makefile $(OUT) cd $* && $(MAKE) tool %.dbg: %/makefile $(OUT) cd $* && $(MAKE) dbg %.def: %/makefile $(TMP)/typesize.def \ + $(OUT)/k/internal.egroup.h \ $(TMP)/system_calls.h \ $(TMP)/system_calls.s \ $(TMP)/error_table.h \ $(OUT) $(OUT)/k cd $* && $(MAKE) def @@ -131,7 +141,17 @@ @# using `ar rc` and ranlib here instead of @# `ar rcs` in case `ar` isn't the GNU version ar rc $@ $^ ranlib $@ +$(OUT)/man/doc: + mkdir -p $@ + +$(OUT)/k/internal.egroup.h: global/modules global/genconds.awk $(OUT)/k + awk -f global/genconds.awk <$< >$@ +$(TMP)/internal.ident.c: global/modules global/genident.awk $(OUT)/k/internal.egroup.h $(TMP) + awk -f global/genident.awk <$< >$@ +$(OUT)/%.o: $(TMP)/%.c $(OUT) + $(CC) $(cflags) -c $< -o $@ + $(OUT) $(OUT)/k $(TMP): mkdir -p $@ Index: modmake ================================================================== --- modmake +++ modmake @@ -1,9 +1,11 @@ #- modmake # this is the master makefile that controls the building of each # libk module. it is included from each k*/makefile. # vim: ft=make + +include ../makerule mod = $(notdir $(PWD)) src = $(wildcard *.c) $(wildcard *.s) $(filter-out %.h,$(patsubst %.m,%,$(wildcard *.m))) bare = $(mod:k%=%) headers = $(wildcard *.h) $(gen-headers) $(patsubst %.m,%,$(wildcard *.h.m)) @@ -11,22 +13,10 @@ tools = $(filter %.exe.c, $(src)) nontools = $(filter-out %.exe.c, $(src)) cobjects = $(filter %.c, $(nontools)) sobjects = $(filter %.${TARGET}.s, $(nontools)) -cflags = -std=c11 -isystem ${OUT} -isystem ${TMP} -isystem ${ROOT}/arch -fPIC -nostdlib ${COMPLIB} -L${OUT} - -m-env = atom_target_arch=${ARCH} -m-env += atom_target_os=${OS} -ifneq (${BITS},) #!!! ifdef does NOT work with environment variables - m-env += atom_target_bits=${BITS} -endif -m-env += target_posix=${POSIX} -m-env += target_unix=${UNIX} - -m-comp = ${m4} $(m-env:%=-D%) - obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \ $(sobjects:%.s=${OUT}/$(mod).%.o) tool: $(tools:%.exe.c=${OUT}/$(mod).%) \ ${OUT}/libk.a