libk  Check-in [e794c5edef]

Overview
Comment:add a bunch of code, port the header mechanism to gpp; add a fuckton of definitions and compatibility header code; notably, add core function kstop and x86.lin.{32,64} impl. update docs accordingly
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e794c5edef00e56053792a71a97b4e5b24560627fba9624f86cc00e5357911ce
User & Date: lexi on 2019-06-29 09:31:50
Other Links: manifest | tags
Context
2019-07-26
09:51
major update. fix ridiculous old type size determination mechanism. mmap is still broken and i'm not sure why; the syscall does not appear to be going through correctly - see posix_mmap, kmheapa, and kcore/testbin.exe.fn check-in: 6479e060a3 user: lexi tags: trunk
2019-06-29
09:31
add a bunch of code, port the header mechanism to gpp; add a fuckton of definitions and compatibility header code; notably, add core function kstop and x86.lin.{32,64} impl. update docs accordingly check-in: e794c5edef user: lexi tags: trunk
2019-06-28
04:52
fix stupid bullshit that was including boot.o in libk.a which already HAS the runtime shit ohmyGOD check-in: de8e1eb5d2 user: lexi tags: trunk
Changes

Added grammar/grammar.gpp version [89005aac7c].

            1  +#define flag -#1
            2  +#define		exec x
            3  +#define mode flag(#1)#2
            4  +#define		user U
            5  +#define		meta M
            6  +#define add +#1
            7  +#define del -#1
            8  +#define		unix_lf z
            9  +#define 	keepnl n
           10  +#define		tri #1#2#3
           11  +#define 	comment c
           12  +#define 	string s
           13  +#define		quote q
           14  +#define		eval S
           15  +#define		evalquote Q
           16  +#define stack bal_stack bal_unstack
           17  +#define meta_grammar meta_start meta_end meta_arg_start meta_sep meta_arg_end stack
           18  +#define user_grammar call_start call_end arg_start arg_sep arg_end stack arg_num_char quote_char

Added grammar/makefile version [8c2d1af7ce].

            1  +${TMP}/%: %.gpp grammar.gpp
            2  +	${gpp} $< | tr "\n" ' ' > $@

Added grammar/precomp.g.gpp version [d33952f39e].

            1  +#include grammar.gpp
            2  +#mode comment "//" "\n"
            3  +// this file defines the "precomp" grammar, the grammar
            4  +// that's used to process C code templates
            5  +// vim: ft=c
            6  +#define call_start     "["
            7  +#define call_end       "]"
            8  +#define arg_start      " "
            9  +#define arg_sep        ",\\w"
           10  +#define arg_end        "]"
           11  +#define bal_stack      "\(["
           12  +#define bal_unstack    "\)]"
           13  +#define arg_num_char   "\\$"
           14  +#define quote_char     "|"
           15  +#define meta_start     "\\w["
           16  +#define meta_end       "]\\w"
           17  +#define meta_arg_start " "
           18  +#define meta_sep       "\\w:\\w"
           19  +#define meta_arg_end   "]\\W"
           20  +add(unix_lf)
           21  +add(comment "---" "\\n")
           22  +add(comment "(*" "*)")
           23  +flag(exec)
           24  +mode(user, user_grammar)
           25  +mode(meta, meta_grammar)

Added kcore/__stack_chk_fail.fn.c version [7f5547f66a].

            1  +#include <k/core.h>
            2  +
            3  +void __stack_chk_fail(void) { kstop(-1); }

Modified kcore/boot.rt.x86.lin.64.s from [2671a43f32] to [22c891476d].

     1      1   ; vim: ft=nasm
     2      2   bits 64
     3      3   %include "../arch/x86.lin.64.s"
     4      4   global _start:function
     5      5   extern _boot
     6         -extern entry;
            6  +extern entry
     7      7   
     8      8   _start:
     9      9   	mov rbp, rsp
    10     10   	mov rdi, [rbp + 0] ; argc
    11     11   	lea rsi, [rbp + 8] ; argv
    12     12   
    13     13   	call _boot
    14     14   
    15     15   	mov sys.reg.1, sys.reg.ret
    16     16   	mov sys.reg.0, sys.exit
    17     17   	sys.call

