Saturday, May 6, 2023

 

/*

    tsdebug.h -- Bob Trower 02/09/91

 

This file has been created to add some debugging extensions

to C code.  It allows existing debugging code and

information messages to be cleaned up in the 'LA3' system.

*/

#define TS_USR_CALLBACK

#define INCL_CONTX

#define INCL_TRACE

#define INCL_PRINT

#define INCL_TS_DEBUG_CODE

#define INCL_LIST

#define INCL_MALLO

#define TS_TESTCODE

 

#include <stdarg.h>

#define TS_VERMAJ 0

#define TS_VERMIN 6

#define TS_VERREL 00

 

/*

To add this file to an application, add the following lines

to main.h and main.c:

 

Add the following line to main.h:

 

    #include "tsdebug.h"

 

Add the following 4 lines to the end of main.c:

 

    #ifdef TS_DEBUG

    #define INCL_TS_DEBUG_CODE

    #include "tsdebug.h"

    #endif

 

Debug code will be included if TS_DEBUG is defined when the

code is compiled.  The debug code is affected by the

environment variables described below.

 

To turn on debugging messages, set the environment

variables:

 

    set TS_DEBUG_MODE=1

            .

            .

            .

    set TS_DEBUG_MODE=9

 

        TS_DEBUG_MODE must be set in the environment

        for any messages to appear from the system,

        otherwise, all printf statements are

        discarded. The maximum debug level is 9,

        which will cause all debugging information

        to appear.

 

    set TS_MAIL=<Mail Address>

 

        Some printed messages also cause a mail

        message to be sent (use with caution).  If

        this variable is set (i.e

        TS_MAIL=btrower@ipgnet.com), mail will be

        sent to that address.  If the variable is

        not set, messages are not sent. Note that

        this requires a program similar to UNIX

        'mail', with the name 'mail'.

 

    set TS_MEMVERBOSE=1

    set TS_MEMVERBOSE=2

 

        Setting TS_MEMVERBOSE causes messages to be

        printed from the memory allocation code.  A

        higher number indicates a more verbose mode.

 

This code causes all instances of malloc, calloc, realloc

and free at the application level to be replaced with

debugging versions that track the memory used and check for

memory corruption, or freeing of invalid memory.

 

In addition to memory functions, this code will patch

USR_FunctionBegin, and USR_FunctionEnd to add tracing to the

debug code if TS_USR_CALLBACK is defined.

 

*/

 

#define TS_PORT

#define tsLPSTR char *

#ifndef TS_PORT

    #include <string.h>

    #ifndef FAR

    #define FAR _far

    #endif

 

    #ifndef tsLPSTR

    typedef char FAR*      tsLPSTR;

    #endif

    #define strcpy _fstrcpy

#endif

 

 

#ifndef mytsLPSTR_DEFINED

    typedef tsLPSTR mytsLPSTR;

    #define mytsLPSTR_DEFINED

#endif

 

#ifdef TS_TESTSHELL_CONTX

    #define INCL_CONTX

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_TESTSHELL_PRINT

    #define INCL_CONTX

    #define INCL_PRINT

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_TESTSHELL_MALLO

    #define INCL_CONTX

    #define INCL_MALLO

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_TESTSHELL_LIST

    #define INCL_LIST

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_TESTSHELL_TRACE

    #define TS_DEBUG

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_TESTSHELL_TSDEBUG

    #define TS_DEBUG

    #define TS_TESTCODE

    #define INCL_TS_DEBUG_CODE

#endif

 

#ifdef TS_DEBUG

    #define INCL_CONTX

    #define INCL_PRINT

    #define INCL_MALLO

    #define INCL_LIST

    #define INCL_TRACE

#endif

 

/********** External interface:   TSdCONTEXT           ** Start **/

#if defined(INCL_CONTX)

    #if !defined(tsdcontx_h)

    #define tsdcontx_h

 

    #if !defined(size_t)

        #include <stdio.h>

        #include <string.h>

    #endif

 

    #ifndef TRUE

        #define TRUE 1

        #define FALSE 0

    #endif

 

    tsLPSTR TSdSetContextFile(tsLPSTR Name);

    int TSdSetContextLine(int Number);

    tsLPSTR TSdSetContextFunc(tsLPSTR Name);

 

    void TSdSetContext(tsLPSTR FileName, int Line, tsLPSTR FuncName);

 

    #define TSdSetCurContext(FuncName) \

        TSdSetContext(__FILE__, __LINE__, FuncName);

 

    tsLPSTR TSdGetContextFunc(void);

    int TSdGetContextLine(void);

    tsLPSTR TSdGetContextFile(void);

    int TSdIncFunctionDepth(void);

    int TSdDecFunctionDepth(void);

    tsLPSTR TSdPadStr(void);

    tsLPSTR TSdContextStr(void);

    size_t TSdSetContextMem(size_t MemAllocated);

    size_t TSdSetContextTotMem(size_t TotMemAllocated);

    size_t TSdGetContextMem(void);

    size_t TSdGetContextTotMem(void);

 

    void test_tsdcontx(void);

 

    #define TSdMAX_FILE_NAME_LEN    512

    #define TSdMAX_FUNC_NAME_LEN    512

    #define TSdBUF_LEN_WORK_MEDIUM  1024

 

    #endif

#else

    #define TSdSetCurContext(FuncName)

#endif

/********** External interface:   TSdCONTEXT           ** End   **/

 

/********** External interface:   TSdMalloc         ** Start **/

#if defined(INCL_MALLO)

    #if !defined(tsdmallo_h)

    #define tsdmallo_h

 

    #if !defined(max)

        #include <stdlib.h>

    #endif

 

    #if !defined(size_t)

        #include <string.h>

    #endif

 

    /*

    ** Redefine normal library calls to our replacements

    */

 

    #define malloc(Size)                TSdMalloc(Size)

    #define realloc(Ptr, Size)          TSdRealloc(Ptr, Size)

    #define free(Ptr)                   TSdFree(Ptr)

    #define calloc(Nelem, Esize)        TSdCalloc(Nelem, Esize)

    #define strdup(Str)                 TSdStrDup(Str)

    #define memalign(Alignment, Size)   TSdMalloc(Size)

 

    /*

    ** Export prototypes for our replacements

    */

 

    void    TSdFree(void *ptr);

    void *  TSdMalloc(size_t Size);

    void *  TSdCalloc(size_t Nelem, size_t Esize);

    void *  TSdRealloc(void *Ptr, size_t Size);

    tsLPSTR   TSdStrDup(const tsLPSTR Str);

 

    void *TSdAddTrustedPtr(void *Ptr);

    void test_tsdmallo(void);

 

    #endif

#endif

/********** External interface:   TSdMalloc         ** End   **/

 

/********** External interface:   TSdPRINTF         ** Start **/

#if defined(INCL_PRINT)

    #if !defined(tsdprint_h)

    #define tsdprint_h

 

    #if !defined(max)

        #include <stdlib.h>

    #endif

 

    #if !defined(stdin)

        #include <stdio.h>

    #endif

 

    #if !defined(size_t)

        #include <string.h>

    #endif

 

    int TSdDebugMode(void);

 

    #define TSdMAX_DEBUG_MODE 9

    #define TSdPrintf(x) TSdebug_Printf x

    #define TSdPrintf2(x) if(TSdDebugMode() > 1) TSdebug_Printf x

    #define TSdPrintf3(x) if(TSdDebugMode() > 2) TSdebug_Printf x

    #define TSdPrintf4(x) if(TSdDebugMode() > 3) TSdebug_Printf x

    #define TSdPrintf5(x) if(TSdDebugMode() > 4) TSdebug_Printf x

    #define TSdPrintf6(x) if(TSdDebugMode() > 5) TSdebug_Printf x

    #define TSdPrintf7(x) if(TSdDebugMode() > 6) TSdebug_Printf x

    #define TSdPrintf8(x) if(TSdDebugMode() > 7) TSdebug_Printf x

    #define TSdPrintf9(x) if(TSdDebugMode() > 8) \

        TSdebug_Printf("%s", TSdPadStr()); TSdebug_Printf x ;\

        TSdebug_Printf(":%s:%i\n", __FILE__, __LINE__);

       

    #define TSdPrint (fmt, ...) TSdebug_Printf(fmt, ## __VA_ARGS__)

    #define TSdPrint2(...) if(TSdDebugMode() > 1) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint3(...) if(TSdDebugMode() > 2) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint4(...) if(TSdDebugMode() > 3) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint5(...) if(TSdDebugMode() > 4) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint6(...) if(TSdDebugMode() > 5) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint7(...) if(TSdDebugMode() > 6) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint8(...) if(TSdDebugMode() > 7) TSdebug_Printf(__VA_ARGS__)

    #define TSdPrint9(...) if(TSdDebugMode() > 8) TSdebug_Printf(__VA_ARGS__)

   

    #define TSdPrintfOutputProcedure(Proc) int (*Proc)(tsLPSTR Output)

    #define TSdSetBufferProcedure(Proc) tsLPSTR (*Proc)(tsLPSTR Buffer)

    #define TSdSetObjectProcedure(Proc) tsLPSTR (*Proc)(void *Object, tsLPSTR Buffer)

 

    extern TSdPrintfOutputProcedure(TSdPrintfOutPut);

    int TSdebug_Printf(const tsLPSTR fmt, ...);

    int TSdDefPrintfOutPut(tsLPSTR Output);

 

    void test_tsdprint(void);

    #endif

