#ifndef KIcore
#define KIcore
#include <k/type.h>
#include <k/io.h>
#include <k/str.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct kvar {
	ksraw name;
	ksraw val;
	char* platform;
} kvar;

typedef struct kenv {
	kiochan std;
	kiochan err;
	sz argc; char** args;
	sz varc; kvar* vars;
} kenv;

/* i'm really sorry okay */
typedef
#if (__STDC_VERSION__ >= 199901L)
	_Bool bool;
#endif
enum
#if !(__STDC_VERSION__ >= 199901L)
	bool /* enum bool { */
#endif
{
	false = 0, no  = 0,
	true  = 1, yes = 1
}
#if !(__STDC_VERSION__ >= 199901L)
	bool /* } bool ; */
#endif
;

#ifndef KFclean
#	include <k/internal.egroup.h>
#	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
#	else
#		define KVvm_args K_TEMP_M2QD52
#		define KVvm_spec K_TEMP_M2QD52
#	endif
#	if defined(__GNUC__) || defined(__clang__)
#		define KA(KVvm_spec) __attribute__((KVvm_args))
#	else
#		define KA(KVvm_spec)
#	endif
#	define KAformat(KVvm_spec) KA(format(KVvm_args))
#	define KAexport(KVvm_spec) KA(visibility(KVvm_args))

#	define KAunused   KA(unused)
#	define KAnoreturn KA(noreturn)
#	define KApure     KA(const)
#	define KAinline   KA(always_inline)
#	define KAflatten  KA(flatten)
#	define KAexport_none  KAexport("hidden")
#	define KAexport_force KAexport("default")
/*  now we define standard version flags,
 *  to make it easy for the user to write
 *  more portable code. */
#	if (__STDC_VERSION__ >= 199901L) 
#		define KFstd_c89
#		define KFstd_c99
#		define KVstd c99
#	else
#		ifdef __STDC__
#			define KFstd_c89
#			define KVstd c89
#		else
#			define KVstd K&R /* UH OH */
#		endif
#	endif
#	if (__STDC_VERSION__ >= 201103L)
#		define KFstd_c11
#		define KVstd c11
#	endif
#	ifdef __cplusplus
#		define KFstd_c89
#		define KFstd_cpp
#		define KVstd c++
#		if (__cplusplus >= 201103L)
#			define KFstd_cpp11
#			define KVstd c++11
#		endif /* TODO: add more */
#	endif
#endif

#ifdef KFstd_c11
#	define Kassert _Static_assert
#else
#	define Kassert(x) { struct { int assertion_failed[(x) ? 1 : -1] }; }
#endif

/* hooo boy. null. that one's got a storied
 * history across the versions and dialects.
 * below, we try to find the ideal way to
 * offer a "null" "keyword" depending on
 * dialect, version, and whether the user
 * has asked for macros to be suspended.
 * note that this may result in no "null"
 * being defined in C++ or K&R C. */
#if defined (__cplusplus) && ! defined(KFclean)
#	if __cplusplus >= 201103L
#		define null nullptr
#	else
#		define null ((void*)0)
#	endif
#elif defined __STDC__ && (!defined __clang__ || defined KFclean)
	enum { null = 0 };
	/* believe it or not, this is actually
	 * completely legal. doesn't even raise
	 * a single warning in GCC. i was surprised
	 * too. alas, it later turned out that
	 * clang will throw a fit about this, so
	 * we only use the enum method if __clang__
	 * is undefined, or if the alternative is
	 * no null keyword at all. */
#elif ! defined(KFclean)
#	define null ((void*)0)
#endif

#ifndef KFclean
#	ifdef __cplusplus
#		define noreturn [[ noreturn ]]
#	elif __STDC_VERSION__ >= 201103L
#		define noreturn _Noreturn
#	else
#		define noreturn
#	endif
#endif

#ifdef __cplusplus
	[[noreturn]] void kstop(stat_long code);
#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