Modified kcore/core.h from [cb5067b74b] to [ded1289884].

     1      1   #ifndef KIcore
     2      2   #define KIcore
     3      3   #include <k/type.h>
     4      4   #include <k/io.h>
     5      5   #include <k/str.h>
     6      6   
     7         -static void* const null = (void*)0;
     8         -
     9      7   typedef struct kvar {
    10      8   	ksraw name;
    11      9   	ksraw val;
    12     10   	char* platform;
    13     11   } kvar;
    14     12   
    15     13   typedef struct kenv {
    16     14   	kiochan std;
    17     15   	kiochan err;
    18     16   	sz argc; char** argv;
    19     17   	kvar* vars;
    20     18   } kenv;
    21     19   
           20  +
           21  +/* i'm really sorry okay */
           22  +typedef
           23  +#if (__STDC_VERSION__ >= 199901L)
           24  +	_Bool bool;
           25  +#endif
           26  +enum
           27  +#if !(__STDC_VERSION__ >= 199901L)
           28  +	bool /* enum bool { */
           29  +#endif
           30  +{
           31  +	false = 0, no  = 0,
           32  +	true  = 1, yes = 1
           33  +}
           34  +#if !(__STDC_VERSION__ >= 199901L)
           35  +	bool /* } bool ; */
           36  +#endif
           37  +;
           38  +
           39  +#ifndef KFclean
           40  +#	if (__STDC_VERSION__ >= 199901L) ||\
           41  +	   (__cplusplus      >= 201103L)
           42  +#		define KVvm_args __VA_ARGS__
           43  +#		define KVvm_spec ...
           44  +#		define KFfeat_variadic_macro
           45  +#	else
           46  +#		define KVvm_args K_TEMP_M2QD52
           47  +#		define KVvm_spec K_TEMP_M2QD52
           48  +#	endif
           49  +#	if defined(__GNUC__) || defined(__clang__)
           50  +#		define KA(KVvm_spec) __attribute__((KVvm_args))
           51  +#	else
           52  +#		define KA(KVvm_spec)
           53  +#	endif
           54  +#	define KAformat(KVvm_spec) KA(format(KVvm_args))
           55  +#	define KAexport(KVvm_spec) KA(visibility(KVvm_args))
           56  +
           57  +#	define KAunused   KA(unused)
           58  +#	define KAnoreturn KA(noreturn)
           59  +#	define KApure     KA(const)
           60  +#	define KAinline   KA(always_inline)
           61  +#	define KAflatten  KA(flatten)
           62  +#	define KAexport_none  KAexport("hidden")
           63  +#	define KAexport_force KAexport("default")
           64  +/*  now we define standard version flags,
           65  + *  to make it easy for the user to write
           66  + *  more portable code. */
           67  +#	if (__STDC_VERSION__ >= 199901L) 
           68  +#		define KFstd_c89
           69  +#		define KFstd_c99
           70  +#		define KVstd c99
           71  +#	else
           72  +#		ifdef __STDC__
           73  +#			define KFstd_c89
           74  +#			define KVstd c89
           75  +#		else
           76  +#			define KVstd K&R /* UH OH */
           77  +#		endif
           78  +#	endif
           79  +#	if (__STDC_VERSION__ >= 201103L)
           80  +#		define KFstd_c11
           81  +#		define KVstd c11
           82  +#	endif
           83  +#	ifdef __cplusplus
           84  +#		define KFstd_cpp
           85  +#		define KVstd c++
           86  +#		if (__cplusplus >= 201103L)
           87  +#			define KFstd_cpp11
           88  +#			define KVstd c++11
           89  +#		endif /* TODO: add more */
           90  +#	endif
           91  +#endif
           92  +
           93  +/* hooo boy. null. that one's got a storied
           94  + * history across the versions and dialects.
           95  + * below, we try to find the ideal way to
           96  + * offer a "null" "keyword" depending on
           97  + * dialect, version, and whether the user
           98  + * has asked for macros to be suspended.
           99  + * note that this may result in no "null"
          100  + * being defined in C++ or K&R C. */
          101  +#if defined (__cplusplus) && ! defined(KFclean)
          102  +#	if __cplusplus >= 201103L
          103  +#		define null nullptr
          104  +#	else
          105  +#		define null ((void*)0)
          106  +#	endif
          107  +#elif defined __STDC__
          108  +	enum { null = 0 };
          109  +	/* believe it or not, this is actually
          110  +	 * completely legal. doesn't even raise
          111  +	 * a single warning. i was surprised too. */
          112  +#elif ! defined(KFclean)
          113  +#	define null ((void*)0)
          114  +#endif
          115  +
          116  +#ifdef __cplusplus
          117  +#	define noreturn [[ noreturn ]]
          118  +#elif __STDC_VERSION__ >= 201103L
          119  +#	define noreturn _Noreturn
          120  +#else
          121  +#	define noreturn
          122  +#endif
          123  +
          124  +noreturn void kstop(longstat code);
          125  +
          126  +#ifdef KFclean
          127  +#	undef noreturn
          128  +#endif
          129  +
    22    130   #endif

Deleted kcore/def.fbsd.i version [4373f0187e].

     1         -#define KVos fbsd
     2         -typedef unsigned char stat;

Deleted kcore/def.h version [5f84d85008].

     1         -#include <k/type.h>
     2         -/* <k/def.h>
     3         - * ~ lexi hale <lexi@hale.su>
     4         - * define flags so we can reason about
     5         - * our environment. */
     6         -
     7         -#if (KVos == lin)  ||\
     8         -    (KVos == fbsd) ||\
     9         -    (KVos == obsd) ||\
    10         -    (KVos == nbsd) ||\
    11         -    (KVos == dar) ||\
    12         -    (KVos == and)  
    13         -#   define KFenv_unix
    14         -#endif
    15         -
    16         -#if defined(KFenv_unix)  ||\
    17         -           (KVos == hai) ||\
    18         -           (KVos == mgw)
    19         -#   define KFenv_posix
    20         -#endif
    21         -

Added kcore/def.h.m version [9abe158651].

            1  +--- kcore/def.h.m → <k/def.h>
            2  +--- ~ lexi hale <lexi@hale.su>
            3  +--- this file gathers information on the environment it's
            4  +--- being compiled in, setting macros that other headers
            5  +--- need. it will be emitted as <k/def.h>.
            6  +--- vim: ft=c
            7  +
            8  +[ifdef atom_target_bits]
            9  +	[define target: [atom_target_arch].[atom_target_os].[atom_target_bits]]
           10  +	#define KVbits [atom_target_bits]
           11  +[else]
           12  +	[define target: [atom_target_arch].[atom_target_os]]
           13  +[endif]
           14  +#define KVtarget [target]
           15  +#define KVos [atom_target_os]
           16  +#define KVarch [atom_target_arch]
           17  +[if [target_unix] == yes]
           18  +	#define KFenv_unix
           19  +	#define KFenv_posix
           20  +[else]
           21  +	[if [target_posix] == yes]
           22  +		#define KFenv_posix
           23  +	[endif]
           24  +[endif]
           25  +
           26  +#define Kpragma(p) _Pragma(#p)
           27  +#if defined(__GNUC__) || defined(__clang__)
           28  +#   define Kerror(msg) Kpragma(GCC error #msg) 
           29  +#else
           30  +#   define Kerror(msg) Kpragma(message #msg)
           31  +#endif
           32  +#define Knoimpl(fn) Kerror(no implementation of fn for platform [target])

Deleted kcore/def.lin.i version [0178d496a4].

     1         -#define KVos lin
     2         -typedef unsigned char stat;

Deleted kcore/def.win.i version [11ccc3c2e7].

     1         -#define KVos win
     2         -typedef u32 stat;

Added kcore/exit.fn.x86.lin.32.s version [4c4a17d7b6].

            1  +bits 32
            2  +%include "../arch/x86.lin.32.s"
            3  +; vim: ft=nasm
            4  +global kio_posix_exit
            5  +
            6  +kio_posix_exit:
            7  +	mov sys.reg.0, sys.call.exit
            8  +	mov sys.reg.1, [esp + 4] ; first C int argument
            9  +	sys.call
           10  +	; does not return

Added kcore/exit.fn.x86.lin.64.s version [4c49f79d26].

            1  +bits 64
            2  +%include "../arch/x86.lin.64.s"
            3  +%include "../arch/x86.cdecl.64.s"
            4  +; vim: ft=nasm
            5  +
            6  +global kio_posix_exit
            7  +kio_posix_exit:
            8  +	mov sys.reg.1, ccall.reg.0 ;nop - rdi → rdi
            9  +	mov sys.reg.0, sys.exit
           10  +	sys.call
           11  +	; no return