#else

    #define TSdPrintf (x)

    #define TSdPrintf2(x)

    #define TSdPrintf3(x)

    #define TSdPrintf4(x)

    #define TSdPrintf5(x)

    #define TSdPrintf6(x)

    #define TSdPrintf7(x)

    #define TSdPrintf8(x)

    #define TSdPrintf9(x)

 

    #define TSdPrint (x)

    #define TSdPrint2(x)

    #define TSdPrint3(x)

    #define TSdPrint4(x)

    #define TSdPrint5(x)

    #define TSdPrint6(x)

    #define TSdPrint7(x)

    #define TSdPrint8(x)

    #define TSdPrint9(x)

 

#endif

/********** External interface:   TSdPRINTF         ** End   **/

 

/********** External interface:   TSdLIST             ** Start **/

#if defined(INCL_LIST)

    #if !defined(tsdlist_h)

    #define tsdlist_h

 

    /* List Messages */

    #define TSD_MSG_NEW_LIST     16705

    #define TSD_MSG_INI_LIST     16706

    #define TSD_MSG_DEL_LIST     16707

    #define TSD_MSG_EMT_LIST     16708

    #define TSD_MSG_NEW_NODE     16709

    #define TSD_MSG_INI_NODE     16710

    #define TSD_MSG_ADD_NODE     16711

    #define TSD_MSG_DEL_NODE     16712

    #define TSD_MSG_PUT_NODE     16713

    #define TSD_MSG_GET_NODE     16714

    #define TSD_MSG_SET_FCMP     16715

 

    #define TSD_LIST_TYPE_ANY      0

    #define TSD_LIST_TYPE_LIST    1

 

    typedef int TSdMsgType;

 

    typedef struct tagTSdListNode {

        tsLPSTR Data;

        struct tagTSdListNode *next;

    }TSdListNode, *pTSdListNode;

 

    typedef union{

        void *(*Func)(void *);

        void *Data;

    }TSdGP;

 

    #define TSdListProcedure(Proc) void *(*Proc)(struct tagTSdList *List, TSdMsgType Msg, void *Data)

    #define TSdCompareProcedure(Proc) int (*Proc)(void *Data1, void *Data2)

    #define TSdCompareProcedureProt int (*)(void *, void *)

 

    typedef struct tagTSdList {

        int Type;

         pTSdListNode head;

        pTSdListNode tail;

        pTSdListNode curr;

        TSdListProcedure(Proc);

        TSdCompareProcedure(Compare);

        tsLPSTR Name;

    }TSdList, *pTSdList;

 

    #define GetTSdNewList(List, ListProc, Data) ListProc(List, TSD_MSG_NEW_LIST, Data)

 

    #define TSdNewList(Name) GetTSdNewList(TSd_ListOfLists(),TSdDefListProc,Name)

    #define TSdAddList(List, Name) GetTSdNewList(List,TSdDefListProc,Name)

 

    #define t_TSdNewListNode(List, Data) (List->Proc)(List,TSD_MSG_NEW_NODE,Data)

    #define t_TSdAddListNode(List, Data) (List->Proc)(List,TSD_MSG_ADD_NODE,TSdNewListNode(List, Data))

    #define t_TSdDelListNode(List, Data) (List->Proc(List, TSD_MSG_DEL_NODE, Data))

    #define t_TSdGetListNode(List, Data) (List->Proc(List, TSD_MSG_GET_NODE, Data))

    #define t_TSdSetCmpFunc(List, Func)  (List->Proc(List, TSD_MSG_SET_FCMP, Func))

    #define t_TSdDisposeList(List) (List ? (List->Proc(List, TSD_MSG_DEL_LIST, NULL)) : NULL)

    #define t_TSdEmptyList(List) (List->Proc(List, TSD_MSG_EMT_LIST, NULL))

 

    #define TSdNewListNode(List, Data) (List ? t_TSdNewListNode(List, Data) : NULL)

    #define TSdAddListNode(List, Data) (List ? t_TSdAddListNode(List, Data) : NULL)

    #define TSdDelListNode(List, Data) (List ? t_TSdDelListNode(List, Data) : NULL)

    #define TSdGetListNode(List, Data) (List ? t_TSdGetListNode(List, Data) : NULL)

    #define TSdSetCmpFunc(List, Func)  (List ? t_TSdSetCmpFunc(List, Func)  : NULL)

    #define TSdDisposeList(List)       (List ? t_TSdDisposeList(List)       : NULL)

    #define TSdEmptyList(List)         (List ? t_TSdEmptyList(List)         : NULL)

 

    #define TSdSetListType(List, TSdListType) (List ? List->Type |= TSdListType : TSD_LIST_TYPE_ANY)

    #define TSdSetListIsList(List) TSdSetListType(List, TSD_LIST_TYPE_LIST)

    #define TSdListType(List) (List ? List->Type : TSD_LIST_TYPE_ANY)

    #define TSdListIsList(List) (List ? (TSdListType(List) & TSD_LIST_TYPE_LIST) : TSD_LIST_TYPE_ANY)

 

    extern pTSdList TSd_ListOfLists_;

    #define TSd_ListOfLists() TSd_ListOfLists_

 

    void *TSdDefListProc(pTSdList List, TSdMsgType Msg, void *Data);

 

    void test_tsdlist(void);

 

    #endif

#endif

/********** External interface:   TSdLIST             ** End   **/

 

/********** External interface:   TSdTRACING           ** Start **/

#if defined(INCL_TRACE)

    #if !defined(tsdtrace_h)

    #define tsdtrace_h

 

    #define printf TSdebug_Printf

 

    #define USR_FunctionBegin(Name)  TSdFunctionBegin(Name)

    #define USR_FunctionEnd(Name)   TSdFunctionEnd(Name)

 

    int TSdebug_FunctionBegin(const tsLPSTR FunctionName);

    int TSdebug_FunctionEnd(const tsLPSTR FunctionName);

 

    #define TSdFunctionBegin(Name)  TSdSetCurContext(Name);\

                    TSdebug_FunctionBegin(Name)

    #define TSdFunctionEnd(Name)    TSdSetCurContext(Name);\

                    TSdebug_FunctionEnd(Name)

 

    void test_tsdtrace(void);

    tsLPSTR TSdPadStr(void);

    #endif

#else

    #define TSdFunctionBegin(Name)

    #define TSdFunctionEnd(Name)

#endif

/********** External interface:   TSdTRACING           ** End   **/

 

/********** External interface:   TSdDEBUG           ** Start **/

 

#if defined(TS_DEBUG)

    #if !defined(tsdebug_h)

    #define tsdebug_h

    #endif

#endif

 

/********** External interface:   TSdDEBUG           ** End   **/

 

/********** Internal Implementation: TSdCONTEXT        ** Start **/

#if defined(INCL_CONTX) && defined(INCL_TS_DEBUG_CODE)

#if !defined(tsdcontx_c)

#define tsdcontx_c

 

#if !defined(size_t)

    #include <stdio.h>

    #include <string.h>

#endif

 

typedef struct tagContext{

    char FileName[TSdMAX_FILE_NAME_LEN];

    char FuncName[TSdMAX_FUNC_NAME_LEN];

    int Line;

    size_t MemAllocated;

    size_t TotMemAllocated;

    int FunctionDepth;

    int DepthStep;

}tTSdContext, *ptTSdContext;

 

static tTSdContext TSdContextInfo = {

    "",

    "",

    0,

    0,

    0,

    0,

    4,

}, *TSdContext = &TSdContextInfo;

 

tsLPSTR TSdSetContextFile(tsLPSTR Name)

{

    strncpy(TSdContext->FileName, Name, TSdMAX_FILE_NAME_LEN - 1);

    return(TSdContext->FileName);

}

 

tsLPSTR TSdSetContextFunc(tsLPSTR Name)

{

    strncpy(TSdContext->FuncName, Name, TSdMAX_FUNC_NAME_LEN - 1);

    return(TSdContext->FuncName);

}

 

int TSdSetContextLine(int Number)

{

    TSdContext->Line = Number;

    return(TSdContext->Line);

}

 

size_t TSdSetContextMem(size_t MemAllocated)

{

    TSdContext->MemAllocated = MemAllocated;

    return(TSdContext->MemAllocated);

}

 

size_t TSdSetContextTotMem(size_t TotMemAllocated)

{

    TSdContext->TotMemAllocated = TotMemAllocated;

    return(TSdContext->TotMemAllocated);

}

 

