diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:21:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:21:29 +0000 |
commit | 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc (patch) | |
tree | 63ef546b10a81d461e5cf5ed9e98a68cd7dee1aa /src/lib/kStuff/include/k | |
parent | Initial commit. (diff) | |
download | kbuild-29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc.tar.xz kbuild-29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc.zip |
Adding upstream version 1:0.1.9998svn3589+dfsg.upstream/1%0.1.9998svn3589+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/kStuff/include/k')
53 files changed, 10515 insertions, 0 deletions
diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h new file mode 100644 index 0000000..90efdee --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlBase.h @@ -0,0 +1,626 @@ +/* $Id: kAvlBase.h 36 2009-11-09 22:49:02Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, The Mandatory Base Code. + */ + +/* + * Copyright (c) 2001-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** @page pg_kAvlTmpl Template Configuration. + * + * This is a templated implementation of AVL trees in C. The template + * parameters relates to the kind of key used and how duplicates are + * treated. + * + * \#define KAVL_EQUAL_ALLOWED + * Define this to tell us that equal keys are allowed. + * Then Equal keys will be put in a list pointed to by KAVLNODE::pList. + * This is by default not defined. + * + * \#define KAVL_CHECK_FOR_EQUAL_INSERT + * Define this to enable insert check for equal nodes. + * This is by default not defined. + * + * \#define KAVL_MAX_STACK + * Use this to specify the max number of stack entries the stack will use when + * inserting and removing nodes from the tree. The size should be something like + * log2(<max nodes>) + 3 + * Must be defined. + * + * \#define KAVL_RANGE + * Define this to enable key ranges. + * + * \#define KAVL_OFFSET + * Define this to link the tree together using self relative offset + * instead of memory pointers, thus making the entire tree relocatable + * provided all the nodes - including the root node variable - are moved + * the exact same distance. + * + * \#define KAVL_LOOKTHRU + * Define this to employ a lookthru cache (direct) to speed up lookup for + * some usage patterns. The value should be the number of members of the + * array. + * + * \#define KAVL_LOOKTHRU_HASH(Key) + * Define this to specify a more efficient translation of the key into + * a lookthru array index. The default is key % size. + * For some key types this is required as the default will not compile. + * + * \#define KAVL_LOCKED + * Define this if you wish for the tree to be locked via the + * KAVL_WRITE_LOCK, KAVL_WRITE_UNLOCK, KAVL_READ_LOCK and + * KAVL_READ_UNLOCK macros. If not defined the tree will not be subject + * do any kind of locking and the problem of concurrency is left the user. + * + * \#define KAVL_WRITE_LOCK(pRoot) + * Lock the tree for writing. + * + * \#define KAVL_WRITE_UNLOCK(pRoot) + * Counteracts KAVL_WRITE_LOCK. + * + * \#define KAVL_READ_LOCK(pRoot) + * Lock the tree for reading. + * + * \#define KAVL_READ_UNLOCK(pRoot) + * Counteracts KAVL_READ_LOCK. + * + * \#define KAVLKEY + * Define this to the name of the AVL key type. + * + * \#define KAVL_STD_KEY_COMP + * Define this to use the standard key compare macros. If not set all the + * compare operations for KAVLKEY have to be defined: KAVL_G, KAVL_E, KAVL_NE, + * KAVL_R_IS_IDENTICAL, KAVL_R_IS_INTERSECTING and KAVL_R_IS_IN_RANGE. The + * latter three are only required when KAVL_RANGE is defined. + * + * \#define KAVLNODE + * Define this to the name (typedef) of the AVL node structure. This + * structure must have a mpLeft, mpRight, mKey and mHeight member. + * If KAVL_RANGE is defined a mKeyLast is also required. + * If KAVL_EQUAL_ALLOWED is defined a mpList member is required. + * It's possible to use other member names by redefining the names. + * + * \#define KAVLTREEPTR + * Define this to the name (typedef) of the tree pointer type. This is + * required when KAVL_OFFSET is defined. When not defined it defaults + * to KAVLNODE *. + * + * \#define KAVLROOT + * Define this to the name (typedef) of the AVL root structure. This + * is optional. However, if specified it must at least have a mpRoot + * member of KAVLTREEPTR type. If KAVL_LOOKTHRU is non-zero a + * maLookthru[KAVL_LOOKTHRU] member of the KAVLTREEPTR type is also + * required. + * + * \#define KAVL_FN + * Use this to alter the names of the AVL functions. + * Must be defined. + * + * \#define KAVL_TYPE(prefix, name) + * Use this to make external type names and unique. The prefix may be empty. + * Must be defined. + * + * \#define KAVL_INT(name) + * Use this to make internal type names and unique. The prefix may be empty. + * Must be defined. + * + * \#define KAVL_DECL(rettype) + * Function declaration macro that should be set according to the scope + * the instantiated template should have. For instance an inlined scope + * (private or public) should K_DECL_INLINE(rettype) here. + * + * This version of the kAVL tree offers the option of inlining the entire + * implementation. This depends on the compiler doing a decent job in both + * making use of the inlined code and to eliminate const variables. + */ + + +/******************************************************************************* +* Internal Functions * +*******************************************************************************/ +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kHlpAssert.h> + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#define KAVL_HEIGHTOF(pNode) ((KU8)((pNode) != NULL ? (pNode)->mHeight : 0)) + +/** @def KAVL_GET_POINTER + * Reads a 'pointer' value. + * + * @returns The native pointer. + * @param pp Pointer to the pointer to read. + * @internal + */ + +/** @def KAVL_GET_POINTER_NULL + * Reads a 'pointer' value which can be KAVL_NULL. + * + * @returns The native pointer. + * @returns NULL pointer if KAVL_NULL. + * @param pp Pointer to the pointer to read. + * @internal + */ + +/** @def KAVL_SET_POINTER + * Writes a 'pointer' value. + * For offset-based schemes offset relative to pp is calculated and assigned to *pp. + * + * @returns stored pointer. + * @param pp Pointer to where to store the pointer. + * @param p Native pointer to assign to *pp. + * @internal + */ + +/** @def KAVL_SET_POINTER_NULL + * Writes a 'pointer' value which can be KAVL_NULL. + * + * For offset-based schemes offset relative to pp is calculated and assigned to *pp, + * if p is not KAVL_NULL of course. + * + * @returns stored pointer. + * @param pp Pointer to where to store the pointer. + * @param pp2 Pointer to where to pointer to assign to pp. This can be KAVL_NULL + * @internal + */ + +#ifndef KAVLTREEPTR +# define KAVLTREEPTR KAVLNODE * +#endif + +#ifndef KAVLROOT +# define KAVLROOT KAVL_TYPE(,ROOT) +# define KAVL_NEED_KAVLROOT +#endif + +#ifdef KAVL_LOOKTHRU +# ifndef KAVL_LOOKTHRU_HASH +# define KAVL_LOOKTHRU_HASH(Key) ( (Key) % (KAVL_LOOKTHRU) ) +# endif +#elif defined(KAVL_LOOKTHRU_HASH) +# error "KAVL_LOOKTHRU_HASH without KAVL_LOOKTHRU!" +#endif + +#ifdef KAVL_LOOKTHRU +# define KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, Key) \ + do { \ + KAVLTREEPTR **ppEntry = &pRoot->maLookthru[KAVL_LOOKTHRU_HASH(Key)]; \ + if ((pNode) == KAVL_GET_POINTER_NULL(ppEntry)) \ + *ppEntry = KAVL_NULL; \ + } while (0) +#else +# define KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, Key) do { } while (0) +#endif + +#ifndef KAVL_LOCKED +# define KAVL_WRITE_LOCK(pRoot) do { } while (0) +# define KAVL_WRITE_UNLOCK(pRoot) do { } while (0) +# define KAVL_READ_LOCK(pRoot) do { } while (0) +# define KAVL_READ_UNLOCK(pRoot) do { } while (0) +#endif + +#ifdef KAVL_OFFSET +# define KAVL_GET_POINTER(pp) ( (KAVLNODE *)((KIPTR)(pp) + *(pp)) ) +# define KAVL_GET_POINTER_NULL(pp) ( *(pp) != KAVL_NULL ? KAVL_GET_POINTER(pp) : NULL ) +# define KAVL_SET_POINTER(pp, p) ( (*(pp)) = ((KIPTR)(p) - (KIPTR)(pp)) ) +# define KAVL_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) != KAVL_NULL ? (KIPTR)KAVL_GET_POINTER(pp2) - (KIPTR)(pp) : KAVL_NULL ) +#else +# define KAVL_GET_POINTER(pp) ( *(pp) ) +# define KAVL_GET_POINTER_NULL(pp) ( *(pp) ) +# define KAVL_SET_POINTER(pp, p) ( (*(pp)) = (p) ) +# define KAVL_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) ) +#endif + + +/** @def KAVL_NULL + * The NULL 'pointer' equivalent. + */ +#ifdef KAVL_OFFSET +# define KAVL_NULL 0 +#else +# define KAVL_NULL NULL +#endif + +#ifdef KAVL_STD_KEY_COMP +# define KAVL_G(key1, key2) ( (key1) > (key2) ) +# define KAVL_E(key1, key2) ( (key1) == (key2) ) +# define KAVL_NE(key1, key2) ( (key1) != (key2) ) +# ifdef KAVL_RANGE +# define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) ( (key1B) == (key2B) && (key1E) == (key2E) ) +# define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) ( (key1B) <= (key2E) && (key1E) >= (key2B) ) +# define KAVL_R_IS_IN_RANGE(key1B, key1E, key2) KAVL_R_IS_INTERSECTING(key1B, key2, key1E, key2) +# endif +#endif + +#ifndef KAVL_RANGE +# define KAVL_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) KAVL_E(key1B, key2B) +# define KAVL_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) KAVL_E(key1B, key2B) +#endif + + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Stack used to avoid recursive calls during insert and removal. + */ +typedef struct +{ + unsigned cEntries; + KAVLTREEPTR *aEntries[KAVL_MAX_STACK]; +} KAVL_INT(STACK); + +/** + * The callback used by the Destroy and DoWithAll functions. + */ +typedef int (* KAVL_TYPE(PFN,CALLBACK))(KAVLNODE *, void *); + +#ifdef KAVL_NEED_KAVLROOT +/** + * The AVL root structure. + */ +typedef struct +{ + KAVLTREEPTR mpRoot; +# ifdef KAVL_LOOKTHRU + KAVLTREEPTR maLookthru[KAVL_LOOKTHRU]; +# endif +} KAVLROOT; +#endif + + +/** + * Rewinds a stack of node pointer pointers, rebalancing the tree. + * + * @param pStack Pointer to stack to rewind. + * @sketch LOOP thru all stack entries + * BEGIN + * Get pointer to pointer to node (and pointer to node) from the stack. + * IF 2 higher left subtree than in right subtree THEN + * BEGIN + * IF higher (or equal) left-sub-subtree than right-sub-subtree THEN + * * n+2|n+3 + * / \ / \ + * n+2 n ==> n+1 n+1|n+2 + * / \ / \ + * n+1 n|n+1 n|n+1 n + * + * Or with keys: + * + * 4 2 + * / \ / \ + * 2 5 ==> 1 4 + * / \ / \ + * 1 3 3 5 + * + * ELSE + * * n+2 + * / \ / \ + * n+2 n n+1 n+1 + * / \ ==> / \ / \ + * n n+1 n L R n + * / \ + * L R + * + * Or with keys: + * 6 4 + * / \ / \ + * 2 7 ==> 2 6 + * / \ / \ / \ + * 1 4 1 3 5 7 + * / \ + * 3 5 + * END + * ELSE IF 2 higher in right subtree than in left subtree THEN + * BEGIN + * Same as above but left <==> right. (invert the picture) + * ELSE + * IF correct height THEN break + * ELSE correct height. + * END + */ +K_DECL_INLINE(void) KAVL_FN(Rebalance)(KAVL_INT(STACK) *pStack) +{ + while (pStack->cEntries > 0) + { + KAVLTREEPTR *ppNode = pStack->aEntries[--pStack->cEntries]; + KAVLNODE *pNode = KAVL_GET_POINTER(ppNode); + KAVLNODE *pLeftNode = KAVL_GET_POINTER_NULL(&pNode->mpLeft); + KU8 uLeftHeight = KAVL_HEIGHTOF(pLeftNode); + KAVLNODE *pRightNode = KAVL_GET_POINTER_NULL(&pNode->mpRight); + KU8 uRightHeight = KAVL_HEIGHTOF(pRightNode); + + if (uRightHeight + 1 < uLeftHeight) + { + KAVLNODE *pLeftLeftNode = KAVL_GET_POINTER_NULL(&pLeftNode->mpLeft); + KAVLNODE *pLeftRightNode = KAVL_GET_POINTER_NULL(&pLeftNode->mpRight); + KU8 uLeftRightHeight = KAVL_HEIGHTOF(pLeftRightNode); + + if (KAVL_HEIGHTOF(pLeftLeftNode) >= uLeftRightHeight) + { + KAVL_SET_POINTER_NULL(&pNode->mpLeft, &pLeftNode->mpRight); + KAVL_SET_POINTER(&pLeftNode->mpRight, pNode); + pLeftNode->mHeight = (KU8)(1 + (pNode->mHeight = (KU8)(1 + uLeftRightHeight))); + KAVL_SET_POINTER(ppNode, pLeftNode); + } + else + { + KAVL_SET_POINTER_NULL(&pLeftNode->mpRight, &pLeftRightNode->mpLeft); + KAVL_SET_POINTER_NULL(&pNode->mpLeft, &pLeftRightNode->mpRight); + KAVL_SET_POINTER(&pLeftRightNode->mpLeft, pLeftNode); + KAVL_SET_POINTER(&pLeftRightNode->mpRight, pNode); + pLeftNode->mHeight = pNode->mHeight = uLeftRightHeight; + pLeftRightNode->mHeight = uLeftHeight; + KAVL_SET_POINTER(ppNode, pLeftRightNode); + } + } + else if (uLeftHeight + 1 < uRightHeight) + { + KAVLNODE *pRightLeftNode = KAVL_GET_POINTER_NULL(&pRightNode->mpLeft); + KU8 uRightLeftHeight = KAVL_HEIGHTOF(pRightLeftNode); + KAVLNODE *pRightRightNode = KAVL_GET_POINTER_NULL(&pRightNode->mpRight); + + if (KAVL_HEIGHTOF(pRightRightNode) >= uRightLeftHeight) + { + KAVL_SET_POINTER_NULL(&pNode->mpRight, &pRightNode->mpLeft); + KAVL_SET_POINTER(&pRightNode->mpLeft, pNode); + pRightNode->mHeight = (KU8)(1 + (pNode->mHeight = (KU8)(1 + uRightLeftHeight))); + KAVL_SET_POINTER(ppNode, pRightNode); + } + else + { + KAVL_SET_POINTER_NULL(&pRightNode->mpLeft, &pRightLeftNode->mpRight); + KAVL_SET_POINTER_NULL(&pNode->mpRight, &pRightLeftNode->mpLeft); + KAVL_SET_POINTER(&pRightLeftNode->mpRight, pRightNode); + KAVL_SET_POINTER(&pRightLeftNode->mpLeft, pNode); + pRightNode->mHeight = pNode->mHeight = uRightLeftHeight; + pRightLeftNode->mHeight = uRightHeight; + KAVL_SET_POINTER(ppNode, pRightLeftNode); + } + } + else + { + KU8 uHeight = (KU8)(K_MAX(uLeftHeight, uRightHeight) + 1); + if (uHeight == pNode->mHeight) + break; + pNode->mHeight = uHeight; + } + } + +} + + +/** + * Initializes the root of the AVL-tree. + * + * @param pTree Pointer to the root structure. + */ +KAVL_DECL(void) KAVL_FN(Init)(KAVLROOT *pRoot) +{ +#ifdef KAVL_LOOKTHRU + unsigned i; +#endif + + pRoot->mpRoot = KAVL_NULL; +#ifdef KAVL_LOOKTHRU + for (i = 0; i < (KAVL_LOOKTHRU); i++) + pRoot->maLookthru[i] = KAVL_NULL; +#endif +} + + +/** + * Inserts a node into the AVL-tree. + * @returns K_TRUE if inserted. + * K_FALSE if node exists in tree. + * @param pRoot Pointer to the AVL-tree root structure. + * @param pNode Pointer to the node which is to be added. + * @sketch Find the location of the node (using binary tree algorithm.): + * LOOP until NULL leaf pointer + * BEGIN + * Add node pointer pointer to the AVL-stack. + * IF new-node-key < node key THEN + * left + * ELSE + * right + * END + * Fill in leaf node and insert it. + * Rebalance the tree. + */ +KAVL_DECL(KBOOL) KAVL_FN(Insert)(KAVLROOT *pRoot, KAVLNODE *pNode) +{ + KAVL_INT(STACK) AVLStack; + KAVLTREEPTR *ppCurNode = &pRoot->mpRoot; + register KAVLKEY Key = pNode->mKey; +#ifdef KAVL_RANGE + register KAVLKEY KeyLast = pNode->mKeyLast; +#endif + +#ifdef KAVL_RANGE + if (Key > KeyLast) + return K_FALSE; +#endif + + KAVL_WRITE_LOCK(pRoot); + + AVLStack.cEntries = 0; + while (*ppCurNode != KAVL_NULL) + { + register KAVLNODE *pCurNode = KAVL_GET_POINTER(ppCurNode); + + kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); + AVLStack.aEntries[AVLStack.cEntries++] = ppCurNode; +#ifdef KAVL_EQUAL_ALLOWED + if (KAVL_R_IS_IDENTICAL(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast)) + { + /* + * If equal then we'll use a list of equal nodes. + */ + pNode->mpLeft = pNode->mpRight = KAVL_NULL; + pNode->mHeight = 0; + KAVL_SET_POINTER_NULL(&pNode->mpList, &pCurNode->mpList); + KAVL_SET_POINTER(&pCurNode->mpList, pNode); + KAVL_WRITE_UNLOCK(pRoot); + return K_TRUE; + } +#endif +#ifdef KAVL_CHECK_FOR_EQUAL_INSERT + if (KAVL_R_IS_INTERSECTING(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast)) + { + KAVL_WRITE_UNLOCK(pRoot); + return K_FALSE; + } +#endif + if (KAVL_G(pCurNode->mKey, Key)) + ppCurNode = &pCurNode->mpLeft; + else + ppCurNode = &pCurNode->mpRight; + } + + pNode->mpLeft = pNode->mpRight = KAVL_NULL; +#ifdef KAVL_EQUAL_ALLOWED + pNode->mpList = KAVL_NULL; +#endif + pNode->mHeight = 1; + KAVL_SET_POINTER(ppCurNode, pNode); + + KAVL_FN(Rebalance)(&AVLStack); + + KAVL_WRITE_UNLOCK(pRoot); + return K_TRUE; +} + + +/** + * Removes a node from the AVL-tree. + * @returns Pointer to the node. + * @param pRoot Pointer to the AVL-tree root structure. + * @param Key Key value of the node which is to be removed. + * @sketch Find the node which is to be removed: + * LOOP until not found + * BEGIN + * Add node pointer pointer to the AVL-stack. + * IF the keys matches THEN break! + * IF remove key < node key THEN + * left + * ELSE + * right + * END + * IF found THEN + * BEGIN + * IF left node not empty THEN + * BEGIN + * Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack: + * Start at left node. + * LOOP until right node is empty + * BEGIN + * Add to stack. + * go right. + * END + * Link out the found node. + * Replace the node which is to be removed with the found node. + * Correct the stack entry for the pointer to the left tree. + * END + * ELSE + * BEGIN + * Move up right node. + * Remove last stack entry. + * END + * Balance tree using stack. + * END + * return pointer to the removed node (if found). + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(Remove)(KAVLROOT *pRoot, KAVLKEY Key) +{ + KAVL_INT(STACK) AVLStack; + KAVLTREEPTR *ppDeleteNode = &pRoot->mpRoot; + register KAVLNODE *pDeleteNode; + + KAVL_WRITE_LOCK(pRoot); + + AVLStack.cEntries = 0; + for (;;) + { + if (*ppDeleteNode == KAVL_NULL) + { + KAVL_WRITE_UNLOCK(pRoot); + return NULL; + } + pDeleteNode = KAVL_GET_POINTER(ppDeleteNode); + + kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); + AVLStack.aEntries[AVLStack.cEntries++] = ppDeleteNode; + if (KAVL_E(pDeleteNode->mKey, Key)) + break; + + if (KAVL_G(pDeleteNode->mKey, Key)) + ppDeleteNode = &pDeleteNode->mpLeft; + else + ppDeleteNode = &pDeleteNode->mpRight; + } + + if (pDeleteNode->mpLeft != KAVL_NULL) + { + /* find the rightmost node in the left tree. */ + const unsigned iStackEntry = AVLStack.cEntries; + KAVLTREEPTR *ppLeftLeast = &pDeleteNode->mpLeft; + register KAVLNODE *pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); + + while (pLeftLeast->mpRight != KAVL_NULL) + { + kHlpAssert(AVLStack.cEntries < KAVL_MAX_STACK); + AVLStack.aEntries[AVLStack.cEntries++] = ppLeftLeast; + ppLeftLeast = &pLeftLeast->mpRight; + pLeftLeast = KAVL_GET_POINTER(ppLeftLeast); + } + + /* link out pLeftLeast */ + KAVL_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->mpLeft); + + /* link it in place of the delete node. */ + KAVL_SET_POINTER_NULL(&pLeftLeast->mpLeft, &pDeleteNode->mpLeft); + KAVL_SET_POINTER_NULL(&pLeftLeast->mpRight, &pDeleteNode->mpRight); + pLeftLeast->mHeight = pDeleteNode->mHeight; + KAVL_SET_POINTER(ppDeleteNode, pLeftLeast); + AVLStack.aEntries[iStackEntry] = &pLeftLeast->mpLeft; + } + else + { + KAVL_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->mpRight); + AVLStack.cEntries--; + } + + KAVL_FN(Rebalance)(&AVLStack); + + KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pDeleteNode, Key); + + KAVL_WRITE_UNLOCK(pRoot); + return pDeleteNode; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h new file mode 100644 index 0000000..17115f3 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDestroy.h @@ -0,0 +1,129 @@ +/* $Id: kAvlDestroy.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Destroy the tree. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Destroys the specified tree, starting with the root node and working our way down. + * + * @returns 0 on success. + * @returns Return value from callback on failure. On failure, the tree will be in + * an unbalanced condition and only further calls to the Destroy should be + * made on it. Note that the node we fail on will be considered dead and + * no action is taken to link it back into the tree. + * @param pRoot Pointer to the AVL-tree root structure. + * @param pfnCallBack Pointer to callback function. + * @param pvUser User parameter passed on to the callback function. + */ +KAVL_DECL(int) KAVL_FN(Destroy)(KAVLROOT *pRoot, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser) +{ +#ifdef KAVL_LOOKTHRU + unsigned i; +#endif + unsigned cEntries; + KAVLNODE *apEntries[KAVL_MAX_STACK]; + int rc; + + KAVL_WRITE_LOCK(pRoot); + if (pRoot->mpRoot == KAVL_NULL) + { + KAVL_WRITE_UNLOCK(pRoot); + return 0; + } + +#ifdef KAVL_LOOKTHRU + /* + * Kill the lookthru cache. + */ + for (i = 0; i < (KAVL_LOOKTHRU); i++) + pRoot->maLookthru[i] = KAVL_NULL; +#endif + + cEntries = 1; + apEntries[0] = KAVL_GET_POINTER(&pRoot->mpRoot); + while (cEntries > 0) + { + /* + * Process the subtrees first. + */ + KAVLNODE *pNode = apEntries[cEntries - 1]; + if (pNode->mpLeft != KAVL_NULL) + apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft); + else if (pNode->mpRight != KAVL_NULL) + apEntries[cEntries++] = KAVL_GET_POINTER(&pNode->mpRight); + else + { +#ifdef KAVL_EQUAL_ALLOWED + /* + * Process nodes with the same key. + */ + while (pNode->pList != KAVL_NULL) + { + KAVLNODE *pEqual = KAVL_GET_POINTER(&pNode->pList); + KAVL_SET_POINTER(&pNode->pList, KAVL_GET_POINTER_NULL(&pEqual->pList)); + pEqual->pList = KAVL_NULL; + + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KAVL_WRITE_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* + * Unlink the node. + */ + if (--cEntries > 0) + { + KAVLNODE *pParent = apEntries[cEntries - 1]; + if (KAVL_GET_POINTER(&pParent->mpLeft) == pNode) + pParent->mpLeft = KAVL_NULL; + else + pParent->mpRight = KAVL_NULL; + } + else + pRoot->mpRoot = KAVL_NULL; + + kHlpAssert(pNode->mpLeft == KAVL_NULL); + kHlpAssert(pNode->mpRight == KAVL_NULL); + rc = pfnCallBack(pNode, pvUser); + if (rc) + { + KAVL_WRITE_UNLOCK(pRoot); + return rc; + } + } + } /* while */ + kHlpAssert(pRoot->mpRoot == KAVL_NULL); + + KAVL_WRITE_UNLOCK(pRoot); + return 0; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h new file mode 100644 index 0000000..f2eaba1 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlDoWithAll.h @@ -0,0 +1,166 @@ +/* $Id: kAvlDoWithAll.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, The Callback Iterator. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Stack used by DoWithAll to avoid recusive function calls. + */ +typedef struct +{ + unsigned cEntries; + KAVLNODE *aEntries[KAVL_MAX_STACK]; + char achFlags[KAVL_MAX_STACK]; + KAVLROOT pRoot; +} KAVL_INT(STACK2); + + +/** + * Iterates thru all nodes in the given tree. + * + * @returns 0 on success. Return from callback on failure. + * @param pRoot Pointer to the AVL-tree root structure. + * @param fFromLeft K_TRUE: Left to right. + * K_FALSE: Right to left. + * @param pfnCallBack Pointer to callback function. + * @param pvUser User parameter passed on to the callback function. + */ +KAVL_DECL(int) KAVL_FN(DoWithAll)(KAVLROOT *pRoot, KBOOL fFromLeft, KAVL_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser) +{ + KAVL_INT(STACK2) AVLStack; + KAVLNODE *pNode; +#ifdef KAVL_EQUAL_ALLOWED + KAVLNODE *pEqual; +#endif + int rc; + + KAVL_READ_LOCK(pRoot); + if (pRoot->mpRoot == KAVL_NULL) + { + KAVL_READ_UNLOCK(pRoot); + return 0; + } + + AVLStack.cEntries = 1; + AVLStack.achFlags[0] = 0; + AVLStack.aEntries[0] = KAVL_GET_POINTER(&pRoot->mpRoot); + + if (fFromLeft) + { /* from left */ + while (AVLStack.cEntries > 0) + { + pNode = AVLStack.aEntries[AVLStack.cEntries - 1]; + + /* left */ + if (!AVLStack.achFlags[AVLStack.cEntries - 1]++) + { + if (pNode->mpLeft != KAVL_NULL) + { + AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */ + AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft); + continue; + } + } + + /* center */ + rc = pfnCallBack(pNode, pvUser); + if (rc) + return rc; +#ifdef KAVL_EQUAL_ALLOWED + if (pNode->mpList != KAVL_NULL) + for (pEqual = KAVL_GET_POINTER(&pNode->mpList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->mpList)) + { + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KAVL_READ_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* right */ + AVLStack.cEntries--; + if (pNode->mpRight != KAVL_NULL) + { + AVLStack.achFlags[AVLStack.cEntries] = 0; + AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpRight); + } + } /* while */ + } + else + { /* from right */ + while (AVLStack.cEntries > 0) + { + pNode = AVLStack.aEntries[AVLStack.cEntries - 1]; + + /* right */ + if (!AVLStack.achFlags[AVLStack.cEntries - 1]++) + { + if (pNode->mpRight != KAVL_NULL) + { + AVLStack.achFlags[AVLStack.cEntries] = 0; /* 0 first, 1 last */ + AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpRight); + continue; + } + } + + /* center */ + rc = pfnCallBack(pNode, pvUser); + if (rc) + return rc; +#ifdef KAVL_EQUAL_ALLOWED + if (pNode->mpList != KAVL_NULL) + for (pEqual = KAVL_GET_POINTER(&pNode->mpList); pEqual; pEqual = KAVL_GET_POINTER_NULL(&pEqual->pList)) + { + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KAVL_READ_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* left */ + AVLStack.cEntries--; + if (pNode->mpLeft != KAVL_NULL) + { + AVLStack.achFlags[AVLStack.cEntries] = 0; + AVLStack.aEntries[AVLStack.cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft); + } + } /* while */ + } + + KAVL_READ_UNLOCK(pRoot); + return 0; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h new file mode 100644 index 0000000..da151d1 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlEnum.h @@ -0,0 +1,187 @@ +/* $Id: kAvlEnum.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Node Enumeration. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Enumeration control data. + * + * This is initialized by BeginEnum and used by GetNext to figure out what + * to do next. + */ +typedef struct KAVL_TYPE(,ENUMDATA) +{ + KBOOL fFromLeft; + KI8 cEntries; + KU8 achFlags[KAVL_MAX_STACK]; + KAVLNODE * aEntries[KAVL_MAX_STACK]; +} KAVL_TYPE(,ENUMDATA), *KAVL_TYPE(P,ENUMDATA); + + +/** + * Ends an enumeration. + * + * The purpose of this function is to unlock the tree should the + * AVL implementation include locking. It's good practice to call + * it anyway even if the tree doesn't do any locking. + * + * @param pEnumData Pointer to enumeration control data. + */ +KAVL_DECL(void) KAVL_FN(EndEnum)(KAVL_TYPE(,ENUMDATA) *pEnumData) +{ + KAVLROOT pRoot = pEnumData->pRoot; + pEnumData->pRoot = NULL; + if (pRoot) + KAVL_READ_UNLOCK(pEnumData->pRoot); +} + + +/** + * Get the next node in the tree enumeration. + * + * The current implementation of this function willl not walk the mpList + * chain like the DoWithAll function does. This may be changed later. + * + * @returns Pointer to the next node in the tree. + * NULL is returned when the end of the tree has been reached, + * it is not necessary to call EndEnum in this case. + * @param pEnumData Pointer to enumeration control data. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(GetNext)(KAVL_TYPE(,ENUMDATA) *pEnumData) +{ + if (pEnumData->fFromLeft) + { /* from left */ + while (pEnumData->cEntries > 0) + { + KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; + + /* left */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + if (pNode->mpLeft != KAVL_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */ + pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft); + continue; + } + } + + /* center */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + return pNode; + } + + /* right */ + pEnumData->cEntries--; + if (pNode->mpRight != KAVL_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; + pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight); + } + } /* while */ + } + else + { /* from right */ + while (pEnumData->cEntries > 0) + { + KAVLNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; + + /* right */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + if (pNode->mpRight != KAVL_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 right, 1 center, 2 left */ + pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpRight); + continue; + } + } + + /* center */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + return pNode; + } + + /* left */ + pEnumData->cEntries--; + if (pNode->mpLeft != KAVL_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; + pEnumData->aEntries[pEnumData->cEntries++] = KAVL_GET_POINTER(&pNode->mpLeft); + } + } /* while */ + } + + /* + * Call EndEnum. + */ + KAVL_FN(EndEnum)(pEnumData); + return NULL; +} + + +/** + * Starts an enumeration of all nodes in the given AVL tree. + * + * The current implementation of this function will not walk the mpList + * chain like the DoWithAll function does. This may be changed later. + * + * @returns Pointer to the first node in the enumeration. + * If NULL is returned the tree is empty calling EndEnum isn't + * strictly necessary (although it will do no harm). + * @param pRoot Pointer to the AVL-tree root structure. + * @param pEnumData Pointer to enumeration control data. + * @param fFromLeft K_TRUE: Left to right. + * K_FALSE: Right to left. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(BeginEnum)(KAVLROOT *pRoot, KAVL_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft) +{ + KAVL_READ_LOCK(pRoot); + pEnumData->pRoot = pRoot; + if (pRoot->mpRoot != KAVL_NULL) + { + pEnumData->fFromLeft = fFromLeft; + pEnumData->cEntries = 1; + pEnumData->aEntries[0] = KAVL_GET_POINTER(pRoot->mpRoot); + pEnumData->achFlags[0] = 0; + } + else + pEnumData->cEntries = 0; + + return KAVL_FN(GetNext)(pEnumData); +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h new file mode 100644 index 0000000..a80eb49 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGet.h @@ -0,0 +1,89 @@ +/* $Id: kAvlGet.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Get a Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Gets a node from the tree (does not remove it!) + * + * @returns Pointer to the node holding the given key. + * @param pRoot Pointer to the AVL-tree root structure. + * @param Key Key value of the node which is to be found. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(Get)(KAVLROOT *pRoot, KAVLKEY Key) +{ + KAVLNODE *pNode; +#ifdef KAVL_LOOKTHRU_CACHE + KAVLTREEPTR *ppEntry; +#endif + + KAVL_READ_LOCK(pRoot); + if (pRoot->mpRoot == KAVL_NULL) + { + KAVL_READ_UNLOCK(pRoot); + return NULL; + } + +#ifdef KAVL_LOOKTHRU_CACHE + ppEntry = &pRoot->maLookthru[KAVL_LOOKTHRU_HASH(Key)]; + pNode = KAVL_GET_POINTER_NULL(ppEntry); + if (!pNode || KAVL_NE(pNode->mKey, Key)) +#endif + { + pNode = KAVL_GET_POINTER(&pRoot->mpRoot); + while (KAVL_NE(pNode->mKey, Key)) + { + if (KAVL_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KAVL_NULL) + { + KAVL_READ_UNLOCK(pRoot); + return NULL; + } + pNode = KAVL_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KAVL_NULL) + { + KAVL_READ_UNLOCK(pRoot); + return NULL; + } + pNode = KAVL_GET_POINTER(&pNode->mpRight); + } + } + +#ifdef KAVL_LOOKTHRU_CACHE + KAVL_SET_POINTER(ppEntry, pNode); +#endif + } + + KAVL_READ_UNLOCK(pRoot); + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h new file mode 100644 index 0000000..1d51709 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetBestFit.h @@ -0,0 +1,112 @@ +/* $Id: kAvlGetBestFit.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Get Best Fitting Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Finds the best fitting node in the tree for the given Key value. + * + * @returns Pointer to the best fitting node found. + * @param pRoot Pointer to the AVL-tree root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. + * K_FALSE: Returned node is have the closest key to Key from below. + * @sketch The best fitting node is always located in the searchpath above you. + * >= (above): The node where you last turned left. + * <= (below): the node where you last turned right. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(GetBestFit)(KAVLROOT *pRoot, KAVLKEY Key, KBOOL fAbove) +{ + register KAVLNODE *pNode; + KAVLNODE *pNodeLast; + + KAVL_READ_LOCK(pLook); + if (pRoot->mpRoot == KAVL_NULL) + { + KAVL_READ_UNLOCK(pLook); + return NULL; + } + + pNode = KAVL_GET_POINTER(&pRoot->mpRoot); + pNodeLast = NULL; + if (fAbove) + { /* pNode->mKey >= Key */ + while (KAVL_NE(pNode->mKey, Key)) + { + if (KAVL_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KAVL_NULL) + { + KAVL_READ_UNLOCK(pLook); + return pNode; + } + pNodeLast = pNode; + pNode = KAVL_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KAVL_NULL) + { + KAVL_READ_UNLOCK(pLook); + return pNodeLast; + } + pNode = KAVL_GET_POINTER(&pNode->mpRight); + } + } + } + else + { /* pNode->mKey <= Key */ + while (KAVL_NE(pNode->mKey, Key)) + { + if (KAVL_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KAVL_NULL) + { + KAVL_READ_UNLOCK(pLook); + return pNodeLast; + } + pNode = KAVL_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KAVL_NULL) + { + KAVL_READ_UNLOCK(pLook); + return pNode; + } + pNodeLast = pNode; + pNode = KAVL_GET_POINTER(&pNode->mpRight); + } + } + } + + /* perfect match or nothing. */ + KAVL_READ_UNLOCK(pLook); + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h new file mode 100644 index 0000000..997c394 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlGetWithParent.h @@ -0,0 +1,65 @@ +/* $Id: kAvlGetWithParent.h 34 2009-11-08 19:38:40Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Get Node With Parent. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Gets a node from the tree and its parent node (if any). + * The tree remains unchanged. + * + * @returns Pointer to the node holding the given key. + * @param pRoot Pointer to the AVL-tree root structure. + * @param ppParent Pointer to a variable which will hold the pointer to the partent node on + * return. When no node is found, this will hold the last searched node. + * @param Key Key value of the node which is to be found. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(GetWithParent)(KAVLROOT *pRoot, KAVLNODE **ppParent, KAVLKEY Key) +{ + register KAVLNODE *pNode; + register KAVLNODE *pParent; + + KAVL_READ_LOCK(pRoot); + + pParent = NULL; + pNode = KAVL_GET_POINTER_NULL(&pRoot->mpRoot); + while ( pNode != NULL + && KAVL_NE(pNode->mKey, Key)) + { + pParent = pNode; + if (KAVL_G(pNode->mKey, Key)) + pNode = KAVL_GET_POINTER_NULL(&pNode->mpLeft); + else + pNode = KAVL_GET_POINTER_NULL(&pNode->mpRight); + } + + KAVL_READ_UNLOCK(pRoot); + + *ppParent = pParent; + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h new file mode 100644 index 0000000..d027014 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemove2.h @@ -0,0 +1,133 @@ +/* $Id: kAvlRemove2.h 34 2009-11-08 19:38:40Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Remove A Specific Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Removes the specified node from the tree. + * + * @returns Pointer to the removed node (NULL if not in the tree) + * @param pRoot Pointer to the AVL-tree root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * + * @remark This implementation isn't the most efficient, but this short and + * easier to manage. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(Remove2)(KAVLROOT *pRoot, KAVLNODE *pNode) +{ +#ifdef KAVL_EQUAL_ALLOWED + /* + * Find the right node by key and see if it's what we want. + */ + KAVLNODE *pParent; + KAVLNODE *pCurNode = KAVL_FN(GetWithParent)(pRoot, pNode->mKey, &pParent); + if (!pCurNode) + return NULL; + KAVL_WRITE_LOCK(pRoot); /** @todo the locking here isn't 100% sane. The only way to archive that is by no calling worker functions. */ + if (pCurNode != pNode) + { + /* + * It's not the one we want, but it could be in the duplicate list. + */ + while (pCurNode->mpList != KAVL_NULL) + { + KAVLNODE *pNext = KAVL_GET_POINTER(&pCurNode->mpList); + if (pNext == pNode) + { + KAVL_SET_POINTER_NULL(&pCurNode->mpList, KAVL_GET_POINTER_NULL(&pNode->mpList)); + pNode->mpList = KAVL_NULL; + KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KAVL_WRITE_UNLOCK(pRoot); + return pNode; + } + pCurNode = pNext; + } + KAVL_WRITE_UNLOCK(pRoot); + return NULL; + } + + /* + * Ok, it's the one we want alright. + * + * Simply remove it if it's the only one with they Key, + * if there are duplicates we'll have to unlink it and + * insert the first duplicate in our place. + */ + if (pNode->mpList == KAVL_NULL) + { + KAVL_WRITE_UNLOCK(pRoot); + KAVL_FN(Remove)(pRoot, pNode->mKey); + } + else + { + KAVLNODE *pNewUs = KAVL_GET_POINTER(&pNode->mpList); + + pNewUs->mHeight = pNode->mHeight; + + if (pNode->mpLeft != KAVL_NULL) + KAVL_SET_POINTER(&pNewUs->mpLeft, KAVL_GET_POINTER(&pNode->mpLeft)) + else + pNewUs->mpLeft = KAVL_NULL; + + if (pNode->mpRight != KAVL_NULL) + KAVL_SET_POINTER(&pNewUs->mpRight, KAVL_GET_POINTER(&pNode->mpRight)) + else + pNewUs->mpRight = KAVL_NULL; + + if (pParent) + { + if (KAVL_GET_POINTER_NULL(&pParent->mpLeft) == pNode) + KAVL_SET_POINTER(&pParent->mpLeft, pNewUs); + else + KAVL_SET_POINTER(&pParent->mpRight, pNewUs); + } + else + KAVL_SET_POINTER(&pRoot->mpRoot, pNewUs); + + KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KAVL_WRITE_UNLOCK(pRoot); + } + + return pNode; + +#else + /* + * Delete it, if we got the wrong one, reinsert it. + * + * This ASSUMS that the caller is NOT going to hand us a lot + * of wrong nodes but just uses this API for his convenience. + */ + KAVLNODE *pRemovedNode = KAVL_FN(Remove)(pRoot, pNode->mKey); + if (pRemovedNode == pNode) + return pRemovedNode; + + KAVL_FN(Insert)(pRoot, pRemovedNode); + return NULL; +#endif +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h new file mode 100644 index 0000000..3c9ed98 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlRemoveBestFit.h @@ -0,0 +1,70 @@ +/* $Id: kAvlRemoveBestFit.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Templated AVL Trees, Remove Best Fitting Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Finds the best fitting node in the tree for the given Key value and removes the node. + * + * @returns Pointer to the removed node. + * @param pRoot Pointer to the AVL-tree root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. + * K_FALSE: Returned node is have the closest key to Key from below. + * + * @remark This implementation uses GetBestFit and then Remove and might therefore + * not be the most optimal kind of implementation, but it reduces the complexity + * code size, and the likelyhood for bugs. + */ +KAVL_DECL(KAVLNODE *) KAVL_FN(RemoveBestFit)(KAVLROOT *pRoot, KAVLKEY Key, KBOOL fAbove) +{ + /* + * If we find anything we'll have to remove the node and return it. + * Now, if duplicate keys are allowed we'll remove a duplicate before + * removing the in-tree node as this is way cheaper. + */ + KAVLNODE *pNode = KAVL_FN(GetBestFit)(pRoot, Key, fAbove); + if (pNode != NULL) + { +#ifdef KAVL_EQUAL_ALLOWED + KAVL_WRITE_LOCK(pRoot); /** @todo the locking isn't quite sane here. :-/ */ + if (pNode->mpList != KAVL_NULL) + { + KAVLNODE *pRet = KAVL_GET_POINTER(&pNode->mpList); + KAVL_SET_POINTER_NULL(&pNode->mpList, &pRet->mpList); + KAVL_LOOKTHRU_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KAVL_WRITE_UNLOCK(pRoot); + return pRet; + } + KAVL_WRITE_UNLOCK(pRoot); +#endif + pNode = KAVL_FN(Remove)(pRoot, pNode->mKey); + } + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h b/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h new file mode 100644 index 0000000..bd6957f --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlTmpl/kAvlUndef.h @@ -0,0 +1,79 @@ +/* $Id: kAvlUndef.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvlTmpl - Undefines All Macros (both config and temp). + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The configuration. + */ +#undef KAVL_EQUAL_ALLOWED +#undef KAVL_CHECK_FOR_EQUAL_INSERT +#undef KAVL_MAX_STACK +#undef KAVL_RANGE +#undef KAVL_OFFSET +#undef KAVL_STD_KEY_COMP +#undef KAVL_LOOKTHRU +#undef KAVL_LOOKTHRU_HASH +#undef KAVL_LOCKED +#undef KAVL_WRITE_LOCK +#undef KAVL_WRITE_UNLOCK +#undef KAVL_READ_LOCK +#undef KAVL_READ_UNLOCK +#undef KAVLKEY +#undef KAVLNODE +#undef KAVLTREEPTR +#undef KAVLROOT +#undef KAVL_FN +#undef KAVL_TYPE +#undef KAVL_INT +#undef KAVL_DECL +#undef mKey +#undef mKeyLast +#undef mHeight +#undef mpLeft +#undef mpRight +#undef mpList +#undef mpRoot +#undef maLookthru + +/* + * The internal macros. + */ +#undef KAVL_HEIGHTOF +#undef KAVL_GET_POINTER +#undef KAVL_GET_POINTER_NULL +#undef KAVL_SET_POINTER +#undef KAVL_SET_POINTER_NULL +#undef KAVL_NULL +#undef KAVL_G +#undef KAVL_E +#undef KAVL_NE +#undef KAVL_R_IS_IDENTICAL +#undef KAVL_R_IS_INTERSECTING +#undef KAVL_R_IS_IN_RANGE + diff --git a/src/lib/kStuff/include/k/kAvlU32.h b/src/lib/kStuff/include/k/kAvlU32.h new file mode 100644 index 0000000..7aacb15 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlU32.h @@ -0,0 +1,66 @@ +/* $Id: kAvlU32.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvl - AVL Tree Implementation, KU32 keys. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kAvlU32_h___ +#define ___k_kAvlU32_h___ + +typedef struct KAVLU32 +{ + KU32 mKey; + KU8 mHeight; + struct KAVLU32 *mpLeft; + struct KAVLU32 *mpRight; +} KAVLU32, *PKAVLU32, **PPKAVLU32; + +/*#define KAVL_EQUAL_ALLOWED*/ +#define KAVL_CHECK_FOR_EQUAL_INSERT +#define KAVL_MAX_STACK 32 +/*#define KAVL_RANGE */ +/*#define KAVL_OFFSET */ +#define KAVL_STD_KEY_COMP +#define KAVLKEY KU32 +#define KAVLNODE KAVLU32 +#define KAVL_FN(name) kAvlU32 ## name +#define KAVL_TYPE(prefix,name) prefix ## KAVLU32 ## name +#define KAVL_INT(name) KAVLU32INT ## name +#define KAVL_DECL(rettype) K_DECL_INLINE(rettype) + +#include <k/kAvlTmpl/kAvlBase.h> +#include <k/kAvlTmpl/kAvlDoWithAll.h> +#include <k/kAvlTmpl/kAvlEnum.h> +#include <k/kAvlTmpl/kAvlGet.h> +#include <k/kAvlTmpl/kAvlGetBestFit.h> +#include <k/kAvlTmpl/kAvlGetWithParent.h> +#include <k/kAvlTmpl/kAvlRemove2.h> +#include <k/kAvlTmpl/kAvlRemoveBestFit.h> +#include <k/kAvlTmpl/kAvlUndef.h> + +#endif + diff --git a/src/lib/kStuff/include/k/kAvloU32.h b/src/lib/kStuff/include/k/kAvloU32.h new file mode 100644 index 0000000..e9ad305 --- /dev/null +++ b/src/lib/kStuff/include/k/kAvloU32.h @@ -0,0 +1,75 @@ +/* $Id: kAvloU32.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvl - AVL Tree Implementation, KU32 keys, Offset Based. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kAvloU32_h___ +#define ___k_kAvloU32_h___ + +typedef KI32 KAVLOU32PTR; + +typedef struct KAVLOU32 +{ + KU32 u32; + KU8 cFloorsToGo; + KAVLOU32PTR offLeft; + KAVLOU32PTR offRight; +} KAVLOU32, *PKAVLOU32, **PPKAVLOU32; + +#define mKey u32 +#define mHeight cFloorsToGo +#define mpLeft offLeft +#define mpRight offRight + +/*#define KAVL_EQUAL_ALLOWED*/ +#define KAVL_CHECK_FOR_EQUAL_INSERT +#define KAVL_MAX_STACK 32 +/*#define KAVL_RANGE */ +#define KAVL_OFFSET +#define KAVL_STD_KEY_COMP +#define KAVLKEY KU32 +#define KAVLTREEPTR KAVLOU32PTR +#define KAVLNODE KAVLOU32 +#define KAVL_FN(name) kAvloU32 ## name +#define KAVL_TYPE(prefix,name) prefix ## KAVLOU32 ## name +#define KAVL_INT(name) KAVLOU32INT ## name +#define KAVL_DECL(rettype) K_DECL_INLINE(rettype) + +#include <k/kAvlTmpl/kAvlBase.h> +#include <k/kAvlTmpl/kAvlDoWithAll.h> +#include <k/kAvlTmpl/kAvlEnum.h> +#include <k/kAvlTmpl/kAvlGet.h> +#include <k/kAvlTmpl/kAvlGetBestFit.h> +#include <k/kAvlTmpl/kAvlGetWithParent.h> +#include <k/kAvlTmpl/kAvlRemove2.h> +#include <k/kAvlTmpl/kAvlRemoveBestFit.h> +#include <k/kAvlTmpl/kAvlUndef.h> + +#endif + + diff --git a/src/lib/kStuff/include/k/kAvlrU32.h b/src/lib/kStuff/include/k/kAvlrU32.h new file mode 100644 index 0000000..532a55d --- /dev/null +++ b/src/lib/kStuff/include/k/kAvlrU32.h @@ -0,0 +1,71 @@ +/* $Id: kAvlrU32.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kAvl - AVL Tree Implementation, KU32 key ranges. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kAvlrU32_h___ +#define ___k_kAvlrU32_h___ + +typedef struct KAVLRU32 +{ + KU32 u32Start; + KU32 u32Last; + struct KAVLRU32 *mpLeft; + struct KAVLRU32 *mpRight; + KU8 mHeight; +} KAVLRU32, *PKAVLRU32, **PPKAVLRU32; + +#define mKey u32Start +#define mKeyLast u32Last + +/*#define KAVL_EQUAL_ALLOWED*/ +#define KAVL_CHECK_FOR_EQUAL_INSERT +#define KAVL_MAX_STACK 32 +#define KAVL_RANGE +/*#define KAVL_OFFSET */ +#define KAVL_STD_KEY_COMP +#define KAVLKEY KU32 +#define KAVLNODE KAVLRU32 +#define KAVL_FN(name) kAvlrU32 ## name +#define KAVL_TYPE(prefix,name) prefix ## KAVLRU32 ## name +#define KAVL_INT(name) KAVLRU32INT ## name +#define KAVL_DECL(rettype) K_DECL_INLINE(rettype) + +#include <k/kAvlTmpl/kAvlBase.h> +#include <k/kAvlTmpl/kAvlDoWithAll.h> +#include <k/kAvlTmpl/kAvlEnum.h> +#include <k/kAvlTmpl/kAvlGet.h> +#include <k/kAvlTmpl/kAvlGetBestFit.h> +#include <k/kAvlTmpl/kAvlGetWithParent.h> +#include <k/kAvlTmpl/kAvlRemove2.h> +#include <k/kAvlTmpl/kAvlRemoveBestFit.h> +#include <k/kAvlTmpl/kAvlUndef.h> + +#endif + + diff --git a/src/lib/kStuff/include/k/kCpu.h b/src/lib/kStuff/include/k/kCpu.h new file mode 100644 index 0000000..bbbf815 --- /dev/null +++ b/src/lib/kStuff/include/k/kCpu.h @@ -0,0 +1,68 @@ +/* $Id: kCpu.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kCpu - The CPU and Architecture API. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kCpu_h___ +#define ___k_kCpu_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kCpus.h> + + +/** @defgroup grp_kCpu kCpu - The CPU And Architecture API + * @{ + */ + +/** @def KCPU_DECL + * Declares a kCpu function according to build context. + * @param type The return type. + */ +#if defined(KCPU_BUILDING_DYNAMIC) +# define KCPU_DECL(type) K_DECL_EXPORT(type) +#elif defined(KCPU_BUILT_DYNAMIC) +# define KCPU_DECL(type) K_DECL_IMPORT(type) +#else +# define KCPU_DECL(type) type +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +KCPU_DECL(void) kCpuGetArchAndCpu(PKCPUARCH penmArch, PKCPU penmCpu); +KCPU_DECL(int) kCpuCompare(KCPUARCH enmCodeArch, KCPU enmCodeCpu, KCPUARCH enmArch, KCPU enmCpu); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif diff --git a/src/lib/kStuff/include/k/kCpus.h b/src/lib/kStuff/include/k/kCpus.h new file mode 100644 index 0000000..6fa8400 --- /dev/null +++ b/src/lib/kStuff/include/k/kCpus.h @@ -0,0 +1,157 @@ +/* $Id: kCpus.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kCpus - CPU Identifiers. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kCpus_h___ +#define ___k_kCpus_h___ + +/** @defgroup grp_kCpus kCpus - CPU Identifiers + * @see the kCpu API for functions operating on the CPU type. + * @{ + */ + +/** + * CPU Architectures. + * + * The constants used by this enum has the same values as + * the K_ARCH_* #defines defined by k/kDefs.h. + */ +typedef enum KCPUARCH +{ + /** @copydoc K_ARCH_UNKNOWN */ + KCPUARCH_UNKNOWN = K_ARCH_UNKNOWN, + /** @copydoc K_ARCH_X86_16 */ + KCPUARCH_X86_16 = K_ARCH_X86_16, + /** @copydoc K_ARCH_X86_32 */ + KCPUARCH_X86_32 = K_ARCH_X86_32, + /** @copydoc K_ARCH_AMD64 */ + KCPUARCH_AMD64 = K_ARCH_AMD64, + /** @copydoc K_ARCH_IA64 */ + KCPUARCH_IA64 = K_ARCH_IA64, + /** @copydoc K_ARCH_ALPHA */ + KCPUARCH_ALPHA = K_ARCH_ALPHA, + /** @copydoc K_ARCH_ALPHA_32 */ + KCPUARCH_ALPHA_32 = K_ARCH_ALPHA_32, + /** @copydoc K_ARCH_ARM_32 */ + KCPUARCH_ARM_32 = K_ARCH_ARM_32, + /** @copydoc K_ARCH_ARM_64 */ + KCPUARCH_ARM_64 = K_ARCH_ARM_64, + /** @copydoc K_ARCH_MIPS_32 */ + KCPUARCH_MIPS_32 = K_ARCH_MIPS_32, + /** @copydoc K_ARCH_MIPS_64 */ + KCPUARCH_MIPS_64 = K_ARCH_MIPS_64, + /** @copydoc K_ARCH_POWERPC_32 */ + KCPUARCH_POWERPC_32 = K_ARCH_POWERPC_32, + /** @copydoc K_ARCH_POWERPC_64 */ + KCPUARCH_POWERPC_64 = K_ARCH_POWERPC_64, + /** @copydoc K_ARCH_SPARC_32 */ + KCPUARCH_SPARC_32 = K_ARCH_SPARC_32, + /** @copydoc K_ARCH_SPARC_64 */ + KCPUARCH_SPARC_64 = K_ARCH_SPARC_64, + + /** Hack to blow the type up to 32-bit. */ + KCPUARCH_32BIT_HACK = 0x7fffffff +} KCPUARCH; + +/** Pointer to a CPU architecture type. */ +typedef KCPUARCH *PKCPUARCH; +/** Pointer to a const CPU architecture type. */ +typedef const KCPUARCH *PCKCPUARCH; + + +/** + * CPU models. + */ +typedef enum KCPU +{ + /** The usual invalid cpu. */ + KCPU_INVALID = 0, + + /** @name K_ARCH_X86_16 + * @{ */ + KCPU_I8086, + KCPU_I8088, + KCPU_I80186, + KCPU_I80286, + KCPU_I386_16, + KCPU_I486_16, + KCPU_I486SX_16, + KCPU_I586_16, + KCPU_I686_16, + KCPU_P4_16, + KCPU_CORE2_16, + KCPU_K6_16, + KCPU_K7_16, + KCPU_K8_16, + KCPU_FIRST_X86_16 = KCPU_I8086, + KCPU_LAST_X86_16 = KCPU_K8_16, + /** @} */ + + /** @name K_ARCH_X86_32 + * @{ */ + KCPU_X86_32_BLEND, + KCPU_I386, + KCPU_I486, + KCPU_I486SX, + KCPU_I586, + KCPU_I686, + KCPU_P4, + KCPU_CORE2_32, + KCPU_K6, + KCPU_K7, + KCPU_K8_32, + KCPU_FIRST_X86_32 = KCPU_I386, + KCPU_LAST_X86_32 = KCPU_K8_32, + /** @} */ + + /** @name K_ARCH_AMD64 + * @{ */ + KCPU_AMD64_BLEND, + KCPU_K8, + KCPU_P4_64, + KCPU_CORE2, + KCPU_FIRST_AMD64 = KCPU_K8, + KCPU_LAST_AMD64 = KCPU_CORE2, + /** @} */ + + /** The end of the valid cpu values (exclusive). */ + KCPU_END, + /** Hack to blow the type up to 32-bit. */ + KCPU_32BIT_HACK = 0x7fffffff +} KCPU; + +/** Pointer to a CPU type. */ +typedef KCPU *PKCPU; +/** Pointer to a const CPU type. */ +typedef const KCPU *PCKCPU; + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kDbg.h b/src/lib/kStuff/include/k/kDbg.h new file mode 100644 index 0000000..07ee431 --- /dev/null +++ b/src/lib/kStuff/include/k/kDbg.h @@ -0,0 +1,243 @@ +/* $Id: kDbg.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kDbg - The Debug Info Reader. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kDbg_h___ +#define ___k_kDbg_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kRdr.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup grp_kDbg Debug Info Reader + * @{ + */ + +/** @def KDBG_DECL + * Declares a kDbg function according to build context. + * @param type The return type. + */ +#if defined(KDBG_BUILDING_DYNAMIC) +# define KDBG_DECL(type) K_DECL_EXPORT(type) +#elif defined(KDBG_BUILT_DYNAMIC) +# define KDBG_DECL(type) K_DECL_IMPORT(type) +#else +# define KDBG_DECL(type) type +#endif + + +/** The kDbg address type. */ +typedef KU64 KDBGADDR; +/** Pointer to a kDbg address. */ +typedef KDBGADDR *PKDBGADDR; +/** Pointer to a const kDbg address. */ +typedef const KDBGADDR *PCKDBGADDR; +/** @def KDBGADDR_PRI + * printf format type. */ +#define KDBGADDR_PRI KX64_PRI +/** @def KDBGADDR_MAX + * Max kDbg address value. */ +#define KDBGADDR_MAX KU64_C(0xfffffffffffffffe) +/** @def KDBGADDR_C + * kDbg address constant. + * @param c The constant value. */ +#define KDBGADDR_C(c) KU64_C(c) +/** NIL address. */ +#define NIL_KDBGADDR KU64_MAX + + +/** @name Special Segments + * @{ */ +/** Relative Virtual Address. + * The specified offset is relative to the image base. The image base is the lowest memory + * address used by the image when loaded with the address assignments indicated in the image. */ +#define KDBGSEG_RVA (-1) +/** Absolute segment. The offset isn't relative to anything. */ +#define KDBGSEG_ABS (-2) +/** @} */ + + +/** The max filename path length used by the debug reader. */ +#define KDBG_PATH_MAX 260 + +/** + * Line number details. + */ +typedef struct KDBGLINE +{ + /** The relative virtual address. */ + KDBGADDR RVA; + /** The offset into the segment. */ + KDBGADDR offSegment; + /** The segment number. */ + KI32 iSegment; + /** The Line number. */ + KU32 iLine; + /** The actual size of this structure. */ + KU16 cbSelf; + /** The length of the filename. */ + KU16 cchFile; + /** The name of the file this line number relates to. */ + char szFile[KDBG_PATH_MAX]; +} KDBGLINE; +/** Pointer to line number details. */ +typedef KDBGLINE *PKDBGLINE; +/** Pointer to const line number details. */ +typedef const KDBGLINE *PCKDBGLINE; +/** Pointer to a pointer to line number details. */ +typedef PKDBGLINE *PPKDBGLINE; + +/** + * Duplicates a line number. + * + * To save heap space, the returned line number will not own more heap space + * than it strictly need to. So, it's not possible to append stuff to the symbol + * or anything of that kind. + * + * @returns Pointer to the duplicate. + * This must be freed using RTDbgSymbolFree(). + * @param pLine The line number to be duplicated. + */ +KDBG_DECL(PKDBGLINE) kDbgLineDup(PCKDBGLINE pLine); + +/** + * Frees a line number obtained from the RTDbg API. + * + * @returns VINF_SUCCESS on success. + * @returns KERR_INVALID_POINTER if a NULL pointer or an !KDBG_VALID_PTR() is passed in. + * + * @param pLine The line number to be freed. + */ +KDBG_DECL(int) kDbgLineFree(PKDBGLINE pLine); + + +/** @name Symbol Flags. + * @{ */ +/** The symbol is weak. */ +#define KDBGSYM_FLAGS_WEAK KU32_C(0x00000000) +/** The symbol is absolute. + * (This also indicated by the segment number.) */ +#define KDBGSYM_FLAGS_ABS KU32_C(0x00000001) +/** The symbol is exported. */ +#define KDBGSYM_FLAGS_EXPORTED KU32_C(0x00000002) +/** The symbol is a function/method/procedure/whatever-executable-code. */ +#define KDBGSYM_FLAGS_CODE KU32_C(0x00000004) +/** The symbol is some kind of data. */ +#define KDBGSYM_FLAGS_DATA KU32_C(0x00000008) +/** @} */ + +/** The max symbol name length used by the debug reader. */ +#define KDBG_SYMBOL_MAX 384 + +/** + * Symbol details. + */ +typedef struct KDBGSYMBOL +{ + /** The adddress of this symbol in the relevant space. + * This is NIL_KDBGADDR unless the information was + * returned by a kDbgSpace API. */ + KDBGADDR Address; + /** The relative virtual address. */ + KDBGADDR RVA; + /** The symbol size. + * This is not a reliable field, it could be a bad guess. Ignore if zero. */ + KDBGADDR cb; + /** The offset into the segment. */ + KDBGADDR offSegment; + /** The segment number. */ + KI32 iSegment; + /** The symbol flags. */ + KU32 fFlags; +/** @todo type info. */ + /** The actual size of this structure. */ + KU16 cbSelf; + /** The length of the symbol name. */ + KU16 cchName; + /** The symbol name. */ + char szName[KDBG_SYMBOL_MAX]; +} KDBGSYMBOL; +/** Pointer to symbol details. */ +typedef KDBGSYMBOL *PKDBGSYMBOL; +/** Pointer to const symbol details. */ +typedef const KDBGSYMBOL *PCKDBGSYMBOL; +/** Pointer to a pointer to symbol details. */ +typedef PKDBGSYMBOL *PPKDBGSYMBOL; + +/** + * Duplicates a symbol. + * + * To save heap space, the returned symbol will not own more heap space than + * it strictly need to. So, it's not possible to append stuff to the symbol + * or anything of that kind. + * + * @returns Pointer to the duplicate. + * This must be freed using kDbgSymbolFree(). + * @param pSymbol The symbol to be freed. + */ +KDBG_DECL(PKDBGSYMBOL) kDbgSymbolDup(PCKDBGSYMBOL pSymbol); + +/** + * Frees a symbol obtained from the kDbg API. + * + * @returns VINF_SUCCESS on success. + * @returns KERR_INVALID_POINTER if a NULL pointer or an !KDBG_VALID_PTR() is passed in. + * + * @param pSymbol The symbol to be freed. + */ +KDBG_DECL(int) kDbgSymbolFree(PKDBGSYMBOL pSymbol); + + +/** Pointer to a debug module. */ +typedef struct KDBGMOD *PKDBGMOD; +/** Pointer to a debug module pointer. */ +typedef PKDBGMOD *PPKDBGMOD; + + +KDBG_DECL(int) kDbgModuleOpen(PPKDBGMOD ppDbgMod, const char *pszFilename, struct KLDRMOD *pLdrMod); +KDBG_DECL(int) kDbgModuleOpenFile(PPKDBGMOD ppDbgMod, PKRDR pRdr, struct KLDRMOD *pLdrMod); +KDBG_DECL(int) kDbgModuleOpenFilePart(PPKDBGMOD ppDbgMod, PKRDR pRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod); +KDBG_DECL(int) kDbgModuleClose(PKDBGMOD pMod); +KDBG_DECL(int) kDbgModuleQuerySymbol(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym); +KDBG_DECL(int) kDbgModuleQuerySymbolA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGSYMBOL ppSym); +KDBG_DECL(int) kDbgModuleQueryLine(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGLINE pLine); +KDBG_DECL(int) kDbgModuleQueryLineA(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PPKDBGLINE ppLine); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/kStuff/include/k/kDbgAll.h b/src/lib/kStuff/include/k/kDbgAll.h new file mode 100644 index 0000000..fde7c0f --- /dev/null +++ b/src/lib/kStuff/include/k/kDbgAll.h @@ -0,0 +1,168 @@ +/* $Id: kDbgAll.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kDbg - The Debug Info Read, All Details and Dependencies Included. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kDbgAll_h___ +#define ___k_kDbgAll_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kRdr.h> +#include <k/kLdr.h> +#include <k/kDbg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup grp_kDbgAll All + * @addtogroup grp_kDbg + * @{ + */ + +/** + * The debug module method table. + */ +typedef struct KDBGMODOPS +{ + /** The name of the reader. */ + const char *pszName; + + /** Pointer to the next debug module readers. + * This is only used for dynamically registered readers. */ + struct KDBGMODOPS *pNext; + + /** + * Tries to open the module. + * + * @returns 0 on success, KDBG_ERR on failure. + * @param ppMod Where to store the module that's been opened. + * @param pRdr The file provider. + * @param fCloseRdrs Whether the reader should be closed or not when the module is destroyed. + * @param off The file offset of the debug info. This is 0 if there isn't + * any specfic debug info section and the reader should start + * looking for debug info at the start of the file. + * @param cb The size of the debug info in the file. INT64_MAX if we don't + * know or there isn't any particular debug info section in the file. + * @param pLdrMod The associated loader module. This can be NULL. + */ + int (*pfnOpen)(PKDBGMOD *ppMod, PKRDR pRdr, KBOOL fCloseRdr, KFOFF off, KFOFF cb, struct KLDRMOD *pLdrMod); + + /** + * Closes the module. + * + * This should free all resources associated with the module + * except the pMod which is freed by the caller. + * + * @returns IPRT status code. + * @param pMod The module. + */ + int (*pfnClose)(PKDBGMOD pMod); + + /** + * Gets a symbol by segment:offset. + * This will be approximated to the nearest symbol if there is no exact match. + * + * @returns 0 on success. KLDR_ERR_* on failure. + * @param pMod The module. + * @param iSegment The segment this offset is relative to. + * The -1 segment is special, it means that the addres is relative to + * the image base. The image base is where the first bit of the image + * is mapped during load. + * @param off The offset into the segment. + * @param pSym Where to store the symbol details. + */ + int (*pfnQuerySymbol)(PKDBGMOD pMod, KI32 iSegment, KDBGADDR off, PKDBGSYMBOL pSym); + + /** + * Gets a line number entry by segment:offset. + * This will be approximated to the nearest line number there is no exact match. + * + * @returns 0 on success. KLDR_ERR_* on failure. + * @param pMod The module. + * @param iSegment The segment this offset is relative to. + * The -1 segment is special, it means that the addres is relative to + * the image base. The image base is where the first bit of the image + * is mapped during load. + * @param off The offset into the segment. + * @param pLine Where to store the line number details. + */ + int (*pfnQueryLine)(PKDBGMOD pMod, KI32 iSegment, KDBGADDR uOffset, PKDBGLINE pLine); + + /** This is just to make sure you've initialized all the fields. + * Must be identical to pszName. */ + const char *pszName2; +} KDBGMODOPS; +/** Pointer to a module method table. */ +typedef KDBGMODOPS *PKDBGMODOPS; +/** Pointer to a const module method table. */ +typedef const KDBGMODOPS *PCKDBGMODOPS; + +/** + * Register a debug module reader with the kDbgModule component. + * + * Dynamically registered readers are kept in FIFO order, and external + * readers will be tried after the builtin ones. + * + * @returns 0 on success. + * @returns KERR_INVALID_POINTER if pOps is missing bits. + * @returns KERR_INVALID_PARAMETER if pOps is already in the list. + * @param pOps The reader method table, kDbg takes owner ship of + * this. This must be writeable as the pNext pointer + * will be update. It must also stick around for as + * long as kDbg is in use. + */ +KDBG_DECL(int) kDbgModuleRegisterReader(PKDBGMODOPS pOps); + + + +/** + * Internal representation of a debug module. + */ +typedef struct KDBGMOD +{ + /** Magic value (KDBGMOD_MAGIC). */ + KI32 u32Magic; + /** Pointer to the method table. */ + PCKDBGMODOPS pOps; + /** The file provider for the file containing the debug info. */ + PKRDR pRdr; + /** Whether or not to close pRdr. */ + KBOOL fCloseRdr; + /** The associated kLdr module. This may be NULL. */ + PKLDRMOD pLdrMod; +} KDBGMOD; + +/** @}*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/kStuff/include/k/kDbgBase.h b/src/lib/kStuff/include/k/kDbgBase.h new file mode 100644 index 0000000..5ae31fb --- /dev/null +++ b/src/lib/kStuff/include/k/kDbgBase.h @@ -0,0 +1,248 @@ +/* $Id: kDbgBase.h 40 2010-02-02 16:02:15Z bird $ */ +/** @file + * kDbg - The Debug Info Reader, Base Definitions and Typedefs. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___kDbgBase_h___ +#define ___kDbgBase_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> + + +/** @defgroup grp_kDbgBase kDbgBase - Base Definitions And Typedefs + * @{ */ + +/* + * kDbg depend on size_t, [u]intNN_t, [u]intptr_t and some related constants. + * If KDBG_ALREADY_INCLUDED_STD_TYPES or KCOMMON_ALREADY_INCLUDED_STD_TYPES + * is defined, these has already been defined. + */ +#if !defined(KDBG_ALREADY_INCLUDED_STD_TYPES) && !defined(KCOMMON_ALREADY_INCLUDED_STD_TYPES) +# define KCOMMON_ALREADY_INCLUDED_STD_TYPES 1 +# include <sys/types.h> +# include <stddef.h> +# ifdef _MSC_VER + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed int int32_t; + typedef unsigned int uint32_t; + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define UINT8_C(c) (c) +# define UINT16_C(c) (c) +# define UINT32_C(c) (c ## U) +# define UINT64_C(c) (c ## ULL) +# define INT8_C(c) (c) +# define INT16_C(c) (c) +# define INT32_C(c) (c) +# define INT64_C(c) (c ## LL) +# define INT8_MIN (INT8_C(-0x7f) - 1) +# define INT16_MIN (INT16_C(-0x7fff) - 1) +# define INT32_MIN (INT32_C(-0x7fffffff) - 1) +# define INT64_MIN (INT64_C(-0x7fffffffffffffff) - 1) +# define INT8_MAX INT8_C(0x7f) +# define INT16_MAX INT16_C(0x7fff) +# define INT32_MAX INT32_C(0x7fffffff) +# define INT64_MAX INT64_C(0x7fffffffffffffff) +# define UINT8_MAX UINT8_C(0xff) +# define UINT16_MAX UINT16_C(0xffff) +# define UINT32_MAX UINT32_C(0xffffffff) +# define UINT64_MAX UINT64_C(0xffffffffffffffff) +# else +# include <stdint.h> +# endif +#endif /* !KDBG_ALREADY_INCLUDED_STD_TYPES && !KCOMMON_ALREADY_INCLUDED_STD_TYPES */ + + +/** @def KDBG_CALL + * The calling convention used by the kDbg functions. */ +#if defined(_MSC_VER) || defined(__OS2__) +# define KDBG_CALL __cdecl +#else +# define KDBG_CALL +#endif + +#ifdef DOXYGEN_RUNNING +/** @def KDBG_BUILDING + * Define KDBG_BUILDING to indicate that kDbg is being built. + */ +# define KDBG_BUILDING +/** @def KDBG_RESIDES_IN_DLL + * Define KDBG_RESIDES_IN_DLL to indicate that kDbg resides in a DLL. + */ +# define KDBG_RESIDES_IN_DLL +#endif + +/** @def KDBG_DECL + * Macro for defining public functions. */ +#if defined(KDBG_RESIDES_IN_DLL) \ + && (defined(_MSC_VER) || defined(__OS2__)) +# ifdef KDBG_BUILDING +# define KDBG_DECL(type) __declspec(dllexport) type +# else +# define KDBG_DECL(type) __declspec(dllimport) type +# endif +#else +# define KDBG_DECL(type) type +#endif + +/** @def KDBG_INLINE + * Macro for defining an inline function. */ +#ifdef __cplusplus +# if defined(__GNUC__) +# define KDBG_INLINE(type) static inline type +# else +# define KDBG_INLINE(type) inline type +# endif +#else +# if defined(__GNUC__) +# define KDBG_INLINE(type) static __inline__ type +# elif defined(_MSC_VER) +# define KDBG_INLINE(type) _inline type +# else +# error "Port me" +# endif +#endif + + +/** The kDbg address type. */ +typedef uint64_t KDBGADDR; +/** Pointer to a kLdr address. */ +typedef KDBGADDR *PKDBGADDR; +/** Pointer to a const kLdr address. */ +typedef const KDBGADDR *PCKDBGADDR; + +/** NIL address. */ +#define NIL_KDBGADDR (~(uint64_t)0) + +/** @def PRI_KDBGADDR + * printf format type. */ +#ifdef _MSC_VER +# define PRI_KDBGADDR "I64x" +#else +# define PRI_KDBGADDR "llx" +#endif + + +/** Get the minimum of two values. */ +#define KDBG_MIN(a, b) ((a) <= (b) ? (a) : (b)) +/** Get the maximum of two values. */ +#define KDBG_MAX(a, b) ((a) >= (b) ? (a) : (b)) +/** Calculate the offset of a structure member. */ +#define KDBG_OFFSETOF(strct, memb) ( (size_t)( &((strct *)0)->memb ) ) +/** Align a size_t value. */ +#define KDBG_ALIGN_Z(val, align) ( ((val) + ((align) - 1)) & ~(size_t)((align) - 1) ) +/** Align a void * value. */ +#define KDBG_ALIGN_P(pv, align) ( (void *)( ((uintptr_t)(pv) + ((align) - 1)) & ~(uintptr_t)((align) - 1) ) ) +/** Align a size_t value. */ +#define KDBG_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KDBGADDR)((align) - 1) ) +/** Number of elements in an array. */ +#define KDBG_ELEMENTS(a) ( sizeof(a) / sizeof((a)[0]) ) +/** @def KDBG_VALID_PTR + * Checks if the specified pointer is a valid address or not. */ +#define KDBG_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U ) + + +/** @def KDBG_LITTLE_ENDIAN + * The kDbg build is for a little endian target. */ +/** @def KDBG_BIG_ENDIAN + * The kDbg build is for a big endian target. */ +#if !defined(KDBG_LITTLE_ENDIAN) && !defined(KDBG_BIG_ENDIAN) +# define KDBG_LITTLE_ENDIAN +#endif +#ifdef DOXYGEN_RUNNING +# define KDBG_BIG_ENDIAN +#endif + + +/** @name Endian Conversion + * @{ */ + +/** @def KDBG_E2E_U16 + * Convert the endian of an unsigned 16-bit value. */ +# define KDBG_E2E_U16(u16) ( (uint16_t) (((u16) >> 8) | ((u16) << 8)) ) +/** @def KDBG_E2E_U32 + * Convert the endian of an unsigned 32-bit value. */ +# define KDBG_E2E_U32(u32) ( ( ((u32) & UINT32_C(0xff000000)) >> 24 ) \ + | ( ((u32) & UINT32_C(0x00ff0000)) >> 8 ) \ + | ( ((u32) & UINT32_C(0x0000ff00)) << 8 ) \ + | ( ((u32) & UINT32_C(0x000000ff)) << 24 ) \ + ) +/** @def KDBG_E2E_U64 + * Convert the endian of an unsigned 64-bit value. */ +# define KDBG_E2E_U64(u64) ( ( ((u64) & UINT64_C(0xff00000000000000)) >> 56 ) \ + | ( ((u64) & UINT64_C(0x00ff000000000000)) >> 40 ) \ + | ( ((u64) & UINT64_C(0x0000ff0000000000)) >> 24 ) \ + | ( ((u64) & UINT64_C(0x000000ff00000000)) >> 8 ) \ + | ( ((u64) & UINT64_C(0x00000000ff000000)) << 8 ) \ + | ( ((u64) & UINT64_C(0x0000000000ff0000)) << 24 ) \ + | ( ((u64) & UINT64_C(0x000000000000ff00)) << 40 ) \ + | ( ((u64) & UINT64_C(0x00000000000000ff)) << 56 ) \ + ) + +/** @def KDBG_LE2H_U16 + * Unsigned 16-bit little-endian to host endian. */ +/** @def KDBG_LE2H_U32 + * Unsigned 32-bit little-endian to host endian. */ +/** @def KDBG_LE2H_U64 + * Unsigned 64-bit little-endian to host endian. */ +/** @def KDBG_BE2H_U16 + * Unsigned 16-bit big-endian to host endian. */ +/** @def KDBG_BE2H_U32 + * Unsigned 32-bit big-endian to host endian. */ +/** @def KDBG_BE2H_U64 + * Unsigned 64-bit big-endian to host endian. */ +#ifdef KDBG_LITTLE_ENDIAN +# define KDBG_LE2H_U16(u16) ((uint16_t)(u16)) +# define KDBG_LE2H_U32(u32) ((uint32_t)(u32)) +# define KDBG_LE2H_U64(u64) ((uint32_t)(u32)) +# define KDBG_BE2H_U16(u16) KDBG_E2E_U16(u16) +# define KDBG_BE2H_U32(u32) KDBG_E2E_U32(u32) +# define KDBG_BE2H_U64(u64) KDBG_E2E_U64(u64) +#elif defined(KDBG_BIG_ENDIAN) +# define KDBG_LE2H_U16(u16) KDBG_E2E_U16(u16) +# define KDBG_LE2H_U32(u32) KDBG_E2E_U32(u32) +# define KDBG_LE2H_U32(u64) KDBG_E2E_U64(u64) +# define KDBG_BE2H_U16(u16) ((uint16_t)(u16)) +# define KDBG_BE2H_U32(u32) ((uint32_t)(u32)) +# define KDBG_BE2H_U64(u64) ((uint32_t)(u32)) +#else +# error "KDBG_BIG_ENDIAN or KDBG_LITTLE_ENDIAN is supposed to be defined." +#endif + +/** @} */ + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kDefs.h b/src/lib/kStuff/include/k/kDefs.h new file mode 100644 index 0000000..ffa1cf2 --- /dev/null +++ b/src/lib/kStuff/include/k/kDefs.h @@ -0,0 +1,596 @@ +/* $Id: kDefs.h 120 2022-02-18 02:00:53Z bird $ */ +/** @file + * kTypes - Defines and Macros. + */ + +/* + * Copyright (c) 2006-2017 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kDefs_h___ +#define ___k_kDefs_h___ + +/** @defgroup grp_kDefs kDefs - Defines and Macros + * @{ */ + +/** @name Operative System Identifiers. + * These are the value that the K_OS \#define can take. + * @{ + */ +/** Unknown OS. */ +#define K_OS_UNKNOWN 0 +/** Darwin - aka Mac OS X. */ +#define K_OS_DARWIN 1 +/** DragonFly BSD. */ +#define K_OS_DRAGONFLY 2 +/** FreeBSD. */ +#define K_OS_FREEBSD 3 +/** GNU/Hurd. */ +#define K_OS_GNU_HURD 4 +/** GNU/kFreeBSD. */ +#define K_OS_GNU_KFBSD 5 +/** GNU/kNetBSD or GNU/NetBSD or whatever the decide to call it. */ +#define K_OS_GNU_KNBSD 6 +/** Haiku. */ +#define K_OS_HAIKU 7 +/** Linux. */ +#define K_OS_LINUX 8 +/** NetBSD. */ +#define K_OS_NETBSD 9 +/** NT (native). */ +#define K_OS_NT 10 +/** OpenBSD*/ +#define K_OS_OPENBSD 11 +/** OS/2 */ +#define K_OS_OS2 12 +/** Solaris */ +#define K_OS_SOLARIS 13 +/** Windows. */ +#define K_OS_WINDOWS 14 +/** The max K_OS_* value (exclusive). */ +#define K_OS_MAX 15 +/** @} */ + +/** @def K_OS + * Indicates which OS we're targetting. It's a \#define with is + * assigned one of the K_OS_* defines above. + * + * So to test if we're on FreeBSD do the following: + * @code + * #if K_OS == K_OS_FREEBSD + * some_funky_freebsd_specific_stuff(); + * #endif + * @endcode + */ +#ifndef K_OS +# if defined(__APPLE__) +# define K_OS K_OS_DARWIN +# elif defined(__DragonFly__) +# define K_OS K_OS_DRAGONFLY +# elif defined(__FreeBSD__) +# define K_OS K_OS_FREEBSD +# elif defined(__FreeBSD_kernel__) +# define K_OS K_OS_GNU_KFBSD +# elif defined(__gnu_hurd__) +# define K_OS K_OS_GNU_HURD +# elif defined(__gnu_linux__) +# define K_OS K_OS_LINUX +# elif defined(__NetBSD__) /*??*/ +# define K_OS K_OS_NETBSD +# elif defined(__NetBSD_kernel__) +# define K_OS K_OS_GNU_KNBSD +# elif defined(__OpenBSD__) /*??*/ +# define K_OS K_OS_OPENBSD +# elif defined(__OS2__) +# define K_OS K_OS_OS2 +# elif defined(__sun__) || defined(__SunOS__) || defined(__sun) || defined(__SunOS) +# define K_OS K_OS_SOLARIS +# elif defined(_WIN32) || defined(_WIN64) +# define K_OS K_OS_WINDOWS +# elif defined(__haiku__) || defined(__HAIKU__) +# define K_OS K_OS_HAIKU +# else +# error "Port Me" +# endif +#endif +#if K_OS < K_OS_UNKNOWN || K_OS >= K_OS_MAX +# error "Invalid K_OS value." +#endif + + + +/** @name Architecture bit width. + * @{ */ +#define K_ARCH_BIT_8 0x0100 /**< 8-bit */ +#define K_ARCH_BIT_16 0x0200 /**< 16-bit */ +#define K_ARCH_BIT_32 0x0400 /**< 32-bit */ +#define K_ARCH_BIT_64 0x0800 /**< 64-bit */ +#define K_ARCH_BIT_128 0x1000 /**< 128-bit */ +#define K_ARCH_BIT_MASK 0x1f00 /**< The bit mask. */ +#define K_ARCH_BIT_SHIFT 5 /**< Shift count for producing the width in bits. */ +#define K_ARCH_BYTE_SHIFT 8 /**< Shift count for producing the width in bytes. */ +/** @} */ + +/** @name Architecture Endianness. + * @{ */ +#define K_ARCH_END_LITTLE 0x2000 /**< Little-endian. */ +#define K_ARCH_END_BIG 0x4000 /**< Big-endian. */ +#define K_ARCH_END_BI 0x6000 /**< Bi-endian, can be switched. */ +#define K_ARCH_END_MASK 0x6000 /**< The endian mask. */ +#define K_ARCH_END_SHIFT 13 /**< Shift count for converting between this K_ENDIAN_*. */ +/** @} */ + +/** @name Architecture Identifiers. + * These are the value that the K_ARCH \#define can take. + *@{ */ +/** Unknown CPU architecture. */ +#define K_ARCH_UNKNOWN ( 0 ) +/** Clone or Intel 16-bit x86. */ +#define K_ARCH_X86_16 ( 1 | K_ARCH_BIT_16 | K_ARCH_END_LITTLE) +/** Clone or Intel 32-bit x86. */ +#define K_ARCH_X86_32 ( 1 | K_ARCH_BIT_32 | K_ARCH_END_LITTLE) +/** AMD64 (including clones). */ +#define K_ARCH_AMD64 ( 2 | K_ARCH_BIT_64 | K_ARCH_END_LITTLE) +/** Itanic (64-bit). */ +#define K_ARCH_IA64 ( 3 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** ALPHA (64-bit). */ +#define K_ARCH_ALPHA ( 4 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** ALPHA limited to 32-bit. */ +#define K_ARCH_ALPHA_32 ( 4 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 32-bit ARM. */ +#define K_ARCH_ARM_32 ( 5 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 64-bit ARM. */ +#define K_ARCH_ARM_64 ( 5 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** Motorola 68000 (32-bit). */ +#define K_ARCH_M68K ( 6 | K_ARCH_BIT_32 | K_ARCH_END_BIG) +/** 32-bit MIPS. */ +#define K_ARCH_MIPS_32 ( 7 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 64-bit MIPS. */ +#define K_ARCH_MIPS_64 ( 7 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** 32-bit PA-RISC. */ +#define K_ARCH_PARISC_32 ( 8 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 64-bit PA-RISC. */ +#define K_ARCH_PARISC_64 ( 8 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** 32-bit PowerPC. */ +#define K_ARCH_POWERPC_32 ( 9 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 64-bit PowerPC. */ +#define K_ARCH_POWERPC_64 ( 9 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** 32(31)-bit S390. */ +#define K_ARCH_S390_32 (10 | K_ARCH_BIT_32 | K_ARCH_END_BIG) +/** 64-bit S390. */ +#define K_ARCH_S390_64 (10 | K_ARCH_BIT_64 | K_ARCH_END_BIG) +/** 32-bit SuperH. */ +#define K_ARCH_SH_32 (11 | K_ARCH_BIT_32 | K_ARCH_END_BI) +/** 64-bit SuperH. */ +#define K_ARCH_SH_64 (11 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** 32-bit SPARC. */ +#define K_ARCH_SPARC_32 (12 | K_ARCH_BIT_32 | K_ARCH_END_BIG) +/** 64-bit SPARC. */ +#define K_ARCH_SPARC_64 (12 | K_ARCH_BIT_64 | K_ARCH_END_BI) +/** 32-bit RISC-V, little endian. */ +#define K_ARCH_RISCV_32 (13 | K_ARCH_BIT_32 | K_ARCH_END_LITTLE) +/** 32-bit RISC-V, big endian. */ +#define K_ARCH_RISCV_32_BE (13 | K_ARCH_BIT_32 | K_ARCH_END_BIG) +/** 64-bit RISC-V, little endian. */ +#define K_ARCH_RISCV_64 (13 | K_ARCH_BIT_64 | K_ARCH_END_LITTLE) +/** 64-bit RISC-V, big endian. */ +#define K_ARCH_RISCV_64_BE (13 | K_ARCH_BIT_64 | K_ARCH_END_BIG) +/** The end of the valid architecture values (exclusive). */ +#define K_ARCH_MAX (12+1) +/** @} */ + + +/** @def K_ARCH + * The value of this \#define indicates which architecture we're targetting. + */ +#ifndef K_ARCH + /* detection based on compiler defines. */ +# if defined(__amd64__) || defined(__x86_64__) || defined(__AMD64__) || defined(_M_X64) || defined(__amd64) +# define K_ARCH K_ARCH_AMD64 +# elif defined(__i386__) || defined(__x86__) || defined(__X86__) || defined(_M_IX86) || defined(__i386) +# define K_ARCH K_ARCH_X86_32 +# elif defined(__ia64__) || defined(__IA64__) || defined(_M_IA64) +# define K_ARCH K_ARCH_IA64 +# elif defined(__alpha__) +# define K_ARCH K_ARCH_ALPHA +# elif defined(__arm__) || defined(__arm32__) +# define K_ARCH K_ARCH_ARM_32 +# elif defined(__aarch64__) || defined(__arm64__) +# define K_ARCH K_ARCH_ARM_64 +# elif defined(__hppa__) && defined(__LP64__) +# define K_ARCH K_ARCH_PARISC_64 +# elif defined(__hppa__) +# define K_ARCH K_ARCH_PARISC_32 +# elif defined(__m68k__) +# define K_ARCH K_ARCH_M68K +# elif defined(__mips64) +# define K_ARCH K_ARCH_MIPS_64 +# elif defined(__mips__) +# define K_ARCH K_ARCH_MIPS_32 +# elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) +# define K_ARCH K_ARCH_POWERPC_64 +# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) +# define K_ARCH K_ARCH_POWERPC_32 +# elif defined(__riscv) +# if __BYTE_ORDER__ == WORDS_BIG_ENDIAN +# if defined(__riscv32) || __riscv_xlen+0 == 32 +# define K_ARCH K_ARCH_RISCV_32_BE +# else +# define K_ARCH K_ARCH_RISCV_64_BE +# endif +# elif defined(__riscv32) || __riscv_xlen+0 == 32 +# define K_ARCH K_ARCH_RISCV_32 +# else +# define K_ARCH K_ARCH_RISCV_64 +# endif +# elif defined(__sparcv9__) || defined(__sparcv9) +# define K_ARCH K_ARCH_SPARC_64 +# elif defined(__sparc__) || defined(__sparc) +# define K_ARCH K_ARCH_SPARC_32 +# elif defined(__s390x__) +# define K_ARCH K_ARCH_S390_64 +# elif defined(__s390__) +# define K_ARCH K_ARCH_S390_32 +# elif defined(__sh__) +# if !defined(__SH5__) +# define K_ARCH K_ARCH_SH_32 +# else +# if __SH5__ == 64 +# define K_ARCH K_ARCH_SH_64 +# else +# define K_ARCH K_ARCH_SH_32 +# endif +# endif +# else +# error "Port Me" +# endif +#else + /* validate the user specified value. */ +# if (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_8 \ + && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_16 \ + && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_32 \ + && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_64 \ + && (K_ARCH & K_ARCH_BIT_MASK) != K_ARCH_BIT_128 +# error "Invalid K_ARCH value (bit)" +# endif +# if (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_LITTLE \ + && (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_BIG \ + && (K_ARCH & K_ARCH_END_MASK) != K_ARCH_END_BI +# error "Invalid K_ARCH value (endian)" +# endif +# if (K_ARCH & ~(K_ARCH_BIT_MASK | K_ARCH_BIT_END_MASK)) < K_ARCH_UNKNOWN \ + || (K_ARCH & ~(K_ARCH_BIT_MASK | K_ARCH_BIT_END_MASK)) >= K_ARCH_MAX +# error "Invalid K_ARCH value" +# endif +#endif + +/** @def K_ARCH_IS_VALID + * Check if the architecture identifier is valid. + * @param arch The K_ARCH_* define to examin. + */ +#define K_ARCH_IS_VALID(arch) ( ( ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_8 \ + || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_16 \ + || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_32 \ + || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_64 \ + || ((arch) & K_ARCH_BIT_MASK) == K_ARCH_BIT_128) \ + && \ + ( ((arch) & K_ARCH_END_MASK) == K_ARCH_END_LITTLE \ + || ((arch) & K_ARCH_END_MASK) == K_ARCH_END_BIG \ + || ((arch) & K_ARCH_END_MASK) == K_ARCH_END_BI) \ + && \ + ( ((arch) & ~(K_ARCH_BIT_MASK | K_ARCH_END_MASK)) >= K_ARCH_UNKNOWN \ + && ((arch) & ~(K_ARCH_BIT_MASK | K_ARCH_END_MASK)) < K_ARCH_MAX) \ + ) + +/** @def K_ARCH_BITS_EX + * Determin the architure byte width of the specified architecture. + * @param arch The K_ARCH_* define to examin. + */ +#define K_ARCH_BITS_EX(arch) ( ((arch) & K_ARCH_BIT_MASK) >> K_ARCH_BIT_SHIFT ) + +/** @def K_ARCH_BYTES_EX + * Determin the architure byte width of the specified architecture. + * @param arch The K_ARCH_* define to examin. + */ +#define K_ARCH_BYTES_EX(arch) ( ((arch) & K_ARCH_BIT_MASK) >> K_ARCH_BYTE_SHIFT ) + +/** @def K_ARCH_ENDIAN_EX + * Determin the K_ENDIAN value for the specified architecture. + * @param arch The K_ARCH_* define to examin. + */ +#define K_ARCH_ENDIAN_EX(arch) ( ((arch) & K_ARCH_END_MASK) >> K_ARCH_END_SHIFT ) + +/** @def K_ARCH_BITS + * Determin the target architure bit width. + */ +#define K_ARCH_BITS K_ARCH_BITS_EX(K_ARCH) + +/** @def K_ARCH_BYTES + * Determin the target architure byte width. + */ +#define K_ARCH_BYTES K_ARCH_BYTES_EX(K_ARCH) + +/** @def K_ARCH_ENDIAN + * Determin the target K_ENDIAN value. + */ +#define K_ARCH_ENDIAN K_ARCH_ENDIAN_EX(K_ARCH) + + + +/** @name Endianness Identifiers. + * These are the value that the K_ENDIAN \#define can take. + * @{ */ +#define K_ENDIAN_LITTLE 1 /**< Little-endian. */ +#define K_ENDIAN_BIG 2 /**< Big-endian. */ +#define K_ENDIAN_BI 3 /**< Bi-endian, can be switched. Only used with K_ARCH. */ +/** @} */ + +/** @def K_ENDIAN + * The value of this \#define indicates the target endianness. + * + * @remark It's necessary to define this (or add the necessary deduction here) + * on bi-endian architectures. + */ +#ifndef K_ENDIAN + /* use K_ARCH if possible. */ +# if K_ARCH_ENDIAN != K_ENDIAN_BI +# define K_ENDIAN K_ARCH_ENDIAN +# elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define K_ENDIAN K_ENDIAN_LITTLE +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define K_ENDIAN K_ENDIAN_BIG +# else +# error "Port Me or define K_ENDIAN." +# endif +# else +# error "Port Me or define K_ENDIAN." +# endif +#else + /* validate the user defined value. */ +# if K_ENDIAN != K_ENDIAN_LITTLE \ + && K_ENDIAN != K_ENDIAN_BIG +# error "K_ENDIAN must either be defined as K_ENDIAN_LITTLE or as K_ENDIAN_BIG." +# endif +#endif + +/** @name Endian Conversion + * @{ */ + +/** @def K_E2E_U16 + * Convert the endian of an unsigned 16-bit value. */ +# define K_E2E_U16(u16) ( (KU16) (((u16) >> 8) | ((u16) << 8)) ) +/** @def K_E2E_U32 + * Convert the endian of an unsigned 32-bit value. */ +# define K_E2E_U32(u32) ( ( ((u32) & KU32_C(0xff000000)) >> 24 ) \ + | ( ((u32) & KU32_C(0x00ff0000)) >> 8 ) \ + | ( ((u32) & KU32_C(0x0000ff00)) << 8 ) \ + | ( ((u32) & KU32_C(0x000000ff)) << 24 ) \ + ) +/** @def K_E2E_U64 + * Convert the endian of an unsigned 64-bit value. */ +# define K_E2E_U64(u64) ( ( ((u64) & KU64_C(0xff00000000000000)) >> 56 ) \ + | ( ((u64) & KU64_C(0x00ff000000000000)) >> 40 ) \ + | ( ((u64) & KU64_C(0x0000ff0000000000)) >> 24 ) \ + | ( ((u64) & KU64_C(0x000000ff00000000)) >> 8 ) \ + | ( ((u64) & KU64_C(0x00000000ff000000)) << 8 ) \ + | ( ((u64) & KU64_C(0x0000000000ff0000)) << 24 ) \ + | ( ((u64) & KU64_C(0x000000000000ff00)) << 40 ) \ + | ( ((u64) & KU64_C(0x00000000000000ff)) << 56 ) \ + ) + +/** @def K_LE2H_U16 + * Unsigned 16-bit little-endian to host endian. */ +/** @def K_LE2H_U32 + * Unsigned 32-bit little-endian to host endian. */ +/** @def K_LE2H_U64 + * Unsigned 64-bit little-endian to host endian. */ +/** @def K_BE2H_U16 + * Unsigned 16-bit big-endian to host endian. */ +/** @def K_BE2H_U32 + * Unsigned 32-bit big-endian to host endian. */ +/** @def K_BE2H_U64 + * Unsigned 64-bit big-endian to host endian. */ +#if K_ENDIAN == K_ENDIAN_LITTLE +# define K_LE2H_U16(u16) ((KU16)(u16)) +# define K_LE2H_U32(u32) ((KU32)(u32)) +# define K_LE2H_U64(u64) ((KU64)(u32)) +# define K_BE2H_U16(u16) K_E2E_U16(u16) +# define K_BE2H_U32(u32) K_E2E_U32(u32) +# define K_BE2H_U64(u64) K_E2E_U64(u64) +#else +# define K_LE2H_U16(u16) K_E2E_U16(u16) +# define K_LE2H_U32(u32) K_E2E_U32(u32) +# define K_LE2H_U64(u64) K_E2E_U64(u64) +# define K_BE2H_U16(u16) ((KU16)(u16)) +# define K_BE2H_U32(u32) ((KU32)(u32)) +# define K_BE2H_U64(u64) ((KU64)(u32)) +#endif + + + +/** @def K_INLINE + * How to say 'inline' in both C and C++ dialects. + * @param type The return type. + */ +#ifdef __cplusplus +# if defined(__GNUC__) +# define K_INLINE static inline +# else +# define K_INLINE inline +# endif +#else +# if defined(__GNUC__) +# define K_INLINE static __inline__ +# elif defined(_MSC_VER) +# define K_INLINE static __inline +# else +# error "Port Me" +# endif +#endif + +/** @def K_EXPORT + * What to put in front of an exported function. + */ +#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS +# define K_EXPORT __declspec(dllexport) +#else +# define K_EXPORT +#endif + +/** @def K_IMPORT + * What to put in front of an imported function. + */ +#if K_OS == K_OS_OS2 || K_OS == K_OS_WINDOWS +# define K_IMPORT __declspec(dllimport) +#else +# define K_IMPORT extern +#endif + +/** @def K_DECL_EXPORT + * Declare an exported function. + * @param type The return type. + */ +#define K_DECL_EXPORT(type) K_EXPORT type + +/** @def K_DECL_IMPORT + * Declare an import function. + * @param type The return type. + */ +#define K_DECL_IMPORT(type) K_IMPORT type + +/** @def K_DECL_INLINE + * Declare an inline function. + * @param type The return type. + * @remark Don't use on (class) methods. + */ +#define K_DECL_INLINE(type) K_INLINE type + + +/** Get the minimum of two values. */ +#define K_MIN(a, b) ( (a) <= (b) ? (a) : (b) ) +/** Get the maximum of two values. */ +#define K_MAX(a, b) ( (a) >= (b) ? (a) : (b) ) +/** Calculate the offset of a structure member. */ +#define K_OFFSETOF(strct, memb) ( (KSIZE)( &((strct *)0)->memb ) ) +/** Align a size_t value. */ +#define K_ALIGN_Z(val, align) ( ((val) + ((align) - 1)) & ~(KSIZE)((align) - 1) ) +/** Align a void * value. */ +#define K_ALIGN_P(pv, align) ( (void *)( ((KUPTR)(pv) + ((align) - 1)) & ~(KUPTR)((align) - 1) ) ) +/** Number of elements in an array. */ +#define K_ELEMENTS(a) ( sizeof(a) / sizeof((a)[0]) ) +/** Checks if the specified pointer is a valid address or not. */ +#define K_VALID_PTR(ptr) ( (KUPTR)(ptr) + 0x1000U >= 0x2000U ) +/** Makes a 32-bit bit mask. */ +#define K_BIT32(bit) ( KU32_C(1) << (bit)) +/** Makes a 64-bit bit mask. */ +#define K_BIT64(bit) ( KU64_C(1) << (bit)) +/** Shuts up unused parameter and unused variable warnings. */ +#define K_NOREF(var) ( (void)(var) ) + + +/** @name Parameter validation macros + * @{ */ + +/** Return/Crash validation of a string argument. */ +#define K_VALIDATE_STRING(str) \ + do { \ + if (!K_VALID_PTR(str)) \ + return KERR_INVALID_POINTER; \ + kHlpStrLen(str); \ + } while (0) + +/** Return/Crash validation of an optional string argument. */ +#define K_VALIDATE_OPTIONAL_STRING(str) \ + do { \ + if (str) \ + K_VALIDATE_STRING(str); \ + } while (0) + +/** Return/Crash validation of an output buffer. */ +#define K_VALIDATE_BUFFER(buf, cb) \ + do { \ + if (!K_VALID_PTR(buf)) \ + return KERR_INVALID_POINTER; \ + if ((cb) != 0) \ + { \ + KU8 __b; \ + KU8 volatile *__pb = (KU8 volatile *)(buf); \ + KSIZE __cbPage1 = 0x1000 - ((KUPTR)(__pb) & 0xfff); /* ASSUMES page size! */ \ + __b = *__pb; *__pb = 0xff; *__pb = __b; \ + if ((cb) > __cbPage1) \ + { \ + KSIZE __cb = (cb) - __cbPage1; \ + __pb -= __cbPage1; \ + for (;;) \ + { \ + __b = *__pb; *__pb = 0xff; *__pb = __b; \ + if (__cb < 0x1000) \ + break; \ + __pb += 0x1000; \ + __cb -= 0x1000; \ + } \ + } \ + } \ + else \ + return KERR_INVALID_PARAMETER; \ + } while (0) + +/** Return/Crash validation of an optional output buffer. */ +#define K_VALIDATE_OPTIONAL_BUFFER(buf, cb) \ + do { \ + if ((buf) && (cb) != 0) \ + K_VALIDATE_BUFFER(buf, cb); \ + } while (0) + +/** Return validation of an enum argument. */ +#define K_VALIDATE_ENUM(arg, enumname) \ + do { \ + if ((arg) <= enumname##_INVALID || (arg) >= enumname##_END) \ + return KERR_INVALID_PARAMETER; \ + } while (0) + +/** Return validation of a flags argument. */ +#define K_VALIDATE_FLAGS(arg, AllowedMask) \ + do { \ + if ((arg) & ~(AllowedMask)) \ + return KERR_INVALID_PARAMETER; \ + } while (0) + +/** @} */ + +/** @def NULL + * The nil pointer value. */ +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((void *)0) +# endif +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kErr.h b/src/lib/kStuff/include/k/kErr.h new file mode 100644 index 0000000..f183ef4 --- /dev/null +++ b/src/lib/kStuff/include/k/kErr.h @@ -0,0 +1,68 @@ +/* $Id: kErr.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kErr - Status Code API. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kErr_h___ +#define ___k_kErr_h___ + +/** @defgroup grp_kErr kErr - Status Code API + * @{ + */ + +/** @def KERR_DECL + * Declares a kRdr function according to build context. + * @param type The return type. + */ +#if defined(KERR_BUILDING_DYNAMIC) +# define KERR_DECL(type) K_DECL_EXPORT(type) +#elif defined(KRDR_BUILT_DYNAMIC) +# define KERR_DECL(type) K_DECL_IMPORT(type) +#else +# define KERR_DECL(type) type +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +KERR_DECL(const char *) kErrName(int rc); +KERR_DECL(int) kErrFromErrno(int); +KERR_DECL(int) kErrFromOS2(unsigned long rcOs2); +KERR_DECL(int) kErrFromNtStatus(long rcNtStatus); +KERR_DECL(int) kErrFromMach(int rcMach); +KERR_DECL(int) kErrFromDarwin(int rcDarwin); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kErrors.h b/src/lib/kStuff/include/k/kErrors.h new file mode 100644 index 0000000..be179ce --- /dev/null +++ b/src/lib/kStuff/include/k/kErrors.h @@ -0,0 +1,327 @@ +/* $Id: kErrors.h 58 2013-10-12 20:18:21Z bird $ */ +/** @file + * kErrors - Status Codes. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kErrors_h___ +#define ___k_kErrors_h___ + +/** @defgroup grp_kErrors Status Codes. + * @{ + */ +/** The base of the kErrors status codes. */ +#define KERR_BASE 42000 + +/** @name General + * @{ + */ +/** The base of the general status codes. */ +#define KERR_GENERAL_BASE (KERR_BASE) +/** Generic error. */ +#define KERR_GENERAL_FAILURE (KERR_GENERAL_BASE + 1) +/** Out of memory. */ +#define KERR_NO_MEMORY (KERR_GENERAL_BASE + 2) +/** Hit some unimplemented functionality - feel free to implement it :-) . */ +#define KERR_NOT_IMPLEMENTED (KERR_GENERAL_BASE + 3) +/** An environment variable wasn't found. */ +#define KERR_ENVVAR_NOT_FOUND (KERR_GENERAL_BASE + 4) +/** Buffer overflow. */ +#define KERR_BUFFER_OVERFLOW (KERR_GENERAL_BASE + 5) +/** @}*/ + +/** @name Input Validation + * @{ + */ +/** The base of the input validation status codes. */ +#define KERR_INPUT_BASE (KERR_GENERAL_BASE + 6) +/** An API was given an invalid parameter. */ +#define KERR_INVALID_PARAMETER (KERR_INPUT_BASE + 0) +/** A pointer argument is not valid. */ +#define KERR_INVALID_POINTER (KERR_INPUT_BASE + 1) +/** A handle argument is not valid. */ +#define KERR_INVALID_HANDLE (KERR_INPUT_BASE + 2) +/** An offset argument is not valid. */ +#define KERR_INVALID_OFFSET (KERR_INPUT_BASE + 3) +/** A size argument is not valid. */ +#define KERR_INVALID_SIZE (KERR_INPUT_BASE + 4) +/** A range argument is not valid. */ +#define KERR_INVALID_RANGE (KERR_INPUT_BASE + 5) +/** A parameter is out of range. */ +#define KERR_OUT_OF_RANGE (KERR_INPUT_BASE + 6) +/** @} */ + +/** @name File System and I/O + * @{ + */ +/** The base of the file system and I/O status cdoes. */ +#define KERR_FILE_SYSTEM_AND_IO_BASE (KERR_INPUT_BASE + 7) +/** The specified file was not found. */ +#define KERR_FILE_NOT_FOUND (KERR_FILE_SYSTEM_AND_IO_BASE + 0) +/** End of file. */ +#define KERR_EOF (KERR_FILE_SYSTEM_AND_IO_BASE + 1) +/** @} */ + +/** @name kDbg Specific + * @{ + */ +/** The base of the kDbg specific status codes. */ +#define KDBG_ERR_BASE (KERR_FILE_SYSTEM_AND_IO_BASE + 2) +/** The (module) format isn't known to use. */ +#define KDBG_ERR_UNKOWN_FORMAT (KDBG_ERR_BASE + 0) +/** The (module) format isn't supported by this kDbg build. */ +#define KDBG_ERR_FORMAT_NOT_SUPPORTED (KDBG_ERR_BASE + 1) +/** The (module) format isn't supported by this kDbg build. */ +#define KDBG_ERR_BAD_EXE_FORMAT (KDBG_ERR_BASE + 2) +/** A specified address or an address found in the debug info is invalid. */ +#define KDBG_ERR_INVALID_ADDRESS (KDBG_ERR_BASE + 3) +/** The dbghelp.dll is too old or something like that. */ +#define KDBG_ERR_DBGHLP_VERSION_MISMATCH (KDBG_ERR_BASE + 4) +/** @} */ + +/** @name kRdr Specific + * @{ + */ +/** the base of the kRdr specific status codes. */ +#define KRDR_ERR_BASE (KDBG_ERR_BASE + 5) +/** The file reader can't take more concurrent mappings. */ +#define KRDR_ERR_TOO_MANY_MAPPINGS (KRDR_ERR_BASE + 0) +/** The pRdr instance passed to a kRdrBuf* API isn't a buffered instance. */ +#define KRDR_ERR_NOT_BUFFERED_RDR (KRDR_ERR_BASE + 1) +/** The line is too long to fit in the buffer passed to kRdrBufLine or kRdrBufLineEx. */ +#define KRDR_ERR_LINE_TOO_LONG (KRDR_ERR_BASE + 2) +/** @} */ + +/** @name kLdr Specific + * @{ + */ +/** The base of the kLdr specific status codes. */ +#define KLDR_ERR_BASE (KRDR_ERR_BASE + 3) + +/** The image format is unknown. */ +#define KLDR_ERR_UNKNOWN_FORMAT (KLDR_ERR_BASE + 0) +/** The MZ image format isn't supported by this kLdr build. */ +#define KLDR_ERR_MZ_NOT_SUPPORTED (KLDR_ERR_BASE + 1) +/** The NE image format isn't supported by this kLdr build. */ +#define KLDR_ERR_NE_NOT_SUPPORTED (KLDR_ERR_BASE + 2) +/** The LX image format isn't supported by this kLdr build. */ +#define KLDR_ERR_LX_NOT_SUPPORTED (KLDR_ERR_BASE + 3) +/** The LE image format isn't supported by this kLdr build. */ +#define KLDR_ERR_LE_NOT_SUPPORTED (KLDR_ERR_BASE + 4) +/** The PE image format isn't supported by this kLdr build. */ +#define KLDR_ERR_PE_NOT_SUPPORTED (KLDR_ERR_BASE + 5) +/** The ELF image format isn't supported by this kLdr build. */ +#define KLDR_ERR_ELF_NOT_SUPPORTED (KLDR_ERR_BASE + 6) +/** The mach-o image format isn't supported by this kLdr build. */ +#define KLDR_ERR_MACHO_NOT_SUPPORTED (KLDR_ERR_BASE + 7) +/** The FAT image format isn't supported by this kLdr build or + * a direct open was attempt without going thru the FAT file provider. + * FAT images are also known as Universal Binaries. */ +#define KLDR_ERR_FAT_NOT_SUPPORTED (KLDR_ERR_BASE + 8) +/** The a.out image format isn't supported by this kLdr build. */ +#define KLDR_ERR_AOUT_NOT_SUPPORTED (KLDR_ERR_BASE + 9) + +/** The module wasn't loaded dynamically. */ +#define KLDR_ERR_NOT_LOADED_DYNAMICALLY (KLDR_ERR_BASE + 10) +/** The module wasn't found. */ +#define KLDR_ERR_MODULE_NOT_FOUND (KLDR_ERR_BASE + 11) +/** A prerequisit module wasn't found. */ +#define KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND (KLDR_ERR_BASE + 12) +/** The module is being terminated and can therefore not be loaded. */ +#define KLDR_ERR_MODULE_TERMINATING (KLDR_ERR_BASE + 13) +/** A prerequisit module is being terminated and can therefore not be loaded. */ +#define KLDR_ERR_PREREQUISITE_MODULE_TERMINATING (KLDR_ERR_BASE + 14) +/** The module initialization failed. */ +#define KLDR_ERR_MODULE_INIT_FAILED (KLDR_ERR_BASE + 15) +/** The initialization of a prerequisite module failed. */ +#define KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED (KLDR_ERR_BASE + 16) +/** The module has already failed initialization and can't be attempted reloaded until + * after we've finished garbage collection. */ +#define KLDR_ERR_MODULE_INIT_FAILED_ALREADY (KLDR_ERR_BASE + 17) +/** A prerequisite module has already failed initialization and can't be attempted + * reloaded until after we've finished garbage collection. */ +#define KLDR_ERR_PREREQUISITE_MODULE_INIT_FAILED_ALREADY (KLDR_ERR_BASE + 18) +/** Prerequisite recursed too deeply. */ +#define KLDR_ERR_PREREQUISITE_RECURSED_TOO_DEEPLY (KLDR_ERR_BASE + 19) +/** Failed to allocate the main stack. */ +#define KLDR_ERR_MAIN_STACK_ALLOC_FAILED (KLDR_ERR_BASE + 20) +/** Symbol not found. */ +#define KLDR_ERR_SYMBOL_NOT_FOUND (KLDR_ERR_BASE + 21) +/** A forward symbol was encountered but the caller didn't provide any means to resolve it. */ +#define KLDR_ERR_FORWARDER_SYMBOL (KLDR_ERR_BASE + 22) +/** Encountered a bad fixup. */ +#define KLDR_ERR_BAD_FIXUP (KLDR_ERR_BASE + 23) +/** The import ordinal was out of bounds. */ +#define KLDR_ERR_IMPORT_ORDINAL_OUT_OF_BOUNDS (KLDR_ERR_BASE + 24) +/** A forwarder chain was too long. */ +#define KLDR_ERR_TOO_LONG_FORWARDER_CHAIN (KLDR_ERR_BASE + 25) +/** The module has no debug info. */ +#define KLDR_ERR_NO_DEBUG_INFO (KLDR_ERR_BASE + 26) +/** The module is already mapped. + * kLdrModMap() can only be called once (without kLdrModUnmap() in between). */ +#define KLDR_ERR_ALREADY_MAPPED (KLDR_ERR_BASE + 27) +/** The module was not mapped. + * kLdrModUnmap() should not called without being preceeded by a kLdrModMap(). */ +#define KLDR_ERR_NOT_MAPPED (KLDR_ERR_BASE + 28) +/** Couldn't fit the address value into the field. Typically a relocation kind of error. */ +#define KLDR_ERR_ADDRESS_OVERFLOW (KLDR_ERR_BASE + 29) +/** Couldn't fit a calculated size value into the native size type of the host. */ +#define KLDR_ERR_SIZE_OVERFLOW (KLDR_ERR_BASE + 30) +/** Thread attach failed. */ +#define KLDR_ERR_THREAD_ATTACH_FAILED (KLDR_ERR_BASE + 31) +/** The module wasn't a DLL or object file. */ +#define KLDR_ERR_NOT_DLL (KLDR_ERR_BASE + 32) +/** The module wasn't an EXE. */ +#define KLDR_ERR_NOT_EXE (KLDR_ERR_BASE + 33) +/** Not implemented yet. */ +#define KLDR_ERR_TODO (KLDR_ERR_BASE + 34) +/** No image matching the requested CPU. */ +#define KLDR_ERR_CPU_ARCH_MISMATCH (KLDR_ERR_BASE + 35) +/** Invalid FAT image header. */ +#define KLDR_ERR_FAT_INVALID (KLDR_ERR_BASE + 36) +/** Unsupported CPU subtype found in a FAT entry. */ +#define KLDR_ERR_FAT_UNSUPPORTED_CPU_SUBTYPE (KLDR_ERR_BASE + 37) +/** The image has no UUID. */ +#define KLDR_ERR_NO_IMAGE_UUID (KLDR_ERR_BASE + 38) +/** Duplicate segment name. */ +#define KLDR_ERR_DUPLICATE_SEGMENT_NAME (KLDR_ERR_BASE + 39) +/** @} */ + +/** @name kLdrModPE Specific + * @{ + */ +/** The base of the kLdrModPE specific status codes. */ +#define KLDR_ERR_PE_BASE (KLDR_ERR_BASE + 40) +/** The machine isn't supported by the interpreter. */ +#define KLDR_ERR_PE_UNSUPPORTED_MACHINE (KLDR_ERR_PE_BASE + 0) +/** The file handler isn't valid. */ +#define KLDR_ERR_PE_BAD_FILE_HEADER (KLDR_ERR_PE_BASE + 1) +/** The the optional headers isn't valid. */ +#define KLDR_ERR_PE_BAD_OPTIONAL_HEADER (KLDR_ERR_PE_BASE + 2) +/** One of the section headers aren't valid. */ +#define KLDR_ERR_PE_BAD_SECTION_HEADER (KLDR_ERR_PE_BASE + 3) +/** Bad forwarder entry. */ +#define KLDR_ERR_PE_BAD_FORWARDER (KLDR_ERR_PE_BASE + 4) +/** Forwarder module not found in the import descriptor table. */ +#define KLDR_ERR_PE_FORWARDER_IMPORT_NOT_FOUND (KLDR_ERR_PE_BASE + 5) +/** Bad PE fixups. */ +#define KLDR_ERR_PE_BAD_FIXUP (KLDR_ERR_PE_BASE + 6) +/** Bad PE import (thunk). */ +#define KLDR_ERR_PE_BAD_IMPORT (KLDR_ERR_PE_BASE + 7) +/** @} */ + +/** @name kLdrModLX Specific + * @{ + */ +/** The base of the kLdrModLX specific status codes. */ +#define KLDR_ERR_LX_BASE (KLDR_ERR_PE_BASE + 8) +/** validation of LX header failed. */ +#define KLDR_ERR_LX_BAD_HEADER (KLDR_ERR_LX_BASE + 0) +/** validation of the loader section (in the LX header) failed. */ +#define KLDR_ERR_LX_BAD_LOADER_SECTION (KLDR_ERR_LX_BASE + 1) +/** validation of the fixup section (in the LX header) failed. */ +#define KLDR_ERR_LX_BAD_FIXUP_SECTION (KLDR_ERR_LX_BASE + 2) +/** validation of the LX object table failed. */ +#define KLDR_ERR_LX_BAD_OBJECT_TABLE (KLDR_ERR_LX_BASE + 3) +/** A bad page map entry was encountered. */ +#define KLDR_ERR_LX_BAD_PAGE_MAP (KLDR_ERR_LX_BASE + 4) +/** Bad iterdata (EXEPACK) data. */ +#define KLDR_ERR_LX_BAD_ITERDATA (KLDR_ERR_LX_BASE + 5) +/** Bad iterdata2 (EXEPACK2) data. */ +#define KLDR_ERR_LX_BAD_ITERDATA2 (KLDR_ERR_LX_BASE + 6) +/** Bad bundle data. */ +#define KLDR_ERR_LX_BAD_BUNDLE (KLDR_ERR_LX_BASE + 7) +/** No soname. */ +#define KLDR_ERR_LX_NO_SONAME (KLDR_ERR_LX_BASE + 8) +/** Bad soname. */ +#define KLDR_ERR_LX_BAD_SONAME (KLDR_ERR_LX_BASE + 9) +/** Bad forwarder entry. */ +#define KLDR_ERR_LX_BAD_FORWARDER (KLDR_ERR_LX_BASE + 10) +/** internal fixup chain isn't implemented yet. */ +#define KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED (KLDR_ERR_LX_BASE + 11) +/** @} */ + +/** @name kLdrModMachO Specific + * @{ + */ +/** The base of the kLdrModMachO specific status codes. */ +#define KLDR_ERR_MACHO_BASE (KLDR_ERR_LX_BASE + 12) +/** Only native endian Mach-O files are supported. */ +#define KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED (KLDR_ERR_MACHO_BASE + 0) +/** The Mach-O header is bad or contains new and unsupported features. */ +#define KLDR_ERR_MACHO_BAD_HEADER (KLDR_ERR_MACHO_BASE + 1) +/** The file type isn't supported. */ +#define KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE (KLDR_ERR_MACHO_BASE + 2) +/** The machine (cputype / cpusubtype combination) isn't supported. */ +#define KLDR_ERR_MACHO_UNSUPPORTED_MACHINE (KLDR_ERR_MACHO_BASE + 3) +/** Bad load command(s). */ +#define KLDR_ERR_MACHO_BAD_LOAD_COMMAND (KLDR_ERR_MACHO_BASE + 4) +/** Encountered an unknown load command.*/ +#define KLDR_ERR_MACHO_UNKNOWN_LOAD_COMMAND (KLDR_ERR_MACHO_BASE + 5) +/** Encountered a load command that's not implemented.*/ +#define KLDR_ERR_MACHO_UNSUPPORTED_LOAD_COMMAND (KLDR_ERR_MACHO_BASE + 6) +/** Bad section. */ +#define KLDR_ERR_MACHO_BAD_SECTION (KLDR_ERR_MACHO_BASE + 7) +/** Encountered a section type that's not implemented.*/ +#define KLDR_ERR_MACHO_UNSUPPORTED_SECTION (KLDR_ERR_MACHO_BASE + 8) +/** Encountered a init function section. */ +#define KLDR_ERR_MACHO_UNSUPPORTED_INIT_SECTION (KLDR_ERR_MACHO_BASE + 9) +/** Encountered a term function section. */ +#define KLDR_ERR_MACHO_UNSUPPORTED_TERM_SECTION (KLDR_ERR_MACHO_BASE + 10) +/** Encountered a section type that's not known to the loader. (probably invalid) */ +#define KLDR_ERR_MACHO_UNKNOWN_SECTION (KLDR_ERR_MACHO_BASE + 11) +/** The sections aren't ordered by segment as expected by the loader. */ +#define KLDR_ERR_MACHO_BAD_SECTION_ORDER (KLDR_ERR_MACHO_BASE + 12) +/** The image is 32-bit and contains 64-bit load commands or vise versa. */ +#define KLDR_ERR_MACHO_BIT_MIX (KLDR_ERR_MACHO_BASE + 13) +/** Bad MH_OBJECT file. */ +#define KLDR_ERR_MACHO_BAD_OBJECT_FILE (KLDR_ERR_MACHO_BASE + 14) +/** Bad symbol table entry. */ +#define KLDR_ERR_MACHO_BAD_SYMBOL (KLDR_ERR_MACHO_BASE + 15) +/** Unsupported fixup type. */ +#define KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE (KLDR_ERR_MACHO_BASE + 16) +/** Both debug and non-debug sections in segment. */ +#define KLDR_ERR_MACHO_MIXED_DEBUG_SECTION_FLAGS (KLDR_ERR_MACHO_BASE + 17) +/** The segment bits are non-contiguous in the file. */ +#define KLDR_ERR_MACHO_NON_CONT_SEG_BITS (KLDR_ERR_MACHO_BASE + 18) +/** @} */ + +/** @name kCpu Specific + * @{ + */ +/** The base of the kCpu specific status codes. */ +#define KCPU_ERR_BASE (KLDR_ERR_MACHO_BASE + 19) +/** The specified ARCH+CPU pairs aren't compatible. */ +#define KCPU_ERR_ARCH_CPU_NOT_COMPATIBLE (KCPU_ERR_BASE + 0) +/** @} */ + +/** End of the valid status codes. */ +#define KERR_END (KCPU_ERR_BASE + 1) +/** @}*/ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlp.h b/src/lib/kStuff/include/k/kHlp.h new file mode 100644 index 0000000..7e83b85 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlp.h @@ -0,0 +1,53 @@ +/* $Id: kHlp.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlp - Helpers, All Of Them. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlp_h___ +#define ___k_kHlp_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kErrors.h> +#include <k/kHlpAlloc.h> +#include <k/kHlpAssert.h> +#include <k/kHlpEnv.h> +#include <k/kHlpPath.h> +#include <k/kHlpProcess.h> +#include <k/kHlpSem.h> +#include <k/kHlpString.h> +#include <k/kHlpThread.h> + +/** @defgroup grp_kHlp kHlp - Helper Functions + * @{ */ + +/** @} */ + +#endif + + diff --git a/src/lib/kStuff/include/k/kHlpAlloc.h b/src/lib/kStuff/include/k/kHlpAlloc.h new file mode 100644 index 0000000..99ae8b6 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpAlloc.h @@ -0,0 +1,78 @@ +/* $Id: kHlpAlloc.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpAlloc - Memory Allocation. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpAlloc_h___ +#define ___k_kHlpAlloc_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpAlloc kHlpAlloc - Memory Allocation + * @addtogroup grp_kHlp + * @{*/ + +/** @def kHlpAllocA + * The alloca() wrapper. */ +#ifdef __GNUC__ +# define kHlpAllocA(a) __builtin_alloca(a) +#elif defined(_MSC_VER) +# include <malloc.h> +# define kHlpAllocA(a) alloca(a) +#else +# error "Port Me." +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +KHLP_DECL(void *) kHlpAlloc(KSIZE cb); +KHLP_DECL(void *) kHlpAllocZ(KSIZE cb); +KHLP_DECL(void *) kHlpDup(const void *pv, KSIZE cb); +KHLP_DECL(char *) kHlpStrDup(const char *psz); +KHLP_DECL(void *) kHlpRealloc(void *pv, KSIZE cb); +KHLP_DECL(void) kHlpFree(void *pv); + +KHLP_DECL(int) kHlpPageAlloc(void **ppv, KSIZE cb, KPROT enmProt, KBOOL fFixed); +KHLP_DECL(int) kHlpPageProtect(void *pv, KSIZE cb, KPROT enmProt); +KHLP_DECL(int) kHlpPageFree(void *pv, KSIZE cb); + +KHLP_DECL(int) kHlpHeapInit(void); +KHLP_DECL(void) kHlpHeapTerm(void); +KHLP_DECL(void) kHlpHeapDonate(void *pv, KSIZE cb); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpAssert.h b/src/lib/kStuff/include/k/kHlpAssert.h new file mode 100644 index 0000000..45105d1 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpAssert.h @@ -0,0 +1,369 @@ +/* $Id: kHlpAssert.h 119 2021-12-19 13:01:47Z bird $ */ +/** @file + * kHlpAssert - Assertion Macros. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___kHlpAssert_h___ +#define ___kHlpAssert_h___ + +#include <k/kHlpDefs.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup grp_kHlpAssert - Assertion Macros + * @addtogroup grp_kHlp + * @{ */ + +/** @def K_STRICT + * Assertions are enabled when K_STRICT is \#defined. */ + +/** @def kHlpAssertBreakpoint + * Emits a breakpoint instruction or somehow triggers a debugger breakpoint. + */ +#ifdef _MSC_VER +# define kHlpAssertBreakpoint() do { __debugbreak(); } while (0) +#elif defined(__GNUC__) && K_OS == K_OS_SOLARIS && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32) +# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int $3"); } while (0) +#elif defined(__GNUC__) && (K_ARCH == K_ARCH_AMD64 || K_ARCH == K_ARCH_X86_32 || K_ARCH == K_ARCH_X86_16) +# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("int3"); } while (0) +#elif defined(__GNUC__) && (K_ARCH == K_ARCH_ARM_64 || K_ARCH == K_ARCH_ARM_32) /* probably not supported by older ARM CPUs */ +# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("brk #0x1"); } while (0) +#elif defined(__GNUC__) && (K_ARCH == K_ARCH_SPARC_32) +# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("unimp 0"); } while (0) /*??*/ +#elif defined(__GNUC__) && (K_ARCH == K_ARCH_SPARC_64) +# define kHlpAssertBreakpoint() do { __asm__ __volatile__ ("illtrap 0"); } while (0) /*??*/ +#else +# error "Port Me" +#endif + +/** @def K_FUNCTION + * Undecorated function name macro expanded by the compiler. + */ +#if defined(__GNUC__) +# define K_FUNCTION __func__ +#else +# define K_FUNCTION __FUNCTION__ +#endif + +#ifdef K_STRICT + +# define kHlpAssert(expr) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + } \ + } while (0) + +# define kHlpAssertStmt(expr, stmt) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + } \ + } while (0) + +# define kHlpAssertReturn(expr, rcRet) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + return (rcRet); \ + } \ + } while (0) + +# define kHlpAssertStmtReturn(expr, stmt, rcRet) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + return (rcRet); \ + } \ + } while (0) + +# define kHlpAssertReturnVoid(expr) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + return; \ + } \ + } while (0) + +# define kHlpAssertStmtReturnVoid(expr, stmt) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + return; \ + } \ + } while (0) + +# define kHlpAssertMsg(expr, msg) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + } \ + } while (0) + +# define kHlpAssertMsgStmt(expr, msg, stmt) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + } \ + } while (0) + +# define kHlpAssertMsgReturn(expr, msg, rcRet) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + return (rcRet); \ + } \ + } while (0) + +# define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + return (rcRet); \ + } \ + } while (0) + +# define kHlpAssertMsgReturnVoid(expr, msg) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + return; \ + } \ + } while (0) + +# define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt) \ + do { \ + if (!(expr)) \ + { \ + kHlpAssertMsg1(#expr, __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + return; \ + } \ + } while (0) + +/* Same as above, only no expression. */ + +# define kHlpAssertFailed() \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + } while (0) + +# define kHlpAssertFailedStmt(stmt) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + } while (0) + +# define kHlpAssertFailedReturn(rcRet) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + return (rcRet); \ + } while (0) + +# define kHlpAssertFailedStmtReturn(stmt, rcRet) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + return (rcRet); \ + } while (0) + +# define kHlpAssertFailedReturnVoid() \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + return; \ + } while (0) + +# define kHlpAssertFailedStmtReturnVoid(stmt) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertBreakpoint(); \ + stmt; \ + return; \ + } while (0) + +# define kHlpAssertMsgFailed(msg) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + } while (0) + +# define kHlpAssertMsgFailedStmt(msg, stmt) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + } while (0) + +# define kHlpAssertMsgFailedReturn(msg, rcRet) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + return (rcRet); \ + } while (0) + +# define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + return (rcRet); \ + } while (0) + +# define kHlpAssertMsgFailedReturnVoid(msg) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + return; \ + } while (0) + +# define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt) \ + do { \ + kHlpAssertMsg1("failed", __FILE__, __LINE__, K_FUNCTION); \ + kHlpAssertMsg2 msg; \ + kHlpAssertBreakpoint(); \ + stmt; \ + return; \ + } while (0) + + +#else /* !K_STRICT */ + +# define kHlpAssert(expr) do { } while (0) +# define kHlpAssertStmt(expr, stmt) do { if (!(expr)) { stmt; } } while (0) +# define kHlpAssertReturn(expr, rcRet) do { if (!(expr)) return (rcRet); } while (0) +# define kHlpAssertStmtReturn(expr, stmt, rcRet) do { if (!(expr)) { stmt; return (rcRet); } } while (0) +# define kHlpAssertReturnVoid(expr) do { if (!(expr)) return; } while (0) +# define kHlpAssertStmtReturnVoid(expr, stmt) do { if (!(expr)) { stmt; return; } } while (0) +# define kHlpAssertMsg(expr, msg) do { } while (0) +# define kHlpAssertMsgStmt(expr, msg, stmt) do { if (!(expr)) { stmt; } } while (0) +# define kHlpAssertMsgReturn(expr, msg, rcRet) do { if (!(expr)) return (rcRet); } while (0) +# define kHlpAssertMsgStmtReturn(expr, msg, stmt, rcRet) do { if (!(expr)) { stmt; return (rcRet); } } while (0) +# define kHlpAssertMsgReturnVoid(expr, msg) do { if (!(expr)) return; } while (0) +# define kHlpAssertMsgStmtReturnVoid(expr, msg, stmt) do { if (!(expr)) { stmt; return; } } while (0) +/* Same as above, only no expression: */ +# define kHlpAssertFailed() do { } while (0) +# define kHlpAssertFailedStmt(stmt) do { stmt; } while (0) +# define kHlpAssertFailedReturn(rcRet) do { return (rcRet); } while (0) +# define kHlpAssertFailedStmtReturn(stmt, rcRet) do { stmt; return (rcRet); } while (0) +# define kHlpAssertFailedReturnVoid() do { return; } while (0) +# define kHlpAssertFailedStmtReturnVoid(stmt) do { stmt; return; } while (0) +# define kHlpAssertMsgFailed(msg) do { } while (0) +# define kHlpAssertMsgFailedStmt(msg, stmt) do { stmt; } while (0) +# define kHlpAssertMsgFailedReturn(msg, rcRet) do { return (rcRet); } while (0) +# define kHlpAssertMsgFailedStmtReturn(msg, stmt, rcRet) do { { stmt; return (rcRet); } } while (0) +# define kHlpAssertMsgFailedReturnVoid(msg) do { return; } while (0) +# define kHlpAssertMsgFailedStmtReturnVoid(msg, stmt) do { stmt; return; } while (0) + +#endif /* !K_STRICT */ + +#define kHlpAssertPtr(ptr) kHlpAssertMsg(K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr))) +#define kHlpAssertPtrReturn(ptr, rcRet) kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet)) +#define kHlpAssertPtrReturn(ptr, rcRet) kHlpAssertMsgReturn(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet)) +#define kHlpAssertPtrReturnVoid(ptr) kHlpAssertMsgReturnVoid(K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet))) +#define kHlpAssertPtrNull(ptr) kHlpAssertMsg(!(ptr) || K_VALID_PTR(ptr), ("%s = %p\n", #ptr, (ptr))) +#define kHlpAssertPtrNullReturn(ptr, rcRet) kHlpAssertMsgReturn(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet)), (rcRet)) +#define kHlpAssertPtrNullReturnVoid(ptr) kHlpAssertMsgReturnVoid(!(ptr) || K_VALID_PTR(ptr), ("%s = %p -> %d\n", #ptr, (ptr), (rcRet))) +#define kHlpAssertRC(rc) kHlpAssertMsg((rc) == 0, ("%s = %d\n", #rc, (rc))) +#define kHlpAssertRCReturn(rc, rcRet) kHlpAssertMsgReturn((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet)), (rcRet)) +#define kHlpAssertRCReturnVoid(rc) kHlpAssertMsgReturnVoid((rc) == 0, ("%s = %d -> %d\n", #rc, (rc), (rcRet))) + + +/** + * Helper function that displays the first part of the assertion message. + * + * @param pszExpr The expression. + * @param pszFile The file name. + * @param iLine The line number is the file. + * @param pszFunction The function name. + * @internal + */ +KHLP_DECL(void) kHlpAssertMsg1(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction); + +/** + * Helper function that displays custom assert message. + * + * @param pszFormat Format string that get passed to vprintf. + * @param ... Format arguments. + * @internal + */ +KHLP_DECL(void) kHlpAssertMsg2(const char *pszFormat, ...); + + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/kStuff/include/k/kHlpDefs.h b/src/lib/kStuff/include/k/kHlpDefs.h new file mode 100644 index 0000000..bcda10a --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpDefs.h @@ -0,0 +1,55 @@ +/* $Id: kHlpDefs.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpDefs - Helper Definitions. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpDefs_h___ +#define ___k_kHlpDefs_h___ + +#include <k/kDefs.h> + +/** @defgroup grp_kHlpDefs - Definitions + * @addtogroup grp_kHlp + * @{ */ + +/** @def KHLP_DECL + * Declares a kHlp function according to build context. + * @param type The return type. + */ +#if defined(KHLP_BUILDING_DYNAMIC) +# define KHLP_DECL(type) K_DECL_EXPORT(type) +#elif defined(KHLP_BUILT_DYNAMIC) +# define KHLP_DECL(type) K_DECL_IMPORT(type) +#else +# define KHLP_DECL(type) type +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpEnv.h b/src/lib/kStuff/include/k/kHlpEnv.h new file mode 100644 index 0000000..95c2bda --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpEnv.h @@ -0,0 +1,55 @@ +/* $Id: kHlpEnv.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpEnv - Environment Manipulation. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpEnv_h___ +#define ___k_kHlpEnv_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpEnv kHlpEnv - Environment Manipulation + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +KHLP_DECL(int) kHlpGetEnv(const char *pszVar, char *pszVal, KSIZE cchVal); +KHLP_DECL(int) kHlpGetEnvUZ(const char *pszVar, KSIZE *pcb); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpPath.h b/src/lib/kStuff/include/k/kHlpPath.h new file mode 100644 index 0000000..c9d6ce5 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpPath.h @@ -0,0 +1,57 @@ +/* $Id: kHlpPath.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpPath - Path Manipulation. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpPath_h___ +#define ___k_kHlpPath_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpPath kHlpPath - Path Manipulation + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +KHLP_DECL(char *) kHlpGetFilename(const char *pszFilename); +KHLP_DECL(char *) kHlpGetSuff(const char *pszFilename); +KHLP_DECL(char *) kHlpGetExt(const char *pszFilename); +KHLP_DECL(int) kHlpIsFilenameOnly(const char *pszFilename); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpProcess.h b/src/lib/kStuff/include/k/kHlpProcess.h new file mode 100644 index 0000000..c637545 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpProcess.h @@ -0,0 +1,54 @@ +/* $Id: kHlpProcess.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpProcess - Process Management. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpProcess_h___ +#define ___k_kHlpProcess_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpProcess kHlpProcess - Process Management + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +KHLP_DECL(void) kHlpExit(int rc); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpSem.h b/src/lib/kStuff/include/k/kHlpSem.h new file mode 100644 index 0000000..72c6407 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpSem.h @@ -0,0 +1,54 @@ +/* $Id: kHlpSem.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpSem - Semaphores. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpSem_h___ +#define ___k_kHlpSem_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpSem kHlpSem - Semaphore + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + + diff --git a/src/lib/kStuff/include/k/kHlpString.h b/src/lib/kStuff/include/k/kHlpString.h new file mode 100644 index 0000000..23da03d --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpString.h @@ -0,0 +1,156 @@ +/* $Id: kHlpString.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpString - String And Memory Routines. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpString_h___ +#define ___k_kHlpString_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +#if 0 /* optimize / fix this later */ +#ifdef __GNUC__ +/** memchr */ +# define kHlpMemChr(a,b,c) __builtin_memchr(a,b,c) +/** memcmp */ +# define kHlpMemComp(a,b,c) __builtin_memcmp(a,b,c) +/** memcpy */ +# define kHlpMemCopy(a,b,c) __builtin_memcpy(a,b,c) +/** memset */ +# define kHlpMemSet(a,b,c) __builtin_memset(a,b,c) +/** strchr */ +# define kHlpStrChr(a, b) __builtin_strchr(a, b) +/** strcmp */ +# define kHlpStrComp(a, b) __builtin_strcmp(a, b) +/** strncmp */ +# define kHlpStrNComp(a,b,c) __builtin_strncmp(a, b, c) +/** strlen */ +# define kHlpStrLen(a) __builtin_strlen(a) + +#elif defined(_MSC_VER) +# pragma intrinsic(memcmp, memcpy, memset, strcmp, strlen) +/** memcmp */ +# define kHlpMemComp(a,b,c) memcmp(a,b,c) +/** memcpy */ +# define kHlpMemCopy(a,b,c) memcpy(a,b,c) +/** memset */ +# define kHlpMemSet(a,b,c) memset(a,b,c) +/** strcmp */ +# define kHlpStrComp(a, b) strcmp(a, b) +/** strlen */ +# define kHlpStrLen(a) strlen(a) +#else +# error "Port Me" +#endif +#endif /* disabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef kHlpMemChr +KHLP_DECL(void *) kHlpMemChr(const void *pv, int ch, KSIZE cb); +#endif +#ifndef kHlpMemComp +KHLP_DECL(int) kHlpMemComp(const void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemComp +KHLP_DECL(void *) kHlpMemPComp(const void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemCopy +KHLP_DECL(void *) kHlpMemCopy(void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemPCopy +KHLP_DECL(void *) kHlpMemPCopy(void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemMove +KHLP_DECL(void *) kHlpMemMove(void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemPMove +KHLP_DECL(void *) kHlpMemPMove(void *pv1, const void *pv2, KSIZE cb); +#endif +#ifndef kHlpMemSet +KHLP_DECL(void *) kHlpMemSet(void *pv1, int ch, KSIZE cb); +#endif +#ifndef kHlpMemPSet +KHLP_DECL(void *) kHlpMemPSet(void *pv1, int ch, KSIZE cb); +#endif +KHLP_DECL(int) kHlpMemICompAscii(const void *pv1, const void *pv2, KSIZE cb); + +#ifndef kHlpStrCat +KHLP_DECL(char *) kHlpStrCat(char *psz1, const char *psz2); +#endif +#ifndef kHlpStrPCat +KHLP_DECL(char *) kHlpStrPCat(char *psz1, const char *psz2); +#endif +#ifndef kHlpStrNCat +KHLP_DECL(char *) kHlpStrNCat(char *psz1, const char *psz2, KSIZE cb); +#endif +#ifndef kHlpStrPNCat +KHLP_DECL(char *) kHlpStrNPCat(char *psz1, const char *psz2, KSIZE cb); +#endif +#ifndef kHlpStrChr +KHLP_DECL(char *) kHlpStrChr(const char *psz, int ch); +#endif +#ifndef kHlpStrRChr +KHLP_DECL(char *) kHlpStrRChr(const char *psz, int ch); +#endif +#ifndef kHlpStrComp +KHLP_DECL(int) kHlpStrComp(const char *psz1, const char *psz2); +#endif +KHLP_DECL(char *) kHlpStrPComp(const char *psz1, const char *psz2); +#ifndef kHlpStrNComp +KHLP_DECL(int) kHlpStrNComp(const char *psz1, const char *psz2, KSIZE cch); +#endif +KHLP_DECL(char *) kHlpStrNPComp(const char *psz1, const char *psz2, KSIZE cch); +KHLP_DECL(int) kHlpStrICompAscii(const char *pv1, const char *pv2); +KHLP_DECL(char *) kHlpStrIPCompAscii(const char *pv1, const char *pv2); +KHLP_DECL(int) kHlpStrNICompAscii(const char *pv1, const char *pv2, KSIZE cch); +KHLP_DECL(char *) kHlpStrNIPCompAscii(const char *pv1, const char *pv2, KSIZE cch); +#ifndef kHlpStrCopy +KHLP_DECL(char *) kHlpStrCopy(char *psz1, const char *psz2); +#endif +#ifndef kHlpStrPCopy +KHLP_DECL(char *) kHlpStrPCopy(char *psz1, const char *psz2); +#endif +#ifndef kHlpStrLen +KHLP_DECL(KSIZE) kHlpStrLen(const char *psz1); +#endif +#ifndef kHlpStrNLen +KHLP_DECL(KSIZE) kHlpStrNLen(const char *psz, KSIZE cchMax); +#endif + +KHLP_DECL(char *) kHlpInt2Ascii(char *psz, KSIZE cch, long lVal, unsigned iBase); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/lib/kStuff/include/k/kHlpSys.h b/src/lib/kStuff/include/k/kHlpSys.h new file mode 100644 index 0000000..63aeaee --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpSys.h @@ -0,0 +1,79 @@ +/* $Id: kHlpSys.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpSys - System Call Prototypes. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpSys_h___ +#define ___k_kHlpSys_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpSys kHlpSys - System Call Prototypes + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* common unix stuff. */ +#if K_OS == K_OS_DARWIN \ + || K_OS == K_OS_FREEBSD \ + || K_OS == K_OS_LINUX \ + || K_OS == K_OS_NETBSD \ + || K_OS == K_OS_OPENBSD \ + || K_OS == K_OS_SOLARIS +KSSIZE kHlpSys_readlink(const char *pszPath, char *pszBuf, KSIZE cbBuf); +int kHlpSys_open(const char *filename, int flags, int mode); +int kHlpSys_close(int fd); +KFOFF kHlpSys_lseek(int fd, int whench, KFOFF off); +KSSIZE kHlpSys_read(int fd, void *pvBuf, KSIZE cbBuf); +KSSIZE kHlpSys_write(int fd, const void *pvBuf, KSIZE cbBuf); +void *kHlpSys_mmap(void *addr, KSIZE len, int prot, int flags, int fd, KI64 off); +int kHlpSys_mprotect(void *addr, KSIZE len, int prot); +int kHlpSys_munmap(void *addr, KSIZE len); +void kHlpSys_exit(int rc); +#endif + +/* specific */ +#if K_OS == K_OS_DARWIN + +#elif K_OS == K_OS_LINUX + +#endif + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + + diff --git a/src/lib/kStuff/include/k/kHlpThread.h b/src/lib/kStuff/include/k/kHlpThread.h new file mode 100644 index 0000000..1b2f233 --- /dev/null +++ b/src/lib/kStuff/include/k/kHlpThread.h @@ -0,0 +1,55 @@ +/* $Id: kHlpThread.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kHlpThread - Thread Manipulation. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kHlpThread_h___ +#define ___k_kHlpThread_h___ + +#include <k/kHlpDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kHlpThread kHlpThread - Thread Management + * @addtogroup grp_kHlp + * @{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +KHLP_DECL(void) kHlpSleep(unsigned cMillies); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + + diff --git a/src/lib/kStuff/include/k/kLdr.h b/src/lib/kStuff/include/k/kLdr.h new file mode 100644 index 0000000..4aefb66 --- /dev/null +++ b/src/lib/kStuff/include/k/kLdr.h @@ -0,0 +1,959 @@ +/* $Id: kLdr.h 117 2020-03-15 15:23:36Z bird $ */ +/** @file + * kLdr - The Dynamic Loader. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kLdr_h___ +#define ___k_kLdr_h___ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Include the base typedefs and macros. + */ +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kCpus.h> + + +/** @defgroup grp_kLdrBasic kLdr Basic Types + * @{ */ + +/** The kLdr address type. */ +typedef KU64 KLDRADDR; +/** Pointer to a kLdr address. */ +typedef KLDRADDR *PKLDRADDR; +/** Pointer to a const kLdr address. */ +typedef const KLDRADDR *PCKLDRADDR; + +/** NIL address. */ +#define NIL_KLDRADDR (~(KU64)0) + +/** @def PRI_KLDRADDR + * printf format type. */ +#ifdef _MSC_VER +# define PRI_KLDRADDR "I64x" +#else +# define PRI_KLDRADDR "llx" +#endif + +/** Align a KSIZE value. */ +#define KLDR_ALIGN_ADDR(val, align) ( ((val) + ((align) - 1)) & ~(KLDRADDR)((align) - 1) ) + + +/** The kLdr size type. */ +typedef KU64 KLDRSIZE; +/** Pointer to a kLdr size. */ +typedef KLDRSIZE *PKLDRSIZE; +/** Pointer to a const kLdr size. */ +typedef const KLDRSIZE *PCKLDRSIZE; + +/** @def PRI_KLDRSIZE + * printf format type. */ +#ifdef _MSC_VER +# define PRI_KLDRSIZE "I64x" +#else +# define PRI_KLDRSIZE "llx" +#endif + + +/** The kLdr file offset type. */ +typedef long KLDRFOFF; +/** Pointer to a kLdr file offset type. */ +typedef KLDRFOFF *PKLDRFOFF; +/** Pointer to a const kLdr file offset type. */ +typedef const KLDRFOFF *PCKLDRFOFF; + +/** @def PRI_KLDRFOFF + * printf format type. */ +#define PRI_KLDRFOFF "lx" + + +/** + * Union of all the integer types. + */ +typedef union KLDRU +{ + KI8 i8; /**< KI8 view. */ + KU8 u8; /**< KU8 view. */ + KI16 i16; /**< KI16 view. */ + KU16 u16; /**< KU16 view. */ + KI32 i32; /**< KI32 view. */ + KU32 u32; /**< KU32 view. */ + KI64 i64; /**< KI64 view. */ + KU64 u64; /**< KU64 view. */ + + KI8 ai8[8]; /**< KI8 array view . */ + KU8 au8[8]; /**< KU8 array view. */ + KI16 ai16[4];/**< KI16 array view . */ + KU16 au16[4];/**< KU16 array view. */ + KI32 ai32[2];/**< KI32 array view . */ + KU32 au32[2];/**< KU32 array view. */ + + signed char ch; /**< signed char view. */ + unsigned char uch; /**< unsigned char view. */ + signed short s; /**< signed short view. */ + unsigned short us; /**< unsigned short view. */ + signed int i; /**< signed int view. */ + unsigned int u; /**< unsigned int view. */ + signed long l; /**< signed long view. */ + unsigned long ul; /**< unsigned long view. */ + void *pv; /**< void pointer view. */ + + KLDRADDR Addr; /**< kLdr address view. */ + KLDRSIZE Size; /**< kLdr size view. */ +} KLDRU; +/** Pointer to an integer union. */ +typedef KLDRU *PKLDRU; +/** Pointer to a const integer union. */ +typedef const KLDRU *PCKLDRU; + + +/** + * Union of pointers to all the integer types. + */ +typedef union KLDRPU +{ + KI8 *pi8; /**< KI8 view. */ + KU8 *pu8; /**< KU8 view. */ + KI16 *pi16; /**< KI16 view. */ + KU16 *pu16; /**< KU16 view. */ + KI32 *pi32; /**< KI32 view. */ + KU32 *pu32; /**< KU32 view. */ + KI64 *pi64; /**< KI64 view. */ + KU64 *pu64; /**< KU64 view. */ + + signed char *pch; /**< signed char view. */ + unsigned char *puch; /**< unsigned char view. */ + signed short *ps; /**< signed short view. */ + unsigned short *pus; /**< unsigned short view. */ + signed int *pi; /**< signed int view. */ + unsigned int *pu; /**< unsigned int view. */ + signed long *pl; /**< signed long view. */ + unsigned long *pul; /**< unsigned long view. */ + void *pv; /**< void pointer view. */ +} KLDRPU; +/** Pointer to an integer pointer union. */ +typedef KLDRPU *PKLDRPU; +/** Pointer to a const integer pointer union. */ +typedef const KLDRPU *PCKLDRPU; + +/** @} */ + + +/** @defgroup grp_kLdrMod kLdrMod - The executable image intepreter + * @{ */ + +/** + * Debug info type (from the loader point of view). + */ +typedef enum KLDRDBGINFOTYPE +{ + /** The usual invalid enum value. */ + KLDRDBGINFOTYPE_INVALID = 0, + /** Unknown debug info format. */ + KLDRDBGINFOTYPE_UNKNOWN, + /** Stabs. */ + KLDRDBGINFOTYPE_STABS, + /** Debug With Arbitrary Record Format (DWARF). */ + KLDRDBGINFOTYPE_DWARF, + /** Microsoft Codeview debug info. */ + KLDRDBGINFOTYPE_CODEVIEW, + /** Watcom debug info. */ + KLDRDBGINFOTYPE_WATCOM, + /** IBM High Level Language debug info.. */ + KLDRDBGINFOTYPE_HLL, + /** The end of the valid debug info values (exclusive). */ + KLDRDBGINFOTYPE_END, + /** Blow the type up to 32-bit. */ + KLDRDBGINFOTYPE_32BIT_HACK = 0x7fffffff +} KLDRDBGINFOTYPE; +/** Pointer to a kLdr debug info type. */ +typedef KLDRDBGINFOTYPE *PKLDRDBGINFOTYPE; + + +/** + * Stack information. + */ +typedef struct KLDRSTACKINFO +{ + /** The base address of the stack (sub) segment. + * Set this to NIL_KLDRADDR if the module doesn't include any stack segment. */ + KLDRADDR Address; + /** The base address of the stack (sub) segment, link address. + * Set this to NIL_KLDRADDR if the module doesn't include any stack (sub)segment. */ + KLDRADDR LinkAddress; + /** The stack size of the main thread. + * If no stack (sub)segment in the module, this is the stack size of the main thread. + * If the module doesn't contain this kind of information this field will be set to 0. */ + KLDRSIZE cbStack; + /** The stack size of non-main threads. + * If the module doesn't contain this kind of information this field will be set to 0. */ + KLDRSIZE cbStackThread; +} KLDRSTACKINFO; +/** Pointer to stack information. */ +typedef KLDRSTACKINFO *PKLDRSTACKINFO; +/** Pointer to const stack information. */ +typedef const KLDRSTACKINFO *PCKLDRSTACKINFO; + + +/** + * Loader segment. + */ +typedef struct KLDRSEG +{ + /** Variable free to use for the kLdr user. */ + void *pvUser; + /** The segment name. (Might not be zero terminated!) */ + const char *pchName; + /** The length of the segment name. */ + KU32 cchName; + /** The flat selector to use for the segment (i.e. data/code). + * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */ + KU16 SelFlat; + /** The 16-bit selector to use for the segment. + * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */ + KU16 Sel16bit; + /** Segment flags. */ + KU32 fFlags; + /** The segment protection. */ + KPROT enmProt; + /** The size of the segment. */ + KLDRSIZE cb; + /** The required segment alignment. + * The to 0 if the segment isn't supposed to be mapped. */ + KLDRADDR Alignment; + /** The link address. + * Set to NIL_KLDRADDR if the segment isn't supposed to be + * mapped or if the image doesn't have link addresses. */ + KLDRADDR LinkAddress; + /** File offset of the segment. + * Set to -1 if no file backing (like BSS). */ + KLDRFOFF offFile; + /** Size of the file bits of the segment. + * Set to -1 if no file backing (like BSS). */ + KLDRFOFF cbFile; + /** The relative virtual address when mapped. + * Set to NIL_KLDRADDR if the segment isn't supposed to be mapped. */ + KLDRADDR RVA; + /** The size of the segment including the alignment gap up to the next segment when mapped. */ + KSIZE cbMapped; + /** The address the segment was mapped at by kLdrModMap(). + * Set to 0 if not mapped. */ + KUPTR MapAddress; +} KLDRSEG; + + +/** @name Segment flags + * @{ */ +/** The segment is 16-bit. When not set the default of the target architecture is assumed. */ +#define KLDRSEG_FLAG_16BIT 1 +/** The segment requires a 16-bit selector alias. (OS/2) */ +#define KLDRSEG_FLAG_OS2_ALIAS16 2 +/** Conforming segment (x86 weirdness). (OS/2) */ +#define KLDRSEG_FLAG_OS2_CONFORM 4 +/** IOPL (ring-2) segment. (OS/2) */ +#define KLDRSEG_FLAG_OS2_IOPL 8 +/** @} */ + + +/** + * Loader module format. + */ +typedef enum KLDRFMT +{ + /** The usual invalid 0 format. */ + KLDRFMT_INVALID = 0, + /** The native OS loader. */ + KLDRFMT_NATIVE, + /** The AOUT loader. */ + KLDRFMT_AOUT, + /** The ELF loader. */ + KLDRFMT_ELF, + /** The LX loader. */ + KLDRFMT_LX, + /** The Mach-O loader. */ + KLDRFMT_MACHO, + /** The PE loader. */ + KLDRFMT_PE, + /** The end of the valid format values (exclusive). */ + KLDRFMT_END, + /** Hack to blow the type up to 32-bit. */ + KLDRFMT_32BIT_HACK = 0x7fffffff +} KLDRFMT; + + +/** + * Loader module type. + */ +typedef enum KLDRTYPE +{ + /** The usual invalid 0 type. */ + KLDRTYPE_INVALID = 0, + /** Object file. */ + KLDRTYPE_OBJECT, + /** Executable module, fixed load address. */ + KLDRTYPE_EXECUTABLE_FIXED, + /** Executable module, relocatable, non-fixed load address. */ + KLDRTYPE_EXECUTABLE_RELOCATABLE, + /** Executable module, position independent code, non-fixed load address. */ + KLDRTYPE_EXECUTABLE_PIC, + /** Shared library, fixed load address. + * Typically a system library. */ + KLDRTYPE_SHARED_LIBRARY_FIXED, + /** Shared library, relocatable, non-fixed load address. */ + KLDRTYPE_SHARED_LIBRARY_RELOCATABLE, + /** Shared library, position independent code, non-fixed load address. */ + KLDRTYPE_SHARED_LIBRARY_PIC, + /** DLL that contains no code or data only imports and exports. (Chiefly OS/2.) */ + KLDRTYPE_FORWARDER_DLL, + /** Core or dump. */ + KLDRTYPE_CORE, + /** Debug module (debug info with empty code & data segments). */ + KLDRTYPE_DEBUG_INFO, + /** The end of the valid types values (exclusive). */ + KLDRTYPE_END, + /** Hack to blow the type up to 32-bit. */ + KLDRTYPE_32BIT_HACK = 0x7fffffff +} KLDRTYPE; + + +/** + * Loader endian indicator. + */ +typedef enum KLDRENDIAN +{ + /** The usual invalid endian. */ + KLDRENDIAN_INVALID, + /** Little endian. */ + KLDRENDIAN_LITTLE, + /** Bit endian. */ + KLDRENDIAN_BIG, + /** Endianness doesn't have a meaning in the context. */ + KLDRENDIAN_NA, + /** The end of the valid endian values (exclusive). */ + KLDRENDIAN_END, + /** Hack to blow the type up to 32-bit. */ + KLDRENDIAN_32BIT_HACK = 0x7fffffff +} KLDRENDIAN; + + +/** @name KLDRMOD::fFlags + * @{ */ +/** The link address doesn't form a contiguous image, from the first to the + * last segment. */ +#define KLDRMOD_FLAGS_NON_CONTIGUOUS_LINK_ADDRS K_BIT32(0) +/** @} */ + +/** Pointer to a module interpreter method table. */ +typedef struct KLDRMODOPS *PKLDRMODOPS; +/** Pointer to const module interpreter methods table. */ +typedef const struct KLDRMODOPS *PCKLDRMODOPS; + +/** + * Module interpreter instance. + * All members are read only unless you're kLdrMod or the module interpreter. + */ +typedef struct KLDRMOD +{ + /** Magic number (KLDRMOD_MAGIC). */ + KU32 u32Magic; + /** The format of this module. */ + KLDRFMT enmFmt; + /** The type of module. */ + KLDRTYPE enmType; + /** The CPU architecture this module was built for. */ + KCPUARCH enmArch; + /** The minium cpu this module was built for. + * This might not be accurate, so use kLdrModCanExecuteOn() to check. */ + KCPU enmCpu; + /** The endian used by the module. */ + KLDRENDIAN enmEndian; + /** Module open flags, KLDRMOD_OPEN_FLAGS_XXX. */ + KU32 fFlags; + /** The filename length (bytes). */ + KU32 cchFilename; + /** The filename. */ + const char *pszFilename; + /** The module name. */ + const char *pszName; + /** The module name length (bytes). */ + KU32 cchName; + /** The number of segments in the module. */ + KU32 cSegments; + /** Pointer to the loader methods. + * Not meant for calling directly thru! */ + PCKLDRMODOPS pOps; + /** Pointer to the read instance. (Can be NULL after kLdrModDone().)*/ + PKRDR pRdr; + /** The module data. */ + void *pvData; + /** Segments. (variable size, can be zero) */ + KLDRSEG aSegments[1]; +} KLDRMOD, *PKLDRMOD, **PPKLDRMOD; + +/** The magic for KLDRMOD::u32Magic. (Kosuke Fujishima) */ +#define KLDRMOD_MAGIC 0x19640707 + + +/** Special base address value alias for the link address. */ +#define KLDRMOD_BASEADDRESS_LINK (~(KLDRADDR)1) +/** Special base address value alias for the actual load address (must be mapped). */ +#define KLDRMOD_BASEADDRESS_MAP (~(KLDRADDR)2) + +/** Special import module ordinal value used to indicate that there is no + * specific module associated with the requested symbol. */ +#define NIL_KLDRMOD_IMPORT (~(KU32)0) + +/** Special symbol ordinal value used to indicate that the symbol + * only has a string name. */ +#define NIL_KLDRMOD_SYM_ORDINAL (~(KU32)0) + + +/** @name Load symbol kind flags. + * @{ */ +/** The bitness doesn't matter. */ +#define KLDRSYMKIND_NO_BIT 0x00000000 +/** 16-bit symbol. */ +#define KLDRSYMKIND_16BIT 0x00000001 +/** 32-bit symbol. */ +#define KLDRSYMKIND_32BIT 0x00000002 +/** 64-bit symbol. */ +#define KLDRSYMKIND_64BIT 0x00000003 +/** Mask out the bit.*/ +#define KLDRSYMKIND_BIT_MASK 0x00000003 +/** We don't know the type of symbol. */ +#define KLDRSYMKIND_NO_TYPE 0x00000000 +/** The symbol is a code object (method/function/procedure/whateveryouwannacallit). */ +#define KLDRSYMKIND_CODE 0x00000010 +/** The symbol is a data object. */ +#define KLDRSYMKIND_DATA 0x00000020 +/** Mask out the symbol type. */ +#define KLDRSYMKIND_TYPE_MASK 0x00000030 +/** Valid symbol kind mask. */ +#define KLDRSYMKIND_MASK 0x00000033 +/** Weak symbol. */ +#define KLDRSYMKIND_WEAK 0x00000100 +/** Forwarder symbol. */ +#define KLDRSYMKIND_FORWARDER 0x00000200 +/** Request a flat symbol address. */ +#define KLDRSYMKIND_REQ_FLAT 0x00000000 +/** Request a segmented symbol address. */ +#define KLDRSYMKIND_REQ_SEGMENTED 0x40000000 +/** Request type mask. */ +#define KLDRSYMKIND_REQ_TYPE_MASK 0x40000000 +/** @} */ + +/** @name kLdrModEnumSymbols flags. + * @{ */ +/** Returns ALL kinds of symbols. The default is to only return public/exported symbols. */ +#define KLDRMOD_ENUM_SYMS_FLAGS_ALL 0x00000001 +/** @} */ + + +/** + * Callback for resolving imported symbols when applying fixups. + * + * @returns 0 on success and *pValue and *pfKind filled. + * @returns Non-zero OS specific or kLdr status code on failure. + * + * @param pMod The module which fixups are begin applied. + * @param iImport The import module ordinal number or NIL_KLDRMOD_IMPORT. + * @param iSymbol The symbol ordinal number or NIL_KLDRMOD_SYM_ORDINAL. + * @param pchSymbol The symbol name. Can be NULL if iSymbol isn't nil. Doesn't have to be null-terminated. + * @param cchSymbol The length of the symbol. + * @param pszVersion The symbol version. NULL if not versioned. + * @param puValue Where to store the symbol value. + * @param pfKind Where to store the symbol kind flags. + * @param pvUser The user parameter specified to the relocation function. + */ +typedef int FNKLDRMODGETIMPORT(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol, + const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser); +/** Pointer to a import callback. */ +typedef FNKLDRMODGETIMPORT *PFNKLDRMODGETIMPORT; + +/** + * Symbol enumerator callback. + * + * @returns 0 if enumeration should continue. + * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumSymbols(). + * + * @param pMod The module which symbols are being enumerated.s + * @param iSymbol The symbol ordinal number or NIL_KLDRMOD_SYM_ORDINAL. + * @param pchSymbol The symbol name. This can be NULL if there is a symbol ordinal. + * This can also be an empty string if the symbol doesn't have a name + * or it's name has been stripped. + * Important, this doesn't have to be a null-terminated string. + * @param cchSymbol The length of the symbol. + * @param pszVersion The symbol version. NULL if not versioned. + * @param uValue The symbol value. + * @param fKind The symbol kind flags. + * @param pvUser The user parameter specified to kLdrModEnumSymbols(). + */ +typedef int FNKLDRMODENUMSYMS(PKLDRMOD pMod, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion, + KLDRADDR uValue, KU32 fKind, void *pvUser); +/** Pointer to a symbol enumerator callback. */ +typedef FNKLDRMODENUMSYMS *PFNKLDRMODENUMSYMS; + +/** + * Debug info enumerator callback. + * + * @returns 0 to continue the enumeration. + * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumDbgInfo(). + * + * @param pMod The module. + * @param iDbgInfo The debug info ordinal number / id. + * @param enmType The debug info type. + * @param iMajorVer The major version number of the debug info format. -1 if unknow - implies invalid iMinorVer. + * @param iMinorVer The minor version number of the debug info format. -1 when iMajorVer is -1. + * @param pszPartNm The name of the debug info part, NULL if not applicable. + * @param offFile The file offset *if* this type has one specific location in the executable image file. + * This is -1 if there isn't any specific file location. + * @param LinkAddress The link address of the debug info if it's loadable. NIL_KLDRADDR if not loadable. + * @param cb The size of the debug information. -1 is used if this isn't applicable. + * @param pszExtFile This points to the name of an external file containing the debug info. + * This is NULL if there isn't any external file. + * @param pvUser The user parameter specified to kLdrModEnumDbgInfo. + */ +typedef int FNKLDRENUMDBG(PKLDRMOD pMod, KU32 iDbgInfo, KLDRDBGINFOTYPE enmType, KI16 iMajorVer, KI16 iMinorVer, + const char *pszPartNm, KLDRFOFF offFile, KLDRADDR LinkAddress, KLDRSIZE cb, + const char *pszExtFile, void *pvUser); +/** Pointer to a debug info enumerator callback. */ +typedef FNKLDRENUMDBG *PFNKLDRENUMDBG; + +/** + * Resource enumerator callback. + * + * @returns 0 to continue the enumeration. + * @returns non-zero if the enumeration should stop. This status code will then be returned by kLdrModEnumResources(). + * + * @param pMod The module. + * @param idType The resource type id. NIL_KLDRMOD_RSRC_TYPE_ID if no type id. + * @param pszType The resource type name. NULL if no type name. + * @param idName The resource id. NIL_KLDRMOD_RSRC_NAME_ID if no id. + * @param pszName The resource name. NULL if no name. + * @param idLang The language id. + * @param AddrRsrc The address value for the resource. + * @param cbRsrc The size of the resource. + * @param pvUser The user parameter specified to kLdrModEnumDbgInfo. + */ +typedef int FNKLDRENUMRSRC(PKLDRMOD pMod, KU32 idType, const char *pszType, KU32 idName, const char *pszName, + KU32 idLang, KLDRADDR AddrRsrc, KLDRSIZE cbRsrc, void *pvUser); +/** Pointer to a resource enumerator callback. */ +typedef FNKLDRENUMRSRC *PFNKLDRENUMRSRC; + +/** NIL resource name ID. */ +#define NIL_KLDRMOD_RSRC_NAME_ID ( ~(KU32)0 ) +/** NIL resource type ID. */ +#define NIL_KLDRMOD_RSRC_TYPE_ID ( ~(KU32)0 ) +/** @name Language ID + * + * Except for the special IDs #defined here, the values are considered + * format specific for now since it's only used by the PE resources. + * + * @{ */ +/** NIL language ID. */ +#define NIL_KLDR_LANG_ID ( ~(KU32)0 ) +/** Special language id value for matching any language. */ +#define KLDR_LANG_ID_ANY ( ~(KU32)1 ) +/** Special language id value indicating language neutral. */ +#define KLDR_LANG_ID_NEUTRAL ( ~(KU32)2 ) +/** Special language id value indicating user default language. */ +#define KLDR_LANG_ID_USER_DEFAULT ( ~(KU32)3 ) +/** Special language id value indicating system default language. */ +#define KLDR_LANG_ID_SYS_DEFAULT ( ~(KU32)4 ) +/** Special language id value indicating default custom locale. */ +#define KLDR_LANG_ID_CUSTOM_DEFAULT ( ~(KU32)5 ) +/** Special language id value indicating unspecified custom locale. */ +#define KLDR_LANG_ID_CUSTOM_UNSPECIFIED ( ~(KU32)6 ) +/** Special language id value indicating default custom MUI locale. */ +#define KLDR_LANG_ID_UI_CUSTOM_DEFAULT ( ~(KU32)7 ) +/** @} */ + +/** @name KLDRMOD_OPEN_FLAGS_XXX - Module Open Flags + * @{ */ +/** Indicates that we won't be loading the module, we're just getting + * information (like symbols and line numbers) out of it. */ +#define KLDRMOD_OPEN_FLAGS_FOR_INFO K_BIT32(0) +/** Native: Non-stub kLdrModCallInit & kLdrModCallTerm. */ +#define KLDRMOD_OPEN_FLAGS_NATIVE_ALLOW_INIT_TERM K_BIT32(1) +/** Mask of valid flags. */ +#define KLDRMOD_OPEN_FLAGS_VALID_MASK KU32_C(0x00000003) +/** @} */ + +int kLdrModOpen(const char *pszFilename, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod); +int kLdrModOpenFromRdr(PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, PPKLDRMOD ppMod); +int kLdrModOpenNative(const char *pszFilename, KU32 fFlags, PPKLDRMOD ppMod); +int kLdrModOpenNativeByHandle(KUPTR uHandle, KU32 fFlags, PPKLDRMOD ppMod); +int kLdrModClose(PKLDRMOD pMod); + +int kLdrModQuerySymbol(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol, + const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion, + PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind); +int kLdrModEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, + KU32 fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); +int kLdrModGetImport(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName); +KI32 kLdrModNumberOfImports(PKLDRMOD pMod, const void *pvBits); +int kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu); +int kLdrModGetStackInfo(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo); +int kLdrModQueryMainEntrypoint(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress); +int kLdrModQueryImageUuid(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE cbUuid); +int kLdrModQueryResource(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType, + KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc); +int kLdrModEnumResources(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType, + KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser); +int kLdrModEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser); +int kLdrModHasDbgInfo(PKLDRMOD pMod, const void *pvBits); +int kLdrModMostlyDone(PKLDRMOD pMod); + + +/** @name Operations On The Internally Managed Mapping + * @{ */ +int kLdrModMap(PKLDRMOD pMod); +int kLdrModUnmap(PKLDRMOD pMod); +int kLdrModReload(PKLDRMOD pMod); +int kLdrModFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); +/** @} */ + +/** @name Operations On The Externally Managed Mappings + * @{ */ +KLDRADDR kLdrModSize(PKLDRMOD pMod); +int kLdrModGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); +int kLdrModRelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, + PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); +/** @} */ + +/** @name Operations on both internally and externally managed mappings. + * @{ */ +/** Special pvMapping value to pass to kLdrModAllocTLS, + * kLdrModFreeTLS, kLdrModCallInit, kLdrModCallTerm, and kLdrModCallThread that + * specifies the internal mapping (kLdrModMap). */ +#define KLDRMOD_INT_MAP ((void *)~(KUPTR)0) +int kLdrModAllocTLS(PKLDRMOD pMod, void *pvMapping); +void kLdrModFreeTLS(PKLDRMOD pMod, void *pvMapping); +int kLdrModCallInit(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle); +int kLdrModCallTerm(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle); +int kLdrModCallThread(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching); +/** @} */ + + +/** + * The loader module operation. + */ +typedef struct KLDRMODOPS +{ + /** The name of this module interpreter. */ + const char *pszName; + /** Pointer to the next module interpreter. */ + PCKLDRMODOPS pNext; + + /** + * Create a loader module instance interpreting the executable image found + * in the specified file provider instance. + * + * @returns 0 on success and *ppMod pointing to a module instance. + * On failure, a non-zero OS specific error code is returned. + * @param pOps Pointer to the registered method table. + * @param pRdr The file provider instance to use. + * @param fFlags Flags, MBZ. + * @param enmCpuArch The desired CPU architecture. KCPUARCH_UNKNOWN means + * anything goes, but with a preference for the current + * host architecture. + * @param offNewHdr The offset of the new header in MZ files. -1 if not found. + * @param ppMod Where to store the module instance pointer. + */ + int (* pfnCreate)(PCKLDRMODOPS pOps, PKRDR pRdr, KU32 fFlags, KCPUARCH enmCpuArch, KLDRFOFF offNewHdr, PPKLDRMOD ppMod); + /** + * Destroys an loader module instance. + * + * The caller is responsible for calling kLdrModUnmap() and kLdrFreeTLS() first. + * + * @returns 0 on success, non-zero on failure. The module instance state + * is unknown on failure, it's best not to touch it. + * @param pMod The module. + */ + int (* pfnDestroy)(PKLDRMOD pMod); + + /** @copydoc kLdrModQuerySymbol */ + int (* pfnQuerySymbol)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 iSymbol, + const char *pchSymbol, KSIZE cchSymbol, const char *pszVersion, + PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, KU32 *pfKind); + /** @copydoc kLdrModEnumSymbols */ + int (* pfnEnumSymbols)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 fFlags, + PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); + /** @copydoc kLdrModGetImport */ + int (* pfnGetImport)(PKLDRMOD pMod, const void *pvBits, KU32 iImport, char *pszName, KSIZE cchName); + /** @copydoc kLdrModNumberOfImports */ + KI32 (* pfnNumberOfImports)(PKLDRMOD pMod, const void *pvBits); + /** @copydoc kLdrModCanExecuteOn */ + int (* pfnCanExecuteOn)(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu); + /** @copydoc kLdrModGetStackInfo */ + int (* pfnGetStackInfo)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRSTACKINFO pStackInfo); + /** @copydoc kLdrModQueryMainEntrypoint */ + int (* pfnQueryMainEntrypoint)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, PKLDRADDR pMainEPAddress); + /** @copydoc kLdrModQueryImageUuid */ + int (* pfnQueryImageUuid)(PKLDRMOD pMod, const void *pvBits, void *pvUuid, KSIZE pcbUuid); + /** @copydoc kLdrModQueryResource */ + int (* pfnQueryResource)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType, + KU32 idName, const char *pszName, KU32 idLang, PKLDRADDR pAddrRsrc, KSIZE *pcbRsrc); + /** @copydoc kLdrModEnumResources */ + int (* pfnEnumResources)(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, KU32 idType, const char *pszType, + KU32 idName, const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser); + /** @copydoc kLdrModEnumDbgInfo */ + int (* pfnEnumDbgInfo)(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser); + /** @copydoc kLdrModHasDbgInfo */ + int (* pfnHasDbgInfo)(PKLDRMOD pMod, const void *pvBits); + /** @copydoc kLdrModMap */ + int (* pfnMap)(PKLDRMOD pMod); + /** @copydoc kLdrModUnmap */ + int (* pfnUnmap)(PKLDRMOD pMod); + /** @copydoc kLdrModAllocTLS */ + int (* pfnAllocTLS)(PKLDRMOD pMod, void *pvMapping); + /** @copydoc kLdrModFreeTLS */ + void (*pfnFreeTLS)(PKLDRMOD pMod, void *pvMapping); + /** @copydoc kLdrModReload */ + int (* pfnReload)(PKLDRMOD pMod); + /** @copydoc kLdrModFixupMapping */ + int (* pfnFixupMapping)(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); + /** @copydoc kLdrModCallInit */ + int (* pfnCallInit)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle); + /** @copydoc kLdrModCallTerm */ + int (* pfnCallTerm)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle); + /** @copydoc kLdrModCallThread */ + int (* pfnCallThread)(PKLDRMOD pMod, void *pvMapping, KUPTR uHandle, unsigned fAttachingOrDetaching); + /** @copydoc kLdrModSize */ + KLDRADDR (* pfnSize)(PKLDRMOD pMod); + /** @copydoc kLdrModGetBits */ + int (* pfnGetBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); + /** @copydoc kLdrModRelocateBits */ + int (* pfnRelocateBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, + PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); + /** @copydoc kLdrModMostlyDone */ + int (* pfnMostlyDone)(PKLDRMOD pMod); + /** Dummy which should be assigned a non-zero value. */ + KU32 uEndOfStructure; +} KLDRMODOPS; + + +/** @} */ + + + + +/** @defgroup grp_kLdrDyld kLdrDyld - The dynamic loader + * @{ */ + +/** The handle to a dynamic loader module. */ +typedef struct KLDRDYLDMOD *HKLDRMOD; +/** Pointer to the handle to a dynamic loader module. */ +typedef HKLDRMOD *PHKLDRMOD; +/** NIL handle value. */ +#define NIL_HKLDRMOD ((HKLDRMOD)0) + + +/** + * File search method. + * + * In addition to it's own way of finding files, kLdr emulates + * the methods employed by the most popular systems. + */ +typedef enum KLDRDYLDSEARCH +{ + /** The usual invalid file search method. */ + KLDRDYLD_SEARCH_INVALID = 0, + /** Uses the kLdr file search method. + * @todo invent me. */ + KLDRDYLD_SEARCH_KLDR, + /** Use the emulation closest to the host system. */ + KLDRDYLD_SEARCH_HOST, + /** Emulate the OS/2 file search method. + * On non-OS/2 systems, BEGINLIBPATH, LIBPATH, ENDLIBPATH and LIBPATHSTRICT are + * taken form the environment. */ + KLDRDYLD_SEARCH_OS2, + /** Emulate the standard window file search method. */ + KLDRDYLD_SEARCH_WINDOWS, + /** Emulate the alternative window file search method. */ + KLDRDYLD_SEARCH_WINDOWS_ALTERED, + /** Emulate the most common UNIX file search method. */ + KLDRDYLD_SEARCH_UNIX_COMMON, + /** End of the valid file search method values. */ + KLDRDYLD_SEARCH_END, + /** Hack to blow the type up to 32-bit. */ + KLDRDYLD_SEARCH_32BIT_HACK = 0x7fffffff +} KLDRDYLDSEARCH; + +/** @name kLdrDyldLoad and kLdrDyldFindByName flags. + * @{ */ +/** The symbols in the module should be loaded into the global unix namespace. + * If not specified, the symbols are local and can only be referenced directly. */ +#define KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS 0x00000001 +/** The symbols in the module should be loaded into the global unix namespace and + * it's symbols should take precedence over all currently loaded modules. + * This implies KLDRYDLD_LOAD_FLAGS_GLOBAL_SYMBOLS. */ +#define KLDRYDLD_LOAD_FLAGS_DEEP_SYMBOLS 0x00000002 +/** The module shouldn't be found by a global module search. + * If not specified, the module can be found by unspecified module searches, + * typical used when loading import/dep modules. */ +#define KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE 0x00000004 +/** Do a recursive initialization calls instead of defering them to the outermost call. */ +#define KLDRDYLD_LOAD_FLAGS_RECURSIVE_INIT 0x00000008 +/** We're loading the executable module. + * @internal */ +#define KLDRDYLD_LOAD_FLAGS_EXECUTABLE 0x40000000 +/** @} */ + + +int kLdrDyldLoad(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, + unsigned fFlags, PHKLDRMOD phMod, char *pszErr, KSIZE cchErr); +int kLdrDyldUnload(HKLDRMOD hMod); +int kLdrDyldFindByName(const char *pszDll, const char *pszPrefix, const char *pszSuffix, KLDRDYLDSEARCH enmSearch, + unsigned fFlags, PHKLDRMOD phMod); +int kLdrDyldFindByAddress(KUPTR Address, PHKLDRMOD phMod, KU32 *piSegment, KUPTR *poffSegment); +int kLdrDyldGetName(HKLDRMOD hMod, char *pszName, KSIZE cchName); +int kLdrDyldGetFilename(HKLDRMOD hMod, char *pszFilename, KSIZE cchFilename); +int kLdrDyldQuerySymbol(HKLDRMOD hMod, KU32 uSymbolOrdinal, const char *pszSymbolName, + const char *pszSymbolVersion, KUPTR *pValue, KU32 *pfKind); +int kLdrDyldQueryResource(HKLDRMOD hMod, KU32 idType, const char *pszType, KU32 idName, + const char *pszName, KU32 idLang, void **pvRsrc, KSIZE *pcbRsrc); +int kLdrDyldEnumResources(HKLDRMOD hMod, KU32 idType, const char *pszType, KU32 idName, + const char *pszName, KU32 idLang, PFNKLDRENUMRSRC pfnCallback, void *pvUser); + + +/** @name OS/2 like API + * @{ */ +#if defined(__OS2__) +# define KLDROS2API _System +#else +# define KLDROS2API +#endif +int kLdrDosLoadModule(char *pszObject, KSIZE cbObject, const char *pszModule, PHKLDRMOD phMod); +int kLdrDosFreeModule(HKLDRMOD hMod); +int kLdrDosQueryModuleHandle(const char *pszModname, PHKLDRMOD phMod); +int kLdrDosQueryModuleName(HKLDRMOD hMod, KSIZE cchName, char *pszName); +int kLdrDosQueryProcAddr(HKLDRMOD hMod, KU32 iOrdinal, const char *pszProcName, void **ppvProcAddr); +int kLdrDosQueryProcType(HKLDRMOD hMod, KU32 iOrdinal, const char *pszProcName, KU32 *pfProcType); +int kLdrDosQueryModFromEIP(PHKLDRMOD phMod, KU32 *piObject, KSIZE cbName, char *pszName, KUPTR *poffObject, KUPTR ulEIP); +int kLdrDosReplaceModule(const char *pszOldModule, const char *pszNewModule, const char *pszBackupModule); +int kLdrDosGetResource(HKLDRMOD hMod, KU32 idType, KU32 idName, void **pvResAddr); +int kLdrDosQueryResourceSize(HKLDRMOD hMod, KU32 idType, KU32 idName, KU32 *pcb); +int kLdrDosFreeResource(void *pvResAddr); +/** @} */ + +/** @name POSIX like API + * @{ */ +HKLDRMOD kLdrDlOpen(const char *pszLibrary, int fFlags); +const char *kLdrDlError(void); +void * kLdrDlSym(HKLDRMOD hMod, const char *pszSymbol); +int kLdrDlClose(HKLDRMOD hMod); +/** @todo GNU extensions */ +/** @} */ + +/** @name Win32 like API + * @{ */ +#if defined(_MSC_VER) +# define KLDRWINAPI __stdcall +#else +# define KLDRWINAPI +#endif +HKLDRMOD KLDRWINAPI kLdrWLoadLibrary(const char *pszFilename); +HKLDRMOD KLDRWINAPI kLdrWLoadLibraryEx(const char *pszFilename, void *hFileReserved, KU32 fFlags); +KU32 KLDRWINAPI kLdrWGetModuleFileName(HKLDRMOD hMod, char *pszModName, KSIZE cchModName); +HKLDRMOD KLDRWINAPI kLdrWGetModuleHandle(const char *pszFilename); +int KLDRWINAPI kLdrWGetModuleHandleEx(KU32 fFlags, const char *pszFilename, HKLDRMOD hMod); +void * KLDRWINAPI kLdrWGetProcAddress(HKLDRMOD hMod, const char *pszProcName); +KU32 KLDRWINAPI kLdrWGetDllDirectory(KSIZE cchDir, char *pszDir); +int KLDRWINAPI kLdrWSetDllDirectory(const char *pszDir); +int KLDRWINAPI kLdrWFreeLibrary(HKLDRMOD hMod); +int KLDRWINAPI kLdrWDisableThreadLibraryCalls(HKLDRMOD hMod); + +/** The handle to a resource that's been found. */ +typedef struct KLDRWRSRCFOUND *HKLDRWRSRCFOUND; +/** The handle to a loaded resource. */ +typedef struct KLDRWRSRCLOADED *HKLDRWRSRCLOADED; +HKLDRWRSRCFOUND KLDRWINAPI kLdrWFindResource(HKLDRMOD hMod, const char *pszType, const char *pszName); +HKLDRWRSRCFOUND KLDRWINAPI kLdrWFindResourceEx(HKLDRMOD hMod, const char *pszType, const char *pszName, KU16 idLang); +KU32 KLDRWINAPI kLdrWSizeofResource(HKLDRMOD hMod, HKLDRWRSRCFOUND hFoundRsrc); +HKLDRWRSRCLOADED KLDRWINAPI kLdrWLoadResource(HKLDRMOD hMod, HKLDRWRSRCFOUND hFoundRsrc); +void *KLDRWINAPI kLdrWLockResource(HKLDRMOD hMod, HKLDRWRSRCLOADED hLoadedRsrc); +int KLDRWINAPI kLdrWFreeResource(HKLDRMOD hMod, HKLDRWRSRCLOADED hLoadedRsrc); + +typedef int (KLDRWINAPI *PFNKLDRWENUMRESTYPE)(HKLDRMOD hMod, const char *pszType, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceTypes(HKLDRMOD hMod, PFNKLDRWENUMRESTYPE pfnEnum, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceTypesEx(HKLDRMOD hMod, PFNKLDRWENUMRESTYPE pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang); + +typedef int (KLDRWINAPI *PFNKLDRWENUMRESNAME)(HKLDRMOD hMod, const char *pszType, char *pszName, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceNames(HKLDRMOD hMod, const char *pszType, PFNKLDRWENUMRESNAME pfnEnum, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceNamesEx(HKLDRMOD hMod, const char *pszType, PFNKLDRWENUMRESNAME pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang); + +typedef int (KLDRWINAPI *PFNKLDRWENUMRESLANG)(HKLDRMOD hMod, const char *pszType, const char *pszName, KU16 idLang, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceLanguages(HKLDRMOD hMod, const char *pszType, const char *pszName, PFNKLDRWENUMRESLANG pfnEnum, KUPTR uUser); +int KLDRWINAPI kLdrWEnumResourceLanguagesEx(HKLDRMOD hMod, const char *pszType, const char *pszName, + PFNKLDRWENUMRESLANG pfnEnum, KUPTR uUser, KU32 fFlags, KU16 idLang); +/** @} */ + + +/** @name Process Bootstrapping + * @{ */ + +/** + * Argument package from the stub. + */ +typedef struct KLDREXEARGS +{ + /** Load & search flags, some which will become defaults. */ + KU32 fFlags; + /** The default search method. */ + KLDRDYLDSEARCH enmSearch; + /** The executable file that the stub is supposed to load. */ + char szExecutable[260]; + /** The default prefix used when searching for DLLs. */ + char szDefPrefix[16]; + /** The default suffix used when searching for DLLs. */ + char szDefSuffix[16]; + /** The LD_LIBRARY_PATH prefix for the process.. */ + char szLibPath[4096 - sizeof(KU32) - sizeof(KLDRDYLDSEARCH) - 16 - 16 - 260]; +} KLDREXEARGS, *PKLDREXEARGS; +/** Pointer to a const argument package from the stub. */ +typedef const KLDREXEARGS *PCKLDREXEARGS; + +void kLdrLoadExe(PCKLDREXEARGS pArgs, void *pvOS); /** @todo fix this mess... */ +void kLdrDyldLoadExe(PCKLDREXEARGS pArgs, void *pvOS); +/** @} */ + +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/lib/kStuff/include/k/kLdrFmts/lx.h b/src/lib/kStuff/include/k/kLdrFmts/lx.h new file mode 100644 index 0000000..fc1d1e2 --- /dev/null +++ b/src/lib/kStuff/include/k/kLdrFmts/lx.h @@ -0,0 +1,485 @@ +/* $Id $ */ +/** @file + * LX structures, types and defines. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kLdrFmts_lx_h___ +#define ___k_kLdrFmts_lx_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> + + +#ifndef IMAGE_OS2_SIGNATURE_LX +/** LX signature ("LX") */ +# define IMAGE_LX_SIGNATURE K_LE2H_U16('L' | ('X' << 8)) +#endif + +#pragma pack(1) + +/** + * Linear eXecutable header. + * This structure is exactly 196 bytes long. + */ +struct e32_exe +{ + KU8 e32_magic[2]; + KU8 e32_border; + KU8 e32_worder; + KU32 e32_level; + KU16 e32_cpu; + KU16 e32_os; + KU32 e32_ver; + KU32 e32_mflags; + KU32 e32_mpages; + KU32 e32_startobj; + KU32 e32_eip; + KU32 e32_stackobj; + KU32 e32_esp; + KU32 e32_pagesize; + KU32 e32_pageshift; + /** The size of the fixup section. + * The fixup section consists of the fixup page table, the fixup record table, + * the import module table, and the import procedure name table. + */ + KU32 e32_fixupsize; + KU32 e32_fixupsum; + /** The size of the resident loader section. + * This includes the object table, the object page map table, the resource table, the resident name table, + * the entry table, the module format directives table, and the page checksum table (?). */ + KU32 e32_ldrsize; + /** The checksum of the loader section. 0 if not calculated. */ + KU32 e32_ldrsum; + /** The offset of the object table relative to this structure. */ + KU32 e32_objtab; + /** Count of objects. */ + KU32 e32_objcnt; + /** The offset of the object page map table relative to this structure. */ + KU32 e32_objmap; + /** The offset of the object iterated pages (whatever this is used for) relative to the start of the file. */ + KU32 e32_itermap; + /** The offset of the resource table relative to this structure. */ + KU32 e32_rsrctab; + /** The number of entries in the resource table. */ + KU32 e32_rsrccnt; + /** The offset of the resident name table relative to this structure. */ + KU32 e32_restab; + /** The offset of the entry (export) table relative to this structure. */ + KU32 e32_enttab; + /** The offset of the module format directives table relative to this structure. */ + KU32 e32_dirtab; + /** The number of entries in the module format directives table. */ + KU32 e32_dircnt; + /** The offset of the fixup page table relative to this structure. */ + KU32 e32_fpagetab; + /** The offset of the fixup record table relative to this structure. */ + KU32 e32_frectab; + /** The offset of the import module name table relative to this structure. */ + KU32 e32_impmod; + /** The number of entries in the import module name table. */ + KU32 e32_impmodcnt; + /** The offset of the import procedure name table relative to this structure. */ + KU32 e32_impproc; + /** The offset of the page checksum table relative to this structure. */ + KU32 e32_pagesum; + /** The offset of the data pages relative to the start of the file. */ + KU32 e32_datapage; + /** The number of preload pages (ignored). */ + KU32 e32_preload; + /** The offset of the non-resident name table relative to the start of the file. */ + KU32 e32_nrestab; + /** The size of the non-resident name table. */ + KU32 e32_cbnrestab; + KU32 e32_nressum; + KU32 e32_autodata; + KU32 e32_debuginfo; + KU32 e32_debuglen; + KU32 e32_instpreload; + KU32 e32_instdemand; + KU32 e32_heapsize; + KU32 e32_stacksize; + KU8 e32_res3[20]; +}; + +/** e32_magic[0] */ +#define E32MAGIC1 'L' +/** e32_magic[1] */ +#define E32MAGIC2 'X' +/** MAKEWORD(e32_magic[0], e32_magic[1]) */ +#define E32MAGIC 0x584c +/** e32_border - little endian */ +#define E32LEBO 0 +/** e32_border - big endian */ +#define E32BEBO 1 +/** e32_worder - little endian */ +#define E32LEWO 0 +/** e32_worder - big endian */ +#define E32BEWO 1 +/** e32_level */ +#define E32LEVEL KU32_C(0) +/** e32_cpu - 80286 */ +#define E32CPU286 1 +/** e32_cpu - 80386 */ +#define E32CPU386 2 +/** e32_cpu - 80486 */ +#define E32CPU486 3 +/** e32_pagesize */ +#define OBJPAGELEN KU32_C(0x1000) + + +/** @name e32_mflags + * @{ */ +/** App Type: Fullscreen only. */ +#define E32NOPMW KU32_C(0x00000100) +/** App Type: PM API. */ +#define E32PMAPI KU32_C(0x00000300) +/** App Type: PM VIO compatible. */ +#define E32PMW KU32_C(0x00000200) +/** Application type mask. */ +#define E32APPMASK KU32_C(0x00000300) +/** Executable module. */ +#define E32MODEXE KU32_C(0x00000000) +/** Dynamic link library (DLL / library) module. */ +#define E32MODDLL KU32_C(0x00008000) +/** Protected memory DLL. */ +#define E32PROTDLL KU32_C(0x00010000) +/** Physical Device Driver. */ +#define E32MODPDEV KU32_C(0x00020000) +/** Virtual Device Driver. */ +#define E32MODVDEV KU32_C(0x00028000) +/** Device driver */ +#define E32DEVICE E32MODPDEV +/** Dynamic link library (DLL / library) module. */ +#define E32NOTP E32MODDLL +/** Protected memory DLL. */ +#define E32MODPROTDLL (E32MODDLL | E32PROTDLL) +/** Module Type mask. */ +#define E32MODMASK KU32_C(0x00038000) +/** Not loadable (linker error). */ +#define E32NOLOAD KU32_C(0x00002000) +/** No internal fixups. */ +#define E32NOINTFIX KU32_C(0x00000010) +/** No external fixups (i.e. imports). */ +#define E32NOEXTFIX KU32_C(0x00000020) +/** System DLL, no internal fixups. */ +#define E32SYSDLL KU32_C(0x00000008) +/** Global (set) or per instance (cleared) library initialization. */ +#define E32LIBINIT KU32_C(0x00000004) +/** Global (set) or per instance (cleared) library termination. */ +#define E32LIBTERM KU32_C(0x40000000) +/** Indicates when set in an executable that the process isn't SMP safe. */ +#define E32NOTMPSAFE KU32_C(0x00080000) +/** @} */ + +/** @name Relocations (aka Fixups). + * @{ */ +typedef union _offset +{ + KU16 offset16; + KU32 offset32; +} offset; + +/** A relocation. + * @remark this structure isn't very usable since LX relocations comes in too many size variations. + */ +struct r32_rlc +{ + KU8 nr_stype; + KU8 nr_flags; + KI16 r32_soff; + KU16 r32_objmod; + + union targetid + { + offset intref; + union extfixup + { + offset proc; + KU32 ord; + } extref; + struct addfixup + { + KU16 entry; + offset addval; + } addfix; + } r32_target; + KU16 r32_srccount; + KU16 r32_chain; +}; + +/** @name Some attempt at size constanstants. + * @{ + */ +#define RINTSIZE16 8 +#define RINTSIZE32 10 +#define RORDSIZE 8 +#define RNAMSIZE16 8 +#define RNAMSIZE32 10 +#define RADDSIZE16 10 +#define RADDSIZE32 12 +/** @} */ + +/** @name nr_stype (source flags) + * @{ */ +#define NRSBYT 0x00 +#define NRSSEG 0x02 +#define NRSPTR 0x03 +#define NRSOFF 0x05 +#define NRPTR48 0x06 +#define NROFF32 0x07 +#define NRSOFF32 0x08 +#define NRSTYP 0x0f +#define NRSRCMASK 0x0f +#define NRALIAS 0x10 +#define NRCHAIN 0x20 +/** @} */ + +/** @name nr_flags (target flags) + * @{ */ +#define NRRINT 0x00 +#define NRRORD 0x01 +#define NRRNAM 0x02 +#define NRRENT 0x03 +#define NRRTYP 0x03 +#define NRADD 0x04 +#define NRICHAIN 0x08 +#define NR32BITOFF 0x10 +#define NR32BITADD 0x20 +#define NR16OBJMOD 0x40 +#define NR8BITORD 0x80 +/** @} */ + +/** @} */ + + +/** @name The Object Table (aka segment table) + * @{ */ + +/** The Object Table Entry. */ +struct o32_obj +{ + /** The size of the object. */ + KU32 o32_size; + /** The base address of the object. */ + KU32 o32_base; + /** Object flags. */ + KU32 o32_flags; + /** Page map index. */ + KU32 o32_pagemap; + /** Page map size. (doesn't need to be o32_size >> page shift). */ + KU32 o32_mapsize; + /** Reserved */ + KU32 o32_reserved; +}; + +/** @name o32_flags + * @{ */ +/** Read access. */ +#define OBJREAD KU32_C(0x00000001) +/** Write access. */ +#define OBJWRITE KU32_C(0x00000002) +/** Execute access. */ +#define OBJEXEC KU32_C(0x00000004) +/** Resource object. */ +#define OBJRSRC KU32_C(0x00000008) +/** The object is discarable (i.e. don't swap, just load in pages from the executable). + * This overlaps a bit with object type. */ +#define OBJDISCARD KU32_C(0x00000010) +/** The object is shared. */ +#define OBJSHARED KU32_C(0x00000020) +/** The object has preload pages. */ +#define OBJPRELOAD KU32_C(0x00000040) +/** The object has invalid pages. */ +#define OBJINVALID KU32_C(0x00000080) +/** Non-permanent, link386 bug. */ +#define LNKNONPERM KU32_C(0x00000600) +/** Non-permanent, correct 'value'. */ +#define OBJNONPERM KU32_C(0x00000000) +/** Obj Type: The object is permanent and swappable. */ +#define OBJPERM KU32_C(0x00000100) +/** Obj Type: The object is permanent and resident (i.e. not swappable). */ +#define OBJRESIDENT KU32_C(0x00000200) +/** Obj Type: The object is resident and contigious. */ +#define OBJCONTIG KU32_C(0x00000300) +/** Obj Type: The object is permanent and long locable. */ +#define OBJDYNAMIC KU32_C(0x00000400) +/** Object type mask. */ +#define OBJTYPEMASK KU32_C(0x00000700) +/** x86: The object require an 16:16 alias. */ +#define OBJALIAS16 KU32_C(0x00001000) +/** x86: Big/Default selector setting, i.e. toggle 32-bit or 16-bit. */ +#define OBJBIGDEF KU32_C(0x00002000) +/** x86: conforming selector setting (weird stuff). */ +#define OBJCONFORM KU32_C(0x00004000) +/** x86: IOPL. */ +#define OBJIOPL KU32_C(0x00008000) +/** @} */ + +/** A Object Page Map Entry. */ +struct o32_map +{ + /** The file offset of the page. */ + KU32 o32_pagedataoffset; + /** The number of bytes of raw page data. */ + KU16 o32_pagesize; + /** Per page flags describing how the page is encoded in the file. */ + KU16 o32_pageflags; +}; + +/** @name o32 o32_pageflags + * @{ + */ +/** Raw page (uncompressed) in the file. */ +#define VALID KU16_C(0x0000) +/** RLE encoded page in file. */ +#define ITERDATA KU16_C(0x0001) +/** Invalid page, nothing in the file. */ +#define INVALID KU16_C(0x0002) +/** Zero page, nothing in file. */ +#define ZEROED KU16_C(0x0003) +/** range of pages (what is this?) */ +#define RANGE KU16_C(0x0004) +/** Compressed page in file. */ +#define ITERDATA2 KU16_C(0x0005) +/** @} */ + + +/** Iteration Record format (RLE compressed page). */ +struct LX_Iter +{ + /** Number of iterations. */ + KU16 LX_nIter; + /** The number of bytes that's being iterated. */ + KU16 LX_nBytes; + /** The bytes. */ + KU8 LX_Iterdata; +}; + +/** @} */ + + +/** A Resource Table Entry */ +struct rsrc32 +{ + /** Resource Type. */ + KU16 type; + /** Resource ID. */ + KU16 name; + /** Resource size in bytes. */ + KU32 cb; + /** The index of the object containing the resource. */ + KU16 obj; + /** Offset of the resource that within the object. */ + KU32 offset; +}; + + +/** @name The Entry Table (aka Export Table) + * @{ */ + +/** Entry bundle. + * Header descripting up to 255 entries that follows immediatly after this structure. */ +struct b32_bundle +{ + /** The number of entries. */ + KU8 b32_cnt; + /** The type of bundle. */ + KU8 b32_type; + /** The index of the object containing these entry points. */ + KU16 b32_obj; +}; + +/** @name b32_type + * @{ */ +/** Empty bundle, filling up unused ranges of ordinals. */ +#define EMPTY 0x00 +/** 16-bit offset entry point. */ +#define ENTRY16 0x01 +/** 16-bit callgate entry point. */ +#define GATE16 0x02 +/** 32-bit offset entry point. */ +#define ENTRY32 0x03 +/** Forwarder entry point. */ +#define ENTRYFWD 0x04 +/** Typing information present indicator. */ +#define TYPEINFO 0x80 +/** @} */ + + +/** Entry point. */ +struct e32_entry +{ + /** Entry point flags */ + KU8 e32_flags; /* Entry point flags */ + union entrykind + { + /** ENTRY16 or ENTRY32. */ + offset e32_offset; + /** GATE16 */ + struct callgate + { + /** Offset into segment. */ + KU16 offset; + /** The callgate selector */ + KU16 callgate; + } e32_callgate; + /** ENTRYFWD */ + struct fwd + { + /** Module ordinal number (i.e. into the import module table). */ + KU16 modord; + /** Procedure name or ordinal number. */ + KU32 value; + } e32_fwd; + } e32_variant; +}; + +/** @name e32_flags + * @{ */ +/** Exported entry (set) or private entry (clear). */ +#define E32EXPORT 0x01 +/** Uses shared data. */ +#define E32SHARED 0x02 +/** Parameter word count mask. */ +#define E32PARAMS 0xf8 +/** ENTRYFWD: Imported by ordinal (set) or by name (clear). */ +#define FWD_ORDINAL 0x01 +/** @} */ + +/** @name dunno + * @{ */ +#define FIXENT16 3 +#define FIXENT32 5 +#define GATEENT16 5 +#define FWDENT 7 +/** @} */ + +#pragma pack() + +#endif + diff --git a/src/lib/kStuff/include/k/kLdrFmts/mach-o.h b/src/lib/kStuff/include/k/kLdrFmts/mach-o.h new file mode 100644 index 0000000..61f908c --- /dev/null +++ b/src/lib/kStuff/include/k/kLdrFmts/mach-o.h @@ -0,0 +1,997 @@ +/* $Id: mach-o.h 63 2013-10-30 02:00:14Z bird $ */ +/** @file + * Mach-0 structures, types and defines. + */ + +/* + * Copyright (c) 2006-2012 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kLdrFmts_mach_o_h___ +#define ___k_kLdrFmts_mach_o_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> + + +/** @defgroup grp_mach_o The Mach-O Structures, Types, and Defines. + * @{ + */ + + +#ifndef IMAGE_FAT_SIGNATURE +/** The FAT signature (universal binaries). */ +# define IMAGE_FAT_SIGNATURE KU32_C(0xcafebabe) +#endif +#ifndef IMAGE_FAT_SIGNATURE_OE +/** The FAT signature (universal binaries), other endian. */ +# define IMAGE_FAT_SIGNATURE_OE KU32_C(0xbebafeca) +#endif + +/** + * The fat header found at the start of universal binaries. + * It is followed by \a nfat_arch numbers of \a fat_arch structures. + */ +typedef struct fat_header +{ + KU32 magic; + KU32 nfat_arch; +} fat_header_t; + +/** + * Description of fat file item. + */ +typedef struct fat_arch +{ + KI32 cputype; + KI32 cpusubtype; + KU32 offset; + KU32 size; + KU32 align; /**< Power of 2. */ +} fat_arch_t; + + + +#ifndef IMAGE_MACHO32_SIGNATURE +/** The 32-bit Mach-O signature. */ +# define IMAGE_MACHO32_SIGNATURE KU32_C(0xfeedface) +#endif +#ifndef IMAGE_MACHO32_SIGNATURE_OE +/** The 32-bit Mach-O signature, other endian. */ +# define IMAGE_MACHO32_SIGNATURE_OE KU32_C(0xcefaedfe) +#endif +#define MH_MAGIC IMAGE_MACHO32_SIGNATURE +#define MH_CIGAM IMAGE_MACHO32_SIGNATURE_OE + +/** + * 32-bit Mach-O header. + * This is followed by \a ncmds number of load commands. + * @see mach_header_64 + */ +typedef struct mach_header_32 +{ + KU32 magic; + KI32 cputype; + KI32 cpusubtype; + KU32 filetype; + KU32 ncmds; + KU32 sizeofcmds; + KU32 flags; +} mach_header_32_t; + + + +#ifndef IMAGE_MACHO64_SIGNATURE +/** The 64-bit Mach-O signature. */ +# define IMAGE_MACHO64_SIGNATURE KU32_C(0xfeedfacf) +#endif +#ifndef IMAGE_MACHO64_SIGNATURE_OE +/** The 64-bit Mach-O signature, other endian. */ +# define IMAGE_MACHO64_SIGNATURE_OE KU32_C(0xfefaedfe) +#endif +#define MH_MAGIC_64 IMAGE_MACHO64_SIGNATURE +#define MH_CIGAM_64 IMAGE_MACHO64_SIGNATURE_OE + +/** + * 64-bit Mach-O header. + * This is followed by \a ncmds number of load commands. + * @see mach_header + */ +typedef struct mach_header_64 +{ + KU32 magic; + KI32 cputype; + KI32 cpusubtype; + KU32 filetype; + KU32 ncmds; + KU32 sizeofcmds; + KU32 flags; + KU32 reserved; /**< (for proper struct and command alignment I guess) */ +} mach_header_64_t; + + +/** @name File types (mach_header_64::filetype, mach_header_32::filetype) + * @{ + */ +#define MH_OBJECT KU32_C(1) /**< Object (relocatable). */ +#define MH_EXECUTE KU32_C(2) /**< Executable (demand paged). */ +#define MH_FVMLIB KU32_C(3) /**< Fixed VM shared library. */ +#define MH_CORE KU32_C(4) /**< Core file. */ +#define MH_PRELOAD KU32_C(5) /**< Preloaded executable. */ +#define MH_DYLIB KU32_C(6) /**< Dynamically bound shared library. */ +#define MH_DYLINKER KU32_C(7) /**< Dynamic linker. */ +#define MH_BUNDLE KU32_C(8) /**< Dymamically bound bundle. */ +#define MH_DYLIB_STUB KU32_C(9) /**< Shared library stub for static linking. */ +#define MH_DSYM KU32_C(10)/**< Debug symbols. */ +#define MH_KEXT_BUNDLE KU32_C(11)/**< Kernel extension (introduced with the AMD64 kernel). */ + +/** @} */ + + +/** @name Mach-O Header flags (mach_header_64::flags, mach_header_32::flags) + * @{ + */ +#define MH_NOUNDEFS KU32_C(0x00000001) /**< No undefined symbols. */ +#define MH_INCRLINK KU32_C(0x00000002) /**< Partial increment link output. */ +#define MH_DYLDLINK KU32_C(0x00000004) /**< Food for the dynamic linker, not for ld. */ +#define MH_BINDATLOAD KU32_C(0x00000008) /**< Bind all undefined symbols at load time. */ +#define MH_PREBOUND KU32_C(0x00000010) /**< Contains prebound undefined symbols. */ +#define MH_SPLIT_SEGS KU32_C(0x00000020) /**< Read-only and read-write segments are split. */ +#define MH_LAZY_INIT KU32_C(0x00000040) /**< Obsolete flag for doing lazy init when data is written. */ +#define MH_TWOLEVEL KU32_C(0x00000080) /**< Uses two-level name space bindings. */ +#define MH_FORCE_FLAT KU32_C(0x00000100) /**< Task: The executable forces all images to use flat name space bindings. */ +#define MH_NOMULTIDEFS KU32_C(0x00000200) /**< No multiple symbol definitions, safe to use two-level namespace hints. */ +#define MH_NOFIXPREBINDING KU32_C(0x00000400) /**< The dynamic linker should not notify the prebinding agent about this executable. */ +#define MH_PREBINDABLE KU32_C(0x00000800) /**< Not prebound, but it can be. Invalid if MH_PREBOUND is set. */ +#define MH_ALLMODSBOUND KU32_C(0x00001000) /**< Binds to all two-level namespace modules of preqs. Requires MH_PREBINDABLE and MH_TWOLEVEL to be set. */ +#define MH_SUBSECTIONS_VIA_SYMBOLS KU32_C(0x00002000) /**< Safe to divide sections into sub-sections via symbols for dead code stripping. */ +#define MH_CANONICAL KU32_C(0x00004000) /**< Canonicalized via unprebind. */ +#define MH_WEAK_DEFINES KU32_C(0x00008000) /**< The (finally) linked image has weak symbols. */ +#define MH_BINDS_TO_WEAK KU32_C(0x00010000) /**< The (finally) linked image uses weak symbols. */ +#define MH_ALLOW_STACK_EXECUTION KU32_C(0x00020000) /**< Task: allow stack execution. (MH_EXECUTE only) */ +#define MH_ROOT_SAFE KU32_C(0x00040000) /**< Binary safe for root execution. */ +#define MH_SETUID_SAFE KU32_C(0x00080000) /**< Binary safe for set-uid execution. */ +#define MH_NO_REEXPORTED_DYLIBS KU32_C(0x00100000) /**< No reexported dylibs. */ +#define MH_PIE KU32_C(0x00200000) /**< Address space randomization. (MH_EXECUTE only) */ +#define MH_DEAD_STRIPPABLE_DYLIB KU32_C(0x00400000) /**< Drop dylib dependency if not used. (MH_DYLIB only) */ +#define MH_HAS_TLV_DESCRIPTORS KU32_C(0x00800000) /**< Has a S_TRHEAD_LOCAL_VARIABLES section. TLS support. */ +#define MH_NO_HEAP_EXECUTION KU32_C(0x01000000) /**< Task: no heap execution. (MH_EXECUTE only) */ +#define MH_VALID_FLAGS KU32_C(0x01ffffff) /**< Mask containing the defined flags. */ +/** @} */ + + +/** @name CPU types / bits (mach_header_64::cputype, mach_header_32::cputype, fat_arch::cputype) + * @{ + */ +#define CPU_ARCH_MASK KI32_C(0xff000000) +#define CPU_ARCH_ABI64 KI32_C(0x01000000) +#define CPU_TYPE_ANY KI32_C(-1) +#define CPU_TYPE_VAX KI32_C(1) +#define CPU_TYPE_MC680x0 KI32_C(6) +#define CPU_TYPE_X86 KI32_C(7) +#define CPU_TYPE_I386 CPU_TYPE_X86 +#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) +#define CPU_TYPE_MC98000 KI32_C(10) +#define CPU_TYPE_HPPA KI32_C(11) +#define CPU_TYPE_MC88000 KI32_C(13) +#define CPU_TYPE_SPARC KI32_C(14) +#define CPU_TYPE_I860 KI32_C(15) +#define CPU_TYPE_POWERPC KI32_C(18) +#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) +/** @} */ + + +/** @name CPU subtypes (mach_header_64::cpusubtype, mach_header_32::cpusubtype, fat_arch::cpusubtype) + * @{ */ +#define CPU_SUBTYPE_MULTIPLE KI32_C(-1) +#define CPU_SUBTYPE_LITTLE_ENDIAN KI32_C(0) /**< figure this one out. */ +#define CPU_SUBTYPE_BIG_ENDIAN KI32_C(1) /**< ditto */ + +/* VAX */ +#define CPU_SUBTYPE_VAX_ALL KI32_C(0) +#define CPU_SUBTYPE_VAX780 KI32_C(1) +#define CPU_SUBTYPE_VAX785 KI32_C(2) +#define CPU_SUBTYPE_VAX750 KI32_C(3) +#define CPU_SUBTYPE_VAX730 KI32_C(4) +#define CPU_SUBTYPE_UVAXI KI32_C(5) +#define CPU_SUBTYPE_UVAXII KI32_C(6) +#define CPU_SUBTYPE_VAX8200 KI32_C(7) +#define CPU_SUBTYPE_VAX8500 KI32_C(8) +#define CPU_SUBTYPE_VAX8600 KI32_C(9) +#define CPU_SUBTYPE_VAX8650 KI32_C(10) +#define CPU_SUBTYPE_VAX8800 KI32_C(11) +#define CPU_SUBTYPE_UVAXIII KI32_C(12) + +/* MC680xx */ +#define CPU_SUBTYPE_MC680x0_ALL KI32_C(1) +#define CPU_SUBTYPE_MC68030 KI32_C(1) +#define CPU_SUBTYPE_MC68040 KI32_C(2) +#define CPU_SUBTYPE_MC68030_ONLY KI32_C(3) + +/* I386 */ +#define CPU_SUBTYPE_INTEL(fam, model) ( (KI32)(((model) << 4) | (fam)) ) +#define CPU_SUBTYPE_INTEL_FAMILY(subtype) ( (subtype) & 0xf ) +#define CPU_SUBTYPE_INTEL_MODEL(subtype) ( (subtype) >> 4 ) +#define CPU_SUBTYPE_INTEL_FAMILY_MAX 0xf +#define CPU_SUBTYPE_INTEL_MODEL_ALL 0 + +#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0) +#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0) +#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0) +#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) +#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0) +#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0) +#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1) +#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3) +#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5) +#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6) +#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7) +#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0) +#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1) +#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2) +#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0) +#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0) +#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1) +#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0) +#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1) +#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0) +#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1) + +/* X86 */ +#define CPU_SUBTYPE_X86_ALL KI32_C(3) /* CPU_SUBTYPE_I386_ALL */ +#define CPU_SUBTYPE_X86_64_ALL KI32_C(3) /* CPU_SUBTYPE_I386_ALL */ +#define CPU_SUBTYPE_X86_ARCH1 KI32_C(4) /* CPU_SUBTYPE_I486_ALL */ + +/* MIPS */ +#define CPU_SUBTYPE_MIPS_ALL KI32_C(0) +#define CPU_SUBTYPE_MIPS_R2300 KI32_C(1) +#define CPU_SUBTYPE_MIPS_R2600 KI32_C(2) +#define CPU_SUBTYPE_MIPS_R2800 KI32_C(3) +#define CPU_SUBTYPE_MIPS_R2000a KI32_C(4) +#define CPU_SUBTYPE_MIPS_R2000 KI32_C(5) +#define CPU_SUBTYPE_MIPS_R3000a KI32_C(6) +#define CPU_SUBTYPE_MIPS_R3000 KI32_C(7) + +/* MC98000 (PowerPC) */ +#define CPU_SUBTYPE_MC98000_ALL KI32_C(0) +#define CPU_SUBTYPE_MC98601 KI32_C(1) + +/* HP-PA */ +#define CPU_SUBTYPE_HPPA_ALL KI32_C(0) +#define CPU_SUBTYPE_HPPA_7100 KI32_C(0) +#define CPU_SUBTYPE_HPPA_7100LC KI32_C(1) + +/* MC88000 */ +#define CPU_SUBTYPE_MC88000_ALL KI32_C(0) +#define CPU_SUBTYPE_MC88100 KI32_C(1) +#define CPU_SUBTYPE_MC88110 KI32_C(2) + +/* SPARC */ +#define CPU_SUBTYPE_SPARC_ALL KI32_C(0) + +/* I860 */ +#define CPU_SUBTYPE_I860_ALL KI32_C(0) +#define CPU_SUBTYPE_I860_860 KI32_C(1) + +/* PowerPC */ +#define CPU_SUBTYPE_POWERPC_ALL KI32_C(0) +#define CPU_SUBTYPE_POWERPC_601 KI32_C(1) +#define CPU_SUBTYPE_POWERPC_602 KI32_C(2) +#define CPU_SUBTYPE_POWERPC_603 KI32_C(3) +#define CPU_SUBTYPE_POWERPC_603e KI32_C(4) +#define CPU_SUBTYPE_POWERPC_603ev KI32_C(5) +#define CPU_SUBTYPE_POWERPC_604 KI32_C(6) +#define CPU_SUBTYPE_POWERPC_604e KI32_C(7) +#define CPU_SUBTYPE_POWERPC_620 KI32_C(8) +#define CPU_SUBTYPE_POWERPC_750 KI32_C(9) +#define CPU_SUBTYPE_POWERPC_7400 KI32_C(10) +#define CPU_SUBTYPE_POWERPC_7450 KI32_C(11) +#define CPU_SUBTYPE_POWERPC_Max KI32_C(10) +#define CPU_SUBTYPE_POWERPC_SCVger KI32_C(11) +#define CPU_SUBTYPE_POWERPC_970 KI32_C(100) + +/* Subtype capability / feature bits, added in 10.5. X86 only? */ +#define CPU_SUBTYPE_MASK KU32_C(0xff000000) +#define CPU_SUBTYPE_LIB64 KU32_C(0x8000000) + +/** @} */ + + + +/** @defgroup grp_macho_o_lc Load Commands + * @{ */ + +/** + * The load command common core structure. + * + * After the Mach-O header follows an array of variable sized + * load command which all has this header in common. + */ +typedef struct load_command +{ + KU32 cmd; /**< The load command id. */ + KU32 cmdsize; /**< The size of the command (including this header). */ +} load_command_t; + +/** @name Load Command IDs (load_command::cmd) + * @{ + */ +/** Flag that when set requires the dynamic linker to fail if it doesn't + * grok the command. The dynamic linker will otherwise ignore commands it + * doesn't understand. Introduced with Mac OS X 10.1. */ +#define LC_REQ_DYLD KU32_C(0x80000000) + +#define LC_SEGMENT_32 KU32_C(0x01) /**< Segment to be mapped (32-bit). See segment_command_32. */ +#define LC_SYMTAB KU32_C(0x02) /**< 'stab' symbol table. See symtab_command. */ +#define LC_SYMSEG KU32_C(0x03) /**< Obsoleted gdb symbol table. */ +#define LC_THREAD KU32_C(0x04) /**< Thread. See thread_command. */ +#define LC_UNIXTHREAD KU32_C(0x05) /**< Unix thread (includes stack and stuff). See thread_command. */ +#define LC_LOADFVMLIB KU32_C(0x06) /**< Load a specified fixed VM shared library (obsolete?). See fvmlib_command. */ +#define LC_IDFVMLIB KU32_C(0x07) /**< Fixed VM shared library id (obsolete?). See fvmlib_command. */ +#define LC_IDENT KU32_C(0x08) /**< Identification info (obsolete). See ident_command. */ +#define LC_FVMFILE KU32_C(0x09) /**< Fixed VM file inclusion (internal). See fvmfile_command. */ +#define LC_PREPAGE KU32_C(0x0a) /**< Prepage command (internal). See ?? */ +#define LC_DYSYMTAB KU32_C(0x0b) /**< Symbol table for dynamic linking. See dysymtab_command. */ +#define LC_LOAD_DYLIB KU32_C(0x0c) /**< Load a dynamically linked shared library. See dylib_command. */ +#define LC_ID_DYLIB KU32_C(0x0d) /**< Dynamically linked share library ident. See dylib_command. */ +#define LC_LOAD_DYLINKER KU32_C(0x0e) /**< Load a dynamical link editor. See dylinker_command. */ +#define LC_ID_DYLINKER KU32_C(0x0f) /**< Dynamic link editor ident. See dylinker_command. */ +#define LC_PREBOUND_DYLIB KU32_C(0x10) /**< Prebound modules for dynamically linking of a shared lib. See prebound_dylib_command. */ +#define LC_ROUTINES KU32_C(0x11) /**< Image routines. See routines_command_32. */ +#define LC_SUB_FRAMEWORK KU32_C(0x12) /**< Sub framework. See sub_framework_command. */ +#define LC_SUB_UMBRELLA KU32_C(0x13) /**< Sub umbrella. See sub_umbrella_command. */ +#define LC_SUB_CLIENT KU32_C(0x14) /**< Sub client. See sub_client_command. */ +#define LC_SUB_LIBRARY KU32_C(0x15) /**< Sub library. See sub_library_command. */ +#define LC_TWOLEVEL_HINTS KU32_C(0x16) /**< Two-level namespace lookup hints. See twolevel_hints_command. */ +#define LC_PREBIND_CKSUM KU32_C(0x17) /**< Prebind checksum. See prebind_cksum_command. */ +#define LC_LOAD_WEAK_DYLIB (KU32_C(0x18) | LC_REQ_DYLD) /**< Dylib that can be missing, all symbols weak. See dylib_command. */ +#define LC_SEGMENT_64 KU32_C(0x19) /**< segment to be mapped (64-bit). See segment_command_32. */ +#define LC_ROUTINES_64 KU32_C(0x1a) /**< Image routines (64-bit). See routines_command_32. */ +#define LC_UUID KU32_C(0x1b) /**< The UUID of the object module. See uuid_command. */ +#define LC_RPATH (KU32_C(0x1c) | LC_REQ_DYLD) /**< Runpth additions. See rpath_command. */ +#define LC_CODE_SIGNATURE KU32_C(0x1d) /**< Code signature location. See linkedit_data_command. */ +#define LC_SEGMENT_SPLIT_INFO KU32_C(0x1e)/**< Segment split info location. See linkedit_data_command. */ +#define LC_REEXPORT_DYLIB (KU32_C(0x1f) | LC_REQ_DYLD)/**< Load and re-export the given dylib - DLL forwarding. See dylib_command. */ +#define LC_LAZY_LOAD_DYLIB KU32_C(0x20) /**< Delays loading of the given dylib until used. See dylib_command? */ +#define LC_ENCRYPTION_INFO KU32_C(0x21) /**< Segment encryption information. See encryption_info_command. */ +#define LC_DYLD_INFO KU32_C(0x22) /**< Compressed dylib relocation information, alternative present. See dyld_info_command. */ +#define LC_DYLD_INFO_ONLY (KU32_C(0x22) | LC_REQ_DYLD) /**< Compressed dylib relocation information, no alternative. See dyld_info_command. */ +#define LC_LOAD_UPWARD_DYLIB KU32_C(0x23) /**< ???? */ +#define LC_VERSION_MIN_MACOSX KU32_C(0x24) /**< The image requires the given Mac OS X version. See version_min_command. */ +#define LC_VERSION_MIN_IPHONEOS KU32_C(0x25) /**< The image requires the given iOS version. See version_min_command. */ +#define LC_FUNCTION_STARTS KU32_C(0x26) /**< Where to find the compress function start addresses. See linkedit_data_command. */ +#define LC_DYLD_ENVIRONMENT KU32_C(0x27) /**< Environment variable for the dynamic linker. See dylinker_command. */ +#define LC_MAIN (KU32_C(0x28) | LC_REQ_DYLD) /**< Simpler alternative to LC_UNIXTHREAD. */ +#define LC_DATA_IN_CODE KU32_C(0x29) /**< Table of data in the the text section. */ +#define LC_SOURCE_VERSION KU32_C(0x2a) /**< Source code revision / version hint. */ +#define LC_DYLIB_CODE_SIGN_DRS KU32_C(0x2b) /**< Code signing designated requirements copied from dylibs prequisites. */ +/** @} */ + + +/** + * Load Command String. + */ +typedef struct lc_str +{ + /** Offset of the string relative to the load_command structure. + * The string is zero-terminated. the size of the load command + * is zero padded up to a multiple of 4 bytes. */ + KU32 offset; +} lc_str_t; + + +/** + * Segment load command (32-bit). + */ +typedef struct segment_command_32 +{ + KU32 cmd; /**< LC_SEGMENT */ + KU32 cmdsize; /**< sizeof(self) + sections. */ + char segname[16]; /**< The segment name. */ + KU32 vmaddr; /**< Memory address of this segment. */ + KU32 vmsize; /**< Size of this segment. */ + KU32 fileoff; /**< The file location of the segment. */ + KU32 filesize; /**< The file size of the segment. */ + KU32 maxprot; /**< Maximum VM protection. */ + KU32 initprot; /**< Initial VM protection. */ + KU32 nsects; /**< Number of section desciptors following this structure. */ + KU32 flags; /**< Flags (SG_*). */ +} segment_command_32_t; + + +/** + * Segment load command (64-bit). + * Same as segment_command_32 except 4 members has been blown up to 64-bit. + */ +typedef struct segment_command_64 +{ + KU32 cmd; /**< LC_SEGMENT */ + KU32 cmdsize; /**< sizeof(self) + sections. */ + char segname[16]; /**< The segment name. */ + KU64 vmaddr; /**< Memory address of this segment. */ + KU64 vmsize; /**< Size of this segment. */ + KU64 fileoff; /**< The file location of the segment. */ + KU64 filesize; /**< The file size of the segment. */ + KU32 maxprot; /**< Maximum VM protection. */ + KU32 initprot; /**< Initial VM protection. */ + KU32 nsects; /**< Number of section desciptors following this structure. */ + KU32 flags; /**< Flags (SG_*). */ +} segment_command_64_t; + +/** @name Segment flags (segment_command_64::flags, segment_command_32::flags) + * @{ */ +/** Map the file bits in the top end of the memory area for the segment + * instead of the low end. Intended for stacks in core dumps. + * The part of the segment memory not covered by file bits will be zeroed. */ +#define SG_HIGHVM KU32_C(0x00000001) +/** This segment is the virtual memory allocated by a fixed VM library. + * (Used for overlap checking in the linker.) */ +#define SG_FVMLIB KU32_C(0x00000002) +/** No relocations for or symbols that's relocated to in this segment. + * The segment can therefore safely be replaced. */ +#define SG_NORELOC KU32_C(0x00000004) +/** The segment is protected. + * The first page isn't protected if it starts at file offset 0 + * (so that the mach header and this load command can be easily mapped). */ +#define SG_PROTECTED_VERSION_1 KU32_C(0x00000008) +/** @} */ + + +/** + * 32-bit section (part of a segment load command). + */ +typedef struct section_32 +{ + char sectname[16]; /**< The section name. */ + char segname[16]; /**< The name of the segment this section goes into. */ + KU32 addr; /**< The memory address of this section. */ + KU32 size; /**< The size of this section. */ + KU32 offset; /**< The file offset of this section. */ + KU32 align; /**< The section alignment (**2). */ + KU32 reloff; /**< The file offset of the relocations. */ + KU32 nreloc; /**< The number of relocations. */ + KU32 flags; /**< The section flags; section type and attribs */ + KU32 reserved1; /**< Reserved / offset / index. */ + KU32 reserved2; /**< Reserved / count / sizeof. */ +} section_32_t; + +/** + * 64-bit section (part of a segment load command). + */ +typedef struct section_64 +{ + char sectname[16]; /**< The section name. */ + char segname[16]; /**< The name of the segment this section goes into. */ + KU64 addr; /**< The memory address of this section. */ + KU64 size; /**< The size of this section. */ + KU32 offset; /**< The file offset of this section. */ + KU32 align; /**< The section alignment (**2). */ + KU32 reloff; /**< The file offset of the relocations. */ + KU32 nreloc; /**< The number of relocations. */ + KU32 flags; /**< The section flags; section type and attribs */ + KU32 reserved1; /**< Reserved / offset / index. */ + KU32 reserved2; /**< Reserved / count / sizeof. */ + KU32 reserved3; /**< (Just) Reserved. */ +} section_64_t; + +/** @name Section flags (section_64::flags, section_32::flags) + * @{ + */ +/** Section type mask. */ +#define SECTION_TYPE KU32_C(0x000000ff) +/** Regular section. */ +#define S_REGULAR 0x00 +/** Zero filled section. */ +#define S_ZEROFILL 0x01 +/** C literals. */ +#define S_CSTRING_LITERALS 0x02 +/** 4 byte literals. */ +#define S_4BYTE_LITERALS 0x03 +/** 8 byte literals. */ +#define S_8BYTE_LITERALS 0x04 +/** Pointer to literals. */ +#define S_LITERAL_POINTERS 0x05 +/** Section containing non-lazy symbol pointers. + * Reserved1 == start index in the indirect symbol table. */ +#define S_NON_LAZY_SYMBOL_POINTERS 0x06 +/** Section containing lazy symbol pointers. + * Reserved1 == start index in the indirect symbol table. */ +#define S_LAZY_SYMBOL_POINTERS 0x07 +/** Section containing symbol stubs. + * Reserved2 == stub size. */ +#define S_SYMBOL_STUBS 0x08 +/** Section containing function pointers for module initialization. . */ +#define S_MOD_INIT_FUNC_POINTERS 0x09 +/** Section containing function pointers for module termination. . */ +#define S_MOD_TERM_FUNC_POINTERS 0x0a +/** Section containing symbols that are to be coalesced. */ +#define S_COALESCED 0x0b +/** Zero filled section that be larger than 4GB. */ +#define S_GB_ZEROFILL 0x0c +/** Section containing pairs of function pointers for interposing. */ +#define S_INTERPOSING 0x0d +/** 16 byte literals. */ +#define S_16BYTE_LITERALS 0x0e +/** DTrace byte code / definitions (DOF = DTrace object format). */ +#define S_DTRACE_DOF 0x0f +/** Section containing pointers to symbols in lazily loaded dylibs. */ +#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 + +/** Section attribute mask. */ +#define SECTION_ATTRIBUTES KU32_C(0xffffff00) + +/** User settable attribute mask. */ +#define SECTION_ATTRIBUTES_USR KU32_C(0xff000000) +/** Pure instruction (code). */ +#define S_ATTR_PURE_INSTRUCTIONS KU32_C(0x80000000) +/** ranlib, ignore my symbols... */ +#define S_ATTR_NO_TOC KU32_C(0x40000000) +/** May strip static symbols when linking int a MH_DYLDLINK file. */ +#define S_ATTR_STRIP_STATIC_SYMS KU32_C(0x20000000) +/** No dead stripping. */ +#define S_ATTR_NO_DEAD_STRIP KU32_C(0x10000000) +/** Live support. */ +#define S_ATTR_LIVE_SUPPORT KU32_C(0x08000000) +/** Contains self modifying code (generally i386 code stub for dyld). */ +#define S_ATTR_SELF_MODIFYING_CODE KU32_C(0x04000000) +/** Debug info (DWARF usually). */ +#define S_ATTR_DEBUG KU32_C(0x02000000) + +/** System settable attribute mask. */ +#define SECTION_ATTRIBUTES_SYS KU32_C(0x00ffff00) +/** Contains some instructions (code). */ +#define S_ATTR_SOME_INSTRUCTIONS KU32_C(0x00000400) +/** Has external relocations. */ +#define S_ATTR_EXT_RELOC KU32_C(0x00000200) +/** Has internal (local) relocations. */ +#define S_ATTR_LOC_RELOC KU32_C(0x00000100) +/** @} */ + +/** @name Known Segment and Section Names. + * Some of these implies special linker behaviour. + * @{ + */ +/** Page zero - not-present page for catching invalid access. (MH_EXECUTE typically) */ +#define SEG_PAGEZERO "__PAGEZERO" +/** Traditional UNIX text segment. + * Defaults to R-X. */ +#define SEG_TEXT "__TEXT" +/** The text part of SEG_TEXT. */ +#define SECT_TEXT "__text" +/** The fvmlib initialization. */ +#define SECT_FVMLIB_INIT0 "__fvmlib_init0" +/** The section following the fvmlib initialization. */ +#define SECT_FVMLIB_INIT1 "__fvmlib_init1" +/** The traditional UNIX data segment. (DGROUP to DOS and OS/2 people.) */ +#define SEG_DATA "__DATA" +/** The initialized data section. */ +#define SECT_DATA "__data" +/** The uninitialized data section. */ +#define SECT_BSS "__bss" +/** The common symbol section. */ +#define SECT_COMMON "__common" +/** Objective-C runtime segment. */ +#define SEG_OBJC "__OBJC" +/** Objective-C symbol table section. */ +#define SECT_OBJC_SYMBOLS "__symbol_table" +/** Objective-C module information section. */ +#define SECT_OBJC_MODULES "__module_info" +/** Objective-C string table section. */ +#define SECT_OBJC_STRINGS "__selector_strs" +/** Objective-C string table section. */ +#define SECT_OBJC_REFS "__selector_refs" +/** Icon segment. */ +#define SEG_ICON "__ICON" +/** The icon headers. */ +#define SECT_ICON_HEADER "__header" +/** The icons in the TIFF format. */ +#define SECT_ICON_TIFF "__tiff" +/** ld -seglinkedit segment containing all the structs create and maintained + * by the linker. MH_EXECUTE and MH_FVMLIB only. */ +#define SEG_LINKEDIT "__LINKEDIT" +/** The unix stack segment. */ +#define SEG_UNIXSTACK "__UNIXSTACK" +/** The segment for the self modifying code for dynamic linking. + * Implies RWX permissions. */ +#define SEG_IMPORT "__IMPORT" +/** @} */ + + +/** @todo fvmlib */ +/** @todo fvmlib_command (LC_IDFVMLIB or LC_LOADFVMLIB) */ +/** @todo dylib */ +/** @todo dylib_command (LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, + * LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB) */ +/** @todo sub_framework_command (LC_SUB_FRAMEWORK) */ +/** @todo sub_client_command (LC_SUB_CLIENT) */ +/** @todo sub_umbrella_command (LC_SUB_UMBRELLA) */ +/** @todo sub_library_command (LC_SUB_LIBRARY) */ +/** @todo prebound_dylib_command (LC_PREBOUND_DYLIB) */ +/** @todo dylinker_command (LC_ID_DYLINKER or LC_LOAD_DYLINKER, + * LC_DYLD_ENVIRONMENT) */ + +/** + * Thread command. + * + * State description of a thread that is to be created. The description + * is made up of a number of state structures preceded by a 32-bit flavor + * and 32-bit count field stating the kind of stat structure and it's size + * in KU32 items respecitvly. + * + * LC_UNIXTHREAD differs from LC_THREAD in that it implies stack creation + * and that it's started with the typical main(int, char **, char **) frame + * on the stack. + */ +typedef struct thread_command +{ + KU32 cmd; /**< LC_UNIXTHREAD or LC_THREAD. */ + KU32 cmdsize; /**< The size of the command (including this header). */ +} thread_command_t; + + +/** @todo routines_command (LC_ROUTINES) */ +/** @todo routines_command_64 (LC_ROUTINES_64) */ + + +/** + * Symbol table command. + * Contains a.out style symbol table with some tricks. + */ +typedef struct symtab_command +{ + KU32 cmd; /**< LC_SYMTAB */ + KU32 cmdsize; /** sizeof(symtab_command_t) */ + KU32 symoff; /** The file offset of the symbol table. */ + KU32 nsyms; /** The number of symbols in the symbol table. */ + KU32 stroff; /** The file offset of the string table. */ + KU32 strsize; /** The size of the string table. */ +} symtab_command_t; + + +/** @todo dysymtab_command (LC_DYSYMTAB) */ +/** @todo dylib_table_of_contents */ +/** @todo dylib_module_32 */ +/** @todo dylib_module_64 */ +/** @todo dylib_reference */ +/** @todo twolevel_hints_command (LC_TWOLEVEL_HINTS) */ +/** @todo twolevel_hint */ +/** @todo prebind_cksum_command (LC_PREBIND_CKSUM) */ + + +/** + * UUID generated by ld. + */ +typedef struct uuid_command +{ + KU32 cmd; /**< LC_UUID */ + KU32 cmdsize; /**< sizeof(uuid_command_t) */ + KU8 uuid[16]; /** The UUID bytes. */ +} uuid_command_t; + + +/** @todo symseg_command (LC_SYMSEG) */ +/** @todo ident_command (LC_IDENT) */ +/** @todo fvmfile_command (LC_FVMFILE) */ +/** @todo rpath_command (LC_RPATH) */ + +typedef struct linkedit_data_command +{ + KU32 cmd; /**< LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS */ + KU32 cmdsize; /**< size of this structure. */ + KU32 dataoff; /**< Offset into the file of the data. */ + KU32 datasize; /**< The size of the data. */ +} linkedit_data_command_t; + +/** @todo encryption_info_command (LC_ENCRYPTION_INFO) */ +/** @todo dyld_info_command (LC_DYLD_INFO, LC_DYLD_INFO_ONLY) */ + +typedef struct version_min_command +{ + KU32 cmd; /**< LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS */ + KU32 cmdsize; /**< size of this structure. */ + KU32 version; /**< 31..16=major, 15..8=minor, 7..0=patch. */ + KU32 reserved; /**< MBZ. */ +} version_min_command_t; + +/** @} */ + + + +/** @defgroup grp_macho_o_syms Symbol Table + * @{ */ + +/** + * The 32-bit Mach-O version of the nlist structure. + * + * This differs from the a.out nlist struct in that the unused n_other field + * was renamed to n_sect and used for keeping the relevant section number. + * @remark This structure is not name mach_nlist_32 in the Apple headers, but nlist. + */ +typedef struct macho_nlist_32 +{ + union + { + KI32 n_strx; /**< Offset (index) into the string table. 0 means "". */ + } n_un; + KU8 n_type; /**< Symbol type. */ + KU8 n_sect; /**< Section number of NO_SECT. */ + KI16 n_desc; /**< Type specific, debug info details mostly.*/ + KU32 n_value; /**< The symbol value or stab offset. */ +} macho_nlist_32_t; + + +/** + * The 64-bit Mach-O version of the nlist structure. + * @see macho_nlist_32 + */ +typedef struct macho_nlist_64 +{ + union + { + KU32 n_strx; /**< Offset (index) into the string table. 0 means "". */ + } n_un; + KU8 n_type; /**< Symbol type. */ + KU8 n_sect; /**< Section number of NO_SECT. */ + KI16 n_desc; /**< Type specific, debug info details mostly.*/ + KU64 n_value; /**< The symbol value or stab offset. */ +} macho_nlist_64_t; + + +/** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type) + * + * In the Mach-O world n_type is somewhat similar to a.out, meaning N_EXT, N_UNDF, N_ABS + * and the debug symbols are essentially the same, but the remaining stuff is different. + * The main reason for this is that the encoding of section has been moved to n_sect + * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting + * the abs symbols and set vectors). + * + * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_ + * prefix here. + * + * Common symbols (aka communal symbols and comdefs) are represented by + * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving + * the size. + * + * + * Symbol table entries can be inserted directly in the assembly code using + * this notation: + * @code + * .stabs "n_name", n_type, n_sect, n_desc, n_value + * @endcode + * + * (1) The line number is optional, GCC doesn't set it. + * (2) The type is optional, GCC doesn't set it. + * (3) The binutil header is "skeptical" about the line. I'm skeptical about the whole thing... :-) + * (M) Mach-O specific? + * (S) Sun specific? + * @{ + */ + +/* Base masks. */ +#define MACHO_N_EXT KU8_C(0x01) /**< External symbol (when set) (N_EXT). */ +#define MACHO_N_TYPE KU8_C(0x0e) /**< Symbol type (N_TYPE without the 8th bit). */ +#define MACHO_N_PEXT KU8_C(0x10) /**< Private extern symbol (when set). (M) */ +#define MACHO_N_STAB KU8_C(0xe0) /**< Debug symbol mask (N_STAB). */ + +/* MACHO_N_TYPE values. */ +#define MACHO_N_UNDF KU8_C(0x00) /**< MACHO_N_TYPE: Undefined symbol (N_UNDF). n_sect = NO_SECT. */ +#define MACHO_N_ABS KU8_C(0x02) /**< MACHO_N_TYPE: Absolute symbol (N_UNDF). n_sect = NO_SECT. */ +#define MACHO_N_INDR KU8_C(0x0a) /**< MACHO_N_TYPE: Indirect symbol, n_value is the index of the symbol. (M) */ +#define MACHO_N_PBUD KU8_C(0x0c) /**< MACHO_N_TYPE: Prebound undefined symbo (defined in a dylib). (M) */ +#define MACHO_N_SECT KU8_C(0x0e) /**< MACHO_N_TYPE: Defined in the section given by n_sects. (M) */ + +/* Debug symbols. */ +#define MACHO_N_GSYM KU8_C(0x20) /**< Global variable. "name",, NO_SECT, type, 0 (2) */ +#define MACHO_N_FNAME KU8_C(0x22) /**< Function name (F77). "name",, NO_SECT, 0, 0 */ +#define MACHO_N_FUN KU8_C(0x24) /**< Function / text var. "name",, section, line, address (1) */ +#define MACHO_N_STSYM KU8_C(0x26) /**< Static data symbol. "name",, section, type, address (2) */ +#define MACHO_N_LCSYM KU8_C(0x28) /**< static bss symbol. "name",, section, type, address (2) */ + /* omits N_MAIN and N_ROSYM. */ +#define MACHO_N_BNSYM KU8_C(0x2e) /**< Begin nsect symbol. 0,, section, 0, address (M) */ +#define MACHO_N_PC KU8_C(0x30) /**< Global pascal symbol. "name",, NO_SECT, subtype?, line (3) */ + /* omits N_NSYMS, N_NOMAP and N_OBJ. */ +#define MACHO_N_OPT KU8_C(0x3c) /**< Options for the debugger related to the language of the + source file. "options?",,,, */ +#define MACHO_N_RSYM KU8_C(0x40) /**< Register variable. "name",, NO_SECT, type, register */ + /* omits N_M2C */ +#define MACHO_N_SLINE KU8_C(0x44) /**< Source line. 0,, section, line, address */ + /* omits N_DSLINE, N_BSLINE / N_BROWS, N_DEFD and N_FLINE. */ +#define MACHO_N_ENSYM KU8_C(0x4e) /**< End nsect symbol. 0,, section, 0, address (M) */ + /* omits N_EHDECL / N_MOD2 and N_CATCH. */ +#define MACHO_N_SSYM KU8_C(0x60) /**< Struct/union element. "name",, NO_SECT, type, offset */ + /* omits N_ENDM */ +#define MACHO_N_SO KU8_C(0x64) /**< Source file name. "fname",, section, 0, address */ +#define MACHO_N_OSO KU8_C(0x66) /**< Object file name. "fname",, 0, 0, st_mtime (M?) */ + /* omits N_ALIAS */ +#define MACHO_N_LSYM KU8_C(0x80) /**< Stack variable. "name",, NO_SECT, type, frame_offset */ +#define MACHO_N_BINCL KU8_C(0x82) /**< Begin #include. "fname",, NO_SECT, 0, sum? */ +#define MACHO_N_SOL KU8_C(0x84) /**< #included file. "fname",, section, 0, start_address (S) */ +#define MACHO_N_PARAMS KU8_C(0x86) /**< Compiler params. "params",, NO_SECT, 0, 0 */ +#define MACHO_N_VERSION KU8_C(0x88) /**< Compiler version. "version",, NO_SECT, 0, 0 */ +#define MACHO_N_OLEVEL KU8_C(0x8A) /**< Compiler -O level. "level",, NO_SECT, 0, 0 */ +#define MACHO_N_PSYM KU8_C(0xa0) /**< Parameter variable. "name",, NO_SECT, type, frame_offset */ +#define MACHO_N_EINCL KU8_C(0xa2) /**< End #include. "fname",, NO_SECT, 0, 0 (S) */ +#define MACHO_N_ENTRY KU8_C(0xa4) /**< Alternate entry point. "name",, section, line, address */ +#define MACHO_N_LBRAC KU8_C(0xc0) /**< Left bracket. 0,, NO_SECT, nesting_level, address */ +#define MACHO_N_EXCL KU8_C(0xc2) /**< Deleted include file. "fname",, NO_SECT, 0, sum? (S) */ + /* omits N_SCOPE */ +#define MACHO_N_RBRAC KU8_C(0xe0) /**< Right bracket. 0,, NO_SECT, nesting_level, address */ +#define MACHO_N_BCOMM KU8_C(0xe2) /**< Begin common. "name",, NO_SECT?, 0, 0 */ +#define MACHO_N_ECOMM KU8_C(0xe4) /**< End common. "name",, section, 0, 0 */ +#define MACHO_N_ECOML KU8_C(0xe8) /**< End local common. 0,, section, 0, address */ +#define MACHO_N_LENG KU8_C(0xfe) /**< Length-value of the preceding entry. + "name",, NO_SECT, 0, length */ + +/** @} */ + +/** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc) + * + * Mach-O puts the n_desc field to a number of uses, like lazy binding , library + * ordinal numbers for -twolevel_namespace, stripping and weak symbol handling. + * + * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit), + * they are more like enum values. + * @{ + */ + +#define REFERENCE_TYPE KU16_C(0x000f) /**< The reference type mask. */ +#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0 /**< Normal undefined symbol. */ +#define REFERENCE_FLAG_UNDEFINED_LAZY 1 /**< Lazy undefined symbol. */ +#define REFERENCE_FLAG_DEFINED 2 /**< Defined symbol (dynamic linking). */ +#define REFERENCE_FLAG_PRIVATE_DEFINED 3 /**< Defined private symbol (dynamic linking). */ +#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4 /**< Normal undefined private symbol. */ +#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5 /**< Lazy undefined private symbol. */ + +#define REFERENCED_DYNAMICALLY KU16_C(0x0010) /**< Don't strip. */ + + +/** Get the dynamic library ordinal. */ +#define GET_LIBRARY_ORDINAL(n_desc) \ + (((n_desc) >> 8) & 0xff) +/** Set the dynamic library ordinal. */ +#define SET_LIBRARY_ORDINAL(n_desc, ordinal) \ + (n_desc) = (((n_desc) & 0xff) | (((ordinal) & 0xff) << 8)) +#define SELF_LIBRARY_ORDINAL 0x00 /**< Special ordinal for refering to onself. */ +#define MAX_LIBRARY_ORDINAL 0xfd /**< Maximum ordinal number. */ +#define DYNAMIC_LOOKUP_ORDINAL 0xfe /**< Special ordinal number for dynamic lookup. (Mac OS X 10.3 and later) */ +#define EXECUTABLE_ORDINAL 0xff /**< Special ordinal number for the executable. */ + + +/** Only MH_OBJECT: Never dead strip me! */ +#define N_NO_DEAD_STRIP KU16_C(0x0020) +/** Not MH_OBJECT: Discarded symbol. */ +#define N_DESC_DISCARDED KU16_C(0x0020) +/** Weak external symbol. Symbol can be missing, in which case it's will have the value 0. */ +#define N_WEAK_REF KU16_C(0x0040) +/** Weak symbol definition. The symbol can be overridden by another weak + * symbol already present or by a non-weak (strong) symbol definition. + * Currently only supported for coalesed symbols. + * @remark This bit means something differently for undefined symbols, see N_REF_TO_WEAK. + */ +#define N_WEAK_DEF KU16_C(0x0080) +/** Reference to a weak symbol, resolve using flat namespace searching. + * @remark This bit means something differently for defined symbols, see N_WEAK_DEF. */ +#define N_REF_TO_WEAK KU16_C(0x0080) + +/** @} */ + +/** @} */ + + +/** @defgroup grp_macho_o_relocs Relocations + * @{ */ + +/** + * Relocation entry. + * + * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and + * that r_pad is made into r_type. + * + * @remark This structure and type has been prefixed with macho_ to avoid + * confusion with the original a.out type. + */ +typedef struct macho_relocation_info +{ + KI32 r_address; /**< Section relative address of the fixup. + The top bit (signed) indicates that this is a scattered + relocation if set, see scattered_relocation_info_t. */ + KU32 r_symbolnum : 24, /**< r_extern=1: Symbol table index, relocate with the address of this symbol. + r_extern=0: Section ordinal, relocate with the address of this section. */ + r_pcrel : 1, /**< PC (program counter) relative fixup; subtract the fixup address. */ + r_length : 2, /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. */ + r_extern : 1, /**< External or internal fixup, decides the r_symbolnum interpretation.. */ + r_type : 4; /**< Relocation type; 0 is standard, non-zero are machine specific. */ +} macho_relocation_info_t; + +/** Special section ordinal value for absolute relocations. */ +#define R_ABS 0 + +/** Flag in r_address indicating that the relocation is of the + * scattered_relocation_info_t kind and not macho_relocation_info_t. */ +#define R_SCATTERED KU32_C(0x80000000) + +/** + * Scattered relocation. + * + * This is a hack mainly for RISC machines which restricts section size + * to 16MB among other things. + * + * The reason for the big/little endian differences here is of course because + * of the R_SCATTERED mask and the way bitfields are implemented by the + * C/C++ compilers. + */ +typedef struct scattered_relocation_info +{ +#if K_ENDIAN == K_ENDIAN_LITTLE + KU32 r_address : 24, /**< Section relative address of the fixup. (macho_relocation_info_t::r_address) */ + r_type : 4, /**< Relocation type; 0 is standard, non-zero are machine specific. (macho_relocation_info_t::r_type) */ + r_length : 2, /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. (macho_relocation_info_t::r_length) */ + r_pcrel : 1, /**< PC (program counter) relative fixup; subtract the fixup address. (macho_relocation_info_t::r_pcrel) */ + r_scattered : 1; /**< Set if scattered relocation, clear if normal relocation. */ +#elif K_ENDIAN == K_ENDIAN_BIG + KU32 r_scattered : 1, /**< Set if scattered relocation, clear if normal relocation. */ + r_pcrel : 1, /**< PC (program counter) relative fixup; subtract the fixup address. (macho_relocation_info_t::r_pcrel) */ + r_length : 2, /**< Fixup length: 0=KU8, 1=KU16, 2=KU32, 3=KU64. (macho_relocation_info_t::r_length) */ + r_type : 4, /**< Relocation type; 0 is standard, non-zero are machine specific. (macho_relocation_info_t::r_type) */ + r_address : 24; /**< Section relative address of the fixup. (macho_relocation_info_t::r_address) */ +#else +# error "Neither K_ENDIAN isn't LITTLE or BIG!" +#endif + KI32 r_value; /**< The value the fixup is refering to (without offset added). */ +} scattered_relocation_info_t; + +/** + * Relocation type values for a generic implementation (for r_type). + */ +typedef enum reloc_type_generic +{ + GENERIC_RELOC_VANILLA = 0, /**< Standard relocation. */ + GENERIC_RELOC_PAIR, /**< Follows GENERIC_RELOC_SECTDIFF. */ + GENERIC_RELOC_SECTDIFF, /**< ??? */ + GENERIC_RELOC_PB_LA_PTR, /**< Prebound lazy pointer whatever that. */ + GENERIC_RELOC_LOCAL_SECTDIFF /**< ??? */ +} reloc_type_generic_t; + +/** + * Relocation type values for AMD64 (for r_type). + */ +typedef enum reloc_type_x86_64 +{ + X86_64_RELOC_UNSIGNED = 0, /**< Absolute address. */ + X86_64_RELOC_SIGNED, /**< Signed displacement. */ + X86_64_RELOC_BRANCH, /**< Branch displacement (jmp/call, adj by size). */ + X86_64_RELOC_GOT_LOAD, /**< GOT entry load. */ + X86_64_RELOC_GOT, /**< GOT reference. */ + X86_64_RELOC_SUBTRACTOR, /**< ??. */ + X86_64_RELOC_SIGNED_1, /**< Signed displacement with a -1 added. */ + X86_64_RELOC_SIGNED_2, /**< Signed displacement with a -2 added. */ + X86_64_RELOC_SIGNED_4 /**< Signed displacement with a -4 added. */ +} reloc_type_x86_64_t; + +/** @} */ + + +/** @} */ +#endif + diff --git a/src/lib/kStuff/include/k/kLdrFmts/mz.h b/src/lib/kStuff/include/k/kLdrFmts/mz.h new file mode 100644 index 0000000..b159cac --- /dev/null +++ b/src/lib/kStuff/include/k/kLdrFmts/mz.h @@ -0,0 +1,70 @@ +/* $Id: mz.h 31 2009-07-01 21:08:06Z bird $ */ +/** @file + * MZ structures, types and defines. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kLdrFmts_mz_h___ +#define ___k_kLdrFmts_mz_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> + +#pragma pack(1) /* not required */ + +typedef struct _IMAGE_DOS_HEADER +{ + KU16 e_magic; + KU16 e_cblp; + KU16 e_cp; + KU16 e_crlc; + KU16 e_cparhdr; + KU16 e_minalloc; + KU16 e_maxalloc; + KU16 e_ss; + KU16 e_sp; + KU16 e_csum; + KU16 e_ip; + KU16 e_cs; + KU16 e_lfarlc; + KU16 e_ovno; + KU16 e_res[4]; + KU16 e_oemid; + KU16 e_oeminfo; + KU16 e_res2[10]; + KU32 e_lfanew; +} IMAGE_DOS_HEADER; +typedef IMAGE_DOS_HEADER *PIMAGE_DOS_HEADER; + +#ifndef IMAGE_DOS_SIGNATURE +# define IMAGE_DOS_SIGNATURE K_LE2H_U16('M' | ('Z' << 8)) +#endif + +#pragma pack() + +#endif + diff --git a/src/lib/kStuff/include/k/kLdrFmts/pe.h b/src/lib/kStuff/include/k/kLdrFmts/pe.h new file mode 100644 index 0000000..42af4df --- /dev/null +++ b/src/lib/kStuff/include/k/kLdrFmts/pe.h @@ -0,0 +1,566 @@ +/* $Id: pe.h 92 2016-09-08 15:31:37Z bird $ */ +/** @file + * PE structures, types and defines. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kLdrFmts_pe_h___ +#define ___k_kLdrFmts_pe_h___ + + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include <k/kTypes.h> +#include <k/kDefs.h> + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +#ifndef IMAGE_NT_SIGNATURE +# define IMAGE_NT_SIGNATURE K_LE2H_U32('P' | ('E' << 8)) +#endif + +/* file header */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_EBC 0x0ebc + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_16BIT_MACHINE 0x0040 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +/** Raw UUID byte for the ANON_OBJECT_HEADER_BIGOBJ::ClassID value. + * These make out {d1baa1c7-baee-4ba9-af20-faf66aa4dcb8}. */ +#define ANON_OBJECT_HEADER_BIGOBJ_CLS_ID_BYTES \ + 0xc7, 0xa1, 0xba, 0xd1,/*-*/ 0xee, 0xba,/*-*/ 0xa9, 0x4b,/*-*/ 0xaf, 0x20,/*-*/ 0xfa, 0xf6, 0x6a, 0xa4, 0xdc, 0xb8 + +/* optional header */ +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10B +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20B + +#define IMAGE_SUBSYSTEM_UNKNOWN 0x0 +#define IMAGE_SUBSYSTEM_NATIVE 0x1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 0x2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 0x3 +#define IMAGE_SUBSYSTEM_OS2_GUI 0x4 +#define IMAGE_SUBSYSTEM_OS2_CUI 0x5 +#define IMAGE_SUBSYSTEM_POSIX_CUI 0x7 + +#define IMAGE_LIBRARY_PROCESS_INIT 0x0001 +#define IMAGE_LIBRARY_PROCESS_TERM 0x0002 +#define IMAGE_LIBRARY_THREAD_INIT 0x0004 +#define IMAGE_LIBRARY_THREAD_TERM 0x0008 +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 0x10 + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0x0 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 0x1 +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 0x2 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 0x3 +#define IMAGE_DIRECTORY_ENTRY_SECURITY 0x4 +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 0x5 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 0x6 +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 0x7 +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT IMAGE_DIRECTORY_ENTRY_ARCHITECTURE +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 0x8 +#define IMAGE_DIRECTORY_ENTRY_TLS 0x9 +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0xa +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 0xb +#define IMAGE_DIRECTORY_ENTRY_IAT 0xc +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 0xd +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 0xe + + +/* section header */ +#define IMAGE_SIZEOF_SHORT_NAME 0x8 + +#define IMAGE_SCN_TYPE_REG 0x00000000 +#define IMAGE_SCN_TYPE_DSECT 0x00000001 +#define IMAGE_SCN_TYPE_NOLOAD 0x00000002 +#define IMAGE_SCN_TYPE_GROUP 0x00000004 +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 +#define IMAGE_SCN_TYPE_COPY 0x00000010 + +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 +#define IMAGE_SCN_TYPE_OVER 0x00000400 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_LNK_COMDAT 0x00001000 +#define IMAGE_SCN_MEM_PROTECTED 0x00004000 +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 +#define IMAGE_SCN_GPREL 0x00008000 +#define IMAGE_SCN_MEM_FARDATA 0x00008000 +#define IMAGE_SCN_MEM_SYSHEAP 0x00010000 +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + + +/* relocations */ +#define IMAGE_REL_BASED_ABSOLUTE 0x0 +#define IMAGE_REL_BASED_HIGH 0x1 +#define IMAGE_REL_BASED_LOW 0x2 +#define IMAGE_REL_BASED_HIGHLOW 0x3 +#define IMAGE_REL_BASED_HIGHADJ 0x4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 0x5 +#define IMAGE_REL_BASED_SECTION 0x6 +#define IMAGE_REL_BASED_REL32 0x7 +/*#define IMAGE_REL_BASED_RESERVED1 0x8 */ +#define IMAGE_REL_BASED_MIPS_JMPADDR16 0x9 +#define IMAGE_REL_BASED_IA64_IMM64 0x9 +#define IMAGE_REL_BASED_DIR64 0xa +#define IMAGE_REL_BASED_HIGH3ADJ 0xb + +/* imports */ +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL32(ord) ((ord) & 0xffff) +#define IMAGE_SNAP_BY_ORDINAL32(ord) (!!((ord) & IMAGE_ORDINAL_FLAG32)) + +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000ULL +#define IMAGE_ORDINAL64(ord) ((ord) & 0xffff) +#define IMAGE_SNAP_BY_ORDINAL64(ord) (!!((ord) & IMAGE_ORDINAL_FLAG64)) + + +/* dll/tls entry points argument */ +#define DLL_PROCESS_DETACH 0 +#define DLL_PROCESS_ATTACH 1 +#define DLL_THREAD_ATTACH 2 +#define DLL_THREAD_DETACH 3 + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +#pragma pack(4) + +typedef struct _IMAGE_FILE_HEADER +{ + KU16 Machine; + KU16 NumberOfSections; + KU32 TimeDateStamp; + KU32 PointerToSymbolTable; + KU32 NumberOfSymbols; + KU16 SizeOfOptionalHeader; + KU16 Characteristics; +} IMAGE_FILE_HEADER; +typedef IMAGE_FILE_HEADER *PIMAGE_FILE_HEADER; + + +typedef struct _ANON_OBJECT_HEADER +{ + KU16 Sig1; + KU16 Sig2; + KU16 Version; /**< >= 1 */ + KU16 Machine; + KU32 TimeDataStamp; + KU8 ClassID[16]; + KU32 SizeOfData; +} ANON_OBJECT_HEADER; +typedef ANON_OBJECT_HEADER *PANON_OBJECT_HEADER; + + +typedef struct _ANON_OBJECT_HEADER_V2 +{ + KU16 Sig1; + KU16 Sig2; + KU16 Version; /**< >= 2 */ + KU16 Machine; + KU32 TimeDataStamp; + KU8 ClassID[16]; + KU32 SizeOfData; + /* New fields for Version >= 2: */ + KU32 Flags; + KU32 MetaDataSize; /**< CLR metadata */ + KU32 MetaDataOffset; +} ANON_OBJECT_HEADER_V2; +typedef ANON_OBJECT_HEADER_V2 *PANON_OBJECT_HEADER_V2; + + +typedef struct _ANON_OBJECT_HEADER_BIGOBJ +{ + KU16 Sig1; + KU16 Sig2; + KU16 Version; /**< >= 2 */ + KU16 Machine; + KU32 TimeDataStamp; + KU8 ClassID[16]; /**< ANON_OBJECT_HEADER_BIGOBJ_CLS_ID_BYTES */ + KU32 SizeOfData; + /* New fields for Version >= 2: */ + KU32 Flags; + KU32 MetaDataSize; /**< CLR metadata */ + KU32 MetaDataOffset; + /* Specific for bigobj: */ + KU32 NumberOfSections; + KU32 PointerToSymbolTable; + KU32 NumberOfSymbols; +} ANON_OBJECT_HEADER_BIGOBJ; +typedef ANON_OBJECT_HEADER_BIGOBJ *PANON_OBJECT_HEADER_BIGOBJ; + + +typedef struct _IMAGE_DATA_DIRECTORY +{ + KU32 VirtualAddress; + KU32 Size; +} IMAGE_DATA_DIRECTORY; +typedef IMAGE_DATA_DIRECTORY *PIMAGE_DATA_DIRECTORY; + + +typedef struct _IMAGE_OPTIONAL_HEADER32 +{ + KU16 Magic; + KU8 MajorLinkerVersion; + KU8 MinorLinkerVersion; + KU32 SizeOfCode; + KU32 SizeOfInitializedData; + KU32 SizeOfUninitializedData; + KU32 AddressOfEntryPoint; + KU32 BaseOfCode; + KU32 BaseOfData; + KU32 ImageBase; + KU32 SectionAlignment; + KU32 FileAlignment; + KU16 MajorOperatingSystemVersion; + KU16 MinorOperatingSystemVersion; + KU16 MajorImageVersion; + KU16 MinorImageVersion; + KU16 MajorSubsystemVersion; + KU16 MinorSubsystemVersion; + KU32 Win32VersionValue; + KU32 SizeOfImage; + KU32 SizeOfHeaders; + KU32 CheckSum; + KU16 Subsystem; + KU16 DllCharacteristics; + KU32 SizeOfStackReserve; + KU32 SizeOfStackCommit; + KU32 SizeOfHeapReserve; + KU32 SizeOfHeapCommit; + KU32 LoaderFlags; + KU32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32; +typedef IMAGE_OPTIONAL_HEADER32 *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_OPTIONAL_HEADER64 +{ + KU16 Magic; + KU8 MajorLinkerVersion; + KU8 MinorLinkerVersion; + KU32 SizeOfCode; + KU32 SizeOfInitializedData; + KU32 SizeOfUninitializedData; + KU32 AddressOfEntryPoint; + KU32 BaseOfCode; + KU64 ImageBase; + KU32 SectionAlignment; + KU32 FileAlignment; + KU16 MajorOperatingSystemVersion; + KU16 MinorOperatingSystemVersion; + KU16 MajorImageVersion; + KU16 MinorImageVersion; + KU16 MajorSubsystemVersion; + KU16 MinorSubsystemVersion; + KU32 Win32VersionValue; + KU32 SizeOfImage; + KU32 SizeOfHeaders; + KU32 CheckSum; + KU16 Subsystem; + KU16 DllCharacteristics; + KU64 SizeOfStackReserve; + KU64 SizeOfStackCommit; + KU64 SizeOfHeapReserve; + KU64 SizeOfHeapCommit; + KU32 LoaderFlags; + KU32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64; +typedef IMAGE_OPTIONAL_HEADER64 *PIMAGE_OPTIONAL_HEADER64; + + +typedef struct _IMAGE_NT_HEADERS +{ + KU32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} IMAGE_NT_HEADERS32; +typedef IMAGE_NT_HEADERS32 *PIMAGE_NT_HEADERS32; + +typedef struct _IMAGE_NT_HEADERS64 +{ + KU32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64; +typedef IMAGE_NT_HEADERS64 *PIMAGE_NT_HEADERS64; + + +typedef struct _IMAGE_SECTION_HEADER +{ + KU8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union + { + KU32 PhysicalAddress; + KU32 VirtualSize; + } Misc; + KU32 VirtualAddress; + KU32 SizeOfRawData; + KU32 PointerToRawData; + KU32 PointerToRelocations; + KU32 PointerToLinenumbers; + KU16 NumberOfRelocations; + KU16 NumberOfLinenumbers; + KU32 Characteristics; +} IMAGE_SECTION_HEADER; +typedef IMAGE_SECTION_HEADER *PIMAGE_SECTION_HEADER; + + +typedef struct _IMAGE_BASE_RELOCATION +{ + KU32 VirtualAddress; + KU32 SizeOfBlock; +} IMAGE_BASE_RELOCATION; +typedef IMAGE_BASE_RELOCATION *PIMAGE_BASE_RELOCATION; + + +typedef struct _IMAGE_EXPORT_DIRECTORY +{ + KU32 Characteristics; + KU32 TimeDateStamp; + KU16 MajorVersion; + KU16 MinorVersion; + KU32 Name; + KU32 Base; + KU32 NumberOfFunctions; + KU32 NumberOfNames; + KU32 AddressOfFunctions; + KU32 AddressOfNames; + KU32 AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + + +typedef struct _IMAGE_IMPORT_DESCRIPTOR +{ + union + { + KU32 Characteristics; + KU32 OriginalFirstThunk; + } u; + KU32 TimeDateStamp; + KU32 ForwarderChain; + KU32 Name; + KU32 FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR; +typedef IMAGE_IMPORT_DESCRIPTOR *PIMAGE_IMPORT_DESCRIPTOR; + + +typedef struct _IMAGE_IMPORT_BY_NAME +{ + KU16 Hint; + KU8 Name[1]; +} IMAGE_IMPORT_BY_NAME; +typedef IMAGE_IMPORT_BY_NAME *PIMAGE_IMPORT_BY_NAME; + + +/* The image_thunk_data32/64 structures are not very helpful except for getting RSI. keep them around till all the code has been converted. */ +typedef struct _IMAGE_THUNK_DATA64 +{ + union + { + KU64 ForwarderString; + KU64 Function; + KU64 Ordinal; + KU64 AddressOfData; + } u1; +} IMAGE_THUNK_DATA64; +typedef IMAGE_THUNK_DATA64 *PIMAGE_THUNK_DATA64; + +typedef struct _IMAGE_THUNK_DATA32 +{ + union + { + KU32 ForwarderString; + KU32 Function; + KU32 Ordinal; + KU32 AddressOfData; + } u1; +} IMAGE_THUNK_DATA32; +typedef IMAGE_THUNK_DATA32 *PIMAGE_THUNK_DATA32; + + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32 +{ + KU32 Size; + KU32 TimeDateStamp; + KU16 MajorVersion; + KU16 MinorVersion; + KU32 GlobalFlagsClear; + KU32 GlobalFlagsSet; + KU32 CriticalSectionDefaultTimeout; + KU32 DeCommitFreeBlockThreshold; + KU32 DeCommitTotalFreeThreshold; + KU32 LockPrefixTable; + KU32 MaximumAllocationSize; + KU32 VirtualMemoryThreshold; + KU32 ProcessHeapFlags; + KU32 ProcessAffinityMask; + KU16 CSDVersion; + KU16 Reserved1; + KU32 EditList; + KU32 SecurityCookie; + KU32 SEHandlerTable; + KU32 SEHandlerCount; +} IMAGE_LOAD_CONFIG_DIRECTORY32; +typedef IMAGE_LOAD_CONFIG_DIRECTORY32 PIMAGE_LOAD_CONFIG_DIRECTORY32; + +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64 +{ + KU32 Size; + KU32 TimeDateStamp; + KU16 MajorVersion; + KU16 MinorVersion; + KU32 GlobalFlagsClear; + KU32 GlobalFlagsSet; + KU32 CriticalSectionDefaultTimeout; + KU64 DeCommitFreeBlockThreshold; + KU64 DeCommitTotalFreeThreshold; + KU64 LockPrefixTable; + KU64 MaximumAllocationSize; + KU64 VirtualMemoryThreshold; + KU64 ProcessAffinityMask; + KU32 ProcessHeapFlags; + KU16 CSDVersion; + KU16 Reserved1; + KU64 EditList; + KU64 SecurityCookie; + KU64 SEHandlerTable; + KU64 SEHandlerCount; +} IMAGE_LOAD_CONFIG_DIRECTORY64; +typedef IMAGE_LOAD_CONFIG_DIRECTORY64 *PIMAGE_LOAD_CONFIG_DIRECTORY64; + +typedef struct _IMAGE_DEBUG_DIRECTORY +{ + KU32 Characteristics; + KU32 TimeDateStamp; + KU16 MajorVersion; + KU16 MinorVersion; + KU32 Type; + KU32 SizeOfData; + KU32 AddressOfRawData; + KU32 PointerToRawData; +} IMAGE_DEBUG_DIRECTORY; +typedef IMAGE_DEBUG_DIRECTORY *PIMAGE_DEBUG_DIRECTORY; + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 /* 4.0 */ +#define IMAGE_DEBUG_TYPE_FPO 3 /* FPO = frame pointer omission */ +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_BORLAND 9 + +typedef struct _IMAGE_TLS_DIRECTORY32 +{ + KU32 StartAddressOfRawData; + KU32 EndAddressOfRawData; + KU32 AddressOfIndex; + KU32 AddressOfCallBacks; + KU32 SizeOfZeroFill; + KU32 Characteristics; +} IMAGE_TLS_DIRECTORY32; +typedef IMAGE_TLS_DIRECTORY32 *PIMAGE_TLS_DIRECTORY32; + +typedef struct _IMAGE_TLS_DIRECTORY64 +{ + KU64 StartAddressOfRawData; + KU64 EndAddressOfRawData; + KU64 AddressOfIndex; + KU64 AddressOfCallBacks; + KU32 SizeOfZeroFill; + KU32 Characteristics; +} IMAGE_TLS_DIRECTORY64; +typedef IMAGE_TLS_DIRECTORY64 *PIMAGE_TLS_DIRECTORY64; + + +#pragma pack() + +#endif + diff --git a/src/lib/kStuff/include/k/kMagics.h b/src/lib/kStuff/include/k/kMagics.h new file mode 100644 index 0000000..9690b9b --- /dev/null +++ b/src/lib/kStuff/include/k/kMagics.h @@ -0,0 +1,43 @@ +/* $Id: kMagics.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kMagics - Various Magic Constants. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef ___k_kMagics_h___ +#define ___k_kMagics_h___ + +/** The magic for KRDR::u32Magic. (Katsu Aki (Katsuaki Nakamura)) + * @ingroup grp_kRdrAll */ +#define KRDR_MAGIC 0x19610919 +/** The magic value for the debug module structure. (Some manga artist) + * @ingroup grp_kDbgAll */ +#define KDBGMOD_MAGIC 0x19200501 + +#endif + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h b/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h new file mode 100644 index 0000000..03c17a4 --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbAssert.h @@ -0,0 +1,136 @@ +/* $Id: kRbAssert.h 38 2009-11-10 00:01:38Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Assert Valid Tree. + */ + +/* + * Copyright (c) 2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Internal helper for KRB_FN(Assert) + * + * @returns The number of black nodes. -1 is return if the tree is invalid. + * @param pRoot The root of the (sub-)tree to assert. + */ +K_DECL_INLINE(int) KRB_FN(AssertRecurse)(KRBNODE *pRoot) +{ + int cLeft; + int cRight; + + if (!pRoot) + /* leafs are black. */ + return 1; + +#ifdef KRB_EQUAL_ALLOWED + /* equal nodes are equal :) */ + if (pNode->mpList != KRB_NULL) + { + KRBROOT *pEqual; + for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->mpList)) + kHlpAssertReturn(K_CMP_E(pEqual->mKey, pNode->mKey), -1); + } +#endif + + /* binary tree. */ + kHlpAssertReturn(pRoot->mpLeft != KRB_NULL && KRB_CMP_G(KRB_GET_POINTER(&pRoot->mpLeft)->mpKey, pRoot->mKey), -1); + kHlpAssertReturn(pRoot->mpRight != KRB_NULL && KRB_CMP_G(pRoot->mKey, KRB_GET_POINTER(&pRoot->mpRigth)->mpKey), -1); + + /* both children of red nodes are black. */ + kHlpAssertReturn(!KRB_IS_RED(pRoot) || (!KRB_IS_RED(pRoot->mpLeft) && !KRB_IS_RED(pRoot->mpRight)), -1); + + /* all paths to leafs contains the same number of black nodes. */ + cLeft = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpLeft)); + cRight = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpRight)); + kHlpAssertMsgReturn(cLeft == cRight || cLeft == -1 || cRight == -1, ("%d vs. %d\n", cLeft, cRight), -1); + + return cLeft + !KRB_IS_RED(pRoot); +} + + +/** + * Asserts the validity of the Red-Black tree. + * + * This method is using recursion and may therefore consume quite a bit of stack + * on a large tree. + * + * @returns K_TRUE if valid. + * @returns K_FALSE if invalid, assertion raised on each violation. + * @param pRoot Pointer to the Red-Back tree's root structure. + */ +KRB_DECL(KBOOL) KRB_FN(Assert)(KRBROOT *pRoot) +{ + KBOOL fRc = K_TRUE; +#ifdef KRB_CACHE_SIZE + unsigned i; +#endif + KRBNODE *pNode; + + KRB_READ_LOCK(pRoot); + if (pRoot->mpRoot == KRB_NULL) + { + KRB_READ_UNLOCK(pRoot); + return 0; + } + +#ifdef KRB_CACHE_SIZE + /* + * Validate the cache. + */ + for (i = 0; i < (KRB_CACHE_SIZE); i++) + if (pRoot->maLookthru[i] != KRB_NULL) + { + KRBNODE pCache = KRB_GET_POINTER(&pRoot->maLookthru[i]); + + /** @todo ranges */ + kHlpAssertMsgStmt(i == KRB_CACHE_HASH(pCache->Key), ("Invalid cache entry %u, hashed to %u\n", i, KRB_CACHE_HASH(pCache->Key)), fRc = K_FALSE); + + pNode = KRB_GET_POINTER(&pRoot->mpRoot); + while (pNode) + { + if (KRB_CMP_E(pCache->mKey, pNode->mKey)) + { + kHlpAssertMsgStmt(pNode == pCache, ("Invalid cache entry %u=%p, found %p\n", i, pCache, pNode), fRc = K_FALSE); + break; + } + if (KRB_CMP_G(pCache->mKey, pNode->mKey)) + pNode = KRB_GET_POINTER_NULL(&pNode->mRight); + else + pNode = KRB_GET_POINTER_NULL(&pNode->mLeft); + } + kHlpAssertMsgStmt(pNode, ("Invalid cache entry %u/%p - not found\n", i, pCache), fRc = K_FALSE); + } +#endif + + /* + * Recurse thru the tree. + */ + if (KRB_FN(AssertRecurse)(KRB_GET_POINTER(&pRoot->mpRoot)) == -1) + fRc = K_FALSE; + + KRB_READ_UNLOCK(pRoot); + return fRc; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h b/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h new file mode 100644 index 0000000..c79f7ce --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbBase.h @@ -0,0 +1,609 @@ +/* $Id: kRbBase.h 38 2009-11-10 00:01:38Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, The Mandatory Base Code. + */ + +/* + * Copyright (c) 2001-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** @page pg_kAvlTmpl Template Configuration. + * + * This is a templated implementation of Red-Black trees in C. The template + * parameters relates to the kind of key used and how duplicates are treated. + * + * \#define KRB_EQUAL_ALLOWED + * Define this to tell us that equal keys are allowed. + * Then Equal keys will be put in a list pointed to by KRBNODE::pList. + * This is by default not defined. + * + * \#define KRB_CHECK_FOR_EQUAL_INSERT + * Define this to enable insert check for equal nodes. + * This is by default not defined. + * + * \#define KRB_MAX_STACK + * Use this to specify the max number of stack entries the stack will use when + * inserting and removing nodes from the tree. The size should be something like + * log2(<max nodes>) + 3 + * Must be defined. + * + * \#define KRB_RANGE + * Define this to enable key ranges. + * + * \#define KRB_OFFSET + * Define this to link the tree together using self relative offset + * instead of memory pointers, thus making the entire tree relocatable + * provided all the nodes - including the root node variable - are moved + * the exact same distance. + * + * \#define KRB_CACHE_SIZE + * Define this to employ a lookthru cache (direct) to speed up lookup for + * some usage patterns. The value should be the number of members of the array. + * + * \#define KRB_CACHE_HASH(Key) + * Define this to specify a more efficient translation of the key into + * a lookthru array index. The default is key % size. + * For some key types this is required as the default will not compile. + * + * \#define KRB_LOCKED + * Define this if you wish for the tree to be locked via the + * KRB_WRITE_LOCK, KRB_WRITE_UNLOCK, KRB_READ_LOCK and + * KRB_READ_UNLOCK macros. If not defined the tree will not be subject + * do any kind of locking and the problem of concurrency is left the user. + * + * \#define KRB_WRITE_LOCK(pRoot) + * Lock the tree for writing. + * + * \#define KRB_WRITE_UNLOCK(pRoot) + * Counteracts KRB_WRITE_LOCK. + * + * \#define KRB_READ_LOCK(pRoot) + * Lock the tree for reading. + * + * \#define KRB_READ_UNLOCK(pRoot) + * Counteracts KRB_READ_LOCK. + * + * \#define KRBKEY + * Define this to the name of the AVL key type. + * + * \#define KRB_STD_KEY_COMP + * Define this to use the standard key compare macros. If not set all the + * compare operations for KRBKEY have to be defined: KRB_CMP_G, KRB_CMP_E, KRB_CMP_NE, + * KRB_R_IS_IDENTICAL, KRB_R_IS_INTERSECTING and KRB_R_IS_IN_RANGE. The + * latter three are only required when KRB_RANGE is defined. + * + * \#define KRBNODE + * Define this to the name (typedef) of the AVL node structure. This + * structure must have a mpLeft, mpRight, mKey and mHeight member. + * If KRB_RANGE is defined a mKeyLast is also required. + * If KRB_EQUAL_ALLOWED is defined a mpList member is required. + * It's possible to use other member names by redefining the names. + * + * \#define KRBTREEPTR + * Define this to the name (typedef) of the tree pointer type. This is + * required when KRB_OFFSET is defined. When not defined it defaults + * to KRBNODE *. + * + * \#define KRBROOT + * Define this to the name (typedef) of the AVL root structure. This + * is optional. However, if specified it must at least have a mpRoot + * member of KRBTREEPTR type. If KRB_CACHE_SIZE is non-zero a + * maLookthru[KRB_CACHE_SIZE] member of the KRBTREEPTR type is also + * required. + * + * \#define KRB_FN + * Use this to alter the names of the AVL functions. + * Must be defined. + * + * \#define KRB_TYPE(prefix, name) + * Use this to make external type names and unique. The prefix may be empty. + * Must be defined. + * + * \#define KRB_INT(name) + * Use this to make internal type names and unique. The prefix may be empty. + * Must be defined. + * + * \#define KRB_DECL(rettype) + * Function declaration macro that should be set according to the scope + * the instantiated template should have. For instance an inlined scope + * (private or public) should K_DECL_INLINE(rettype) here. + * + * This version of the kAVL tree offers the option of inlining the entire + * implementation. This depends on the compiler doing a decent job in both + * making use of the inlined code and to eliminate const variables. + */ + + +/******************************************************************************* +* Internal Functions * +*******************************************************************************/ +#include <k/kDefs.h> +#include <k/kTypes.h> +#include <k/kHlpAssert.h> + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ +/** @def KRB_GET_POINTER + * Reads a 'pointer' value. + * + * @returns The native pointer. + * @param pp Pointer to the pointer to read. + * @internal + */ + +/** @def KRB_GET_POINTER_NULL + * Reads a 'pointer' value which can be KRB_NULL. + * + * @returns The native pointer. + * @returns NULL pointer if KRB_NULL. + * @param pp Pointer to the pointer to read. + * @internal + */ + +/** @def KRB_SET_POINTER + * Writes a 'pointer' value. + * For offset-based schemes offset relative to pp is calculated and assigned to *pp. + * + * @returns stored pointer. + * @param pp Pointer to where to store the pointer. + * @param p Native pointer to assign to *pp. + * @internal + */ + +/** @def KRB_SET_POINTER_NULL + * Writes a 'pointer' value which can be KRB_NULL. + * + * For offset-based schemes offset relative to pp is calculated and assigned to *pp, + * if p is not KRB_NULL of course. + * + * @returns stored pointer. + * @param pp Pointer to where to store the pointer. + * @param pp2 Pointer to where to pointer to assign to pp. This can be KRB_NULL + * @internal + */ + +#ifndef KRBTREEPTR +# define KRBTREEPTR KRBNODE * +#endif + +#ifndef KRBROOT +# define KRBROOT KRB_TYPE(,ROOT) +# define KRB_NEED_KRBROOT +#endif + +#ifdef KRB_CACHE_SIZE +# ifndef KRB_CACHE_HASH +# define KRB_CACHE_HASH(Key) ( (Key) % (KRB_CACHE_SIZE) ) +# endif +#elif defined(KRB_CACHE_HASH) +# error "KRB_CACHE_HASH without KRB_CACHE_SIZE!" +#endif + +#ifdef KRB_CACHE_SIZE +# define KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, Key) \ + do { \ + KRBTREEPTR **ppEntry = &pRoot->maLookthru[KRB_CACHE_HASH(Key)]; \ + if ((pNode) == KRB_GET_POINTER_NULL(ppEntry)) \ + *ppEntry = KRB_NULL; \ + } while (0) +#else +# define KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, Key) do { } while (0) +#endif + +#ifndef KRB_LOCKED +# define KRB_WRITE_LOCK(pRoot) do { } while (0) +# define KRB_WRITE_UNLOCK(pRoot) do { } while (0) +# define KRB_READ_LOCK(pRoot) do { } while (0) +# define KRB_READ_UNLOCK(pRoot) do { } while (0) +#endif + +#ifdef KRB_OFFSET +# define KRB_GET_POINTER(pp) ( (KRBNODE *)((KIPTR)(pp) + *(pp)) ) +# define KRB_GET_POINTER_NULL(pp) ( *(pp) != KRB_NULL ? KRB_GET_POINTER(pp) : NULL ) +# define KRB_SET_POINTER(pp, p) ( (*(pp)) = ((KIPTR)(p) - (KIPTR)(pp)) ) +# define KRB_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) != KRB_NULL ? (KIPTR)KRB_GET_POINTER(pp2) - (KIPTR)(pp) : KRB_NULL ) +#else +# define KRB_GET_POINTER(pp) ( *(pp) ) +# define KRB_GET_POINTER_NULL(pp) ( *(pp) ) +# define KRB_SET_POINTER(pp, p) ( (*(pp)) = (p) ) +# define KRB_SET_POINTER_NULL(pp, pp2) ( (*(pp)) = *(pp2) ) +#endif + + +/** @def KRB_NULL + * The NULL 'pointer' equivalent. + */ +#ifdef KRB_OFFSET +# define KRB_NULL 0 +#else +# define KRB_NULL NULL +#endif + +#ifdef KRB_STD_KEY_COMP +# define KRB_CMP_G(key1, key2) ( (key1) > (key2) ) +# define KRB_CMP_E(key1, key2) ( (key1) == (key2) ) +# define KRB_CMP_NE(key1, key2) ( (key1) != (key2) ) +# ifdef KRB_RANGE +# define KRB_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) ( (key1B) == (key2B) && (key1E) == (key2E) ) +# define KRB_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) ( (key1B) <= (key2E) && (key1E) >= (key2B) ) +# define KRB_R_IS_IN_RANGE(key1B, key1E, key2) KRB_R_IS_INTERSECTING(key1B, key2, key1E, key2) +# endif +#endif + +#ifndef KRB_RANGE +# define KRB_R_IS_INTERSECTING(key1B, key2B, key1E, key2E) KRB_CMP_E(key1B, key2B) +# define KRB_R_IS_IDENTICAL(key1B, key2B, key1E, key2E) KRB_CMP_E(key1B, key2B) +#endif + + +/** Is the node red or black? + * @returns true / false + * @param pNode Pointer to the node in question. + * @remarks All NULL pointers are considered black leaf nodes. + */ +#define KRB_IS_RED(pNode) ( (pNode) != NULL && (pNode)->mfIsRed ) + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Stack used to avoid recursive calls during insert and removal. + */ +typedef struct +{ + unsigned cEntries; + KRBTREEPTR *aEntries[KRB_MAX_STACK]; +} KRB_INT(STACK); + +/** + * The callback used by the Destroy and DoWithAll functions. + */ +typedef int (* KRB_TYPE(PFN,CALLBACK))(KRBNODE *, void *); + +#ifdef KRB_NEED_KRBROOT +/** + * The Red-Black tree root structure. + */ +typedef struct +{ + KRBTREEPTR mpRoot; +# ifdef KRB_CACHE_SIZE + KRBTREEPTR maLookthru[KRB_CACHE_SIZE]; +# endif +} KRBROOT; +#endif + + + +/** + * Initializes the root of the Red-Black tree. + * + * @param pTree Pointer to the root structure. + */ +KRB_DECL(void) KRB_FN(Init)(KRBROOT *pRoot) +{ +#ifdef KRB_CACHE_SIZE + unsigned i; +#endif + + pRoot->mpRoot = KRB_NULL; +#ifdef KRB_CACHE_SIZE + for (i = 0; i < (KRB_CACHE_SIZE); i++) + pRoot->maLookthru[i] = KRB_NULL; +#endif +} + + +/** + * Rotates the tree to the left (shift direction) and recolors the nodes. + * + * @pre + * + * 2 4 + * / \ / \ + * 1 4 ==> 2 5 + * / \ / \ + * 3 5 1 3 + * + * @endpre + * + * @returns The new root node. + * @param pRoot The root node. + * + * @remarks This will not update any pointer <tt>to</tt> the root node! + */ +K_DECL_INLINE(KRBNODE *) KAVL_FN(RotateLeft)(KRBNODE *pRoot) +{ + KRBNODE *pNewRoot = pRoot->mRight; + pRoot->mRight = pNewRoot->mLeft; + pNewRoot->mLeft = pRoot; + + pRoot->mfIsRed = 1; + pNewRoot->mfIsRed = 0; + return pNewRoot; +} + + +/** + * Rotates the tree to the right (shift direction) and recolors the nodes. + * + * @pre + * + * 4 2 + * / \ / \ + * 2 5 ==> 1 4 + * / \ / \ + * 1 3 3 5 + * + * @endpre + * + * @returns The new root node. + * @param pRoot The root node. + * + * @remarks This will not update any pointer <tt>to</tt> the root node! + */ +K_DECL_INLINE(KRBNODE *) KAVL_FN(RotateRight)(KRBNODE *pRoot) +{ + KRBNODE *pNewRoot = pRoot->mLeft; + pRoot->mLeft = pNewRoot->mRight; + pNewRoot->mRight = pRoot; + + pRoot->mfIsRed = 1; + pNewRoot->mfIsRed = 0; + return pNewRoot; +} + + +/** + * Performs a double left rotation with recoloring. + * + * @pre + * + * 2 2 4 + * / \ / \ / \ + * 1 6 ==> 1 4 ==> 2 6 + * / \ / \ / \ / \ + * 4 7 3 6 1 3 5 7 + * / \ / \ + * 3 5 5 7 + * @endpre + * + * @returns The new root node. + * @param pRoot The root node. + * + * @remarks This will not update any pointer <tt>to</tt> the root node! + */ +K_DECL_INLINE(KRBNODE *) KAVL_FN(DoubleRotateLeft)(KRBNODE *pRoot) +{ + pRoot->mRight = KAVL_FN(RotateRight)(pRoot->mRight); + return KAVL_FN(RotateLeft)(pRoot); +} + + +/** + * Performs a double right rotation with recoloring. + * + * @pre + * 6 6 4 + * / \ / \ / \ + * 2 7 4 7 2 6 + * / \ ==> / \ ==> / \ / \ + * 1 4 2 5 1 3 5 7 + * / \ / \ + * 3 5 1 3 + * + * @endpre + * + * @returns The new root node. + * @param pRoot The root node. + * + * @remarks This will not update any pointer <tt>to</tt> the root node! + */ +K_DECL_INLINE(KRBNODE *) KAVL_FN(DoubleRotateRight)(KRBNODE *pRoot) +{ + pRoot->mLeft = KAVL_FN(RotateLeft)(pRoot->mLeft); + return KAVL_FN(RotateRight)(pRoot); +} + + +/** + * Inserts a node into the Red-Black tree. + * @returns K_TRUE if inserted. + * K_FALSE if node exists in tree. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param pNode Pointer to the node which is to be added. + */ +KRB_DECL(KBOOL) KRB_FN(Insert)(KRBROOT *pRoot, KRBNODE *pNode) +{ + KRBTREEPTR *ppCurNode = &pRoot->mpRoot; + register KRBKEY Key = pNode->mKey; +#ifdef KRB_RANGE + register KRBKEY KeyLast = pNode->mKeyLast; +#endif + +#ifdef KRB_RANGE + if (Key > KeyLast) + return K_FALSE; +#endif + + KRB_WRITE_LOCK(pRoot); + + Stack.cEntries = 0; + while (*ppCurNode != KRB_NULL) + { + register KRBNODE *pCurNode = KRB_GET_POINTER(ppCurNode); + + kHlpAssert(Stack.cEntries < KRB_MAX_STACK); + Stack.aEntries[Stack.cEntries++] = ppCurNode; +#ifdef KRB_EQUAL_ALLOWED + if (KRB_R_IS_IDENTICAL(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast)) + { + /* + * If equal then we'll use a list of equal nodes. + */ + pNode->mpLeft = pNode->mpRight = KRB_NULL; + pNode->mHeight = 0; + KRB_SET_POINTER_NULL(&pNode->mpList, &pCurNode->mpList); + KRB_SET_POINTER(&pCurNode->mpList, pNode); + KRB_WRITE_UNLOCK(pRoot); + return K_TRUE; + } +#endif +#ifdef KRB_CHECK_FOR_EQUAL_INSERT + if (KRB_R_IS_INTERSECTING(pCurNode->mKey, Key, pCurNode->mKeyLast, KeyLast)) + { + KRB_WRITE_UNLOCK(pRoot); + return K_FALSE; + } +#endif + if (KRB_CMP_G(pCurNode->mKey, Key)) + ppCurNode = &pCurNode->mpLeft; + else + ppCurNode = &pCurNode->mpRight; + } + + pNode->mpLeft = pNode->mpRight = KRB_NULL; +#ifdef KRB_EQUAL_ALLOWED + pNode->mpList = KRB_NULL; +#endif + pNode->mHeight = 1; + KRB_SET_POINTER(ppCurNode, pNode); + + KRB_FN(Rebalance)(&Stack); + + KRB_WRITE_UNLOCK(pRoot); + return K_TRUE; +} + + +/** + * Removes a node from the Red-Black tree. + * @returns Pointer to the node. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param Key Key value of the node which is to be removed. + * @sketch Find the node which is to be removed: + * LOOP until not found + * BEGIN + * Add node pointer pointer to the AVL-stack. + * IF the keys matches THEN break! + * IF remove key < node key THEN + * left + * ELSE + * right + * END + * IF found THEN + * BEGIN + * IF left node not empty THEN + * BEGIN + * Find the right most node in the left tree while adding the pointer to the pointer to it's parent to the stack: + * Start at left node. + * LOOP until right node is empty + * BEGIN + * Add to stack. + * go right. + * END + * Link out the found node. + * Replace the node which is to be removed with the found node. + * Correct the stack entry for the pointer to the left tree. + * END + * ELSE + * BEGIN + * Move up right node. + * Remove last stack entry. + * END + * Balance tree using stack. + * END + * return pointer to the removed node (if found). + */ +KRB_DECL(KRBNODE *) KRB_FN(Remove)(KRBROOT *pRoot, KRBKEY Key) +{ + KRB_INT(STACK) Stack; + KRBTREEPTR *ppDeleteNode = &pRoot->mpRoot; + register KRBNODE *pDeleteNode; + + KRB_WRITE_LOCK(pRoot); + + Stack.cEntries = 0; + for (;;) + { + if (*ppDeleteNode == KRB_NULL) + { + KRB_WRITE_UNLOCK(pRoot); + return NULL; + } + pDeleteNode = KRB_GET_POINTER(ppDeleteNode); + + kHlpAssert(Stack.cEntries < KRB_MAX_STACK); + Stack.aEntries[Stack.cEntries++] = ppDeleteNode; + if (KRB_CMP_E(pDeleteNode->mKey, Key)) + break; + + if (KRB_CMP_G(pDeleteNode->mKey, Key)) + ppDeleteNode = &pDeleteNode->mpLeft; + else + ppDeleteNode = &pDeleteNode->mpRight; + } + + if (pDeleteNode->mpLeft != KRB_NULL) + { + /* find the rightmost node in the left tree. */ + const unsigned iStackEntry = Stack.cEntries; + KRBTREEPTR *ppLeftLeast = &pDeleteNode->mpLeft; + register KRBNODE *pLeftLeast = KRB_GET_POINTER(ppLeftLeast); + + while (pLeftLeast->mpRight != KRB_NULL) + { + kHlpAssert(Stack.cEntries < KRB_MAX_STACK); + Stack.aEntries[Stack.cEntries++] = ppLeftLeast; + ppLeftLeast = &pLeftLeast->mpRight; + pLeftLeast = KRB_GET_POINTER(ppLeftLeast); + } + + /* link out pLeftLeast */ + KRB_SET_POINTER_NULL(ppLeftLeast, &pLeftLeast->mpLeft); + + /* link it in place of the delete node. */ + KRB_SET_POINTER_NULL(&pLeftLeast->mpLeft, &pDeleteNode->mpLeft); + KRB_SET_POINTER_NULL(&pLeftLeast->mpRight, &pDeleteNode->mpRight); + pLeftLeast->mHeight = pDeleteNode->mHeight; + KRB_SET_POINTER(ppDeleteNode, pLeftLeast); + Stack.aEntries[iStackEntry] = &pLeftLeast->mpLeft; + } + else + { + KRB_SET_POINTER_NULL(ppDeleteNode, &pDeleteNode->mpRight); + Stack.cEntries--; + } + + KRB_FN(Rebalance)(&Stack); + + KRB_CACHE_INVALIDATE_NODE(pRoot, pDeleteNode, Key); + + KRB_WRITE_UNLOCK(pRoot); + return pDeleteNode; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h b/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h new file mode 100644 index 0000000..0300a9a --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbDestroy.h @@ -0,0 +1,129 @@ +/* $Id: kRbDestroy.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Destroy the tree. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Destroys the specified tree, starting with the root node and working our way down. + * + * @returns 0 on success. + * @returns Return value from callback on failure. On failure, the tree will be in + * an unbalanced condition and only further calls to the Destroy should be + * made on it. Note that the node we fail on will be considered dead and + * no action is taken to link it back into the tree. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param pfnCallBack Pointer to callback function. + * @param pvUser User parameter passed on to the callback function. + */ +KRB_DECL(int) KRB_FN(Destroy)(KRBROOT *pRoot, KRB_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser) +{ +#ifdef KRB_CACHE_SIZE + unsigned i; +#endif + unsigned cEntries; + KRBNODE *apEntries[KRB_MAX_STACK]; + int rc; + + KRB_WRITE_LOCK(pRoot); + if (pRoot->mpRoot == KRB_NULL) + { + KRB_WRITE_UNLOCK(pRoot); + return 0; + } + +#ifdef KRB_CACHE_SIZE + /* + * Kill the lookthru cache. + */ + for (i = 0; i < (KRB_CACHE_SIZE); i++) + pRoot->maLookthru[i] = KRB_NULL; +#endif + + cEntries = 1; + apEntries[0] = KRB_GET_POINTER(&pRoot->mpRoot); + while (cEntries > 0) + { + /* + * Process the subtrees first. + */ + KRBNODE *pNode = apEntries[cEntries - 1]; + if (pNode->mpLeft != KRB_NULL) + apEntries[cEntries++] = KRB_GET_POINTER(&pNode->mpLeft); + else if (pNode->mpRight != KRB_NULL) + apEntries[cEntries++] = KRB_GET_POINTER(&pNode->mpRight); + else + { +#ifdef KRB_EQUAL_ALLOWED + /* + * Process nodes with the same key. + */ + while (pNode->pList != KRB_NULL) + { + KRBNODE *pEqual = KRB_GET_POINTER(&pNode->pList); + KRB_SET_POINTER(&pNode->pList, KRB_GET_POINTER_NULL(&pEqual->pList)); + pEqual->pList = KRB_NULL; + + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KRB_WRITE_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* + * Unlink the node. + */ + if (--cEntries > 0) + { + KRBNODE *pParent = apEntries[cEntries - 1]; + if (KRB_GET_POINTER(&pParent->mpLeft) == pNode) + pParent->mpLeft = KRB_NULL; + else + pParent->mpRight = KRB_NULL; + } + else + pRoot->mpRoot = KRB_NULL; + + kHlpAssert(pNode->mpLeft == KRB_NULL); + kHlpAssert(pNode->mpRight == KRB_NULL); + rc = pfnCallBack(pNode, pvUser); + if (rc) + { + KRB_WRITE_UNLOCK(pRoot); + return rc; + } + } + } /* while */ + kHlpAssert(pRoot->mpRoot == KRB_NULL); + + KRB_WRITE_UNLOCK(pRoot); + return 0; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h b/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h new file mode 100644 index 0000000..a9de71c --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbDoWithAll.h @@ -0,0 +1,166 @@ +/* $Id: kRbDoWithAll.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, The Callback Iterator. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Stack used by DoWithAll to avoid recusive function calls. + */ +typedef struct +{ + unsigned cEntries; + KRBNODE *aEntries[KRB_MAX_STACK]; + char achFlags[KRB_MAX_STACK]; + KRBROOT pRoot; +} KRB_INT(STACK2); + + +/** + * Iterates thru all nodes in the given tree. + * + * @returns 0 on success. Return from callback on failure. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param fFromLeft K_TRUE: Left to right. + * K_FALSE: Right to left. + * @param pfnCallBack Pointer to callback function. + * @param pvUser User parameter passed on to the callback function. + */ +KRB_DECL(int) KRB_FN(DoWithAll)(KRBROOT *pRoot, KBOOL fFromLeft, KRB_TYPE(PFN,CALLBACK) pfnCallBack, void *pvUser) +{ + KRB_INT(STACK2) Stack; + KRBNODE *pNode; +#ifdef KRB_EQUAL_ALLOWED + KRBNODE *pEqual; +#endif + int rc; + + KRB_READ_LOCK(pRoot); + if (pRoot->mpRoot == KRB_NULL) + { + KRB_READ_UNLOCK(pRoot); + return 0; + } + + Stack.cEntries = 1; + Stack.achFlags[0] = 0; + Stack.aEntries[0] = KRB_GET_POINTER(&pRoot->mpRoot); + + if (fFromLeft) + { /* from left */ + while (Stack.cEntries > 0) + { + pNode = Stack.aEntries[Stack.cEntries - 1]; + + /* left */ + if (!Stack.achFlags[Stack.cEntries - 1]++) + { + if (pNode->mpLeft != KRB_NULL) + { + Stack.achFlags[Stack.cEntries] = 0; /* 0 first, 1 last */ + Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpLeft); + continue; + } + } + + /* center */ + rc = pfnCallBack(pNode, pvUser); + if (rc) + return rc; +#ifdef KRB_EQUAL_ALLOWED + if (pNode->mpList != KRB_NULL) + for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->mpList)) + { + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KRB_READ_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* right */ + Stack.cEntries--; + if (pNode->mpRight != KRB_NULL) + { + Stack.achFlags[Stack.cEntries] = 0; + Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpRight); + } + } /* while */ + } + else + { /* from right */ + while (Stack.cEntries > 0) + { + pNode = Stack.aEntries[Stack.cEntries - 1]; + + /* right */ + if (!Stack.achFlags[Stack.cEntries - 1]++) + { + if (pNode->mpRight != KRB_NULL) + { + Stack.achFlags[Stack.cEntries] = 0; /* 0 first, 1 last */ + Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpRight); + continue; + } + } + + /* center */ + rc = pfnCallBack(pNode, pvUser); + if (rc) + return rc; +#ifdef KRB_EQUAL_ALLOWED + if (pNode->mpList != KRB_NULL) + for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->pList)) + { + rc = pfnCallBack(pEqual, pvUser); + if (rc) + { + KRB_READ_UNLOCK(pRoot); + return rc; + } + } +#endif + + /* left */ + Stack.cEntries--; + if (pNode->mpLeft != KRB_NULL) + { + Stack.achFlags[Stack.cEntries] = 0; + Stack.aEntries[Stack.cEntries++] = KRB_GET_POINTER(&pNode->mpLeft); + } + } /* while */ + } + + KRB_READ_UNLOCK(pRoot); + return 0; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h b/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h new file mode 100644 index 0000000..d022410 --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbEnum.h @@ -0,0 +1,187 @@ +/* $Id: kRbEnum.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Node Enumeration. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * Enumeration control data. + * + * This is initialized by BeginEnum and used by GetNext to figure out what + * to do next. + */ +typedef struct KRB_TYPE(,ENUMDATA) +{ + KBOOL fFromLeft; + KI8 cEntries; + KU8 achFlags[KRB_MAX_STACK]; + KRBNODE * aEntries[KRB_MAX_STACK]; +} KRB_TYPE(,ENUMDATA), *KRB_TYPE(P,ENUMDATA); + + +/** + * Ends an enumeration. + * + * The purpose of this function is to unlock the tree should the Red-Black tree + * implementation include locking. It's good practice to call it anyway even if + * the tree doesn't do any locking. + * + * @param pEnumData Pointer to enumeration control data. + */ +KRB_DECL(void) KRB_FN(EndEnum)(KRB_TYPE(,ENUMDATA) *pEnumData) +{ + KRBROOT pRoot = pEnumData->pRoot; + pEnumData->pRoot = NULL; + if (pRoot) + KRB_READ_UNLOCK(pEnumData->pRoot); +} + + +/** + * Get the next node in the tree enumeration. + * + * The current implementation of this function willl not walk the mpList + * chain like the DoWithAll function does. This may be changed later. + * + * @returns Pointer to the next node in the tree. + * NULL is returned when the end of the tree has been reached, + * it is not necessary to call EndEnum in this case. + * @param pEnumData Pointer to enumeration control data. + */ +KRB_DECL(KRBNODE *) KRB_FN(GetNext)(KRB_TYPE(,ENUMDATA) *pEnumData) +{ + if (pEnumData->fFromLeft) + { /* from left */ + while (pEnumData->cEntries > 0) + { + KRBNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; + + /* left */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + if (pNode->mpLeft != KRB_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 left, 1 center, 2 right */ + pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpLeft); + continue; + } + } + + /* center */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + return pNode; + } + + /* right */ + pEnumData->cEntries--; + if (pNode->mpRight != KRB_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; + pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpRight); + } + } /* while */ + } + else + { /* from right */ + while (pEnumData->cEntries > 0) + { + KRBNODE *pNode = pEnumData->aEntries[pEnumData->cEntries - 1]; + + /* right */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 0) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + if (pNode->mpRight != KRB_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; /* 0 right, 1 center, 2 left */ + pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpRight); + continue; + } + } + + /* center */ + if (pEnumData->achFlags[pEnumData->cEntries - 1] == 1) + { + pEnumData->achFlags[pEnumData->cEntries - 1]++; + return pNode; + } + + /* left */ + pEnumData->cEntries--; + if (pNode->mpLeft != KRB_NULL) + { + pEnumData->achFlags[pEnumData->cEntries] = 0; + pEnumData->aEntries[pEnumData->cEntries++] = KRB_GET_POINTER(&pNode->mpLeft); + } + } /* while */ + } + + /* + * Call EndEnum. + */ + KRB_FN(EndEnum)(pEnumData); + return NULL; +} + + +/** + * Starts an enumeration of all nodes in the given tree. + * + * The current implementation of this function will not walk the mpList + * chain like the DoWithAll function does. This may be changed later. + * + * @returns Pointer to the first node in the enumeration. + * If NULL is returned the tree is empty calling EndEnum isn't + * strictly necessary (although it will do no harm). + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param pEnumData Pointer to enumeration control data. + * @param fFromLeft K_TRUE: Left to right. + * K_FALSE: Right to left. + */ +KRB_DECL(KRBNODE *) KRB_FN(BeginEnum)(KRBROOT *pRoot, KRB_TYPE(,ENUMDATA) *pEnumData, KBOOL fFromLeft) +{ + KRB_READ_LOCK(pRoot); + pEnumData->pRoot = pRoot; + if (pRoot->mpRoot != KRB_NULL) + { + pEnumData->fFromLeft = fFromLeft; + pEnumData->cEntries = 1; + pEnumData->aEntries[0] = KRB_GET_POINTER(pRoot->mpRoot); + pEnumData->achFlags[0] = 0; + } + else + pEnumData->cEntries = 0; + + return KRB_FN(GetNext)(pEnumData); +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h new file mode 100644 index 0000000..b03d4e1 --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGet.h @@ -0,0 +1,89 @@ +/* $Id: kRbGet.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Get a Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Gets a node from the tree (does not remove it!) + * + * @returns Pointer to the node holding the given key. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param Key Key value of the node which is to be found. + */ +KRB_DECL(KRBNODE *) KRB_FN(Get)(KRBROOT *pRoot, KRBKEY Key) +{ + KRBNODE *pNode; +#ifdef KRB_CACHE_SIZE + KRBTREEPTR *ppEntry; +#endif + + KRB_READ_LOCK(pRoot); + if (pRoot->mpRoot == KRB_NULL) + { + KRB_READ_UNLOCK(pRoot); + return NULL; + } + +#ifdef KRB_CACHE_SIZE + ppEntry = &pRoot->maLookthru[KRB_CACHE_HASH(Key)]; + pNode = KRB_GET_POINTER_NULL(ppEntry); + if (!pNode || KRB_CMP_NE(pNode->mKey, Key)) +#endif + { + pNode = KRB_GET_POINTER(&pRoot->mpRoot); + while (KRB_CMP_NE(pNode->mKey, Key)) + { + if (KRB_CMP_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KRB_NULL) + { + KRB_READ_UNLOCK(pRoot); + return NULL; + } + pNode = KRB_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KRB_NULL) + { + KRB_READ_UNLOCK(pRoot); + return NULL; + } + pNode = KRB_GET_POINTER(&pNode->mpRight); + } + } + +#ifdef KRB_CACHE_SIZE + KRB_SET_POINTER(ppEntry, pNode); +#endif + } + + KRB_READ_UNLOCK(pRoot); + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h new file mode 100644 index 0000000..bfda27a --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGetBestFit.h @@ -0,0 +1,112 @@ +/* $Id: kRbGetBestFit.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Get Best Fitting Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Finds the best fitting node in the tree for the given Key value. + * + * @returns Pointer to the best fitting node found. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. + * K_FALSE: Returned node is have the closest key to Key from below. + * @sketch The best fitting node is always located in the searchpath above you. + * >= (above): The node where you last turned left. + * <= (below): the node where you last turned right. + */ +KRB_DECL(KRBNODE *) KRB_FN(GetBestFit)(KRBROOT *pRoot, KRBKEY Key, KBOOL fAbove) +{ + register KRBNODE *pNode; + KRBNODE *pNodeLast; + + KRB_READ_LOCK(pLook); + if (pRoot->mpRoot == KRB_NULL) + { + KRB_READ_UNLOCK(pLook); + return NULL; + } + + pNode = KRB_GET_POINTER(&pRoot->mpRoot); + pNodeLast = NULL; + if (fAbove) + { /* pNode->mKey >= Key */ + while (KRB_CMP_NE(pNode->mKey, Key)) + { + if (KRB_CMP_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KRB_NULL) + { + KRB_READ_UNLOCK(pLook); + return pNode; + } + pNodeLast = pNode; + pNode = KRB_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KRB_NULL) + { + KRB_READ_UNLOCK(pLook); + return pNodeLast; + } + pNode = KRB_GET_POINTER(&pNode->mpRight); + } + } + } + else + { /* pNode->mKey <= Key */ + while (KRB_CMP_NE(pNode->mKey, Key)) + { + if (KRB_CMP_G(pNode->mKey, Key)) + { + if (pNode->mpLeft == KRB_NULL) + { + KRB_READ_UNLOCK(pLook); + return pNodeLast; + } + pNode = KRB_GET_POINTER(&pNode->mpLeft); + } + else + { + if (pNode->mpRight == KRB_NULL) + { + KRB_READ_UNLOCK(pLook); + return pNode; + } + pNodeLast = pNode; + pNode = KRB_GET_POINTER(&pNode->mpRight); + } + } + } + + /* perfect match or nothing. */ + KRB_READ_UNLOCK(pLook); + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h b/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h new file mode 100644 index 0000000..05a7d8c --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbGetWithParent.h @@ -0,0 +1,65 @@ +/* $Id: kRbGetWithParent.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Get Node With Parent. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Gets a node from the tree and its parent node (if any). + * The tree remains unchanged. + * + * @returns Pointer to the node holding the given key. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param ppParent Pointer to a variable which will hold the pointer to the partent node on + * return. When no node is found, this will hold the last searched node. + * @param Key Key value of the node which is to be found. + */ +KRB_DECL(KRBNODE *) KRB_FN(GetWithParent)(KRBROOT *pRoot, KRBNODE **ppParent, KRBKEY Key) +{ + register KRBNODE *pNode; + register KRBNODE *pParent; + + KRB_READ_LOCK(pRoot); + + pParent = NULL; + pNode = KRB_GET_POINTER_NULL(&pRoot->mpRoot); + while ( pNode != NULL + && KRB_CMP_NE(pNode->mKey, Key)) + { + pParent = pNode; + if (KRB_CMP_G(pNode->mKey, Key)) + pNode = KRB_GET_POINTER_NULL(&pNode->mpLeft); + else + pNode = KRB_GET_POINTER_NULL(&pNode->mpRight); + } + + KRB_READ_UNLOCK(pRoot); + + *ppParent = pParent; + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h b/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h new file mode 100644 index 0000000..deed81d --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbRemove2.h @@ -0,0 +1,133 @@ +/* $Id: kRbRemove2.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Remove A Specific Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Removes the specified node from the tree. + * + * @returns Pointer to the removed node (NULL if not in the tree) + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * + * @remark This implementation isn't the most efficient, but this short and + * easier to manage. + */ +KRB_DECL(KRBNODE *) KRB_FN(Remove2)(KRBROOT *pRoot, KRBNODE *pNode) +{ +#ifdef KRB_EQUAL_ALLOWED + /* + * Find the right node by key and see if it's what we want. + */ + KRBNODE *pParent; + KRBNODE *pCurNode = KRB_FN(GetWithParent)(pRoot, pNode->mKey, &pParent); + if (!pCurNode) + return NULL; + KRB_WRITE_LOCK(pRoot); /** @todo the locking here isn't 100% sane. The only way to archive that is by no calling worker functions. */ + if (pCurNode != pNode) + { + /* + * It's not the one we want, but it could be in the duplicate list. + */ + while (pCurNode->mpList != KRB_NULL) + { + KRBNODE *pNext = KRB_GET_POINTER(&pCurNode->mpList); + if (pNext == pNode) + { + KRB_SET_POINTER_NULL(&pCurNode->mpList, KRB_GET_POINTER_NULL(&pNode->mpList)); + pNode->mpList = KRB_NULL; + KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KRB_WRITE_UNLOCK(pRoot); + return pNode; + } + pCurNode = pNext; + } + KRB_WRITE_UNLOCK(pRoot); + return NULL; + } + + /* + * Ok, it's the one we want alright. + * + * Simply remove it if it's the only one with they Key, + * if there are duplicates we'll have to unlink it and + * insert the first duplicate in our place. + */ + if (pNode->mpList == KRB_NULL) + { + KRB_WRITE_UNLOCK(pRoot); + KRB_FN(Remove)(pRoot, pNode->mKey); + } + else + { + KRBNODE *pNewUs = KRB_GET_POINTER(&pNode->mpList); + + pNewUs->mHeight = pNode->mHeight; + + if (pNode->mpLeft != KRB_NULL) + KRB_SET_POINTER(&pNewUs->mpLeft, KRB_GET_POINTER(&pNode->mpLeft)) + else + pNewUs->mpLeft = KRB_NULL; + + if (pNode->mpRight != KRB_NULL) + KRB_SET_POINTER(&pNewUs->mpRight, KRB_GET_POINTER(&pNode->mpRight)) + else + pNewUs->mpRight = KRB_NULL; + + if (pParent) + { + if (KRB_GET_POINTER_NULL(&pParent->mpLeft) == pNode) + KRB_SET_POINTER(&pParent->mpLeft, pNewUs); + else + KRB_SET_POINTER(&pParent->mpRight, pNewUs); + } + else + KRB_SET_POINTER(&pRoot->mpRoot, pNewUs); + + KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KRB_WRITE_UNLOCK(pRoot); + } + + return pNode; + +#else + /* + * Delete it, if we got the wrong one, reinsert it. + * + * This ASSUMS that the caller is NOT going to hand us a lot + * of wrong nodes but just uses this API for his convenience. + */ + KRBNODE *pRemovedNode = KRB_FN(Remove)(pRoot, pNode->mKey); + if (pRemovedNode == pNode) + return pRemovedNode; + + KRB_FN(Insert)(pRoot, pRemovedNode); + return NULL; +#endif +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h b/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h new file mode 100644 index 0000000..17fc66d --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbRemoveBestFit.h @@ -0,0 +1,70 @@ +/* $Id: kRbRemoveBestFit.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Templated Red-Black Trees, Remove Best Fitting Node. + */ + +/* + * Copyright (c) 1999-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Finds the best fitting node in the tree for the given Key value and removes the node. + * + * @returns Pointer to the removed node. + * @param pRoot Pointer to the Red-Back tree's root structure. + * @param Key The Key of which is to be found a best fitting match for.. + * @param fAbove K_TRUE: Returned node is have the closest key to Key from above. + * K_FALSE: Returned node is have the closest key to Key from below. + * + * @remark This implementation uses GetBestFit and then Remove and might therefore + * not be the most optimal kind of implementation, but it reduces the complexity + * code size, and the likelyhood for bugs. + */ +KRB_DECL(KRBNODE *) KRB_FN(RemoveBestFit)(KRBROOT *pRoot, KRBKEY Key, KBOOL fAbove) +{ + /* + * If we find anything we'll have to remove the node and return it. + * Now, if duplicate keys are allowed we'll remove a duplicate before + * removing the in-tree node as this is way cheaper. + */ + KRBNODE *pNode = KRB_FN(GetBestFit)(pRoot, Key, fAbove); + if (pNode != NULL) + { +#ifdef KRB_EQUAL_ALLOWED + KRB_WRITE_LOCK(pRoot); /** @todo the locking isn't quite sane here. :-/ */ + if (pNode->mpList != KRB_NULL) + { + KRBNODE *pRet = KRB_GET_POINTER(&pNode->mpList); + KRB_SET_POINTER_NULL(&pNode->mpList, &pRet->mpList); + KRB_CACHE_INVALIDATE_NODE(pRoot, pNode, pNode->mKey); + KRB_WRITE_UNLOCK(pRoot); + return pRet; + } + KRB_WRITE_UNLOCK(pRoot); +#endif + pNode = KRB_FN(Remove)(pRoot, pNode->mKey); + } + return pNode; +} + diff --git a/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h b/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h new file mode 100644 index 0000000..793108b --- /dev/null +++ b/src/lib/kStuff/include/k/kRbTmpl/kRbUndef.h @@ -0,0 +1,79 @@ +/* $Id: kRbUndef.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRbTmpl - Undefines All Macros (both config and temp). + */ + +/* + * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The configuration. + */ +#undef KRB_EQUAL_ALLOWED +#undef KRB_CHECK_FOR_EQUAL_INSERT +#undef KRB_MAX_STACK +#undef KRB_RANGE +#undef KRB_OFFSET +#undef KRB_STD_KEY_COMP +#undef KRB_CACHE_SIZE +#undef KRB_CACHE_HASH +#undef KRB_LOCKED +#undef KRB_WRITE_LOCK +#undef KRB_WRITE_UNLOCK +#undef KRB_READ_LOCK +#undef KRB_READ_UNLOCK +#undef KRBKEY +#undef KRBNODE +#undef KRBTREEPTR +#undef KRBROOT +#undef KRB_FN +#undef KRB_TYPE +#undef KRB_INT +#undef KRB_DECL +#undef mKey +#undef mKeyLast +#undef mfIsRed +#undef mpLeft +#undef mpRight +#undef mpList +#undef mpRoot +#undef maLookthru +#undef KRB_CMP_G +#undef KRB_CMP_E +#undef KRB_CMP_NE +#undef KRB_R_IS_IDENTICAL +#undef KRB_R_IS_INTERSECTING +#undef KRB_R_IS_IN_RANGE + +/* + * Internal ones. + */ +#undef KRB_IS_RED +#undef KRB_NULL +#undef KRB_GET_POINTER +#undef KRB_GET_POINTER_NULL +#undef KRB_SET_POINTER +#undef KRB_SET_POINTER_NULL + diff --git a/src/lib/kStuff/include/k/kRbU32.h b/src/lib/kStuff/include/k/kRbU32.h new file mode 100644 index 0000000..3b68b5e --- /dev/null +++ b/src/lib/kStuff/include/k/kRbU32.h @@ -0,0 +1,68 @@ +/* $Id: kRbU32.h 35 2009-11-08 19:39:03Z bird $ */ +/** @file + * kRb - Red-Black Tree Implementation, KU32 keys. + */ + +/* + * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kRbU32_h___ +#define ___k_kRbU32_h___ + +typedef struct KRBU32 +{ + KU32 mKey; + KBOOL mfRed; + struct KRBU32 *mpLeft; + struct KRBU32 *mpRight; +} KRBU32; +typedef KRBU32 *PRBU32; +typedef KRBU32 **PPRBU32; + +/*#define KRB_EQUAL_ALLOWED*/ +#define KRB_CHECK_FOR_EQUAL_INSERT +/*#define KRB_RANGE */ +/*#define KRB_OFFSET */ +#define KRB_MAX_STACK 48 +#define KRB_STD_KEY_COMP +#define KRBKEY KU32 +#define KRBNODE KRBU32 +#define KRB_FN(name) kRbU32 ## name +#define KRB_TYPE(prefix,name) prefix ## KRBU32 ## name +#define KRB_INT(name) KRBU32INT ## name +#define KRB_DECL(rettype) K_DECL_INLINE(rettype) + +#include <k/kRbTmpl/kRbBase.h> +#include <k/kRbTmpl/kRbDoWithAll.h> +#include <k/kRbTmpl/kRbEnum.h> +#include <k/kRbTmpl/kRbGet.h> +#include <k/kRbTmpl/kRbGetBestFit.h> +#include <k/kRbTmpl/kRbGetWithParent.h> +#include <k/kRbTmpl/kRbRemove2.h> +#include <k/kRbTmpl/kRbRemoveBestFit.h> +#include <k/kRbTmpl/kRbUndef.h> + +#endif + diff --git a/src/lib/kStuff/include/k/kRdr.h b/src/lib/kStuff/include/k/kRdr.h new file mode 100644 index 0000000..7e0b5e8 --- /dev/null +++ b/src/lib/kStuff/include/k/kRdr.h @@ -0,0 +1,86 @@ +/* $Id: kRdr.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kRdr - The File Provider. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___kRdr_h___ +#define ___kRdr_h___ + +#include <k/kDefs.h> +#include <k/kTypes.h> + +/** @defgroup grp_kRdr kRdr - The File Provider + * @{ */ + +/** @def KRDR_DECL + * Declares a kRdr function according to build context. + * @param type The return type. + */ +#if defined(KRDR_BUILDING_DYNAMIC) +# define KRDR_DECL(type) K_DECL_EXPORT(type) +#elif defined(KRDR_BUILT_DYNAMIC) +# define KRDR_DECL(type) K_DECL_IMPORT(type) +#else +# define KRDR_DECL(type) type +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +KRDR_DECL(int) kRdrOpen( PPKRDR ppRdr, const char *pszFilename); +KRDR_DECL(int) kRdrClose( PKRDR pRdr); +KRDR_DECL(int) kRdrRead( PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off); +KRDR_DECL(int) kRdrAllMap( PKRDR pRdr, const void **ppvBits); +KRDR_DECL(int) kRdrAllUnmap( PKRDR pRdr, const void *pvBits); +KRDR_DECL(KFOFF) kRdrSize( PKRDR pRdr); +KRDR_DECL(KFOFF) kRdrTell( PKRDR pRdr); +KRDR_DECL(const char *) kRdrName( PKRDR pRdr); +KRDR_DECL(KIPTR) kRdrNativeFH( PKRDR pRdr); +KRDR_DECL(KSIZE) kRdrPageSize( PKRDR pRdr); +KRDR_DECL(int) kRdrMap( PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed); +KRDR_DECL(int) kRdrRefresh( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments); +KRDR_DECL(int) kRdrProtect( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect); +KRDR_DECL(int) kRdrUnmap( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments); +KRDR_DECL(void) kRdrDone( PKRDR pRdr); + +KRDR_DECL(int) kRdrBufOpen(PPKRDR ppRdr, const char *pszFilename); +KRDR_DECL(int) kRdrBufWrap(PPKRDR ppRdr, PKRDR pRdr, KBOOL fCloseIt); +KRDR_DECL(KBOOL) kRdrBufIsBuffered(PKRDR pRdr); +KRDR_DECL(int) kRdrBufLine(PKRDR pRdr, char *pszLine, KSIZE cbLine); +KRDR_DECL(int) kRdrBufLineEx(PKRDR pRdr, char *pszLine, KSIZE *pcbLine); +KRDR_DECL(const char *) kRdrBufLineQ(PKRDR pRdr); + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif + diff --git a/src/lib/kStuff/include/k/kRdrAll.h b/src/lib/kStuff/include/k/kRdrAll.h new file mode 100644 index 0000000..78f946f --- /dev/null +++ b/src/lib/kStuff/include/k/kRdrAll.h @@ -0,0 +1,127 @@ +/* $Id: kRdrAll.h 29 2009-07-01 20:30:29Z bird $ */ +/** @file + * kRdr - The File Provider, All Details and Dependencies Included. + */ + +/* + * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kRdrAll_h___ +#define ___k_kRdrAll_h___ + +#include <k/kDefs.h> +#include <k/kLdr.h> +#include <k/kRdr.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @defgroup grp_kRdrAll All + * @addtogroup grp_kRdr + * @{ + */ + +/** + * File provider instance operations. + */ +typedef struct KRDROPS +{ + /** The name of this file provider. */ + const char *pszName; + /** Pointer to the next file provider. */ + const struct KRDROPS *pNext; + + /** Try create a new file provider instance. + * + * @returns 0 on success, OS specific error code on failure. + * @param ppRdr Where to store the file provider instance. + * @param pszFilename The filename to open. + */ + int (* pfnCreate)( PPKRDR ppRdr, const char *pszFilename); + /** Destroy the file provider instance. + * + * @returns 0 on success, OS specific error code on failure. + * On failure, the file provider instance will be in an indeterminate state - don't touch it! + * @param pRdr The file provider instance. + */ + int (* pfnDestroy)( PKRDR pRdr); + /** @copydoc kRdrRead */ + int (* pfnRead)( PKRDR pRdr, void *pvBuf, KSIZE cb, KFOFF off); + /** @copydoc kRdrAllMap */ + int (* pfnAllMap)( PKRDR pRdr, const void **ppvBits); + /** @copydoc kRdrAllUnmap */ + int (* pfnAllUnmap)(PKRDR pRdr, const void *pvBits); + /** @copydoc kRdrSize */ + KFOFF (* pfnSize)( PKRDR pRdr); + /** @copydoc kRdrTell */ + KFOFF (* pfnTell)( PKRDR pRdr); + /** @copydoc kRdrName */ + const char * (* pfnName)(PKRDR pRdr); + /** @copydoc kRdrNativeFH */ + KIPTR (* pfnNativeFH)(PKRDR pRdr); + /** @copydoc kRdrPageSize */ + KSIZE (* pfnPageSize)(PKRDR pRdr); + /** @copydoc kRdrMap */ + int (* pfnMap)( PKRDR pRdr, void **ppvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fFixed); + /** @copydoc kRdrRefresh */ + int (* pfnRefresh)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments); + /** @copydoc kRdrProtect */ + int (* pfnProtect)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments, KBOOL fUnprotectOrProtect); + /** @copydoc kRdrUnmap */ + int (* pfnUnmap)( PKRDR pRdr, void *pvBase, KU32 cSegments, PCKLDRSEG paSegments); + /** @copydoc kRdrDone */ + void (* pfnDone)( PKRDR pRdr); + /** The usual non-zero dummy that makes sure we've initialized all members. */ + KU32 u32Dummy; +} KRDROPS; +/** Pointer to file provider operations. */ +typedef KRDROPS *PKRDROPS; +/** Pointer to const file provider operations. */ +typedef const KRDROPS *PCKRDROPS; + + +/** + * File provider instance core. + */ +typedef struct KRDR +{ + /** Magic number (KRDR_MAGIC). */ + KU32 u32Magic; + /** Pointer to the file provider operations. */ + PCKRDROPS pOps; +} KRDR; + +void kRdrAddProvider(PKRDROPS pAdd); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/lib/kStuff/include/k/kTypes.h b/src/lib/kStuff/include/k/kTypes.h new file mode 100644 index 0000000..c957566 --- /dev/null +++ b/src/lib/kStuff/include/k/kTypes.h @@ -0,0 +1,531 @@ +/* $Id: kTypes.h 95 2016-09-26 07:23:08Z bird $ */ +/** @file + * kTypes - Typedefs And Related Constants And Macros. + */ + +/* + * Copyright (c) 2006-2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef ___k_kTypes_h___ +#define ___k_kTypes_h___ + +#include <k/kDefs.h> + +/** @defgroup grp_kTypes kTypes - Typedefs And Related Constants And Macros + * @{ + */ + +/** @typedef KI64 + * 64-bit signed integer. */ +/** @typedef KU64 + * 64-bit unsigned integer. */ +/** @def KI64_C + * 64-bit signed integer constant. + * @param c The constant value. */ +/** @def KU64_C + * 64-bit unsigned integer constant. + * @param c The constant value. */ +/** @def KI64_PRI + * 64-bit signed integer printf format. */ +/** @def KU64_PRI + * 64-bit unsigned integer printf format. */ +/** @def KX64_PRI + * 64-bit signed and unsigned integer hexadecimal printf format. */ + +/** @typedef KI32 + * 32-bit signed integer. */ +/** @typedef KU32 + * 32-bit unsigned integer. */ +/** @def KI32_C + * 32-bit signed integer constant. + * @param c The constant value. */ +/** @def KU32_C + * 32-bit unsigned integer constant. + * @param c The constant value. */ +/** @def KI32_PRI + * 32-bit signed integer printf format. */ +/** @def KU32_PRI + * 32-bit unsigned integer printf format. */ +/** @def KX32_PRI + * 32-bit signed and unsigned integer hexadecimal printf format. */ + +/** @typedef KI16 + * 16-bit signed integer. */ +/** @typedef KU16 + * 16-bit unsigned integer. */ +/** @def KI16_C + * 16-bit signed integer constant. + * @param c The value. */ +/** @def KU16_C + * 16-bit unsigned integer constant. + * @param c The value. */ +/** @def KI16_PRI + * 16-bit signed integer printf format. */ +/** @def KU16_PRI + * 16-bit unsigned integer printf format. */ +/** @def KX16_PRI + * 16-bit signed and unsigned integer hexadecimal printf format. */ + +/** @typedef KI8 + * 8-bit signed integer. */ +/** @typedef KU8 + * 8-bit unsigned integer. */ +/** @def KI8_C + * 8-bit signed integer constant. + * @param c The constant value. */ +/** @def KU8_C + * 8-bit unsigned integer constant. + * @param c The constant value. */ +/** @def KI8_PRI + * 8-bit signed integer printf format. */ +/** @def KU8_PRI + * 8-bit unsigned integer printf format. */ +/** @def KX8_PRI + * 8-bit signed and unsigned integer hexadecimal printf format. */ + +/** @typedef KSIZE + * Memory size type; unsigned integer. */ +/** @typedef KSSIZE + * Memory size type; signed integer. */ +/** @def KSIZE_C + * Memory size constant. + * @param c The constant value. */ +/** @def KSSIZE_C + * Memory size constant. + * @param c The constant value. */ +/** @def KSIZE_MAX + * Memory size max constant.*/ +/** @def KSSIZE_MAX + * Memory size max constant.*/ +/** @def KSSIZE_MIN + * Memory size min constant.*/ +/** @def KSIZE_PRI + * Memory size default printf format (hex). */ +/** @def KSIZE_PRI_U + * Memory size unsigned decimal printf format. */ +/** @def KSIZE_PRI_I + * Memory size signed decimal printf format. */ +/** @def KSIZE_PRI_X + * Memory size hexadecimal printf format. */ +/** @def KSSIZE_PRI + * Memory size default printf format (hex). */ +/** @def KSSIZE_PRI_U + * Memory size unsigned decimal printf format. */ +/** @def KSSIZE_PRI_I + * Memory size signed decimal printf format. */ +/** @def KSSIZE_PRI_X + * Memory size hexadecimal printf format. */ + +/** @typedef KIPTR + * Signed integer type capable of containing a pointer value. */ +/** @typedef KUPTR + * Unsigned integer type capable of containing a pointer value. */ +/** @def KIPTR_C + * Signed pointer constant. + * @param c The constant value. */ +/** @def KUPTR_C + * Unsigned pointer constant. + * @param c The constant value. */ +/** @def KIPTR_MAX + * Signed pointer max constant.*/ +/** @def KIPTR_MIN + * Signed pointer min constant.*/ +/** @def KUPTR_MAX + * Unsigned pointer max constant.*/ +/** @def KIPTR_PRI + * Signed pointer printf format. */ +/** @def KUPTR_PRI + * Unsigned pointer printf format. */ + + +#if K_ARCH_BITS == 32 + /* ASSUMES int == long == 32-bit, short == 16-bit, char == 8-bit. */ +# ifdef _MSC_VER +typedef signed __int64 KI64; +typedef unsigned __int64 KU64; +#define KI64_PRI "I64d" +#define KU64_PRI "I64u" +#define KX64_PRI "I64x" +# else +typedef signed long long int KI64; +typedef unsigned long long int KU64; +#define KI64_PRI "lld" +#define KU64_PRI "llu" +#define KX64_PRI "llx" +# endif +typedef signed int KI32; +typedef unsigned int KU32; +typedef signed short int KI16; +typedef unsigned short int KU16; +typedef signed char KI8; +typedef unsigned char KU8; +#define KI64_C(c) (c ## LL) +#define KU64_C(c) (c ## ULL) +#define KI32_C(c) (c) +#define KU32_C(c) (c ## U) +#define KI16_C(c) (c) +#define KU16_C(c) (c) +#define KI8_C(c) (c) +#define KU8_C(c) (c) + +#define KI32_PRI "d" +#define KU32_PRI "u" +#define KX32_PRI "x" +#define KI16_PRI "d" +#define KU16_PRI "u" +#define KX16_PRI "x" +#define KI8_PRI "d" +#define KU8_PRI "u" +#define KX8_PRI "x" + +typedef KI32 KSSIZE; +#define KSSIZE(c) KI32_C(c) +#define KSSIZE_MAX KI32_MAX +#define KSSIZE_MIN KI32_MIN +#define KSSIZE_PRI KX32_PRI + +typedef KU32 KSIZE; +#define KSIZE_C(c) KU32_C(c) +#define KSIZE_MAX KU32_MAX +#define KSIZE_PRI KX32_PRI +#define KSIZE_PRI_U KU32_PRI +#define KSIZE_PRI_I KI32_PRI +#define KSIZE_PRI_X KX32_PRI +#define KIPTR_C(c) KI32_C(c) + +typedef KI32 KIPTR; +#define KIPTR_MAX KI32_MAX +#define KIPTR_MIN KI32_MIN +#define KIPTR_PRI KX32_PRI + +typedef KU32 KUPTR; +#define KUPTR_C(c) KU32_C(c) +#define KUPTR_MAX KU32_MAX +#define KUPTR_PRI KX32_PRI + + +#elif K_ARCH_BITS == 64 + +# if K_OS == K_OS_WINDOWS +# if _MSC_VER +typedef signed __int64 KI64; +typedef unsigned __int64 KU64; +# define KI64_PRI "I64d" +# define KU64_PRI "I64u" +# define KX64_PRI "I64x" +# else +typedef signed long long int KI64; +typedef unsigned long long int KU64; +# define KI64_PRI "lld" +# define KU64_PRI "llu" +# define KX64_PRI "llx" +# endif +# define KI64_C(c) (c ## LL) +# define KU64_C(c) (c ## ULL) +# else +typedef signed long int KI64; +typedef unsigned long int KU64; +# define KI64_C(c) (c ## L) +# define KU64_C(c) (c ## UL) +# define KI64_PRI "ld" +# define KU64_PRI "lu" +# define KX64_PRI "lx" +# endif +typedef signed int KI32; +typedef unsigned int KU32; +typedef signed short KI16; +typedef unsigned short KU16; +typedef signed char KI8; +typedef unsigned char KU8; +#define KI32_C(c) (c) +#define KU32_C(c) (c ## U) +#define KI16_C(c) (c) +#define KU16_C(c) (c) +#define KI8_C(c) (c) +#define KU8_C(c) (c) + +#define KI32_PRI "d" +#define KU32_PRI "u" +#define KX32_PRI "x" +#define KI16_PRI "d" +#define KU16_PRI "u" +#define KX16_PRI "x" +#define KI8_PRI "d" +#define KU8_PRI "u" +#define KX8_PRI "x" + +typedef KI64 KSSIZE; +#define KSSIZE(c) KI64_C(c) +#define KSSIZE_MAX KI64_MAX +#define KSSIZE_MIN KI64_MIN +#define KSSIZE_PRI KX64_PRI +#define KSSIZE_PRI_U KU64_PRI +#define KSSIZE_PRI_I KI64_PRI +#define KSSIZE_PRI_X KX64_PRI + +typedef KU64 KSIZE; +#define KSIZE_C(c) KU64_C(c) +#define KSIZE_MAX KU64_MAX +#define KSIZE_PRI_U KU64_PRI +#define KSIZE_PRI_I KI64_PRI +#define KSIZE_PRI_X KX64_PRI +#define KSIZE_PRI KX64_PRI + +typedef KI64 KIPTR; +#define KIPTR_C(c) KI64_C(c) +#define KIPTR_MAX KI64_MAX +#define KIPTR_MIN KI64_MIN +#define KIPTR_PRI KX64_PRI + +typedef KU64 KUPTR; +#define KUPTR_C(c) KU64_C(c) +#define KUPTR_MAX KU64_MAX +#define KUPTR_PRI KX64_PRI + +#else +# error "Port Me" +#endif + + +/** Min KI8 value. */ +#define KI8_MIN (KI8_C(-0x7f) - 1) +/** Min KI16 value. */ +#define KI16_MIN (KI16_C(-0x7fff) - 1) +/** Min KI32 value. */ +#define KI32_MIN (KI32_C(-0x7fffffff) - 1) +/** Min KI64 value. */ +#define KI64_MIN (KI64_C(-0x7fffffffffffffff) - 1) +/** Max KI8 value. */ +#define KI8_MAX KI8_C(0x7f) +/** Max KI16 value. */ +#define KI16_MAX KI16_C(0x7fff) +/** Max KI32 value. */ +#define KI32_MAX KI32_C(0x7fffffff) +/** Max KI64 value. */ +#define KI64_MAX KI64_C(0x7fffffffffffffff) +/** Max KU8 value. */ +#define KU8_MAX KU8_C(0xff) +/** Max KU16 value. */ +#define KU16_MAX KU16_C(0xffff) +/** Max KU32 value. */ +#define KU32_MAX KU32_C(0xffffffff) +/** Max KU64 value. */ +#define KU64_MAX KU64_C(0xffffffffffffffff) + +/** File offset. */ +typedef KI64 KFOFF; +/** Pointer a file offset. */ +typedef KFOFF *PFOFF; +/** Pointer a const file offset. */ +typedef KFOFF *PCFOFF; +/** The min value for the KFOFF type. */ +#define KFOFF_MIN KI64_MIN +/** The max value for the KFOFF type. */ +#define KFOFF_MAX KI64_MAX +/** File offset contstant. + * @param c The constant value. */ +#define KFOFF_C(c) KI64_C(c) +/** File offset printf format. */ +#define KFOFF_PRI KI64_PRI + + +/** + * Memory Protection. + */ +typedef enum KPROT +{ + /** The usual invalid 0. */ + KPROT_INVALID = 0, + /** No access (page not present). */ + KPROT_NOACCESS, + /** Read only. */ + KPROT_READONLY, + /** Read & write. */ + KPROT_READWRITE, + /** Read & copy on write. */ + KPROT_WRITECOPY, + /** Execute only. */ + KPROT_EXECUTE, + /** Execute & read. */ + KPROT_EXECUTE_READ, + /** Execute, read & write. */ + KPROT_EXECUTE_READWRITE, + /** Execute, read & copy on write. */ + KPROT_EXECUTE_WRITECOPY, + /** The usual end value. (exclusive) */ + KPROT_END, + /** Blow the type up to 32-bits. */ + KPROT_32BIT_HACK = 0x7fffffff +} KPROT; +/** Pointer to a memory protection enum. */ +typedef KPROT *PKPROT; +/** Pointer to a const memory protection enum. */ +typedef KPROT const *PCKPROT; + +/** Boolean. + * This can be used as a tri-state type, but then you *must* do == checks. */ +typedef KI8 KBOOL; +/** Pointer to a boolean value. */ +typedef KBOOL *PKBOOL; +/** Pointer to a const boolean value. */ +typedef KBOOL const *PCKBOOL; +/** Maxium value the KBOOL type can hold (officially). */ +#define KBOOL_MIN KI8_C(-1) +/** Maxium value the KBOOL type can hold (officially). */ +#define KBOOL_MAX KI8_C(1) +/** The KBOOL printf format. */ +#define KBOOL_PRI KU8_PRI +/** Boolean true constant. */ +#define K_TRUE KI8_C(1) +/** Boolean false constant. */ +#define K_FALSE KI8_C(0) +/** Boolean unknown constant (the third state). */ +#define K_UNKNOWN KI8_C(-1) + + +/** + * Integer union. + */ +typedef union KUINT +{ + KFOFF iBig; /**< The biggest member. */ + KBOOL fBool; /**< Boolean. */ + KU8 b; /**< unsigned 8-bit. */ + KU8 u8; /**< unsigned 8-bit. */ + KI8 i8; /**< signed 8-bit. */ + KU16 u16; /**< unsigned 16-bit. */ + KI16 i16; /**< signed 16-bit. */ + KU32 u32; /**< unsigned 32-bit. */ + KI32 i32; /**< signed 32-bit. */ + KU64 u64; /**< unsigned 64-bit. */ + KI64 i64; /**< signed 64-bit. */ + KSIZE cbUnsign; /**< unsigned size. */ + KSSIZE cbSign; /**< signed size. */ + KFOFF offFile; /**< file offset. */ + KUPTR uPtr; /**< unsigned pointer. */ + KIPTR iPtr; /**< signed pointer. */ + void *pv; /**< void pointer. */ + char ch; /**< char. */ + unsigned char uch; /**< unsigned char. */ + signed char chSigned; /**< signed char. */ + unsigned short uShort; /**< Unsigned short. */ + signed short iShort; /**< Signed short. */ + unsigned int uInt; /**< Unsigned int. */ + signed int iInt; /**< Signed int. */ + unsigned long uLong; /**< Unsigned long. */ + signed long iLong; /**< Signed long. */ +} KUINT; + + +/** + * Integer pointer union. + */ +typedef union KPUINT +{ + KFOFF *piBig; /**< The biggest member. */ + KBOOL *pfBool; /**< Boolean. */ + KU8 *pb; /**< unsigned 8-bit. */ + KU8 *pu8; /**< unsigned 8-bit. */ + KI8 *pi8; /**< signed 8-bit. */ + KU16 *pu16; /**< unsigned 16-bit. */ + KI16 *pi16; /**< signed 16-bit. */ + KU32 *pu32; /**< unsigned 32-bit. */ + KI32 *pi32; /**< signed 32-bit. */ + KU64 *pu64; /**< unsigned 64-bit. */ + KI64 *pi64; /**< signed 64-bit. */ + KSIZE *pcbUnsign; /**< unsigned size. */ + KSSIZE *pcbSign; /**< signed size. */ + KFOFF *poffFile; /**< file offset. */ + KUPTR *puPtr; /**< unsigned pointer. */ + KIPTR *piPtr; /**< signed pointer. */ + void **ppv; /**< void pointer pointer. */ + void *pv; /**< void pointer. */ + char *pch; /**< char. */ + char *psz; /**< zero terminated string. */ + unsigned char *puch; /**< unsigned char. */ + signed char *pchSigned; /**< signed char. */ + unsigned short *puShort; /**< Unsigned short. */ + signed short *piShort; /**< Signed short. */ + unsigned int *puInt; /**< Unsigned int. */ + signed int *piInt; /**< Signed int. */ + unsigned long *puLong; /**< Unsigned long. */ + signed long *piLong; /**< Signed long. */ +} KPUINT; + +/** + * Integer const pointer union. + */ +typedef union KPCUINT +{ + KFOFF const *piBig; /**< The biggest member. */ + KBOOL const *pfBool; /**< Boolean. */ + KU8 const *pb; /**< byte. */ + KU8 const *pu8; /**< unsigned 8-bit. */ + KI8 const *pi8; /**< signed 8-bit. */ + KU16 const *pu16; /**< unsigned 16-bit. */ + KI16 const *pi16; /**< signed 16-bit. */ + KU32 const *pu32; /**< unsigned 32-bit. */ + KI32 const *pi32; /**< signed 32-bit. */ + KU64 const *pu64; /**< unsigned 64-bit. */ + KI64 const *pi64; /**< signed 64-bit. */ + KSIZE const *pcbUnsign; /**< unsigned size. */ + KSSIZE const *pcbSign; /**< signed size. */ + KFOFF const *poffFile; /**< file offset. */ + KUPTR const *puPtr; /**< unsigned pointer. */ + KIPTR const *piPtr; /**< signed pointer. */ + void const **ppv; /**< void pointer pointer. */ + void const *pv; /**< void pointer. */ + char const *pch; /**< char. */ + char const *psz; /**< zero terminated string. */ + unsigned char const *puch; /**< unsigned char. */ + signed char const *pchSigned; /**< signed char. */ + unsigned short const *puShort; /**< Unsigned short. */ + signed short const *piShort; /**< Signed short. */ + unsigned int const *puInt; /**< Unsigned int. */ + signed int const *piInt; /**< Signed int. */ + unsigned long const *puLong; /**< Unsigned long. */ + signed long const *piLong; /**< Signed long. */ +} KPCUINT; + + +/** @name Forward Declarations / Handle Types. + * @{ */ + +/** Pointer to a file provider instance. */ +typedef struct KRDR *PKRDR; +/** Pointer to a file provider instance pointer. */ +typedef struct KRDR **PPKRDR; + +/** Pointer to a loader segment. */ +typedef struct KLDRSEG *PKLDRSEG; +/** Pointer to a loader segment. */ +typedef const struct KLDRSEG *PCKLDRSEG; + +/** @} */ + +/** @} */ + +#endif + |