Modified kcore/kcore.md from [d664110812] to [28cd81b166].

     1      1   # kcore
     2         -**kcore** is the foundation for the rest of libk. it defines types and structs that are needed by every program, and provides the stub that launches a program's "entry" function.
            2  +**kcore** is the foundation for the rest of libk. it defines types and structs that are needed by every program, and provides the stub that launches a program's "entry" function. unlike the non-core modules, kcore definitions simply use the prefix `k-`.
     3      3   
     4      4   ## entry
     5      5   when using libk, your program's entry point will not be the `int main(int,char**)` function that libc opens into. libk will call the function `stat entry(kenv)` instead. like libc, the value returned by `entry` will be returned to the host platform.
     6      6   
     7      7   ## types
     8      8   kcore contains fixed-width integer types (in <k/type.h>). note that the availability of each depends on your platform; compilation will fail if e.g. you try to use a u64 or a u128 on a 32-bit platform, so where exact lengths are not required, you may wish to use the built-in C types instead.
     9      9   
................................................................................
    28     28    * `kvar* vars` - a pointer into the program's environment
    29     29   
    30     30   ### struct kvar
    31     31   `kvar` is a struct that abstracts over platform environment variables.
    32     32    * `kstr name` - the name of an environment variable
    33     33    * `kstr val` - the value of an environment variable
    34     34    * `char* platform` - a pointer into the platform's underlying representation
           35  +
           36  +## functions
           37  +
           38  +### kstop()
           39  +
           40  +`noreturn void kstop(stat)` terminates the program immediately, returning the specified integer to the OS as an exit status. the type of integer it takes depends on your operating system. consider using the `enum kbad` defines in `<k/magic.h>`, which are designed to standardize exit statuses across different software and are synchronized with a FreeBSD effort to do the same (`<sysexit.h`).
           41  +
           42  +## definitions
           43  +
           44  +kcore is the only module that defines any terms outside the k- namespace. the only terms it so defines are native C terms like `noreturn`, which are implemented as keywords in a reserved namespace (`_` followed by an uppercase letter; in this case, `_Noreturn`). macros are then defined in new headers for the "natural" version of the term in order to avoid breaking older code. examples of this technique are `<stdbool.h>` and `<stdnoreturn.h>`. since libk is designed for new, modern code, breaking old code isn't a concern, and we turn on all these new keywords as soon as you load `<k/core.h>`.
           45  +
           46  +libk attempts to find the best possible definition and implementation for these various types and keywords, abstracting across different C versions and dialects. you can go ahead and use the normal version of the keywords (e.g. `noreturn`, `bool`) no matter what kind of compiler you're using and you're guaranteed that as long as you don't go fiddling with undefined- or implementation behavior, your code will behave the same every time. at worst, it may lack a few optimizations or warnings.
           47  +
           48  +(the one minor exception is `null`, a new keyword which libk uses in preference to the ugly, hard-to-type C macro `NULL`.)
           49  +
           50  +`bool` is implemented as a `_Bool` typedef if `_Bool` is available, and as an enum typedef otherwise. either way, and regardless of whether `KFclean` has been defined, booleans can be used and set to the values `true`, `false`, `yes`, or `no`. `yes` and `true` are synonyms, as are `false` and `no`.
           51  +
           52  +### macros
           53  +
           54  +if the flag `KFclean` has not been defined, kcore defines a number of macros to abstract over nonstandard C features. for instance, the `KA*` macros can be used to specify GNU/clang attributes without worrying about compatibility, as they'll automatically be blanked under an incompatible compiler. the KA series includes:
           55  +
           56  +	* `KApure` - marks a "pure" function that changes no state and only takes purely numeric arguments, allowing the compiler to avoid repetetive calls to it or even evaluate it at runtime.
           57  +	* `KAnoreturn` - the GNU/clang-specific version of `noreturn`.
           58  +	* `KAunused` - acknowledges that a variable is unused and tells the compiler to shut up about it.
           59  +	* `KAinline` - forces the compiler to inline a function whether it likes it or not.
           60  +	* `KAflatten` - placed on a function, will force-inline all function calls *made by* that function — sort of like `KAinline` in reverse.
           61  +	* `KAformat()` - specifies that the function has printf-style syntax for error-checking purposes. worst hack in history.
           62  +
           63  +if you wish to add more (there are like, hundreds) please consider making a merge request. however, the generic macro KA() is also available in the interim: `KA(unused)`.
           64  +
           65  +however, unlike C++ attributes, GNU-style attributes can only be placed on a function declaration, *not* its definition.

Added kcore/magic.h version [1f7f63c3e2].

            1  +/* <k/magic.h>
            2  + * ~ lexi hale <lexi@hale.su>
            3  + * one of libk's biggest goals is standardization across
            4  + * software. for this reason, we define here a variety
            5  + * of "magical numbers" used to signal or describe
            6  + * various states, messages, and errors. suggestions are
            7  + * welcome.
            8  + */
            9  +#include <k/type.h>
           10  +
           11  +typedef enum kbad {
           12  +	// values to be returned by an entry function
           13  +	kbad_ok = 0,
           14  +		/* the requested operation completed
           15  +		 * successfully */
           16  +
           17  +	/* these are synchronized with freebsd's existing
           18  +	 * sysexit.h conventions. */
           19  +	kbad_usage = 64,
           20  +		/* # fbsd EX_USAGE
           21  +		 * a usage screen was displayed to the user
           22  +		 * on request or due to improperly formed call */
           23  +	kbad_data = 65,
           24  +		/* # fbsd EX_DATAERR
           25  +		 * data supplied by the user was incorrect in
           26  +		 * some way */
           27  +	kbad_no_input = 66,
           28  +		/* # fbsd EX_NOINPUT
           29  +		 * input to the program is absent */
           30  +	kbad_user = 67,
           31  +		/* # fbsd EX_NOUSER
           32  +		 * these aren't the droids you're looking for */
           33  +	kbad_host = 68,
           34  +		/* # fbsd EX_NOHOST
           35  +		 * that host doesn't exist */
           36  +	kbad_avail = 69,
           37  +		/* # fbsd EX_UNAVAILABLE
           38  +		 * a necessary resource or support system isn't
           39  +		 * available, or something else went wrong */
           40  +	kbad_internal = 70,
           41  +		/* # fbsd EX_SOFTWARE
           42  +		 * "my bad" */
           43  +	kbad_os = 71,
           44  +		/* # fbsd EX_OSERR
           45  +		 * the OS did a fucksy-wucksy */
           46  +	kbad_osfile = 72,
           47  +		/* # fbsd EX_OSFILE
           48  +		 * a system file is fucked up or gone */
           49  +	kbad_creat = 73,
           50  +		/* # fbsd EX_CANTCREAT */
           51  +	kbad_io = 74,
           52  +		/* # fbsd EX_IOERR */
           53  +	kbad_try = 75,
           54  +		/* # fbsd EX_TEMPFAIL
           55  +		 * something went wrong this time. try again
           56  +		 * some other time */
           57  +	kbad_proto = 76,
           58  +		/* # fbsd EX_PROTOCOL
           59  +		 * failure to speak a protocol correctly */
           60  +	kbad_perm = 77,
           61  +		/* # fbsd EX_NOPERM
           62  +		 * you or the program do not have permissions
           63  +		 * to do the thing requested */
           64  +	kbad_conf = 78,
           65  +		/* # fbsd EX_CONFIG
           66  +		 * your configuration is fucked */
           67  +} kbad;