tsLPSTR TSdGetContextFile(void)

{

    return(TSdContext->FileName);

}

 

tsLPSTR TSdGetContextFunc(void)

{

    return(TSdContext->FuncName);

}

 

int TSdGetContextLine(void)

{

    return(TSdContext->Line);

}

 

void TSdSetContext(tsLPSTR FileName, int Line, tsLPSTR FuncName)

{

    TSdSetContextFile(FileName);

    TSdSetContextLine(Line);

    TSdSetContextFunc(FuncName);

}

 

size_t TSdGetContextMem(void)

{

    return(TSdContext->MemAllocated);

}

 

size_t TSdGetContextTotMem(void)

{

    return(TSdContext->TotMemAllocated);

}

 

int TSdIncFunctionDepth(void)

{

    return(TSdContext->FunctionDepth++);

}

 

int TSdDecFunctionDepth(void)

{

    return(TSdContext->FunctionDepth--);

}

 

tsLPSTR TSdPadStr(void)

{

    static char Str[TSdBUF_LEN_WORK_MEDIUM];

    int Pad;

 

    Pad = TSdContext->FunctionDepth * TSdContext->DepthStep;

    sprintf(Str, "%*.*s", Pad, Pad, "");

 

    return(Str);

}

 

tsLPSTR TSdContextStr(void)

{

    static char Buf[TSdBUF_LEN_WORK_MEDIUM];

 

    sprintf(Buf,"%s:%s(%i)",    TSdContext->FileName, \

                    TSdContext->FuncName,

                    TSdContext->Line);

    return(Buf);

}

 

#if defined(TS_TESTCODE)

 

void test_tsdcontx(void)

{

    /*tsLPSTR FuncName, *FileName;

    int Line;*/

    printf("Context:%s\n", TSdContextStr());

    TSdSetCurContext("test_tsdcontx");

    printf("Context:%s\n", TSdContextStr());

}

 

#endif

 

#if defined(TS_TESTSHELL_CONTX)

    int main(int argc, tsLPSTR *argv)

    {

        if(argc < 2){

            printf("Usage:  tsdcontx '.'\n");

            printf("(Test Shell for tsdcontx)\n");

        }

        else{

            test_tsdcontx();

        }

        return( 0 );

    }

#endif

 

#endif

 

#endif

/********** Internal Implementation: TSdCONTEXT        ** End   **/

 

/********** Internal Implementation: TSdMalloc          ** Start **/

#if defined(INCL_MALLO) && defined(INCL_TS_DEBUG_CODE)

#if !defined(tsdmallo_c)

#define tsdmallo_c

 

#define TSdMPrintf(x) if(TSdMemVerboseMode(FALSE)) printf x

#define TSdMPrintf2(x) if(TSdMemVerboseMode(FALSE) > 1) printf x

 

#define TSdMPrint (fmt, ...) if(TSdMemVerboseMode(FALSE) > 0) fprintf(stderr, fmt, __VA_ARGS__)

#define TSdMPrint2(fmt, ...) if(TSdMemVerboseMode(FALSE) > 1) fprintf(stderr, fmt, __VA_ARGS__)

 

#define TS_MEMVERBOSE_VAR      "TS_MEMVERBOSE"

 

int TSdMemVerboseMode(int ForceOn)

{

    static int VerboseMode = FALSE;

    static int Initialized = FALSE;

 

    if(ForceOn){

        VerboseMode = ForceOn;

        Initialized = TRUE;

    }

    else if(!Initialized){

        tsLPSTR VerboseSwitch;

 

        VerboseSwitch=getenv(TS_MEMVERBOSE_VAR);

        if(VerboseSwitch){

            VerboseMode = atoi(VerboseSwitch);

            VerboseMode = VerboseMode ? VerboseMode : TRUE;

        }

        Initialized = TRUE;

    }

 

    return(VerboseMode);

}

 

/* Point our redefinitions of standard library code back to the real thing */

#undef malloc

#undef realloc

#undef free

#include <malloc.h>

 

void *TSdTrueMalloc(size_t Size)

{

    return(malloc(Size));

}

 

void TSdTrueFree(void *Ptr)

{

    free(Ptr);

}

 

void *TSdTrueRealloc(void *Ptr, size_t Size)

{

    return(realloc(Ptr, Size));

}

 

/* Restore our redefinitions of standard library code */

#define malloc(Size)        TSdMalloc(Size)

#define realloc(Ptr, Size)    TSdRealloc(Ptr, Size)

#define free(Ptr)          TSdFree(Ptr)

 

/* Trusted memory allocations list stuff */

 

typedef struct tagMgMemTrusted{

    void *Ptr;

    struct tagMgMemTrusted *next;

}tTrustedMem, *ptTrustedMem;

 

ptTrustedMem MgMemTr_head = NULL, MgMemTr_tail = NULL, MgMemTr_current = NULL;

 

void *TSdAddTrustedPtr(void *Ptr)

{

    void *MemPtr = NULL;

 

    if(Ptr){

        MgMemTr_current = malloc(sizeof(tTrustedMem));

        if (MgMemTr_current){

            MemPtr = Ptr;

            MgMemTr_current->Ptr = Ptr;

            MgMemTr_current->next = NULL;

            if (MgMemTr_head == NULL) {

                MgMemTr_head = MgMemTr_tail = MgMemTr_current;

            }

            else {

                MgMemTr_tail->next = MgMemTr_current;

                MgMemTr_tail = MgMemTr_current;

            }

        }

    }

    TSdMPrintf2(("Add Trusted pointer:[%p]\n", MgMemTr_current->Ptr));

    return(MemPtr);

}

 

void *TSdTrustedPtr(void *Ptr)

{

    ptTrustedMem Here, Found = NULL;

    for(Here = MgMemTr_head;Here && !Found;Here = Here->next){

        if( Here->Ptr == Ptr){

            Found = Here;

        }

    }

    return(Found);

}

 

void *TSdDelTrustedPtr(void *Ptr)

{

    ptTrustedMem cur = NULL, prev = NULL;

    ptTrustedMem Found = FALSE;

 

    cur = MgMemTr_head;

    prev = NULL;

    while(cur){

        if (cur->Ptr == Ptr) {

            Found = cur;

            if(prev) {

                prev->next = cur->next;

                free(cur);

                cur = prev->next;

                if(!cur){

                    MgMemTr_tail = prev;

                }

            }

            else {

                MgMemTr_head = cur->next;

                free(cur);

                if(!MgMemTr_head){

                    cur = NULL;

                }

                else {

                    cur = MgMemTr_head->next;

                }

                if(!cur){

                    MgMemTr_tail = MgMemTr_head;

                }

            }

        }

        else {

            prev = cur;

            cur = cur->next;

        }

    }

    if(!Found){

        TSdMPrintf(("%Dc%Df%Dl%DmTSdDelTrustedPtr: Attempt to free invalid pointer\n"));

    }

    return(Found);

}

 

 

#define MgMemStartSentinelValue 121

#define MgMemEndSentinelValue   97

 

typedef unsigned char MgMemSentinel;

 

typedef struct tMemBlock {

    char pad[7];

    MgMemSentinel StartSentinel;

    char data[1];

}tMemBlock;

 

typedef struct tTSdMalloc_tag {

    size_t Size;

    tMemBlock *ptr;

    struct tTSdMalloc_tag *next;

}fMemt;

 

#define MGMEM_UNUSED_FLAG   'u'

#define MGMEM_FREED_FLAG    'f'

 

static fMemt *MgMem_head = NULL;

static fMemt *MgMem_tail = NULL;

static fMemt *MgMem_current = NULL;

 

fMemt *MgMemMalloc(size_t Size)

{

    fMemt *Mem;

 

    Mem = (fMemt *) TSdTrueMalloc(sizeof(fMemt));

    if(Mem){

        Mem->ptr = TSdTrueMalloc(sizeof(tMemBlock) + Size );

        if(!Mem->ptr){

            TSdTrueFree(Mem);

            Mem = NULL;

        }

        else {

            Mem->ptr->StartSentinel = MgMemStartSentinelValue;

            memset(Mem->ptr->data,MGMEM_UNUSED_FLAG,Size);

            Mem->ptr->data[Size] = MgMemEndSentinelValue;

            Mem->Size = Size;

        }

    }

    return(Mem);

}

 

void *TSdMalloc(size_t Size)

{

    void *MemoryPtr = NULL;

 

    TSdMPrintf2(("TSdMalloc:Net Memory in:%li\n", (long) TSdGetContextTotMem()));

    MgMem_current = MgMemMalloc(Size);

    if (MgMem_current){

        MgMem_current->next = NULL;

        if (MgMem_head == NULL) {

            MgMem_head = MgMem_tail = MgMem_current;

        }

        else {

            MgMem_tail->next = MgMem_current;

            MgMem_tail = MgMem_current;

        }

 

        TSdSetContextTotMem(TSdGetContextTotMem() + Size);

        MemoryPtr = MgMem_current->ptr->data;

    }

    TSdMPrintf2(("TSdMalloc:Net Memory:%li", (long) TSdGetContextTotMem()));

    TSdMPrintf2((" at %s\n", (char *) TSdContextStr()));

    return(MemoryPtr);

}

 

void *TSdCalloc(size_t Nelem, size_t Esize)

{

    tsLPSTR Mem;

    size_t Size = Nelem * Esize;

 

    Mem = TSdMalloc(Size);

    if(Mem){

        memset(Mem, 0, Size);

    }

    return(Mem);

}

 

int MgMemValidate(fMemt *Mem)

{

    int Valid = FALSE;

 

    if(!Mem){

        TSdMPrintf(("Attempt to validate null Memory node\n"));

    }

    else if(!Mem->ptr){

        TSdMPrintf(("Memory node has invalid memory pointer\n"));

    }

    else {

        tMemBlock *ptr;

 

        ptr = Mem->ptr;

        if( Mem->ptr->StartSentinel != MgMemStartSentinelValue ){

            TSdMPrintf(("Invalid Start sentinel in memory pointer\n"));

        }

        else if( Mem->ptr->data[Mem->Size] != MgMemEndSentinelValue ){

            TSdMPrintf(("Invalid End sentinel in memory pointer\n"));

        }

        else {

            Valid = TRUE;

        }

    }

    if(!Valid){

        TSdMPrintf(("Error -- Memory Node failed validation\n"));

    }

    return(Valid);

}

 

int MgMemFree(fMemt *Mem)

{

    int Freed = FALSE;

    if(MgMemValidate(Mem)){

        memset(Mem->ptr->data,MGMEM_FREED_FLAG, Mem->Size);

        TSdTrueFree(Mem->ptr);

        TSdTrueFree(Mem);

        Freed = TRUE;

    }

 

    return(Freed);

}

 

fMemt *MgMemRealloc(fMemt *Mem, size_t Size)

{

    if(Mem){

        Mem->ptr = TSdTrueRealloc(Mem->ptr, sizeof(tMemBlock) + Size );

        if(!Mem->ptr){

            TSdTrueFree(Mem);

            Mem = NULL;

        }

        else {

            Mem->ptr->StartSentinel = MgMemStartSentinelValue;

            Mem->ptr->data[Size] = MgMemEndSentinelValue;

            Mem->Size = Size;

        }

    }

    return(Mem);

}

 

void TSdFreeManagedMem(void *ptr)

{

    fMemt *MgMem_cur = NULL, *MgMem_prev = NULL;

    int Found = FALSE;

 

    MgMem_cur = MgMem_head;

    MgMem_prev = NULL;

    while (MgMem_cur != NULL) {

        MgMemValidate(MgMem_cur);

        if (MgMem_cur->ptr->data == ptr) {

            Found = TRUE;

            TSdSetContextTotMem( TSdGetContextTotMem() - MgMem_cur->Size );

            if(MgMem_prev) {

                MgMem_prev->next = MgMem_cur->next;

                MgMemFree(MgMem_cur);

                MgMem_cur = MgMem_prev->next;

                if(!MgMem_cur){

                    MgMem_tail = MgMem_prev;

                }

            }

            else {

                MgMem_head = MgMem_cur->next;

                MgMemFree(MgMem_cur);

                if(!MgMem_head){

                    MgMem_cur = NULL;

                }

                else {

                    MgMem_cur = MgMem_head->next;

                }

                if(!MgMem_cur){

                    MgMem_tail = MgMem_head;

                }

                if(!MgMem_tail) {

                }

            }

        }

        else {

            MgMem_prev = MgMem_cur;

            MgMem_cur = MgMem_cur->next;

        }

    }

    if(!Found){

        TSdMPrintf(("%Dc%Df%Dl%DmError -- Attempt to free invalid pointer\n"));

    }

    TSdMPrintf2(("TSdFreeManagedMem:Net Memory:%li\n", (long) TSdGetContextTotMem()));

}

 

void TSdFree(void *ptr)

{

    TSdMPrintf2(("To Managed Memory: Pointer %p: ", ptr));

    TSdMPrintf2(("To Managed Memory: Value as string '%s'\n", ptr));

    if(TSdTrustedPtr(ptr)){

        TSdDelTrustedPtr(ptr);

        TSdTrueFree(ptr);

    }

    else {

        TSdFreeManagedMem(ptr);

    }

}

 

void *TSdRealloc(void *ptr, size_t Size)

{

    void *MemoryPtr = NULL;

    fMemt *MgMem_cur = NULL, *MgMem_prev = NULL;

 

    TSdMPrintf2(("Reallocating Memory:%Dc%Df\n"));

    MgMem_cur = MgMem_head;

    MgMem_prev = NULL;

    if( !ptr ) {

        ptr = TSdMalloc( Size );

    }

    while (MgMem_cur) {

        MgMemValidate(MgMem_cur);

        if (MgMem_cur->ptr->data == ptr) {

            size_t OldSize = MgMem_cur->Size;

            MgMem_current = MgMemRealloc(MgMem_cur, Size);

            TSdSetContextTotMem( TSdGetContextTotMem() +(Size - OldSize) );

            MgMem_cur = NULL;

            MemoryPtr = MgMem_current->ptr->data;

        }

        else {

            MgMem_prev = MgMem_cur;

            MgMem_cur = MgMem_cur->next;

        }

    }

    if(!MemoryPtr){

        TSdMPrintf(("%Dc%Df%Dl%DmError -- problem re-allocating pointer\n"));

    }

    TSdMPrintf2(("TSdRealloc:Net Memory:%li\n", (long) TSdGetContextTotMem()));

    return(MemoryPtr);

}

 

tsLPSTR TSdStrDup(const tsLPSTR Str)

{

    int len;

    tsLPSTR NewStr;

 

    len = strlen(Str);

    NewStr = (tsLPSTR ) TSdMalloc(len + 1);

    if(NewStr){

        strcpy(NewStr, Str);

    }

 

    return(NewStr);

}

 

#if defined(TS_TESTCODE)

void test_tsdmallo(void)

{

    tsLPSTR str, *p1, *p2;

    tsLPSTR *pp;

    int i;

 

    printf("Testing TSdMalloc module\n");

    if(!TSdMemVerboseMode(FALSE)){

        TSdMemVerboseMode(1);

    }

    pp = TSdCalloc(10, sizeof(tsLPSTR ));

    for(i = 0; i < 9; i++){

        pp[i] = TSdStrDup("Test_String[n]");

        pp[i][12] = (char) (i + '0');

    }

    for(i = 0; pp[i]; i++){

        printf("%s\n", pp[i]);

    }

    for(i = 0; pp[i]; i++){

        TSdFree(pp[i]);

    }

    for(i = 0; pp[i]; i++){

        printf("%16.16s\n", pp[i]);

    }

    TSdFree(pp);

    str = TSdStrDup("Test_String");

    printf("[Forced error]:");

    strcpy(str, "Test_StringO");    /* Last character overwrites sentinel */

    TSdFree(str);

    strcpy(str, "Test_String");    /* reset sentinel so it can be freed */

    TSdFree(str);

    str = TSdStrDup("Test_String3");

    TSdFree(str);

    printf("[Forced error]:");

    TSdFree(str);   /* Pointer is now invalid */

    p1 = TSdMalloc(100);

    str = TSdStrDup("Test_String4");

    p2 = TSdRealloc(p1, 15000);

    printf("Ptr1=%p, Ptr2=%p\n", p1, p2);

    p1 = TSdMalloc(100);

    printf("Ptr2 Contents:'%50.50s'\n", p2);

    free(p1);

    p1 = TSdTrueMalloc(1000);

    TSdAddTrustedPtr(p1);

    printf("Freeing trusted pointer.\n");

    free(p1);

    printf("Freeing formerly trusted pointer.\n");

    printf("[Forced error]:");

    free(p1);

    free(p2);

    free(str);

}

#endif

 

#if defined(TS_TESTSHELL_MALLO)

    int main(int argc, tsLPSTR *argv)

    {

        if(argc < 2){

            printf("Usage:  tsdmallo '.'\n");

            printf("(Test Shell for tsdmallo)\n");

        }

        else{

            test_tsdmallo();

        }

        return( 0 );

    }

#endif

 

#endif

 

#endif

 

/********** Internal Implementation: TSdMalloc          ** End   **/

 

/********** Internal Implementation: TSdPRINTF          ** Start **/

#if defined(INCL_PRINT) && defined(INCL_TS_DEBUG_CODE)

#if !defined(tsdprint_c)

#define tsdprint_c

 

#if !defined(va_start)

    #include <stdarg.h>

#endif

 

#define is_formatchar(c) ((c)=='s')

#define is_formatflag(c) ((c)=='%')

 

#define PRINTF_FLAG_CHARS ".+-0#wl123456789"    /* Note '.' may not be portable */

 