Modified kcore/makefile from [121a62ca71] to [c01fcd380e].

     1      1   ## kcore/makefile
     2      2   # kcore has to include, among other things, a replacement
     3         -# for stddef.h, and that can't be written in portable C,
            3  +# for stddef.h, and that can't be written in portable C.
     4      4   # so we're generating it at build time.
            5  +
            6  +# gen-headers = type.h
            7  +
            8  +include ../modmake
            9  +
           10  +## the below code predates the introduction of gpp
           11  +## to generate these headers from templates instead
           12  +## of trying to write one for everypossible arch 
           13  +## tuple. it is left as a monument to a terrible
           14  +## and now blissfully forgotten past.
     5     15   #
     6     16   # look, imma just be straight with you. the mechanism we're
     7     17   # using to generate these headers is unbelievably heinous.
     8     18   # it's inelegant, it's gross, and it's horrible. in the long
     9     19   # term this NEEDS to be replaced with a bespoke solution
    10     20   # instead of makefile gibberish. hopefully tho this will be
    11     21   # enough in the short term for libk to get going, enough that
    12     22   # someone more competent than me will someday be interested
    13     23   # in fixing this horrorshow.
    14     24   #
    15     25   # until them: i'm sorry.
    16     26   # very sincerely yours, lexi hale
    17         -
    18         -gen-headers = type.h
    19         -
    20         -include ../modmake
    21         -
    22         -${OUT}/k/type.h: ${TMP}/type.${TARGET}.i
    23         -	cp $< $@
    24         -
    25         -# generating C source in make… yaaay
    26         -define arch =
    27         -${TMP}/type.$(1).%.$(2).i: type.$(1).$(2).i def.%.i ${TMP}
    28         -	echo '#ifndef KItype' > $$@
    29         -	echo '#define KItype' >> $$@
    30         -	cat $$< >> $$@
    31         -	cat def.$$*.i >> $$@
    32         -	echo '#endif' >> $$@
    33         -endef
    34         -
    35         -$(eval $(call arch,x86,32))
    36         -$(eval $(call arch,x86,64))
    37         -
           27  +# ${OUT}/k/type.h: ${TMP}/type.${TARGET}.i
           28  +# 	cp $< $@
           29  +#
           30  +# # generating C source in make… yaaay
           31  +# define arch =
           32  +# ${TMP}/type.$(1).%.$(2).i: type.$(1).$(2).i def.%.i ${TMP}
           33  +# 	echo '#ifndef KItype' > $$@
           34  +# 	echo '#define KItype' >> $$@
           35  +# 	cat $$< >> $$@
           36  +# 	cat def.$$*.i >> $$@
           37  +# 	echo '#endif' >> $$@
           38  +# endef
           39  +#
           40  +# $(eval $(call arch,x86,32))
           41  +# $(eval $(call arch,x86,64))
           42  +#

Added kcore/old/def.fbsd.i version [4373f0187e].

            1  +#define KVos fbsd
            2  +typedef unsigned char stat;

Added kcore/old/def.h version [074eb1cc6b].

            1  +#include <k/type.h>
            2  +/* <k/def.h>
            3  + * ~ lexi hale <lexi@hale.su>
            4  + * define flags so we can reason about
            5  + * our environment. */
            6  +
            7  +#if (KVos == lin)  ||\
            8  +    (KVos == fbsd) ||\
            9  +    (KVos == obsd) ||\
           10  +    (KVos == nbsd) ||\
           11  +    (KVos == dar) ||\
           12  +    (KVos == and)  
           13  +#   define KFenv_unix
           14  +#endif
           15  +
           16  +#if defined(KFenv_unix)  ||\
           17  +           (KVos == hai) ||\
           18  +           (KVos == mgw)
           19  +#   define KFenv_posix
           20  +#endif
           21  +
           22  +#define Kpragma(p) _Pragma(#p)
           23  +#if defined(__GNUC__) || defined(__clang__)
           24  +#   define Kerror(msg) Kpragma(GCC error #msg) 
           25  +#else
           26  +#   define Kerror(msg) Kpragma(message #msg)
           27  +#endif
           28  +#define Knoimpl(fn,p) Kerror(no implementation of fn for platform p)

Added kcore/old/def.lin.i version [0178d496a4].

            1  +#define KVos lin
            2  +typedef unsigned char stat;

Added kcore/old/def.win.i version [11ccc3c2e7].

            1  +#define KVos win
            2  +typedef u32 stat;

Added kcore/old/type.x86.32.i version [fe891b76db].

            1  +#define KVarch x86
            2  +#define KVbits 32
            3  +
            4  +typedef unsigned long sz;
            5  +
            6  +typedef unsigned char  u8;
            7  +typedef signed char    s8;
            8  +typedef unsigned short u16;
            9  +typedef signed short   s16;
           10  +typedef unsigned long  u32;
           11  +typedef signed long    s32;
           12  +
           13  +typedef u32  word;
           14  +typedef s32 sword;

Added kcore/old/type.x86.64.i version [03a8b8f372].

            1  +#define KVarch x86
            2  +#define KVbits 64
            3  +
            4  +typedef unsigned long long sz;
            5  +
            6  +typedef unsigned char      u8;
            7  +typedef signed char        s8;
            8  +typedef unsigned short     u16;
            9  +typedef signed short       s16;
           10  +typedef unsigned long      u32;
           11  +typedef signed long        s32;
           12  +typedef unsigned long long u64;
           13  +typedef signed long long   s64;
           14  +typedef __uint128_t        u128;
           15  +typedef __int128_t         s128;
           16  +
           17  +typedef u64  word;
           18  +typedef s64 sword;