#define TS_DEBUG_VAR        "TS_DEBUG_MODE"

 

#define TSSCOPRightold \

                "TSS_DEBUG: 0.00.02 Copr (C) Trantor Standard Systems Inc. 1986-2003"

 

#define COPR_LEN 128

 

static char TSSCpyr[COPR_LEN] = "";

 

char *GetTSScpyr()

{

    sprintf(TSSCpyr,"  tsdebug: %i.%2.2i.%2.2i Copr (C) Bob Trower. 1986-2014",\

    TS_VERMAJ, \

    TS_VERMIN, \

    TS_VERREL);\

   

    return(TSSCpyr);

}

 

#define TSSCOPRight ((*TSSCpyr) == 0 ? GetTSScpyr() : TSSCpyr )

               

int TSdDebugMode(void)

{

    static int DebugMode = FALSE;

    static int Initialized = FALSE;

 

    if(!Initialized){

        tsLPSTR DebugSwitch;

 

        DebugSwitch=getenv(TS_DEBUG_VAR);

        if(!DebugSwitch){

            putenv( TS_DEBUG_VAR"=0" );

            DebugSwitch=getenv(TS_DEBUG_VAR);

        }

        DebugMode = atoi(DebugSwitch);

        DebugMode = DebugMode ? DebugMode : TRUE;

        fprintf( stderr, "%s -- DBG:%i\n", TSSCOPRight, DebugMode );

        Initialized = TRUE;

    }

 

    return(DebugMode);

}

 

int TSdDefPrintfOutPut(tsLPSTR Output)

{

    int RetVal = 0;

 

    fprintf(stdout, "%s", TSdPadStr());

    RetVal = fprintf(stdout, "%s", Output);

    fflush(stdout);

 

    return(RetVal);

}

 

TSdPrintfOutputProcedure(TSdPrintfOutPut) = TSdDefPrintfOutPut;

 

 

#define TS_MAIL_HEADER "--- --- Message from Debug system --- Start ---\n"

#define TS_MAIL_TRAILER "--- --- Message from Debug system ---  End  ---\n.\n"

 

#define TSD_DEF_MAIL_FILE "/tmp/TSdTempMailFile"

 

#define TS_MAIL_ADDRESS_VAR  "TS_MAIL"

#define TSdDefaultMailAddress() "MailForcedByMaximumDebugMode"

 

tsLPSTR TSdMailAddress(void)

{

    tsLPSTR MailAddress;

 

    MailAddress = getenv(TS_MAIL_ADDRESS_VAR);

    if(!MailAddress){

        if(TSdDebugMode() >= TSdMAX_DEBUG_MODE){

            MailAddress = TSdDefaultMailAddress();

        }

    }

 

    return(MailAddress);

}

 

 

tsLPSTR TSdSetOutFileName(tsLPSTR Buf)

{

    tsLPSTR LogName;

    LogName = getenv("LOGNAME");

    if(LogName){

        sprintf(Buf, "%s.%s", TSD_DEF_MAIL_FILE, LogName);

    }

    else {

        sprintf(Buf, "%s.000", TSD_DEF_MAIL_FILE);

    }

    return(Buf);

}

 

void TSdSendMail(tsLPSTR OutFileName, tsLPSTR UserID)

{

    char CmdBuf[TSdBUF_LEN_WORK_MEDIUM];

 

    sprintf(CmdBuf, "mail %s<%s", UserID, OutFileName);

/*

    system(CmdBuf);

*/

}

 

void TSdSendMailMsg(tsLPSTR Message)

{

    char OutFileName[TSdMAX_FILE_NAME_LEN];

 

    if(TSdSetOutFileName(OutFileName)){

        FILE *OutFile = fopen(OutFileName, "wt");

        if(OutFile){

            fprintf(OutFile, "Subject:Message from LiveWire Debug\n");

            fprintf(OutFile, TS_MAIL_HEADER);

            fprintf(OutFile, "File:%s, Line:%i\n", TSdGetContextFile(), TSdGetContextLine() );

            fprintf(OutFile, "Function:%s\n", TSdGetContextFunc() );

            fprintf(OutFile, "Memory Allocated:%li\n", (long)TSdGetContextTotMem() );

            fprintf(OutFile, "%s", Message);

            fprintf(OutFile, TS_MAIL_TRAILER);

            fclose(OutFile);

            TSdSendMail(OutFileName, TSdMailAddress());

            remove(OutFileName);

        }

    }

}

 

tsLPSTR TSdDefSetMsgBuf(tsLPSTR Buffer)

{

    if(TSdMailAddress()){

        sprintf(Buffer, "[SetMsg:Send Mail to %s]", TSdMailAddress() );

    }

    else{

        sprintf(Buffer, "[SetMsg:No Mail Address]" );

    }

    return(Buffer);

}

 

tsLPSTR TSdDefSetContextBuf(tsLPSTR Buffer)

{

    sprintf(Buffer, "[Context(Mem=%9.9li)]", (long)TSdGetContextTotMem());

    return(Buffer);

}

 

tsLPSTR TSdDefSetLogBuf(tsLPSTR Buffer)

{

    sprintf(Buffer, "[SetLog:Not Implemented]");

    return(Buffer);

}

 

TSdSetBufferProcedure(TSdSetMsgBuf) = TSdDefSetMsgBuf;

TSdSetBufferProcedure(TSdSetContextBuf) = TSdDefSetContextBuf;

TSdSetBufferProcedure(TSdSetLogBuf) = TSdDefSetLogBuf;

 

#define TSD_MAX_USR_BUFFER_LEN 8192

 

#ifdef USR_GetStr

    tsLPSTR TSdDefSetObjectBuf(void *Object, tsLPSTR Buffer)

    {

        static tsLPSTR WrkBuffer = NULL;

 

        if(!WrkBuffer){

            WrkBuffer = (tsLPSTR ) malloc(TSD_MAX_USR_BUFFER_LEN * 4);

        }

        if(Object && WrkBuffer){

            USR_GetStr(Object, WrkBuffer, TSD_MAX_USR_BUFFER_LEN * 2);

            strcpy(Buffer, WrkBuffer);

        }

        else{

            *Buffer = 0;

        }

        return(Buffer);

    }

#else

    /* Create a default version of object proc for testing */

    tsLPSTR TSdDefSetObjectBuf(void *Object, tsLPSTR Buffer)

    {

        if(Object){

            sprintf(Buffer, "[%p]", Object);

        }

        else{

            *Buffer = 0;

        }

        return(Buffer);

    }

#endif

 

 

TSdSetObjectProcedure(TSdSetObjectBuf) = TSdDefSetObjectBuf;

 

static  char fmtbuf[TSD_MAX_USR_BUFFER_LEN] = "";

static  char wrkbuf[TSD_MAX_USR_BUFFER_LEN] = "";

static  char outbuf[TSD_MAX_USR_BUFFER_LEN] = "";

int TSdebug_Printf(const tsLPSTR fmt, ...)

{

    va_list  ap;

    tsLPSTR p;

/*

    char fmtbuf[TSD_MAX_USR_BUFFER_LEN] = "";

    char wrkbuf[TSD_MAX_USR_BUFFER_LEN] = "";

    char outbuf[TSD_MAX_USR_BUFFER_LEN] = "";

*/

 

    int i = 0;

    int SendMailFlag = FALSE;

    int DebugMode;

 

    va_start(ap, fmt);

    fmtbuf[0]=0;

    wrkbuf[0]=0;

    outbuf[0]=0;

    DebugMode = TSdDebugMode();  /* Will pre-empt traversing print code if FALSE */

    for(p = (tsLPSTR )fmt;*p && DebugMode;p++){

        fmtbuf[i]=*p;

        if( is_formatflag( *p ) ){

            int in_format = TRUE;

            p++;

            while(in_format){

                switch(*p){

                    case '%':

                        i++;

                        fmtbuf[i] = *p;

                        in_format = FALSE;

                        break;

                    case '*':

                        {

                            char lenbuf[128];

 

                            sprintf(lenbuf, "%d", va_arg(ap,int));

                            strcpy(&fmtbuf[i+1],lenbuf);

                            i = i + strlen(lenbuf);

                        }

                        p++;    /* Just strip out in this version */

                        break;

                    case 'Q':      /* USR Object printing code */

                        TSdSetObjectBuf(va_arg(ap,void *), &fmtbuf[i]);

                        strcat(outbuf, fmtbuf);

                        wrkbuf[i] = 0;

                        i = 0;

                        fmtbuf[i] = 0;

                        in_format = FALSE;

                        break;

                    case 'D':      /* Special debug printing code */

                        fmtbuf[i] = 0;

                        p++;    /* Strip off 'D' */

                        switch(*p){

                            case 'c':      /* Set Context Buffer */

                                TSdSetContextBuf(&fmtbuf[i]);

                                strcat(wrkbuf, fmtbuf);

                                break;

                            case 'f':      /* Set Function */

                                sprintf(&fmtbuf[i],"[%s]", TSdGetContextFunc());

                                strcat(wrkbuf, fmtbuf);

                                break;

                            case 'l':      /* Call Log function */

                                TSdSetLogBuf(&fmtbuf[i]);

                                strcat(wrkbuf, fmtbuf);

                                break;

                            case 'm':      /* Send Mail Message */

                                TSdSetMsgBuf(&fmtbuf[i]);

                                strcat(wrkbuf, fmtbuf);

                                if(TSdMailAddress()){

                                    SendMailFlag = TRUE;

                                }

                                break;

                            case 'd':

                            case 's':

                                sprintf(&fmtbuf[i],"[%s:%i]", TSdGetContextFile(),TSdGetContextLine());

                                strcat(wrkbuf, fmtbuf);

                                break;

                        }

                        strcat(outbuf, wrkbuf);

                        wrkbuf[0] = 0;

                        i = 0;

                        fmtbuf[i] = 0;

                        in_format = FALSE;

                        break;

                    case 'c':

                    case 'f':

                    case 'e':

                    case 'E':

                    case 'g':

                    case 'G':

                    case 'd':

                    case 'i':

                    case 'o':

                    case 'u':

                    case 'x':

                    case 'X':

                    case 's':

                    case 'P':

                    case 'p':

                        i++;

                        fmtbuf[i] = *p;

                        i++;

                        fmtbuf[i] = 0;

                        switch(*p){

                            case 'c':

                                sprintf(wrkbuf, fmtbuf, va_arg(ap,int));

                                break;

                            case 'f':

                            case 'e':

                            case 'E':

                            case 'g':

                            case 'G':

                                sprintf(wrkbuf, fmtbuf, va_arg(ap,double));

                                break;

                            case 'd':

                            case 'i':

                            case 'o':

                            case 'u':

                            case 'x':

                            case 'X':

                                if(fmtbuf[i-2] == 'l'){

                                    sprintf(wrkbuf, fmtbuf, va_arg(ap,long));

                                }

                                else{

                                    sprintf(wrkbuf, fmtbuf, va_arg(ap,int));

                                }

                                break;

                            case 's':

                            case 'P':

                            case 'p':

                                sprintf(wrkbuf, fmtbuf, va_arg(ap,void *));

                                break;

                        }

                        strcat(outbuf, wrkbuf);

                        wrkbuf[0] = 0;

                        i = 0;

                        fmtbuf[i] = 0;

                        in_format = FALSE;

                        break;

                    default:

                        if(strchr(PRINTF_FLAG_CHARS, *p)){

                            i++;

                            fmtbuf[i] = *p;

                            p++;

                        }

                        else {

                            in_format = FALSE;

                        }

                        break;

                }

            }

            fmtbuf[i] = *p;

        }

        else {

            fmtbuf[i] = *p;

            i++;

        }

    }

    va_end(ap);

    fmtbuf[i] = 0;

    strcat(outbuf, fmtbuf);

    if( DebugMode ){

        TSdPrintfOutPut(outbuf);

    }

    if(SendMailFlag){

        TSdSendMailMsg(outbuf);

    }

    return(strlen(outbuf));

}

 

#if defined(TS_TESTCODE)

void test_tsdprint(void)

{

    TSdPrintf(("Test1%Dc%Df%Dl%Dm\n"));

    TSdPrintf(("TestStr%s%s%Dc\n",":","(str)"));

    TSdPrintf(("TestInt%li%Dc\n",(long)999L));

    TSdPrintf(("TestObj%Q%%\n","Q"));

}

#endif

 

#if defined(TS_TESTSHELL_PRINT)

    int main(int argc, tsLPSTR *argv)

    {

        if(argc < 2){

            printf("Usage:  tsdprint '.'\n");

            printf("(Test Shell for tsdprint)\n");

        }

        else{

            test_tsdprint();

        }

        return( 0 );

    }

#endif

#endif

#endif

/********** Internal Implementation: TSdPRINTF          ** End   **/

 

/********** Internal Implementation: TSdLIST              ** Start **/

#if defined(INCL_LIST) && defined(INCL_TS_DEBUG_CODE)

#if !defined(tsdlist_c)

#define tsdlist_c

 

#if !defined(max)

    #include <stdlib.h>

#endif

 

#if !defined(size_t)

    #include <stdio.h>

    #include <string.h>

#endif

 

pTSdList TSd_ListOfLists_ = NULL;

 

int TSdDefCmpFuncStr(void *D1, void *D2)

{

    return(strcmp(D1, D2));

}

 

int TSdDefCmpFuncPtr(void *D1, void *D2)

{

    int RetVal = 0;

 

    if(D1 != D2){

        if(D1 > D2){

            RetVal = 1;

        }

        else {

            RetVal = -1;

        }

    }

 

    return(RetVal);

}

 

pTSdList TSdDefNewList(TSdListProcedure(Proc), void *Data)

{

    pTSdList List;

 

    List = (pTSdList) malloc(sizeof(TSdList));

    if(List){

        List->Type = TSD_LIST_TYPE_ANY;

        List->head = NULL;

        List->tail = NULL;

        List->curr = NULL;

        List->Proc = Proc;

        List->Compare = TSdDefCmpFuncPtr;

        Proc(List, TSD_MSG_INI_LIST, Data);

    }

    return(List);

}

 

pTSdListNode TSdDefNewNode(pTSdList List, void *Data)

{

    pTSdListNode ListNode, CurrNode;

 

    ListNode = (pTSdListNode) malloc(sizeof(TSdListNode));

    if(ListNode){

        ListNode->next = NULL;

        CurrNode = List->curr;

        List->curr = ListNode;

        List->Proc(List, TSD_MSG_INI_NODE, Data);

        List->curr = CurrNode;

    }

    return(ListNode);

}

 

pTSdListNode TSdDefGetNode(pTSdList List, void *Data)

{

    pTSdListNode Found = NULL;

 

    if(List->head) {

        for(List->curr = List->head;List->curr && !Found;){

            if(!(List->Compare( List->curr->Data, Data))){

                Found = List->curr;

            }

            else {

                List->curr = List->curr->next;

            }

        }

    }

 

    return(Found);

}

 

pTSdListNode TSdDefAddNode(pTSdList List, pTSdListNode ListNode)

{

    if(ListNode){

        if(!List->head){

            List->head = List->tail = List->curr = ListNode;

        }

        else {

            if(!List->curr){    /* No current value? -- add to front */

                ListNode->next = List->head;

                List->head = ListNode;

            }

            else {        /* Current value -- add after current value */

                ListNode->next = List->curr->next;

                List->curr->next = ListNode;

                if(List->tail->next){

                    List->tail = List->tail->next;

                }

            }

            List->curr = ListNode;

        }

    }

    return(ListNode);

}

 

pTSdListNode TSdDefDelNode(pTSdList List, pTSdListNode ListNode)

{

    pTSdListNode ListCur = NULL;

 

    if(List->head && ListNode){

        pTSdListNode Found = NULL;

        if(ListNode == List->head){

            Found = ListNode;

            List->head = List->head->next;

            if(!List->head){

                if(List->tail) {free(List->tail);}

                List->tail = NULL;

                if(List->curr) {free(List->curr);}

                List->curr = NULL;

            }

        }

        else {

            List->curr = List->head;

            while(List->curr->next && List->curr->next != ListNode){

                List->curr = List->curr->next;

            }

            if(List->curr->next == ListNode){

                Found = ListNode;

                List->curr->next = ListNode->next;

                if(ListNode == List->tail){

                    List->tail = List->curr;

                }

            }

            else {

                if(List->curr != List->tail) {

                    free(List->curr);

                    List->curr = List->tail;

                }

            }

        }

        ListCur = List->curr;

        if(Found){

            free(Found);

        }

        else {

            free(ListNode);

        }

    }

   

    return(ListCur);

}

 

typedef union tagTSdSwapType    /* Use to suppress compiler warnings */

{  

    void *dp;                   /* As Data Pointer */

    int (*fp)(void);            /* As Function Pointer (still need cast) */

} TSdSwapType;

 

void *TSdDefListProc(pTSdList List, TSdMsgType Msg, void *Data)