Added kcore/stop.fn.c version [c4373dead4].

            1  +/* kcore/stop.fn.c - kstop()
            2  + * ~ lexi hale <lexi@hale.su>
            3  + * this file defines a function that prematurely exits from
            4  + * a running libk program with an appropriate exit status. */
            5  +
            6  +#include <k/core.h>
            7  +#include <k/def.h> // so we know what system this is
            8  +#include <k/type.h>
            9  +
           10  +#ifdef KFenv_posix
           11  +#	define STOPFN kio_posix_exit
           12  +	extern void STOPFN(int);
           13  +#else
           14  +	Knoimpl(kstop)
           15  +#endif
           16  +
           17  +noreturn void kstop (longstat code) { STOPFN(code); }

Added kcore/testbin.exe.c version [f1bdb07ea2].

            1  +#include <k/core.h>
            2  +#include <k/mem.h>
            3  +#include <k/io.h>
            4  +#include <k/magic.h>
            5  +
            6  +kbad entry(kenv e) {
            7  +	const char msg[] = "hello from libk\n";
            8  +	ksraw ptr = { Kmsz(msg), msg };
            9  +
           10  +	bool maybe = true;
           11  +	maybe = no;
           12  +
           13  +	if (kiosend(e.std, ptr, null) == kiocond_ok) {
           14  +		return kbad_ok;
           15  +	} else {
           16  +		return kbad_io;
           17  +	}
           18  +}

Added kcore/type.h.m version [8b1f2e0cb2].

            1  +--- kcore/type.h.m → <k/def.h>
            2  +--- ~ lexi hale <lexi@hale.su>
            3  +--- this file gathers information on the environment it's
            4  +--- being compiled in, defining types that our code
            5  +--- needs. it will be emitted as <k/type.h>.
            6  +--- vim: ft=c
            7  +
            8  +// arch bit length [atom_target_bits]
            9  +--- make some gigantic fucking assumptions
           10  +[if [atom_target_bits] >= 8]
           11  +    typedef unsigned char  u8;
           12  +    typedef signed char    s8;
           13  +    [if [atom_target_bits] >= 16]
           14  +        typedef unsigned short u16;
           15  +        typedef signed short   s16;
           16  +        [if [atom_target_bits] >= 32]
           17  +            typedef unsigned long  u32;
           18  +            typedef signed long    s32;
           19  +            [if [atom_target_bits] >= 64]
           20  +                typedef unsigned long long u64;
           21  +                typedef signed long long s64;
           22  +                [if [atom_target_arch] == x86]
           23  +                    #if defined(__GNUC__) || defined(__clang__)
           24  +                        typedef __uint128_t u128;
           25  +                        typedef __int128_t  s128;
           26  +                    #endif
           27  +                [endif]
           28  +            [endif]
           29  +        [endif]
           30  +    [endif]
           31  +[endif]
           32  +
           33  +typedef u[atom_target_bits]  sz;
           34  +typedef s[atom_target_bits] ssz;
           35  +
           36  +--- make sure something unlikely doesn't happen
           37  +[define [maxtype name, n]:
           38  +	[if [n] > [atom_target_bits]]
           39  +		typedef u[atom_target_bits] [name]
           40  +	[else]
           41  +		typedef u[n] [name]
           42  +	[endif]]
           43  +
           44  +// exit status integer types - pls use kbad in <k/magic.h> instead
           45  +[if [target_posix] == yes]
           46  +	/* by convention, posix return values are 8-bit,
           47  +	 * but note that many modern UNIXes do technically
           48  +	 * support higher-bit values. for this reason,
           49  +	 * longstat is defined differently under posix. */
           50  +	typedef u8 stat;
           51  +	[maxtype longstat, 32];
           52  +[else]
           53  +	[if ([atom_target_os] == win) ||
           54  +		([atom_target_os] == vms)]
           55  +		[maxtype stat, 32]
           56  +	[else]
           57  +		typedef u8 stat;
           58  +		/* we don't know a specific exit status type
           59  +		 * for your arch so we're going with a sane
           60  +		 * default. if this is wrong, help us fix it! */
           61  +	[endif]
           62  +	typedef stat longstat;
           63  +[endif]

Deleted kcore/type.x86.32.i version [fe891b76db].

     1         -#define KVarch x86
     2         -#define KVbits 32
     3         -
     4         -typedef unsigned long sz;
     5         -
     6         -typedef unsigned char  u8;
     7         -typedef signed char    s8;
     8         -typedef unsigned short u16;
     9         -typedef signed short   s16;
    10         -typedef unsigned long  u32;
    11         -typedef signed long    s32;
    12         -
    13         -typedef u32  word;
    14         -typedef s32 sword;

Deleted kcore/type.x86.64.i version [03a8b8f372].

     1         -#define KVarch x86
     2         -#define KVbits 64
     3         -
     4         -typedef unsigned long long sz;
     5         -
     6         -typedef unsigned char      u8;
     7         -typedef signed char        s8;
     8         -typedef unsigned short     u16;
     9         -typedef signed short       s16;
    10         -typedef unsigned long      u32;
    11         -typedef signed long        s32;
    12         -typedef unsigned long long u64;
    13         -typedef signed long long   s64;
    14         -typedef __uint128_t        u128;
    15         -typedef __int128_t         s128;
    16         -
    17         -typedef u64  word;
    18         -typedef s64 sword;

Added kio/send.c version [d88d1642fe].

            1  +#include <k/io.h>
            2  +#include <k/core.h>
            3  +#include <k/def.h>
            4  +/* send.c - kiosend()
            5  + * ~ lexi hale <lexi@hale.su>
            6  + * kiosend() writes to a channel with an open out stream
            7  + */
            8  +
            9  +// we define all platform functions here,
           10  +// whether or not they're for the correct
           11  +// platform - only the ones actually called
           12  +// by the generated code will be linked
           13  +extern sz kio_posix_fd_write(int fd, const char* buf, sz len);
           14  +
           15  +kiocond kiosend(kiochan target, ksraw string, sz* len) {
           16  +#	ifdef KFenv_posix
           17  +		sz size = kio_posix_fd_write(target.out.platform_fd, string.ptr, string.size);
           18  +		if (size == -1) return kiocond_fail; //TODO: retrieve errno and offer more specific errors
           19  +#	else
           20  +#		if KVos == win
           21  +#			error windows IO send function not yet defined
           22  +#		else
           23  +			Knoimpl(kiosend,KVos);
           24  +#			error missing implementation // boring error for plebs
           25  +#		endif
           26  +#	endif
           27  +
           28  +	if (len != null) *len = size;
           29  +	return kiocond_ok;
           30  +}