{

    void *ReturnValue = NULL;

 

    switch(Msg){

        case  TSD_MSG_NEW_LIST:

                ReturnValue = TSdDefNewList(TSdDefListProc, (tsLPSTR ) Data);

                if(!List){

                    if(!TSd_ListOfLists()){

                        TSd_ListOfLists() = TSdDefNewList(TSdDefListProc, "TSd_ListOfLists()");

                        TSdSetListIsList(TSd_ListOfLists());

                    }

                    List = TSd_ListOfLists();

                }

                TSdAddListNode(List, ReturnValue);

                break;

        case  TSD_MSG_INI_LIST:

                {

                    TSdSwapType st;

                    List->Name = strdup((const tsLPSTR )Data);

                    st.fp = (int (*)(void)) TSdDefCmpFuncStr;

                    TSdSetCmpFunc( List, st.dp );

                }

                break;

        case  TSD_MSG_DEL_LIST:

                if(!List) {

                    printf("Attempt to del null list\n");

                } else {

                    TSdEmptyList(List);

//#define doofr(x, n) if(List->curr) { printf("List->%s-xxxxxxxxx\n", n); free(x); } else {printf("List->%syyyyyyyyyyyyyyy\n", n);}

//                    doofr(List->Name, "Name")

//                    doofr(List->curr, "curr")

//                    doofr(List->tail, "tail")

//                    doofr(List->head, "head")

                    free(List);

                    List = NULL;

                }

                break;

        case  TSD_MSG_EMT_LIST:

                if(!List) {

                    printf("Attempt to del null list\n");

                } else {

                    List->curr = List->tail;

                    TSdDelListNode(List, List->curr);

                    while(TSdDelListNode(List, List->curr));

                }

                break;

        case  TSD_MSG_NEW_NODE:

                ReturnValue = TSdDefNewNode(List, Data);

                break;

        case  TSD_MSG_INI_NODE:

                List->curr->Data = Data;

                break;

        case  TSD_MSG_ADD_NODE:

                ReturnValue = TSdDefAddNode(List, Data);

                break;

        case  TSD_MSG_DEL_NODE:

                ReturnValue = TSdDefDelNode(List, Data);

                break;

        case  TSD_MSG_PUT_NODE:

                break;

        case  TSD_MSG_GET_NODE:

                ReturnValue = TSdDefGetNode(List, Data);

                break;

        case  TSD_MSG_SET_FCMP:

                List->Compare = (TSdCompareProcedureProt)((TSdGP *)&Data)->Func;

                break;

            default:

                break;

    }

    return(ReturnValue);

}

 

#if defined(TS_TESTCODE)

void EnumerateList(pTSdList List)

{

    static int depth =0;

    int item = 0;

 

    if(!List){

        List = TSd_ListOfLists();

    }

    printf("%*.*s",depth,depth,"");

    printf("Enumerating List:%s\n", List->Name);

    depth+=4;

    if(TSdListIsList(List)){

        pTSdList CurList;

 

        for(List->curr = List->head;List->curr;List->curr=List->curr->next){

            CurList = (pTSdList)List->curr->Data;

            EnumerateList(CurList);

        }

    }

    else {

        if(List->head) {

            for(List->curr = List->head;List->curr;List->curr=List->curr->next){

                printf("%*.*s",depth,depth,"    ");

                printf("Data in list item %i:%s\n", ++item, List->curr->Data);

            }

        }

    }

    if(List->tail) {

        List->curr = List->tail;

    }

    depth-=4;

}

 

void PopulateList(pTSdList List)

{

    if(List){

    TSdAddListNode(List, "Item 1");

        TSdAddListNode(List, "Item 2");

        TSdAddListNode(List, "Item 3");

        TSdAddListNode(List, "Item 4");

        TSdAddListNode(List, "Item 5");

    }

}

 

void PopulateListR(pTSdList List)

{

    if(List){

        TSdAddListNode(List, "Item 1");

        List->curr=NULL;

        TSdAddListNode(List, "Item 2");

        List->curr=NULL;

        TSdAddListNode(List, "Item3 ");

        List->curr=NULL;

        TSdAddListNode(List, "Item 4");

        List->curr=NULL;

        TSdAddListNode(List, "Item 5");

    }

}

 

void test_tsdlist(void)

{

    pTSdList List1, List2, List3, List4, List5;

 

    List1 = NULL, List2 = NULL, List3 = NULL, List4 = NULL, List5 = NULL;

TSdFunctionBegin("test_tsdlist");

//    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1);

//    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1);

//    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1);

//    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1);

//    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1);

//    List1 = TSdNewList("Test-List-1");

    List1 = TSdNewList("Test-List-1"); TSdDisposeList(List1); List1 = NULL;

 

    if(List1) {

//        PopulateList(List1);

        EnumerateList(List1);

        if(List1->head) {

            if(TSdGetListNode(List1, List1->head->Data)){

                printf("Found list item: List1:'%s'\n", List1->curr->Data);

            }

        }

        if(TSdGetListNode(List1, "Item 3")){

            printf("Found list item: List1:'%s'\n", List1->curr->Data);

        } else {

            printf("List is empty\n");

        }

//TSdDisposeList(List1);

  //      TSdEmptyList(List1);

//        EnumerateList(List1);

//        PopulateListR(List1);

//        TSdEmptyList(List1);

//        PopulateList(List1);

//        TSdEmptyList(List1);

        TSdDisposeList(List1);

//        List2 = TSdNewList("Test-List-2");

        if(List2) {

            TSdSetListIsList(List2);

            List3 = TSdAddList(List2, "Test-List-3");

            if(List3) {

                TSdDisposeList(List3);

            }

            List4 = TSdAddList(List2, "Test-List-4");

            if(List4) {

                TSdSetListIsList(List4);

                List5 = TSdAddList(List4, "Test-List-5");

                if(List5){

                    PopulateListR(List5);

                    TSdEmptyList(List5);

                    PopulateList(List5);

                    EnumerateList(List5);

                    TSdEmptyList(List5);

                    TSdDisposeList(List5);

                }

                TSdDisposeList(List4);

            }

            TSdDisposeList(List2);

        return(0);

        }

    }

TSdFunctionEnd("test_tsdlist");

}

#endif

 

#if defined(TS_TESTSHELL_LIST)

    int main(int argc, tsLPSTR *argv)

    {

        if(argc < 2){

            printf("Usage:  tsdlist '.'\n");

            printf("(Test Shell for tsdlist)\n");

        }

        else{

            test_tsdlist();

        }

        return( 0 );

    }

#endif

#endif

#endif

/********** Internal Implementation: TSdLIST              ** End   **/

 

/********** Internal Implementation: TSdTRACING        ** Start **/

#if defined(INCL_TRACE) && defined(INCL_TS_DEBUG_CODE)

#if !defined(tsdtrace_c)

#define tsdtrace_c

 

static pTSdList TSdFuncCallStack = NULL;

 

#define TSdSetFunctionName(FunctionName) TSdSetContextFunc(FunctionName)

#define TSdGetFunctionName() TSdGetContextFunc()

 

pTSdList TSdGetList(tsLPSTR Name)

{

    pTSdList List = NULL;

 

    List = TSd_ListOfLists();

    if(List){

        List = TSdGetListNode(List, Name);

    }

    if(!List){

        List = TSdNewList(Name);

    }

    return(List);

}

 

#define PrintStrIf(condition, fmt, val) if(condition){PrintStr(fmt,val);}

 

typedef struct tTSdFuncName_tag {

    struct tTSdFuncName_tag *next;

    tsLPSTR Name;

    size_t MemStart;

}TSdFuncName, *pTSdFuncName;

 

pTSdFuncName TSdNewFuncName(tsLPSTR Name)

{

    pTSdFuncName Info = NULL;

 

    Info = malloc(sizeof(TSdFuncName));

    if(Info){

//        printf("TSdNewFuncName:%s\n", Name);

        Info->Name = strdup(Name);

        Info->MemStart = TSdGetContextTotMem();

    }

    return(Info);

}

 

//#define MAX_PTR_STACK 16384

//static char *dbgptrstack[MAX_PTR_STACK] = {NULL};

//static int ptrstackinit = 0;

//static int ptrstackindex = 0;

//static char *dbglastptr = "baseofstack";

//#define pushdbgstack(x) \

//                            {\

//                                if(!ptrstackinit) {\

//                                    ptrstackinit = 1;\

//                                }\

//                                dbgptrstack[ptrstackindex] = x;\

//                                ptrstackindex++;\

//                            }

//

//#define popdbgstack() \

//                            {\

//                                if(!ptrstackinit) {\

//                                    printf("Uninitialized dbgptrstack");\

//                                } else {\

//                                    dbglastptr = dbgptrstack[ptrstackindex++];\

//                                    dbgptrstack[ptrstackindex++] = x;\

//                                    ptrstackindex++;\

//                                }\

//                            }

 

int TSdDisposeFuncName( pTSdFuncName Info )

{

    int status = 0;

    if(!Info){

        TSdMPrintf2(("%Dc%Df%Dl%DmError -- attempt to deallocate null Info ptr\n"));

    } else {

        if(!Info->Name){

            TSdMPrintf(("%Dc%Df%Dl%DmError -- attempt to deallocate null Info->Name ptr\n"));

        } else {

            TSdMPrintf2(("=============<Name:'%s'\n", Info->Name));

            free(Info->Name);

            status = 1;

        }

        free(Info);

    }

    return(status);

}

 

void TSdPushFunctionName(tsLPSTR Name)