Modified libk.md from [3c28c4d693] to [65938a7892].

    25     25    5. **intrinsic reentrancy.** because *jesus christ,* libc.
    26     26    6. **interprocess communication.** libc offers no useful IPC abstractions over the paltry array of tools POSIX &co. give us to work with. we can do better.
    27     27    7. **tooling.** libk is intended as more than just a library. it's also intended to work with some basic tooling to automate tasks that current binary tooling is inadequate for -- for instance, embedding binary data into a program binary. (see module [kgraft](kgraft))
    28     28    8. **modularity.** libk is not part of the C specification and it isn't always going to be practical for developers to expect the entire library to be present on the end-user's computer. so libk is designed to be usable in many different ways -- as a traditional library, as a static library, in full form or with only components needed by the developer, to be distributed either on its own or as part of a binary.
    29     29    9. **compatibility.** code that links against libk should be able to compile and run on any operating system. in the ideal case (Linux or FreeBSD) it will be able to do so without touching any other system libraries; for less ideal environments like Windows, libk will when necessary abstract over system libraries or libc itself.
    30     30    10. **sane error-handling.** every time you type `errno` god murders a puppy.
    31     31   
           32  +## dependencies
           33  +
           34  +libk is designed to be as portable and depedency-free as possible. ideally, it will be possible to compile code against libk using nothing but libk itself.
           35  +
           36  +compiling libk is also designed to be as easy as possible. it has only two external dependencies, the macro processor [gpp], needed for compile-time header generation , and the [GNU make] utility, whose advanced features are needed to perform the relatively complex task of building all of libk from the ground up. 
           37  +
           38  + [gpp]: http://en.nothingisreal.com/wiki/GPP
           39  + [GNU make]: http://www.gnu.org/software/make
           40  +
           41  +while gpp is a very small program that builds quickly and has no major dependencies of its own, it is an obscure program not likely to be found in any repositories and with an uncertain future. for these reasons, adding m4 translations of the gpp headers should be a long-term priority. being able to be built with both a very small, easily built macro processor, and a very large but extremely well-supported processor, should make libk maximally buildable and future-proof.
           42  +
           43  +while this project will include gpp tooling and GNU makefiles designed to ease the task of writing and building libk code (as well as tools in many other languages, including native binaries that compile against libk), none of them are required for the task.
           44  +
    32     45   ## naming conventions
    33     46   
    34     47   one of the most frustrating things about libc is its complete and total *lack* of a naming convention. in C, every function and global is injected into a single global namespace, including macros. this means that every libc header you include scatters words all over that namespace, potentially clobbering your function with a macro!
    35     48   
    36     49   libk is designed to fix this (in hindsight) glaring error.
    37     50   
    38     51   however, a common problem with libraries is the proliferation of inordinately long and hard-to-type function names such as `SuperWidget_Widget_Label_Font_Size_Set()`. this may be tolerable in IDEs with robust auto-complete or when referencing a highly-specific, sparsely-used library; it is however completely intolerable in the case of a core library with heavily used functionality.

Modified makefile from [ac03aab83b] to [d63468c69f].

     1      1   export OUT = $(PWD)/out
     2      2   
            3  +# TODO: calculate these using $(MAKE_HOST)
     3      4   export ARCH = x86
     4      5   export OS = lin
     5      6   export BITS = 64
     6      7   export TMP = $(PWD)/tmp
     7      8   
     8         -export TARGET = $(ARCH).$(OS).$(BITS)
            9  +ifneq ($(BITS),)
           10  +    export TARGET = $(ARCH).$(OS).$(BITS)
           11  +else
           12  +    export TARGET = $(ARCH).$(OS)
           13  +endif
     9     14   
           15  +export gpp = gpp
    10     16   export lin-headers = /usr/include/asm
    11     17   export fbsd-headers = /usr/include/sys
    12     18   
    13     19   moddirs = $(wildcard k*)
    14     20   binaries = $(wildcard k*/*.exe.c)
    15     21   functions = $(wildcard k*/*.fn.c) 
    16         -assemblies = $(wildcard k*/*.fn.${TARGET}.s)
           22  +assemblies = $(wildcard k*/*.fn.$(TARGET).s)
    17     23   binmods = $(sort $(dir $(binaries)))
    18     24   
    19     25   # i'm sorry
    20         -collect = $(strip $(foreach dir,$(moddirs),$(addprefix $(OUT)/$(dir).,$(notdir $(wildcard $(dir)/$1)))))
           26  +collect = $(strip $(foreach dir,$(moddirs),$(wildcard $(dir)/*.$1)))
           27  +transform = $(strip $(foreach dir,$(moddirs),$(patsubst $(dir)/%.$1,$(subst @,$(dir),$2),$(wildcard $(dir)/*.$1))))
    21     28   
    22         -cfnsources = $(call collect,*.fn.c)
    23         -sfnsources = $(call collect,*.fn.${TARGET}.s)
    24         -crtsources = $(call collect,*.rt.c)
    25         -srtsources = $(call collect,*.rt.${TARGET}.s)
    26         -fnsources = $(cfnsources) $(sfnsources)
    27         -rtsources = $(crtsources) $(srtsources)
    28         -sources = $(fnsources) $(rtsources)
           29  +m-hdr-macs = $(call collect,h.m)
           30  +m-c-src-macs = $(call collect,c.m)
           31  +m-s-src-macs = $(call collect,$(TARGET).s.m)
    29     32   
    30         -cfnobjects = $(cfnsources:%.c=%.o)
    31         -sfnobjects = $(sfnsources:%.s=%.o)
    32         -crtobjects = $(crtsources:%.c=%.o)
    33         -srtobjects = $(srtsources:%.s=%.o)
    34         -fnobjects = $(cfnobjects) $(sfnobjects)
    35         -rtobjects = $(crtobjects) $(srtobjects)
           33  +m-c-sources = $(call transform,c.m,$(TMP)/@.%.c)
           34  +m-s-sources = $(call transform,$(TARGET).s.m,$(TMP)/@.%.$(TARGET).s)
           35  +
           36  +m-headers = $(call transform,h.m,$(OUT)/k/%.h)
           37  +m-c-objects = $(call transform,c.m,$(OUT)/@.%.o)
           38  +m-s-objects = $(call transform,$(TARGET).s.m,$(OUT)/@.%.$(TARGET).o)
           39  +
           40  +fnobjects = $(call transform,fn.c,$(OUT)/@.%.fn.o) \
           41  +            $(call transform,fn.c.m,$(OUT)/@.%.fn.o) \
           42  +            $(call transform,fn.$(TARGET).s,$(OUT)/@.%.fn.$(TARGET).o) \
           43  +            $(call transform,fn.$(TARGET).s.m,$(OUT)/@.%.fn.$(TARGET).o)
           44  +
           45  +rtobjects = $(call transform,rt.c,$(OUT)/@.%.rt.o) \
           46  +            $(call transform,rt.c.m,$(OUT)/@.%.rt.o) \
           47  +            $(call transform,rt.$(TARGET).s,$(OUT)/@.%.rt.$(TARGET).o) \
           48  +            $(call transform,rt.$(TARGET).s.m,$(OUT)/@.%.rt.$(TARGET).o)
           49  +
    36     50   objects = $(fnobjects) $(rtobjects)
    37     51   
    38     52   header-dir = /usr/include
    39     53   lib-dir = /usr/lib
    40     54   
           55  +unix-oses = lin fbsd dar and
    41     56   posix-oses = lin fbsd dar and hai mgw
    42     57   
    43         -ifeq ($(findstring $(OS),$(posix-oses)),$(OS))
    44         -export POSIX = yes
           58  +ifeq ($(findstring $(OS),$(unix-oses)),$(OS))
           59  +    export UNIX = yes
           60  +    export POSIX = yes
    45     61   else
    46         -export POSIX = no
           62  +    export UNIX = no
           63  +    ifeq ($(findstring $(OS),$(posix-oses)),$(OS))
           64  +        export POSIX = yes
           65  +	else
           66  +        export POSIX = no
           67  +	endif
    47     68   endif
    48     69   
    49     70   # include libgcc.a in gcc builds, just in case
    50     71   ifeq ($(CC),gcc)
    51     72   export COMPLIB = -lgcc
    52     73   endif
    53     74   
    54     75   all: $(OUT) defs obj tool lib.static $(OUT)/boot.o lib.shared
    55     76   lib.static: defs obj $(OUT)/libk.a
    56     77   lib.shared: defs obj $(OUT)/libk.so
    57         -obj: $(moddirs:%=%.obj)
    58         -defs: $(moddirs:%=%.def)
    59         -tool: $(OUT)/libk.a $(binmods:%=%.tool) 
           78  +obj: $(moddirs:%=%.obj) 
           79  +defs: $(moddirs:%=%.def) 
           80  +tool: $(OUT)/boot.o $(OUT)/libk.a $(binmods:%=%.tool) 
    60     81   clean:
    61     82   	rm -rf $(TMP) $(OUT)
    62     83   
    63     84   install: all
    64     85   	install -d $(header-dir)/k -o root -g wheel
    65     86   	install $(OUT)/k/* $(header-dir)/k/ -o root -g wheel -m 0644
    66     87   	install -d $(lib-dir)/k -o root -g wheel
    67     88   	install $(OUT)/libk.a $(OUT)/libk.so $(OUT)/boot.o \
    68     89   		$(lib-dir)/k/ -o root -g wheel -m 0644
    69     90   
    70     91   uninstall: $(header-dir)/k $(lib-dir)/k
    71     92   	rm -rf $^
    72     93   
    73         -lists = moddirs functions assemblies cfnobjects sfnobjects crtobjects srtobjects rtobjects binaries binmods POSIX
           94  +lists = moddirs functions assemblies fnobjects rtobjects binaries binmods POSIX
    74     95   dbg:
    75     96   	@echo -e lists: $(foreach var, $(lists), "\\n - \\e[1m$(var)\\e[m = $($(var))")
    76     97   
    77         -%.obj: %/makefile ${TARGET}.calls $(OUT)
           98  +%.obj: %/makefile $(TMP)/precomp.g $(TARGET).calls $(OUT)
    78     99   	cd $* && $(MAKE) obj
    79    100   
    80         -%.tool: %/makefile $(OUT)
          101  +%.tool: %/makefile $(TMP)/precomp.g $(OUT)
    81    102   	cd $* && $(MAKE) tool
    82    103   
    83    104   %.dbg: %/makefile $(OUT)
    84    105   	cd $* && $(MAKE) dbg
    85    106   
    86         -%.def: %/makefile $(OUT) $(OUT)/k
          107  +%.def: %/makefile $(TMP)/precomp.g $(OUT) $(OUT)/k
    87    108   	cd $* && $(MAKE) def
    88    109   
    89    110   %.calls: arch/makefile
    90    111   	cd arch && $(MAKE) $(TMP)/calls.$*.s
          112  +
          113  +$(TMP)/precomp.g: grammar/precomp.g.gpp $(TMP)
          114  +	cd grammar && $(MAKE) $@
    91    115   
    92    116   $(OUT)/libk.so: $(fnobjects) 
    93    117   	ld -shared $(COMPLIB) -o $@ $^
    94    118   	@# $(CC) -shared -fPIC -nostdlib $(COMPLIB) -o $@ $(OUT)/*.o
    95    119   
    96    120   $(OUT)/boot.o: $(rtobjects)
    97    121   	ld -r $^ -o $(OUT)/boot.o
................................................................................
    98    122   
    99    123   $(OUT)/libk.a: $(fnobjects) $(rtobjects)
   100    124   	@# using `ar rc` and ranlib here instead of
   101    125   	@# `ar rcs` in case `ar` isn't the GNU version
   102    126   	ar rc $@ $^
   103    127   	ranlib $@
   104    128   
   105         -$(OUT) $(OUT)/k:
          129  +$(OUT) $(OUT)/k $(TMP):
   106    130   	mkdir -p $@

Modified modmake from [3c50b488d5] to [eb2aedd9b1].

     1      1   #- modmake
     2      2   # this is the master makefile that controls the building of each
     3      3   # libk module. it is included from each k*/makefile.
     4      4   # vim: ft=make
     5      5   
     6      6   mod = $(notdir $(PWD))
     7         -src = $(wildcard *.c) $(wildcard *.s)
            7  +src = $(wildcard *.c) $(wildcard *.s) $(filter-out %.h,$(patsubst %.m,%,$(wildcard *.m)))
     8      8   bare = $(mod:k%=%)
     9         -headers = $(wildcard *.h) $(gen-headers)
            9  +headers = $(wildcard *.h) $(gen-headers) $(patsubst %.m,%,$(wildcard *.h.m))
    10     10   
    11     11   tools    = $(filter     %.exe.c,   $(src))
    12     12   nontools = $(filter-out %.exe.c,   $(src))
    13     13   cobjects = $(filter     %.c,       $(nontools))
    14     14   sobjects = $(filter %.${TARGET}.s, $(nontools))
    15     15   
    16         -cflags = -isystem ${OUT} -fPIC -nostdlib ${COMPLIB} -L${OUT} -lk
           16  +gpp = gpp
           17  +cflags = -std=c11 -isystem ${OUT} -fPIC -nostdlib ${COMPLIB} -L${OUT}
           18  +
           19  +m-env = atom_target_arch=${ARCH}
           20  +m-env += atom_target_os=${OS}
           21  +ifneq (${BITS},) #!!! ifdef does NOT work with environment variables
           22  +    m-env += atom_target_bits=${BITS}
           23  +endif
           24  +m-env += target_posix=${POSIX}
           25  +m-env += target_unix=${UNIX}
           26  +
           27  +m-grammar = $(file < ${TMP}/precomp.g)
           28  +m-comp = $(gpp) $(m-grammar) $(m-env:%=-D%)
    17     29   
    18     30   obj: $(cobjects:%.c=${OUT}/$(mod).%.o) \
    19     31   	 $(sobjects:%.s=${OUT}/$(mod).%.o)
    20     32   tool: $(tools:%.exe.c=${OUT}/$(mod).%) \
    21     33   	  ${OUT}/libk.a
    22     34   
    23     35   def: $(headers:%=${OUT}/k/%)
    24     36   
    25     37   dbg:
           38  +	@echo src = $(src)
    26     39   	@echo tools = $(tools)
    27     40   	@echo TARGET = ${TARGET}
    28     41   	@echo cobjects = $(cobjects)
    29     42   	@echo sobjects = $(sobjects)
    30     43   	@echo headers = $(headers)
           44  +	@echo m-comp = $(m-comp)
           45  +	@echo m-grammar = $(m-grammar)
           46  +	@echo m-env = $(m-env) "$(m-env:%=-D%)"
    31     47   	@echo mod = $(mod)
    32     48   
    33         -${OUT}/$(mod).%.o: %.c
           49  +${OUT}/k/%.h: %.h.m
           50  +	$(m-comp) $< > $@
           51  +
           52  +.PRECIOUS: ${TMP}/$(mod).%
           53  +${TMP}/$(mod).%: %.m ${TMP}
           54  +	$(m-comp) $< > $@
           55  +
           56  +${OUT}/$(mod).%.o: ${TMP}/$(mod).%.c
           57  +	$(CC) $(cflags) -c $< -o $@
           58  +
           59  +${OUT}/$(mod).%.o: %.c $(bare).h
    34     60   	$(CC) $(cflags) -c $< -o $@
    35     61   
    36     62   ${OUT}/k/%.h: %.h
    37     63   	cp $< $@
    38     64   
    39     65   ${OUT}/$(mod).%: %.exe.c
    40         -	$(CC) $(cflags) $< -o $@
           66  +	$(CC) $(cflags) $< ${OUT}/libk.a -o $@
    41     67   
    42     68   ${TMP}:
    43     69   	mkdir -p ${TMP}
    44     70   
    45     71   #- assembly
    46     72   # compiling  the assembly  code will  be  faster but  a lot  more
    47     73   # complex, given the  nature of assembly and the  large number of
................................................................................
    50     76   # that  requires ugly  make  rules,  we're just  going  to use  a
    51     77   # function to generate these.
    52     78   
    53     79   # ${OUT} = ultimate build directory
    54     80   # $(mod) = module name
    55     81   #      % = function name
    56     82   #   $(1) = arch tuple
    57         -arch = ${OUT}/$(mod).%.$(1).o: %.$(1).s
           83  +arch = ${OUT}/$(mod).%.$(1).o: $2%.$(1).s
    58     84   # invoke with $(call arch,tuple). do not
    59     85   # put spaces between either term though!
    60     86   
    61     87   ifeq ($(debug),yes)
    62     88   yasm-flags = -gdwarf2
    63     89   endif
    64     90   
           91  +yasm = yasm $(yasm-flags) -f$1 -i${TMP} $< -o $@
           92  +
    65     93   #-- linux
    66     94   # linux uses the ELF{32,64} binary format,  and generating these
    67     95   # from yasm is trivial.  linux only supports one ABI per format,
    68     96   # at least with ELF, so that's all we need to do.
    69     97   
    70         -#${OUT}/$(mod).%.x86.lin.32.o: %.x86.lin.32.s
    71         -$(call arch,x86.lin.32)
    72         -	yasm $(yasm-flags) -felf32 -i${TMP} $< -o $@
           98  +
           99  +$(call arch,x86.lin.32,)
          100  +	$(call yasm,elf32)
          101  +
          102  +$(call arch,x86.lin.64,)
          103  +	$(call yasm,elf64)
          104  +
          105  +$(call arch,x86.lin.32,${TMP}/$(mod).)
          106  +	$(call yasm,elf32)
    73    107   
    74         -#${OUT}/$(mod).%.x86.lin.64.o: %.x86.lin.64.s
    75         -$(call arch,x86.lin.64)
    76         -	yasm $(yasm-flags) -felf64 -i${TMP} $< -o $@
          108  +$(call arch,x86.lin.64,${TMP}/$(mod).)
          109  +	$(call yasm,elf64)
    77    110   
    78    111   #-- freebsd
    79    112   # the freebsd ABI is different, so it will require different code
    80    113   # (though there might be ways to minimize that). freebsd uses the
    81    114   # same binary format as Linux  (though it also supports a.out and
    82    115   # COFF) but because freebsd can interpret multiple different ABIs
    83    116   # the  object files  need to  be "branded"  with the  correct one
    84    117   # using the tool brandelf (`brandelf -t [ABI]`)
    85    118   
    86         -$(call arch,x86.fbsd.32)
    87         -	yasm -felf32 $< -o $@
          119  +$(call arch,x86.fbsd.32,)
          120  +	$(call yasm,elf32)
          121  +	brandelf -t FreeBSD $@
          122  +
          123  +$(call arch,x86.fbsd.64,)
          124  +	$(call yasm,elf64)
    88    125   	brandelf -t FreeBSD $@
    89    126   
    90         -$(call arch,x86.fbsd.64)
    91         -	yasm -felf64 $< -o $@
          127  +$(call arch,x86.fbsd.32,${TMP}/$(mod).)
          128  +	$(call yasm,elf32)
    92    129   	brandelf -t FreeBSD $@
    93    130   
          131  +$(call arch,x86.fbsd.64,${TMP}/$(mod).)
          132  +	$(call yasm,elf64)
          133  +	brandelf -t FreeBSD $@