{

    /* TSdFuncName *Info; */ /* Revisit RST*/

    TSdMPrintf2(("=============>Name:'%s'\n", Name));

    if(!TSdFuncCallStack){

        TSdFuncCallStack = TSdNewList("Function Call Stack");

        TSdSetCurContext("Function Name Stack Base");

        TSdPushFunctionName("Name");

    }

    if(TSdFuncCallStack){

        TSdAddListNode(TSdFuncCallStack, TSdNewFuncName( Name ));

        TSdSetFunctionName(Name);

    }

}

 

tsLPSTR TSdPopFunctionName(void)

{

    TSdFuncName *Info;

    tsLPSTR Name = NULL;

    if(!TSdFuncCallStack){

        TSdMPrintf(("Attempt to pop empty FunctionName stack\n", Name));

    } else {

        if(TSdFuncCallStack->tail){

            Info = (pTSdFuncName)TSdFuncCallStack->tail->Data;

            TSdDelListNode(TSdFuncCallStack, TSdFuncCallStack->tail);

            /*

            printf("Info->Name='%s'\n", Info->Name);

            printf("%Df:Info->Mem=%i, %i, [%i]\n", Info->MemStart, \

                TSdGetContextTotMem(), \

                TSdGetContextTotMem() - Info->MemStart);

            */

            printf( " [%i]<-- Net memory allocated\n", \

                TSdGetContextTotMem() - Info->MemStart);

            TSdDisposeFuncName(Info);

            if(TSdFuncCallStack->curr){

                Name = TSdFuncCallStack->curr->Data;

            }

        }

        if(Name){

            int assigned =   Name[0] != 'u' &&\

                             Name[1] != 'u' &&\

                             Name[2] != 'u' &&\

                             Name[3] != 'u';

            char *FuncName = assigned ? FuncName : "[Internal]";

            TSdSetFunctionName(FuncName);

        }

        else{

            TSdSetFunctionName(strdup("Unknown"));

        }

    }

    return(TSdGetFunctionName());

}

 

#undef USR_FunctionBegin

#undef USR_FunctionEnd

 

extern int USR_FunctionEnd(const tsLPSTR Name);

extern int USR_FunctionBegin(const tsLPSTR Name);

 

int TSdebug_FunctionBegin(const tsLPSTR FunctionName)

{

    int RetVal;

    static int TraceInitialized = FALSE;

 

    if(!TraceInitialized){

        if(TSdDebugMode() >= TSdMAX_DEBUG_MODE){

            TSdMemVerboseMode(TSdMAX_DEBUG_MODE);  /* Force other debug tracing on */

        }

    }

    TSdPushFunctionName((tsLPSTR )FunctionName);

#ifdef TS_USR_CALLBACK

    RetVal = USR_FunctionBegin(FunctionName);

#else

    RetVal = 0;

#endif

    printf("Starting function:%s\n", TSdGetFunctionName());

    TSdIncFunctionDepth();

 

    return(RetVal);

}

 

int TSdebug_FunctionEnd(const tsLPSTR FunctionName)

{

    int RetVal;

    tsLPSTR TS_FunctionName;

 

    TSdDecFunctionDepth();

    TS_FunctionName = TSdGetFunctionName();

    if( TSdDebugMode() > 7 ){

        if( strcmp( TS_FunctionName, FunctionName ) ){

        printf("End called as '%s', ", FunctionName );

        }

    }

    printf("Leaving function:%s\n", TS_FunctionName);

#ifdef TS_USR_CALLBACK

    RetVal = USR_FunctionEnd(FunctionName);

#else

    RetVal = 0;

#endif

    TSdPopFunctionName();

 

    return(RetVal);

}

 

#if defined(TS_TESTCODE)

 

int USR_FunctionBegin(const tsLPSTR Name)

{

    printf("USR_FunctionBegin('%s')\n", Name);

    return(TRUE);

}

 

int USR_FunctionEnd(const tsLPSTR Name)

{

    printf("USR_FunctionEnd('%s')\n", Name);

    return(TRUE);

}

 

void tsdtrace_internal_call(void)

{

    TSdFunctionBegin("tsdtrace_internal_call");

    printf("%Dc:Nothing happened here\n");

    TSdFunctionEnd("tsdtrace_internal_call");

}

 

void test_tsdtrace(void)

{

    TSdPrintf(("Context:%Dc\n"));

    TSdFunctionBegin("test_tsdtrace");

    TSdPrintf(("Context:%Dc\n"));

    tsdtrace_internal_call();

    tsdtrace_internal_call();

    tsdtrace_internal_call();

    tsdtrace_internal_call();

    tsdtrace_internal_call();

    TSdFunctionEnd("test_tsdtrace");

}

#endif

 

#if defined(TS_TESTSHELL_TRACE)

    int main(int argc, tsLPSTR *argv)

    {

        TSdFunctionBegin("main");

        if(argc < 2){

            printf("Usage:  tsdtrace '.'\n");

            printf("(Test Shell for tsdtrace)\n");

        }

        else{

            test_tsdtrace();

        }

        TSdFunctionEnd("main");

        return( 0 );

    }

#endif

 

#endif

 

#endif

 

/********** Internal Implementation: TSdTRACING        ** End   **/

 

/********** Internal Implementation: TSdDEBUG            ** Start **/

 

#if defined(TS_DEBUG) && defined(INCL_TS_DEBUG_CODE)

 

#if defined(TS_TESTSHELL_TSDEBUG)

 

    #define Printp(str) fputs(str, stdout)

 

    void test_showhelp(void)

    {

        Printp("TSDEBUG Test Shell\n");

        Printp("\n");

        Printp("Environment settings:\n");

        Printp("\n");

        Printp("set TS_DEBUG_MODE=1\n");

        Printp("set TS_MAIL=<Mail Address>\n");

        Printp("set TS_MEMVERBOSE=1>\n");

        Printp("\n");

    }

 

    void test_showuse(void)

    {

        printf("  tsd      (TS Debug test shell)    Bob Trower  2014-09-21\n");

        printf("                                              Version %i.%2.2i\n", VERMAJ, VERMIN);

        printf("  Usage:   tsd <Test> [opt]\n");

        printf("  Purpose: This command will run unit tests on the tsdebug\n");

        printf("           debug wrapper.\n");

        printf("  Tests:   'c' Test context\n");

        printf("           'l' Test list\n");

        printf("           'p' Test print\n");

        printf("           'm' Test malloc\n");

        printf("           't' Test trace\n");

        printf("           'h' Display help\n");

        printf("  Options: '-s' do side call\n");

        printf("  Example: tsd h\n");

        printf("  Note:    Side call adds extra function calls to test\n");

        printf("           the effect of additional function calls.\n");

        printf("  Note:    Debug functions use some resources so last\n");

        printf("           displayed memory allocation is greater than zero.\n");

        printf("  Release: %i.%2.2i.%2.2i, Thu Oct 09 2014 12:04:05:10, ANSI-C\n", VERMAJ, VERMIN, VERREL);

    }

 

    /**

     *  side call to exercise tracing code.

     */

    void tsd_sidecall()

    {

        TSdFunctionBegin("tsd_sidecall");

        {

            TSdFunctionBegin("tsd_sidecall_localblock");

            {

                char *p1, *p2;

                p1 = malloc(1000);

                if(p1) {

                    TSdFunctionBegin("tsd_sidecall_localblock1");

                    p2 = malloc(10000);

                    if(p2) {

                        TSdFunctionBegin("tsd_sidecall_localblock2");

                        free(p2);

                        TSdFunctionEnd("tsd_sidecall_localblock2");

                    }

                    free(p1);

                    TSdFunctionEnd("tsd_sidecall_localblock1");

                }

            }

            TSdFunctionEnd("tsd_sidecall_localblock");

        }

        TSdFunctionEnd("tsd_sidecall");

    }

   

    void tsd(char opt)

    {

        TSdFunctionBegin("tsd");

        switch(opt){

              case 'c': test_tsdcontx(); break;

              case 'l': test_tsdlist(); break;

              case 'p': test_tsdprint(); break;

              case 'm': test_tsdmallo(); break;

              case 't': test_tsdtrace(); break;

              case 'h': test_showhelp(); break;

              default:  test_showuse();break;

        }

        TSdFunctionEnd("tsd");

    }

   

#define Is_Opt(s, x) (s && s[0] == '-' && s[1] == x ? x : 0)   

    int main(int argc, char **argv)

    {

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

        TSdFunctionBegin("main");

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

        if(argc < 2){

            test_showuse();

        }

        else{

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

            if(Is_Opt(argv[2],'s') == 's' ) { tsd_sidecall(); }

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

            tsd(*argv[1]);

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

            if(Is_Opt(argv[2],'s') == 's' ) { tsd_sidecall(); };

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

        }

        TSdFunctionEnd("main");

    printf("main:Net Memory:%li\n", (long) TSdGetContextTotMem());

       

        return( 0 );

    }

#endif

#endif

/********** Internal Implementation: TSdDEBUG            ** End   **/