/******************************************************************************/
/*                                                                            */
/* Name:        pdump.c                                                       */
/* Description: Present process level dump in readable form                   */
/* By:          Diem Dang, Julie Reese, Jeff Baker, David Jaramillo           */
/* History:     06/13/94  Original                                            */
/*              08/17/94  David J.  Code Review Changes                       */
/*              09/07/94  David J.  Fix 64k limitation everywhere             */
/*              06/26/96  Jody B.   Recognize the range parameter  on the    */
/*                                    dump memory commands  158084           */
/*              07/17/96  Jody B.   Don't send extra \r\n over pipe.  It     */
/*                                    causes structure formatting to fail    */
/*                                    159912                                 */
/******************************************************************************/

#define SCCSID ""
#define FAR32   _far                    // fp (48-bit pointer, restricted)
#define _stdcall
#define FALSE           0
#define TRUE            1
#define SUCCESS         1
#define SELECTOR16REG   0x0000ffff
#define NUMSIZE         20
#define CMDLEN          80
#define DB              1
#define DW              2
#define DD              4
typedef unsigned long  ulong_t;
typedef unsigned short ushort_t;
typedef unsigned char  uchar_t;
typedef unsigned int   uint_t;

/******************************************************************************/
/*                              Include Files                                 */
/******************************************************************************/
#if 0
#define INCL_DOS
#define INCL_SUB
#define INCL_ERROR_H            /* for bseerr.h */
#define INCL_TYPES
#define FOR_EXEHDR      1
#include <os2.h>
#include <os2defp.h>
#include <sigdef.h>
#include <osconst.h>
#include <ostypes.h>
#include <dossymc.h>
#include <screen.h>
#include <dirent.h>
#include <except.h>
#include <sem.h>
#include <vmexport.h>
#include <pgexport.h>
#include <tkexport.h>
#define  FAR32 _far                     //  fp (48-bit pointer, restricted)
typedef (PASCAL FAR32 *FPVOID)();       //  fp (the only kind of FPVOID allowed)
#include <kmode.h>
#include <infoseg.h>
#include <tkptda.h>

#include <mi.h>
#include <newexe.h>
#include <exe386.h>

#undef PT_16BIT
#undef PT_32BIT
#undef HEADER_EXEINFO
#undef HEADER_READRSRCTBL
#undef HEADER_READSECTOR
#undef HEADER_LIBPATHLEN
#undef HEADER_LIBPATH
#undef HEADER_FIXENTRY
#undef HEADER_STE
#undef HEADER_MAPSEL
#include <ldrxport.h>
#include <ldrvars.h>

#ifdef SMP
#include <bsetib.h>
#include <..\memory\pglocal.h>
#include <tkmp.h>
#include <mplock.h>
#include <ipc.h>
#endif
#endif

#define INCL_ERROR_H            /* for bseerr.h */
#define INCL_TYPES
#define  INCL_DOS
#define INCL_SUB
#include <os2.h>
//#include <basemac.h>
//#include <basedef.h>
#include <osconst.h>
#include <ostypes.h>

#define FNO_NUM         FNO_LDRMTE_C
#include <fnomem.h>
#include <osmac.h>
#include <mi.h>
#include <bseerr.h>
#include <dossymc.h>
#include <sigdef.h>
#include <except.h>
#include <pgexport.h>
#include <vmexport.h>
#include <selxport.h>
#include <tkexport.h>
typedef (PASCAL FAR32 *FPVOID)();       // fp (the only kind of FPVOID allowed)
#include <kmode.h>
#include <infoseg.h>
#include <curdir.h>
#include <dirent.h>
#include <find.h>
#include <screen.h>
#include <sem.h>
#include <tkptda.h>
#define FOR_EXEHDR      1
#include <newexe.h>
#include <exe386.h>

#undef PT_16BIT
#undef PT_32BIT
#undef HEADER_EXEINFO
#undef HEADER_READRSRCTBL
#undef HEADER_READSECTOR
#undef HEADER_LIBPATHLEN
#undef HEADER_LIBPATH
#undef HEADER_FIXENTRY
#undef HEADER_STE
#undef HEADER_MAPSEL
#include <ldrxport.h>
#include <ldrvars.h>

#include <vmowner.h>
#include <seldesc.h>
#include <sft.h>
#include <mvdmexp.h>
#include <kutil.h>
#include <string.h>
#include <dynxport.h>
#include <harderr.h>
#include <limits.h>
#include <memory.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "df.h"

// instrumnt.h
#define FFSTHERE(str,var1,var2)  \
        ffsthere(__FILE__,__LINE__,str,var1,var2)

/* prototype for FFSTHERE */
void ffsthere(char * fname,int line,char *str, unsigned long var1,unsigned long var2);
// end of instrument.h

/******************************************************************************/
/*                                                                            */
/* Function Prototypes                                                        */
/*                                                                            */
/******************************************************************************/

void  PDump(char *pdumpName);
void  LDTSInfo(ULONG numBytes, int searchflag, ULONG selector );                    // get LDTS information
void  LDTSSearch(ULONG seladdr, int noldt, ULONG numBytes);
void  LDTData(ULONG index, int ldtinc);
void  MemoryList(void);                          // summary memory records
int   GetAddr(char *ptrCmd, ULONG *addr);        // get address from command line
void  DumpAllMEM(void);                          // dump all memory in bytes
//158084 void  DumpMEMory(int type, ULONG *startAddr,
//158084                int addrType);  // get memory information
void  DumpMEMory(int type, ULONG *startAddr,
                int addrType, int requestSize);  //158084 get memory information
int   PrintMem(ULONG addr, ULONG numbyte,
             ULONG *offs, int bytes,
             int addrType);                      // print memory in hex
void  PrintMemChr(ULONG coffs, ULONG numbyte);       // print memory in char
void  PrintLastLine(ULONG addr, ULONG lastline,
                   ULONG offs, int type,
                   int addrType);                // print last line in memory record
void  MODCBInfo(ULONG length);                     // get MODCB information
void  REGSInfo(ULONG threadNum);                   // get registers information
ULONG GetReg(ULONG regrec, ULONG crirec,
             int regno, int *flag);              // get register value from the dump file
void  SUMMInfo(ULONG posprcd, ULONG posheader);      // print summary
void  TASKCBInfo(ULONG len, ULONG postcbd);          // get TASKCB information
void  PrintFake(int start, int end, ULONG rec);    // print fake string
void  VMARInfo(void);                            // get VMAR information
void  VMOBInfo(void);                            // get VMOB information
int   PrintVMInfo(ULONG addr, int numRecs,
                    int VMType);
void  DotPInfo(ULONG len, int sType, USHORT threadnum );              // get information for processes
void  ListMTEs(ULONG len, ULONG listobjs );
int   GetPdumpMem(ULONG ulAddr, int nBytes,
                char *buffer);                   // dump memory into buffer
void  FormatData(ushort_t pSlot,
                ULONG ulTCBLinearAddr,
                char *szBuf, int bufLen);       // get data for .p command
void  FormatBlockData(ushort_t pSlot,
                     char *szBuf, int bufLen);  // get data for .p command
void  FormatUserData(ushort_t pSlot,
                    char *szBuf, int bufLen);   // get data for .p command
ULONG GetOffs(ULONG ulAddr, ULONG *recNum,
            ULONG *offs);                         // get offset to dump mem
ULONG GetPos(UCHAR *string);                    // get starting positions for headers
void  GetCmd(char *cmd);                        // get command line
char  *GetVal(ULONG posstart, ULONG length);        // get data from the dump file
int   CheckESC(void);                           // check if the user press ESC

int ReadInDumpFile( char *szDumpFile, ULONG *numBytes );

#ifdef  WARP
void dumpDebug( void );
#endif

/******************************************************************************/
/*                                                                            */
/*  Global variables                                                          */
/*                                                                            */
/******************************************************************************/

UCHAR huge  *dumpPtr;                        //  string used to store the dump data
ULONG  *daddr;                               //  sys dump address
ULONG  *dsize;                               //  dump size
ULONG  *doffs;                               //  offset in dump
ULONG  npdrecs;                              //  number of records
ULONG  tsum;                                 //  starting position for thread summary
ULONG  nthreads;                             //  number of threads
USHORT currThreadnum;                        //  current thread number
USHORT defThreadnum;                         //  default thread number
ULONG  pdsize;                               //  pdump size
ULONG  pospmem;                              //  starting position for memory table
ULONG  posptda;                              //  starting position for ptda
ULONG  posmted;                              //  starting position for mte
int    sort=1;                               //  sort data?
ULONG  *seq;                                 //  sorted order of entry recs
char   szMTEModName[MTE_NAME_LEN+1];         //  short mte name
char   szProcState[11];                      //  process state name

PSZ    MemListHeader = "Ord# Rec#    begAddr     endAddr      sel:off      Size\n";
PSZ    VMARHeader =    " har     par      cpg        va    flg next prev link hash hob   hal\n";
CHAR   VMARFormat[] =  " %04x %%%08lx %08lx %%%08lx %03x %04x %04x %04x %04x %04x %04x     =%04x\n";
PSZ    RecHeader =     "   Rec#  daddr[Rec#]  doffs[Rec#]  dsize[Rec#]\n";
PSZ    VMOBHeader =    " hob   har hobnxt flgs own  hmte  sown,cnt lt st xf\n";
CHAR   VMOBFormat[] =  " %04x  %04x %04x  %04x %04x %04x  %04x %02x  %02x %02x %02x\n";

CHAR cmdLine[CMDLEN];   //   used to store command line

// from df.c
extern BOOL fFrontEnd;
extern HPIPE hPipe;

// from process.c
extern struct ptda_s FAR *vpPTDA;
extern struct tcb_s FAR *vpTCB;
extern struct tsd_s FAR *vpTSD;
extern PSZ ProcStatHeader1;
extern CHAR szPTDASumFormat1[];
extern CHAR szPTDASumFormat2[];
extern PSZ ProcStatHeader2;
extern CHAR szBlockFormat[];
extern PSZ ProcStatHeader3;
extern CHAR szUserFormat1[];
extern CHAR szUserFormat2[];

//from header.inc in dfcmd.asm
extern char ourversion[];


// external function definitions in process.c
extern VOID  GetProcessState(SHORT sState, CHAR *szState);
extern PCHAR print_reg(ULONG);
extern int   CActivateMap( CHAR far * szMapName );
extern int   CListSyms( CHAR far * szSymbol );
extern int   CListNear( CHAR far * szSymbol );
extern int   CListMaps( void );
extern int   CListGroups( CHAR far * szGroupName );
extern int   CListAbsolutes( CHAR far * szGroupName );
extern int   CdeActivateMap( CHAR far * szMapName );

/******************************************************************************/
/*                                                                            */
/* Function:        PDump                                                     */
/*                                                                            */
/* Entry:           Called from df.c                                          */
/*                                                                            */
/* Parameters:      Process dump file name                                    */
/*                                                                            */
/******************************************************************************/

void PDump(char *pdumpName)
{
//    HFILE dumpHandle;       //   file handle for dump file
//    USHORT usAction;        //   open action taken
    ULONG rc=0;             //   return code
//    ULONG ulPos;            //   pdump position pointer
    ULONG numRead;          //   number of bytes to be read from dump file
    ULONG startAddr=0;      //   the address to start dumping memory
    ULONG *result;          //   used to store the result which is gotten from dump file
//    char cmdLine[CMDLEN];   //   used to store command line
    int dumpCmd=0;          //   code used to continue dumping memory with command 'd'
    ULONG offs;               //   used to calculate the position to access into the dump
    ULONG posprcd;            //   store the starting position of "PRCD" in the dump
    ULONG postcbd;            //   store the starting position of "TCBD" in the dump
    ULONG posheader;          //   store the starting position for driver level
    ULONG pospmdm;            //   store the starting postion of memory information
    ULONG ptrval;             //   the position to access into the dump
    ULONG numBytes;           //   number of bytes in dump file
    int addrType=0;         //    0: linear address;   1: sel:off
    LONG currentseq;         //   used in sorting process
    ULONG lastseq;            //   the last rec in sorted array
    ULONG recNum;             //   used in sorting process
    USHORT threadNum;          //   thread number
    LONG i, j;               //   index variables
    static int requestSize=0;  //158084 Requested size of the dump memory
    char *tempstr;             //158085 Temporary pointer to command line data


    rc = (ULONG) ReadInDumpFile( pdumpName, &numBytes );

    if (rc != ERR_NO_ERROR)
    {
        // numBytes should always equal numRead
//        FFSTHERE("Error reading in process dump",0,0);
        fprintf(stdout, "Error reading in process dump file %s,  rc=%ld",pdumpName,rc);
        return;
    }

    /* get starting positions for headers */
    posprcd = GetPos("PRCD");
    postcbd = GetPos("TCB");
    posptda = GetPos("PTDA");
    posmted = GetPos("MTE");
    posheader = GetPos("Internal revision ");




    /* get process dump memory table pointer in ASCII */
    ptrval = posprcd+8;                 //  offset to access the dump
    result = (ULONG *)GetVal(ptrval, 4);
    pospmem = *result;
    if (pospmem == 0)
    {
        fprintf(stdout, "Offset to memory table is zero - Searching for memory table...\n");

        /* Try to find the last ldt entry which is for selector dfff */
        /* the local infoseg, this will always have length 23 and should  */
        /* probably always be present */

        for (i=numRead-7; i>0; i=i-4)
        {
            result = (ULONG *)GetVal(i+4, 4);
            //  if (*result == 0xffdf000023000000) then set pospmem = i+11 and leave
            if (*result == 0xffdf0000)
            {
                result = (ULONG *)GetVal(i, 4);
                if (*result == 0x23000000)
                {
                    pospmem = i + 11;
                    i = 0;
                }
            }
        }
        ptrval = GetPos("PDUMPHDR");
        if (pospmem < ptrval)
        {
//            FFSTHERE("Memory Record Table not present (pospmem,ptrval)",pospmem,ptrval);
            fprintf(stdout, "Unable to find location of memory record table\n");
            return;
        }
        else
            fprintf(stdout, "Memory record table located at offset %08lx\n", pospmem);
    }

    //  find number of records
    ptrval = pospmem;
    result = (ULONG *)GetVal(ptrval, 4);
    npdrecs = *result;
    pospmdm = ptrval+4;     //  starting position to dump the memory information

    if ((daddr = (ULONG *)malloc((int)npdrecs * sizeof(ULONG))) == NULL)
    {
        fprintf(stdout, "Error allocating memory for daddr\n");
        return;
    }
    if ((dsize = (ULONG *)malloc((int)npdrecs * sizeof(ULONG))) == NULL)
    {
        fprintf(stdout, "Error allocating memory for dsize\n");
        return;
    }
    if ((doffs = (ULONG *)malloc((int)npdrecs * sizeof(ULONG))) == NULL)
    {
        fprintf(stdout, "Error allocating memory for doffs\n");
        return;
    }

    offs = 0;
    for(i=0; i<(LONG)npdrecs; i++)
    {
        ptrval = pospmdm + offs;
        result = (ULONG *)GetVal(ptrval, 4);
        daddr[i] = *result;                /* starting dump address of each record */
        ptrval = pospmdm+offs+4;
        result = (ULONG *)GetVal(ptrval, 4);
        dsize[i] = *result;                /* dump size of each record */
        ptrval = pospmdm+offs+8;
        result = (ULONG *)GetVal(ptrval, 4);
        doffs[i] = *result;                /* offset in dump of each record */
        offs += 12;
    }

    ptrval = postcbd+7;
    result = (ULONG *)GetVal(ptrval, 4);
    tsum = *result;                        /* starting position of thread summary */
    ptrval = postcbd+15;
    result = (ULONG *)GetVal(ptrval, 4);
    nthreads = *result;                    /* number of threads */

    ptrval = tsum+8;
    result = (ULONG *)GetVal(ptrval, 2);
    currThreadnum = (USHORT)*result;               /* current thread number */
    defThreadnum = (USHORT)*result;                /* current thread number */


    //    SORT the dump data. Diem 07/20/94
    if ( (seq = (ULONG *)malloc((int)npdrecs * sizeof(ULONG))) == NULL )
    {
       fprintf(stdout,  " Error allocating memory for seq...\n" );
       fprintf(stdout,  " Dump data will not be sorted.\n" );
       sort = 0;
    }
    else if (sort)
    {
        seq[0] = 0;     //  set seq[0]=the first record, will be sorted later
        lastseq = 0;    //  last record(largest) that has been sorted
        for (i=1; i<(LONG)npdrecs; i++)
        {
            recNum = seq[lastseq++];

            if (daddr[i] >= daddr[recNum])
                seq[lastseq] = i;   //  if the next record > the lastseq record, put it at the end
            else
            {
                currentseq = lastseq/2;
                recNum = seq[currentseq];

                //  if the next record > the midseq record, then sort the larger half records
                if (daddr[i] > daddr[recNum])
                {
                    for (currentseq++; currentseq<(LONG)lastseq; currentseq++)
                    {
                        recNum = seq[currentseq];
                        if (daddr[i] <= daddr[recNum])
                            break;
                    }
                }
                else //  if the next record < the midseq record, then sort the smaller half records
                {
                    for (currentseq--; currentseq>=0; currentseq--)
//                    for (currentseq--; currentseq>0; currentseq--)
                    {
                        recNum = seq[currentseq];
                        if (daddr[i] >= daddr[recNum])
                        {
                            currentseq++;
                            break;
                        }
                    }
                }
                if (currentseq<0)   currentseq = 0;

                //   rearrange the sequence
                for (j=lastseq; j>currentseq; j--)
                    seq[j] = seq[j-1];
                seq[j] = i;
            }
        }

    }

    SUMMInfo(posprcd, posheader);   //  get dump summary

    DotPInfo(numBytes, 1, currThreadnum);
    fprintf(stdout, "\n");
    REGSInfo(currThreadnum);

    GetCmd(cmdLine);    //  get command line

    if (cmdLine[0]=='q' || cmdLine[0]=='Q')
        return;

    //  start process the command
    while (cmdLine[0]!='q' && cmdLine[0]!='Q')
    {

        if (!strcmp(strlwr(cmdLine), "all") || !strcmp(strlwr(cmdLine), "a"))
        {
//          SUMMInfo( posprcd, posheader);
//          if (CheckESC())
//            return;

            TASKCBInfo(numBytes, postcbd);
            if (CheckESC())
              return;

//          REGSInfo(0);
//          if (CheckESC())
//            return;

            VMARInfo();
            if (CheckESC())
              return;

            VMOBInfo();
            if (CheckESC())
              return;

            LDTSInfo(numBytes, 0, 0);
            if (CheckESC())
              return;

            ListMTEs( numBytes, 1 );
            if (CheckESC())
              return;

            MemoryList();
            if (CheckESC())
              return;

            DumpAllMEM();
        }
        else if (!strncmp(strlwr(cmdLine), "db", 2))
        {
            dumpCmd = 1;
            //  get the starting address and address type
            addrType = GetAddr(&cmdLine[3], &startAddr);

            //158084 Get the range if the user entered it
            tempstr = strstr(cmdLine, "l");
            if (tempstr == NULL)
            {
               requestSize = 0;
            } else
            {
               requestSize = 0;
               sscanf((tempstr+1), "%x", &requestSize);
            } /* endif */


//158084            DumpMEMory(DB, &startAddr, addrType);
            DumpMEMory(DB, &startAddr, addrType, requestSize);  //158084
        }
        else if (!strncmp(strlwr(cmdLine), "dw", 2))
        {
            dumpCmd = 2;
            addrType = GetAddr(&cmdLine[3], &startAddr);

            //158084 Get the range if the user entered it
            tempstr = strstr(cmdLine, "l");
            if (tempstr == NULL)
            {
               requestSize = 0;
            } else
            {
               requestSize = 0;
               sscanf((tempstr+1), "%x", &requestSize);
               requestSize *= 2;
            } /* endif */


//158084            DumpMEMory(DW, &startAddr, addrType);
            DumpMEMory(DW, &startAddr, addrType, requestSize);  //158084
        }
        else if (!strncmp(strlwr(cmdLine), "dd", 2))
        {
            dumpCmd = 3;
            addrType = GetAddr(&cmdLine[3], &startAddr);

            //158084 Get the range if the user entered it
            tempstr = strstr(cmdLine, "l");
            if (tempstr == NULL)
            {
               requestSize = 0;
            } else
            {
               requestSize = 0;
               sscanf((tempstr+1), "%x", &requestSize);
               requestSize *= 4;
            } /* endif */


//158084            DumpMEMory(DD, &startAddr, addrType);
            DumpMEMory(DD, &startAddr, addrType, requestSize);  //158084
        }
        else if (!strcmp(strlwr(cmdLine), "d"))
        {
            switch (dumpCmd)
            {
                case 1: DumpMEMory(DB, &startAddr, addrType, requestSize); //158084
                       //158084 DumpMEMory(DB, &startAddr, addrType);
                        break;
                case 2: DumpMEMory(DW, &startAddr, addrType, requestSize); //158084
                        //158084 DumpMEMory(DW, &startAddr, addrType);
                        break;
                case 3: DumpMEMory(DD, &startAddr, addrType, requestSize); //158084
                        //158084 DumpMEMory(DD, &startAddr, addrType);
                        break;
            }
        }
        else if (!strcmp(strlwr(cmdLine), "ldts") ||
                 !strcmp(strlwr(cmdLine), "l"))
        {
            LDTSInfo(numBytes, 0, 0 );
        }
        else if (!strncmp(strlwr(cmdLine), "dg",2) ||
                 !strncmp(strlwr(cmdLine), "dl",2))
        {
            startAddr=0;
            addrType=GetAddr(&cmdLine[3], &startAddr);

//158084            if (startAddr)
              LDTSInfo(numBytes, 1, startAddr );
//158084            else
//158084              LDTSInfo(numBytes, 0, 0 );

        }
        else if (!strcmp(strlwr(cmdLine), ".ml"))
        {
            MemoryList();
        }
        else if (!strcmp(strlwr(cmdLine), "memory") ||
                 !strcmp(strlwr(cmdLine), ".mla"))
        {
            DumpAllMEM();
        }
        else if (!strcmp(strlwr(cmdLine), "modcb") ||
                 !strcmp(strlwr(cmdLine), "mod"))
        {
            MODCBInfo(numBytes);
        }
        else if (tolower(cmdLine[0]) == 'r')   //  cmdLine[0]=r
        {
            if(cmdLine[1] == '\0')
            {
                threadNum = currThreadnum;
                REGSInfo(threadNum);
            }
            else
            {
                sscanf(&cmdLine[1],"%4x",&threadNum);
                REGSInfo(threadNum);
            }
        }
        else if (!strcmp(strlwr(cmdLine), "summ") ||
                 !strcmp(strlwr(cmdLine), "s"))
        {
            SUMMInfo(posprcd,posheader);
        }
        else if (!strcmp(strlwr(cmdLine), "taskcb") ||
                 !strcmp(strlwr(cmdLine), "t"))
        {
            TASKCBInfo(numBytes, postcbd);
        }
        else if (!strcmp(strlwr(cmdLine), ".ma"))
        {
            VMARInfo();
        }
        else if (!strcmp(strlwr(cmdLine), ".mo"))
        {
            VMOBInfo();
        }
        else if (!strcmp(strlwr(cmdLine), "vmcb"))
        {
            VMARInfo();
            if (CheckESC())
              return;
            VMOBInfo();
        }
        #ifdef WARP
        else if (!strcmp(strlwr(cmdLine), ".debug"))
        {
            dumpDebug();
        }
        #endif
        else if (!strncmp(strlwr(cmdLine), ".pb",3))
        {
            if (cmdLine[3] == ' ')
                sscanf(&cmdLine[4],"%4x",&threadNum);
            else if(cmdLine[3] == '\0')
                threadNum = 0;
            else if(cmdLine[3] == '#')
                threadNum = currThreadnum;
            else if(cmdLine[3] == '*')
                threadNum = defThreadnum;
            else
                sscanf(&cmdLine[3],"%4x",&threadNum);
            DotPInfo(numBytes, 2, threadNum);
        }
        else if (!strncmp(strlwr(cmdLine), ".pu",3))
        {
            if (cmdLine[3] == ' ')
                sscanf(&cmdLine[4],"%4x",&threadNum);
            else if(cmdLine[3] == '\0')
                threadNum = 0;
            else if(cmdLine[3] == '#')
                threadNum = currThreadnum;
            else if(cmdLine[3] == '*')
                threadNum = defThreadnum;
            else
                sscanf(&cmdLine[3],"%4x",&threadNum);
            DotPInfo(numBytes, 4, threadNum);
        }
        else if (!strncmp(strlwr(cmdLine), ".p",2))
        {
            if (cmdLine[2] == ' ')
                sscanf(&cmdLine[3],"%4x",&threadNum);
            else if(cmdLine[2] == '\0')
                threadNum = 0;
            else if(cmdLine[2] == '#')
                threadNum = currThreadnum;
            else if(cmdLine[3] == '*')
                threadNum = defThreadnum;
            else
                sscanf(&cmdLine[2],"%4x",&threadNum);
            DotPInfo(numBytes, 1, threadNum);
        }
        else if (!strncmp(strlwr(cmdLine), ".s",2))
        {
            USHORT tmpThreadnum=0;

            if (cmdLine[2] == ' ')
                sscanf(&cmdLine[3],"%4x",&tmpThreadnum);
            else if(cmdLine[2] == '\0')
                tmpThreadnum = currThreadnum;
            else if(cmdLine[3] == '*')
                tmpThreadnum = currThreadnum;
            else
                sscanf(&cmdLine[2],"%4x",&tmpThreadnum);

            if ((tmpThreadnum!=0) && (tmpThreadnum <= (USHORT)nthreads))
            {
              currThreadnum = tmpThreadnum;
              fprintf(stdout, "Current thread number: %x\n",currThreadnum);
            }
            else
              fprintf(stdout, "Invalid thread number: %x\n",tmpThreadnum);
        }
        else if (!strncmp(strlwr(cmdLine), ".lmo",4))
        {
            ListMTEs( numBytes, 1 );
        }
        else if (!strncmp(strlwr(cmdLine), ".lm",3))
        {
            ListMTEs( numBytes, 0 );
        }
        else if (!strncmp(strlwr(cmdLine), "lm",2))
        {
            CListMaps();
        }
        else if (!strncmp(strlwr(cmdLine), "lg",2))
        {
            CListGroups(&cmdLine[2]);
        }
        else if (!strncmp(strlwr(cmdLine), "ls",2))
        {
            cmdLine[2]=(CHAR)strlen(&cmdLine[3]);
            CListSyms(&cmdLine[2]);
        }
        else if (!strncmp(strlwr(cmdLine), "la",2))
        {
            CListAbsolutes(&cmdLine[2]);
        }
        else if (!strncmp(strlwr(cmdLine), "wa",2))
        {
            CActivateMap(&cmdLine[2]);
        }
        else if (!strncmp(strlwr(cmdLine), "wr",2))
        {
            CdeActivateMap(&cmdLine[2]);
        }
        else if (!strncmp(strlwr(cmdLine), "ln",2))
        {
            ULONG offset;
            SEL   sel;
            CHAR *tmpptr;

            if (tmpptr=strchr(&cmdLine[2],':'))
            {
                *tmpptr=0;
                sscanf(&cmdLine[2],"%4x", &sel);
                sscanf(++tmpptr,"%8lx",&offset);
            }
            else
            {
                sel=0;
                sscanf(&cmdLine[3],"%%%8lx",&offset);
            }
            cmdLine[2]=0;
            memcpy(&cmdLine[3],&offset,sizeof(ULONG));
            memcpy(&cmdLine[7],&sel,sizeof(SEL));
            CListNear(&cmdLine[2]);
        }
        else if (cmdLine[0] == '.' && cmdLine[1] == '?')
        {
            fprintf(stdout, " .?             : print help menu for '.' commands\n");
            fprintf(stdout, " .p[b|u][ord]   : prints process status\n");
            fprintf(stdout, " .lm[o]         : prints modules status\n");
            fprintf(stdout, " .ma            : prints memory arena records\n");
            fprintf(stdout, " .mo            : prints memory object records\n");
            fprintf(stdout, " .ml[a]         : prints memory dump records\n");
            fprintf(stdout, " .s [ord]       : switch thread number\n");
        }
        else if (cmdLine[0] == '?')
        {
            fprintf(stdout, " ?              : print help menu\n");
            fprintf(stdout, " DB <addr>      : dump memory in bytes starting at <addr>\n");
            fprintf(stdout, " DW <addr>      : dump memory in words starting at <addr>\n");
            fprintf(stdout, " DD <addr>      : dump memory in dwords starting at <addr>\n");
            fprintf(stdout, " D              : continue dumping memory\n");
            fprintf(stdout, " DL [<sel>]     : display Local Descriptor\n");
            fprintf(stdout, " DG [<sel>]     : display Local Descriptor\n");
            fprintf(stdout, " R [reg#]       : display registers\n");
            fprintf(stdout, " LG [<mapname>] : list groups in active maps\n");
            fprintf(stdout, " LM             : list linked and active maps\n");
            fprintf(stdout, " LN [<addr>]    : list near symbols\n");
            fprintf(stdout, " LA [<mapname>] : list absolute symbols in active maps\n");
            fprintf(stdout, " LS [<addr>]    : list symbols in group\n");
            fprintf(stdout, " R [<reg>]      : registers\n");
            fprintf(stdout, " WA <mapname>|* :  add a map to the active list\n");
            fprintf(stdout, " WR <mapname>|* :  remove a map from the active list\n");
            fprintf(stdout, " . - external commands, execute "".?"" for help\n");
            fprintf(stdout, " ? - print help menu\n");
        }
        else if (cmdLine[0] != '\r'  && cmdLine[0] != '\n' && cmdLine[0] != '\0' )
        {
          fprintf(stdout, "^ Error\n");
        }

        fflush(stdout);
        GetCmd(cmdLine);
    }
//    free(dumpPtr);
    free(daddr); free(dsize); free(doffs); free(seq);
}

/******************************************************************************/
/*                                                                            */
/*  Function:       LDTSInfo(ULONG, int, ULONG)                                   */
/*  Description:    Report LDT header information                             */
/*  By:             Julie Reese                                               */
/*                  Shreya                                                    */
/*                                                                            */
/******************************************************************************/
void  LDTSInfo(ULONG numBytes, int searchflag, ULONG selector)
{

   ULONG  posldtd;              //   starting position
   ULONG  index, index2;        //   for loop indexes
   ULONG  ldta;                 //   address of LDT
   int    ldtinc = 0;           //   increment to access each LDT entry
   ULONG  ldtl;                 //   total length of LDT
   ULONG  ldtlen;               //   length of each LDT entry
   ULONG  noldt;                //   number of LDTs
   ULONG  ptrval;               //   pointer value
   ULONG  *result;              //   return value from hex conversion function

    /* get starting position */
    posldtd = GetPos("LDT");

   #if DEBUG
      if (searchflag)
      //   Report LDT header information
      fprintf(stdout,"\nLDT local descriptor table header:\n");
   #endif

   ptrval = posldtd + 7;
   result = (ULONG *)GetVal(ptrval, 4);
   ldtl   = *result;

   #if DEBUG
      if (searchflag)
      fprintf(stdout, "  Length of LDT:   %lu\n", ldtl );
   #endif

   ptrval = posldtd + 11;
   result = (ULONG *)GetVal(ptrval, 4);
   ldta   = *result;

   #if DEBUG
      if (searchflag)
      fprintf(stdout, "  Address of LDT:  %lx\n", ldta );
   #endif

   ptrval = posldtd + 15;
   result = (ULONG *)GetVal(ptrval, 4);
   noldt  = *result;

   #if DEBUG
      if (searchflag)
      fprintf(stdout, "  Number of LDTs:  %lu\n", noldt );
   #endif

   ptrval = posldtd + 19;
   result = (ULONG *)GetVal(ptrval, 4);

   #if DEBUG
      if (searchflag)
      fprintf(stdout, "  Return code:     %04X\n", *result );
   #endif

   //   Report LDT entry



   //   Find out where LDT data starts in the dump
   for ( index=0; index<npdrecs; index++ )
   {
      if ( ldta == daddr[index] )
         break;
   }  //   end for


   //   If LDT data is available, show it
   if ((ldta == daddr[index]) && (doffs[index] + dsize[index] <= numBytes))
   {
      //   Calculate the length of each LDT entry
      ldtlen = (ldtl / noldt);

      //   For each LDT entry, get the LDT entry data
      for ( index2=0; index2< noldt; index2++ )
      {           //   Selector data
         ptrval = doffs[index] + ldtinc;
         result = (ULONG *)GetVal(ptrval, 4);
         if (searchflag)
           {
             if (*result==selector)
              {
                fprintf(stdout, "    Selector   Base   Limit   Flags\n" );
                fprintf(stdout, "    %04lx     ", *result );
                //   LDT Base, Limit, and Flag data
                LDTData(index,ldtinc);
                break;
               }
            }
         else
           {
            if (index2%24==0)
               fprintf(stdout, "    Selector   Base   Limit   Flags\n");

             fprintf(stdout, "    %04lx     ", *result );
             // LDT Base, Limit, and Flag data
             LDTData(index, ldtinc);

            }

        //   Move to next LDT entry
        ldtinc += ldtlen;

        fflush(stdout);

        //   Check for an ESC key (user abort)
        if (CheckESC())
          return;

      }  //   end for each LDT entry

      fprintf(stdout, "\n");
      if ((searchflag) && (noldt==(ULONG)(index2+1)))
        fprintf(stdout,"This is an invalid selector address.\n");
    }  //   end if LDT data is available, show it
    else
     {
       fprintf(stdout, "\n  LDT entries are not in the dump.\n" );
      }  //   end else

    fflush(stdout);
    return;
}  //   end LDTSInfo function

/*****************************************************************************/
/*               LDTData                                                 */
/*****************************************************************************/

void LDTData(ULONG index, int ldtinc)
{
    ULONG   ptrval;             // pointer value
    ULONG   *result;            // return value from hex conversion function

    // Base Data
    ptrval = doffs[index] + ldtinc + 11;
    result = (ULONG *)GetVal(ptrval, 1);
    fprintf(stdout, "%02lx", *result);
    ptrval = doffs[index] + ldtinc + 8;
    result = (ULONG *)GetVal(ptrval, 1);
    fprintf(stdout, "%02lx", *result);
    ptrval = doffs[index] + ldtinc + 6;
    result = (ULONG *)GetVal(ptrval, 2);
    fprintf(stdout, "%04lx   ", *result);

    //Limit Data
     ptrval = doffs[index] + ldtinc + 4;
     result = (ULONG *)GetVal(ptrval, 2);
     fprintf(stdout, "%04lX    ", *result );

     //   Flags
         ptrval = doffs[index] + ldtinc + 9;
         result = (ULONG *)GetVal(ptrval, 2);
         fprintf(stdout, "%04lX\n", *result );


} // end LDTBaseData
/******************************************************************************/
/*                                                                            */
/*  Function:       LDTSSearch(int)                                           */
/*  Description:    Given a selector address it reports that line of info     */
/*                      from the LDTS                                         */
/*  By:             Shreya Shah                                               */
/*  Date:           September 6, 1994                                         */
/*                                                                            */
/******************************************************************************/

/*
void LDTSSearch(ULONG seladdr, int noldt, ULONG numBytes)

{
    ULONG   ii;                              //loop index
    ULONG   ptrval;                          // pointer value
    int     ldtinc = 1;                      // increment to access each LDT entry
    ULONG   *result;                         // return value from hex conversion function
    int     ldtlen;                          // length of each LDT entry
    ULONG   ldtl;                            // total length of LDT

    if (seladdr!=0)
       {
         fprintf(stdout,"\n Number     Selector     ");
         fprintf(stdout,"  Base     Limit     Flags\n");

         ldtlen = (ldtl/noldt);
         for (ii=0; ii<noldt;ii++)
         {
           ptrval = doffs[ii] +ldtinc;
           result=(ULONG *)GetVal(ptrval,4);
           if (seladdr==result)
           {
            //  Selector Data
            fprintf(stdout,"%6d     %04lx     ",ii+1,*result);

            //  Base Data
            ptrval = doffs[ii] + ldtinc +11;
            result = (ULONG *)GetVal(ptrval,1);
            fprintf(stdout,"%02lx",*result);
            ptrval = doffs[ii]+ ldtinc+8;
            result = (ULONG *)GetVal(ptrval,1);
            fprintf(stdout,"%02lx",*result);
            ptrval = doffs[ii]+ ldtinc+6;
            result = (ULONG *)GetVal(ptrval,2);
            fprintf(stdout, "%04lx    ",*result);

            //  Limit Data
            ptrval = doffs[ii] + ldtinc+4;
            result = (ULONG *)GetVal(ptrval,2);
            fprintf(stdout, "%04lX     ",*result);

            //  Flags
            ptrval = doffs[ii] + ldtinc+9;
            result = (ULONG *)GetVal(ptrval,2);
            fprintf(stdout, "%04lX\n",*result);

            //  Move to Next Entry

        } else
          {
             ldtinc += ldtlen;
             fflush(stdout);
             //check for esc (user abort)
             if (CheckESC())
               return;
             // end traversal of entries
            fprintf(stdout, "\n");
        }

        }
    }
   else if (seladdr=0)
        {
            LDTSInfo(numBytes);
        }
   else
   {
    fprintf(stdout,"\nThis is an invalid selector address.\n");
   }
    }
 //end LDTSSearch

  */
/******************************************************************************/
/*                                                                            */
/*  Function:       Memory List (ml)                                          */
/*  Description:    List memory                                               */
/*  By:             Jeff Baker                                                */
/*                                                                            */
/******************************************************************************/
void MemoryList(void)

{   ULONG i,j;
    ULONG sel;
    ULONG offset;
    CHAR indOut[10];

//    indOut = malloc(10);
    for(i=0; i<npdrecs; i++)
    {
        if (sort)
          j = seq[i];                /* print records in sorted order */
                                          /* indicated by seq[] array      */
        else
          j=i;

         sprintf(indOut,"---------");

        if (!(daddr[j] & 0x20000000))    /* below 512 MB boundary */
        {
            offset = daddr[j] & SELECTOR16REG;
            sel = (daddr[j]);
            sel /= 0x10000;
            sel = (sel * 8) + 7;
            sprintf(indOut,"%04lx:%04lx", sel, offset);
        }

        if (i%24 == 0)
            fprintf(stdout, MemListHeader);

        fprintf(stdout, "%03ld   %03ld   %%%08lx   %%%08lx    %s     %04lx\n", i, j, daddr[j],
                 (daddr[j])+(dsize[j]), indOut, dsize[j]);

        fflush(stdout);
        //   Check for an ESC key (user abort)
        if (CheckESC())
            return;
    }
}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetAddr(char *ptrCmd, ULONG *addr)                        */
/*                  ptrCmd: pointer to command line                           */
/*                  addr  : used to get the address from command line         */
/*  Description:    Analyze the command line to get address and address type  */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
int GetAddr(char *ptrCmd, ULONG *addr)
{
    char *tmpAddr, ptrOff[5];
    ULONG sel;
    ULONG offset=0;

    memset(ptrOff, '\0', 5);
    tmpAddr = ptrCmd;
    if (*tmpAddr == '%')    //  linear address
    {
        tmpAddr++;
        sscanf(tmpAddr, "%08lx", addr);

        //158084 jeb   Handle linear addresses with offsets in them
        tmpAddr = strstr(ptrCmd, "+");
        if (tmpAddr != NULL)
        {
           sscanf(tmpAddr+1, "%x", &offset);
           *addr = *addr + offset;
        } /* endif */

        return FALSE;
    }
    if (tmpAddr = strchr(ptrCmd,':'))   //  sel:offs address
    {
        tmpAddr++;                      //   *tmpAddr = offset
        strcpy(ptrOff, tmpAddr--);      //  store offset in ptrOff
        tmpAddr = NULL;
        sscanf(ptrCmd, "%lx", &sel);    //  store selector in sel
        sel = sel >> 3;                 //  thunking the selector
        sprintf(ptrCmd, "%lx", sel);
        strcat(ptrCmd,ptrOff);
        sscanf(ptrCmd, "%lx", addr);
        return TRUE;
    }
    else
    {
        sscanf(ptrCmd, "%08lx", addr);  //  linear address

        //158084 jeb   Handle linear addresses with offsets in them
        tmpAddr = strstr(ptrCmd, "+");
        if (tmpAddr != NULL)
        {
           sscanf((tmpAddr+1), "%x", &offset);
           *addr = *addr + offset;
        } /* endif */

        return FALSE;
    }
}

/******************************************************************************/
/*                                                                            */
/*  Function:       DumpAllMEM(void)                                          */
/*  Description:    Dump memory                                               */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void DumpAllMEM(void)
{
    ULONG i, j;           //  index
    ULONG recNum;         //  number of record
    ULONG offs=0;         //  offset in dump file
    ULONG coffs=0;        //  offset to dump memory in char
    ULONG nline=0;        //  number of lines in each record
    ULONG lastline=0;     //  number of bytes left in each record
    ULONG addr;         //  address to start the dump in each record

    fprintf(stdout, "\nProcess memory dump table\n");
    fprintf(stdout, "   Offset in this dump:         %08lx\n", pospmem);
    fprintf(stdout, "   Number of records:           %d\n", npdrecs);

    //   DISPLAY the dump data
    for (i=0; i<npdrecs; i++ )
    {
        if (sort) recNum=seq[i];  //   malloc ok, show data sorted
        else      recNum=i;       //   malloc failed, show data unsorted anyhow

        addr = daddr[recNum];
        nline = dsize[recNum]/16;
        lastline = dsize[recNum]%16;
        offs = doffs[recNum];
        for (j=0; j<nline; j++)
        {
            coffs = offs;
            if (!PrintMem(addr, 16, &offs, DB, 0))
                return;
            PrintMemChr(coffs, 16);
            fflush(stdout);
            addr += 16;
        }
        if (lastline)
        {
            PrintLastLine(addr, lastline, offs, DB, 0);
        }
    }
    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       DumpMEMory(int type, ULONG *startAddr, int addrType,      */
/*                              int requestSize) //158084                     */
/*                  type     : DB=1, DW=2, DD=4                               */
/*                  startAddr: address to start dumping                       */
/*                  addrType : 0(linear address), 1(sel:offs)                 */
/*  Description:    Dump memory in bytes, words, or double words              */
/*  By:             Diem Dang                                                 */
/*  Date:           07/23/94                                                  */
/*                                                                            */
/******************************************************************************/
//158084 void DumpMEMory(int type, ULONG *startAddr, int addrType)
void DumpMEMory(int type, ULONG *startAddr, int addrType, int requestSize) //158084
{
    int i;              //  index
    ULONG recNum;         //  number of record
    ULONG offs=0;         //  offset in dump file
    ULONG coffs=0;        //  offset to dump memory in char
    int recSize;        //  record size
    int nline=0;        //  number of lines in each record
    ULONG lastline=0;     //  number of bytes left in each record

    if (GetOffs(*startAddr, &recNum, &offs))
    {
        recSize = (int)((daddr[recNum] + dsize[recNum]) - *startAddr);
        if ((recSize < requestSize) || (requestSize == 0))
        {
           requestSize = recSize;
        } /* endif */

        nline = requestSize/16;
        nline = nline>10 ? 10:nline;
        lastline = requestSize%16;

        for (i=0; i<nline; i++)
        {
            coffs = offs;
            switch (type)
            {
                case DB: if (!PrintMem(*startAddr, 16, &offs, type, addrType))
                            return;
                        PrintMemChr(coffs, 16);
                        break;
                case DW:
                case DD: if (!PrintMem(*startAddr, (16/type), &offs, type, addrType))
                            return;
                        fprintf(stdout, "\n");
                        break;
            }
             fflush(stdout);
            *startAddr += 16;
        }
        if (lastline)
        {
            PrintLastLine(*startAddr, lastline, offs, type, addrType);
            *startAddr += lastline;
        }
    }
    else
        fprintf(stdout, "Couldn't dump memory at this address (%lx)\n", *startAddr);

    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       PrintMem(ULONG, int, int, int, ULONG)                     */
/*                  addr    : address to start dumping                        */
/*                  numbyte : number of bytes to be dumped                    */
/*                  offs    : offset in dump file                             */
/*                  bytes   : number of bytes to dump each time(byte, word or */
/*                            double word)                                    */
/*                  addrType: 0(linear address), 1(sel:offs)                  */
/*  Description:    Dump memory in bytes, words, or double words              */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
int PrintMem(ULONG addr, ULONG numbyte, ULONG *offs, int bytes, int addrType)
{
    ULONG i;          //  index
    ULONG *result;
    ULONG offset;
    ULONG selector;

    //   Check for an ESC key (user abort)
    if (CheckESC())
        return 0;

    if (!addrType)
        fprintf(stdout, "%%%08lx ", addr);
    else
    {
        offset = addr & SELECTOR16REG;
        selector = (addr >> 16)*8+7;
        fprintf(stdout, "%04lx:%04lx ", selector, offset);
    }

    for (i=0; i<numbyte; i++)
    {
        result = (ULONG *)GetVal(*offs, bytes);
        switch (bytes)
        {
            case 1: fprintf(stdout, "%02x ", *result);
                    break;
            case 2: fprintf(stdout, "%04x ", *result);
                    break;
            case 4: fprintf(stdout, "%08lx ", *result);
                    break;
        }
        *offs = *offs+bytes;
        fflush(stdout);
    }
    fflush(stdout);
    return TRUE;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       PrintMemChr(int, int)                                     */
/*                  coffs : offset in dump file                               */
/*                  nBytes: number of bytes to be dumped                      */
/*  Description:    Print memory in char                                      */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void PrintMemChr(ULONG coffs, ULONG nBytes)
{
    char *cdata;
    ULONG i;

    fprintf(stdout, "[");
    cdata = GetVal(coffs, nBytes);
    for (i=0; i<nBytes; i++)
    {
        if (cdata[i]>=32)
            fprintf(stdout, "%c", cdata[i]);
        else
            fprintf(stdout, ".");
    }
    if (nBytes < 16)
        for (i=nBytes; i<16; i++)
            fprintf(stdout, " ");
    fprintf(stdout, "]\n");
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       PrintLastLine(ULONG, int, int, int, int)                  */
/*                  addr    : address to start dumping                        */
/*                  lastline: number of bytes in last line                    */
/*                  offs    : offset in dump file                             */
/*                  type    : DB=1, DW=2, DD=4                                */
/*                  addrType: 0(linear address), 1(sel:offs)                  */
/*  Description:    Print last line in memory record                          */
/*  By:             Diem Dang                                                 */
/*  Date:           07/25/94                                                  */
/*                                                                            */
/******************************************************************************/
void PrintLastLine(ULONG addr, ULONG lastline, ULONG offs, int type, int addrType)
{
    ULONG coffs;          //  offset to dump memory in char
    ULONG numblank=0;
    char *blank;
//    char blank[80];
    ULONG i;

    coffs = offs;
    switch(type)
    {
        case DB: if (!PrintMem(addr, lastline, &offs, DB, addrType))
                    return;
                numblank = 3*(16-lastline)+1;
                if ((blank = (char *)malloc((int)numblank*sizeof(char))) == NULL)
                {
                   fprintf(stdout, "Error allocating memory for blank\n");
                    return;
                }
//              memset(blank,0x20,80);
                for(i=0; i<(numblank-1) ; i++)
                    blank[i] = ' ';
                blank[i]='\0';
                fprintf(stdout, "%s", blank);
                PrintMemChr(coffs, lastline);
                fprintf(stdout, "\n");
                break;
        case DW:
        case DD: if (!PrintMem(addr, (lastline/type), &offs, type, addrType))
                    return;
                fprintf(stdout, "\n");
                break;
    }
    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       MODCBInfo(int)                                            */
/*                  len: size of dump file                                    */
/*  Description:    Print MTE module table information                        */
/*  By:             Diem Dang, Julie Reese                                    */
/*                                                                            */
/******************************************************************************/
void MODCBInfo(ULONG len)
{
    ULONG    i;                  //  index
    ULONG  ptrval;
    int    code;
    ULONG  ment=0;
    ULONG  found=0;
    ULONG  index;              //   index to number of MTEs
    ULONG  index2;             //   index to object table
    char   *resname;
    ULONG  mtl1;               //   length of MTE part 1 data
    ULONG  nomte;              //   number of MTEs in dump
    ULONG  *result;
    ULONG  mta1, mta2, mf2, motab, mnobj;

    /* report MTE header information */
    fprintf(stdout, "MTE module table entry header:\n");
    ptrval = posmted+7;
    result = (ULONG *)GetVal(ptrval, 4);
    mtl1 = *result;
    fprintf(stdout, "   Length of MTE part 1:                   %d\n", mtl1);
    ptrval = posmted+11;
    result = (ULONG *)GetVal(ptrval, 4);
    mta1 = *result;
    fprintf(stdout, "   Address of MTE part 1:                  %08lx\n", mta1);
    ptrval = posmted+15;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "   Length of MTE part 2:                   %d\n", *result);
    ptrval = posmted+19;
    result = (ULONG *)GetVal(ptrval, 4);
    mta2 = *result;
    fprintf(stdout, "   Address of MTE part 2:                  %08lx\n", mta2);
    ptrval = posmted+23;
    result = (ULONG *)GetVal(ptrval, 4);
    nomte = *result;
    fprintf(stdout, "   Number of MTEs:                         %d\n", nomte);
    ptrval = posmted+27;
    result = (ULONG *)GetVal(ptrval, 2);
    fprintf(stdout, "   Number of storage requests:             %d\n", *result);
//      ptrval = posmted+31;
    ptrval = posmted+29;
    result = (ULONG *)GetVal(ptrval, 2);
    fprintf(stdout, "   Number of storage request failures:     %d\n", *result);

    /* find out where MTE part 1 data is in the dump */
    for (i=0; i<npdrecs; i++)
        if (mta1 == daddr[i])
        {
            found = 1;
            break;
        }

    /* if MTE part 1 data is in the dump, show it */
//    if ( found &&
//         i + 5 <= npdrecs &&
//         ((doffs[i]+dsize[i]) <= len) )
      if (found && ((doffs[i]+dsize[i]) <= (ULONG)len))
      {
        for ( index=1; index<=nomte; index++ )
        {
            if ( dsize[i] != mtl1 )
            {
                fprintf(stdout,  "\n   ERROR: size %d of record %d", dsize[i], i );
                fprintf(stdout,  "\n          does not match expected size of %d.", mtl1 );
                fprintf(stdout,  "\n   ABORTING MTE option...\n" );
                break;
            }  /* end if dsize[i] != mtl1 */

            fprintf(stdout, "\n   ----------" );
            fprintf(stdout, "\n   MTE #%d\n", index );

#ifdef WARP
            fprintf(stdout, "     Resident module name:                    %s\n",
            GetVal( doffs[i]+24, MTE_NAME_LEN ));
            fprintf(stdout, "     Full path name:                          %s\n",
            GetVal(doffs[i+3], dsize[i+3]));

#else
            fprintf(stdout, "     Resident module name:                    %s\n",
            GetVal(doffs[i+3], dsize[i+3]));
            fprintf(stdout, "     Full path name:                          %s\n",
            GetVal(doffs[i+4], dsize[i+4]));
#endif

            fprintf(stdout, "\n     MTE #%d Part 1 Data\n", index);
            ptrval = doffs[i]+16;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Flags 1:                               %08lx\n", *result);
            ptrval = doffs[i];
            result = (ULONG *)GetVal(ptrval, 2);
            mf2 = *result;
            fprintf(stdout, "     Flags 2:                               %04x\n", *result);
            ptrval = doffs[i]+2;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     Handle:                                %04x\n", *result);
            ptrval = doffs[i]+4;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Link to swappable MTE:                 %08lx\n", *result);
            ptrval = doffs[i]+8;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Pointer to resident module name:       %08lx\n", *result);
            ptrval = doffs[i]+12;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Link to next MTE:                      %08lx\n", *result);
            ptrval = doffs[i]+20;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Number of import module name tables:   %d\n", *result);
            ptrval = doffs[i]+24;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     File system number for open file:      %04x\n", *result);
            ptrval = doffs[i]+26;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     .EXE-only use count:                   %d\n", *result);

            /* bump to next record to get part 2 data */
            i++;
            //   Check for an ESC key (user abort)
            if (CheckESC())
               return;

            fprintf(stdout, "\n     MTE #%d Part 2 Data\n", index);
            ptrval = doffs[i];
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Number of pages:                       %d\n", *result);
            ptrval = doffs[i]+32;
            result = (ULONG *)GetVal(ptrval, 4);
            mnobj = *result;
            fprintf(stdout, "     Number of objects:                     %d\n", mnobj);
            ptrval = doffs[i]+20;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Page shift count:                      %d\n", *result);
            ptrval = doffs[i]+24;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Fixup section size:                    %d\n", *result);
            ptrval = doffs[i]+28;
            result = (ULONG *)GetVal(ptrval, 4);
            motab = *result;
            fprintf(stdout, "     Object table offset:                   %08lx\n", motab);
            ptrval = doffs[i]+36;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Object page map offset:                %08lx\n", *result);
            ptrval = doffs[i]+40;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Object iterated data map offset:       %08lx\n", *result);
            ptrval = doffs[i]+4;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Object number for EIP:                 %08lx\n", *result);
            ptrval = doffs[i]+12;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Object number of ESP:                  %08lx\n", *result);
            ptrval = doffs[i]+8;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     EIP:                                   %08lx\n", *result);
            ptrval = doffs[i]+16;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     ESP:                                   %08lx\n", *result);
            ptrval = doffs[i]+44;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of deficit table:               %08lx\n", *result);
            ptrval = doffs[i]+48;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Number of resource entries:            %d\n", *result);
            ptrval = doffs[i]+52;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of resident name table:         %08lx\n", *result);
            ptrval = doffs[i]+56;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of entry table:                 %08lx\n", *result);
            ptrval = doffs[i]+60;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of fixup page table:            %08lx\n", *result);
            ptrval = doffs[i]+64;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of fixup record table:          %08lx\n", *result);
            ptrval = doffs[i]+68;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of import module name table:    %08lx\n", *result);
            ptrval = doffs[i]+72;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of enumerated data pages:       %08lx\n", *result);
            fprintf(stdout, "     Offset of non-resident name table:     %08lx\n", *result);
            ptrval = doffs[i]+76;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Size of non-resident names table:      %d\n", *result);
            ptrval = doffs[i]+80;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Object # for automatic data object:    %08lx\n", *result);
            ptrval = doffs[i]+84;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset of the debugging information:   %08lx\n", *result);
            ptrval = doffs[i]+88;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Length of debug info in bytes:         %d\n", *result);
            ptrval = doffs[i]+90;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Heap size for 16-bit modules:          %d\n", *result);
            ptrval = doffs[i]+94;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Offset for full pathname:              %08lx\n", *result);
            ptrval = doffs[i]+98;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     Number of threads waiting on MTE sem:  %d\n", *result);
            fprintf(stdout, "     Slot number of MTE sem owner:          %d\n", *result);
            ptrval = doffs[i]+102;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Pointer to file cache:                 %08lx\n", *result);
            ptrval = doffs[i]+106;
            result = (ULONG *)GetVal(ptrval, 4);
            fprintf(stdout, "     Thread 1 stack size from .EXE header:  %ld\n", *result);
            fprintf(stdout, "     Align shift factor for 16-bit modules: %ld\n", *result);
            ptrval = doffs[i]+112;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     EXPVER from NE header:                 %04x\n", *result);
            ptrval = doffs[i]+118;
            result = (ULONG *)GetVal(ptrval, 2);
            fprintf(stdout, "     Number of segments to pack:            %d\n", *result);

            //   Check for an ESC key (user abort)
            if (CheckESC())
               return;

            fflush(stdout);

            /* bump to next record to get object table data */
            i++;
            ment = doffs[i];
            if ((mf2 & 0x0003) == 0x0001)
            {
                code = 16;
                fprintf(stdout, "\n     MTE #%d %d bit Object Table\n", index, code);
                fprintf(stdout, "         Index   Sel           Handle          Size\n");
            }
            else
            {
                fprintf(stdout, "\n     MTE #%d %d bit Object Table\n", index, code);
                fprintf(stdout, "         Index   Sel   Virt Base  Handle    Size       flags\n");
                code = 32;
            }

//            fprintf(stdout, "\n     MTE #%d %d bit Object Table\n", index, code);
//            fprintf(stdout, "         Index   Sel   Virt Base  Handle  Size  flags\n");
            for (index2=1; index2<=mnobj; index2++)
            {
                if (code == 16)
                {
                    result = (ULONG *)GetVal(ment+10, 2);  //selector
                    fprintf(stdout, "      %6d     %04x          ", index2, *result);
                    result = (ULONG *)GetVal(ment+8, 2);   // handle
                    fprintf(stdout, "%04x            ", *result);
                    result = (ULONG *)GetVal(ment+6, 2);   // size
                    fprintf(stdout, "%04x\n", *result);
                    ment += 16;
                }
                else
                {
                    result = (ULONG *)GetVal(ment+20, 2);            // selector
                    fprintf(stdout, "      %6d     %04x  ", index2, *result);
                    result = (ULONG *)GetVal(ment+4 , 4);            // virtual addr
                    fprintf(stdout, "%08lx    ", *result);
                    result = (ULONG *)GetVal(ment+22, 2);            // handle
                    fprintf(stdout, "%04x   ", *result);
                    result = (ULONG *)GetVal(ment, 4);               // size
                    fprintf(stdout, "%08lx   ", *result);
                    result = (ULONG *)GetVal(ment+8 , 4);            // virtual addr
                    fprintf(stdout, "%08lx\n", *result);
                    ment += 24;
                }
            }
            if (code == 16)
            {
                result = (ULONG *)GetVal(ment, 1);
                ptrval = *result;
                resname = GetVal(ment+1, ptrval);
                fprintf(stdout, "       First entry in resource table: %s\n", resname);
            }
            /* bump record number to next MTE entry */
#ifdef WARP
            i += 2;
#else
            i += 3;
#endif
            fflush(stdout);
            //   Check for an ESC key (user abort)
            if (CheckESC())
               return;
        }
    }
    else
        fprintf(stdout, "\n   MTE entries not in dump\n");
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       REGSInfo(ULONG)                                           */
/*                  threadNum: thread number                                  */
/*  Description:    Print register information                                */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void REGSInfo(ULONG reqThreadNum)
{
    ULONG ptrval, tend;
    ULONG totalThread;
    ULONG i;              //  index
    int flag;
    ULONG *result, regaddr, urgaddr, regno;
    ULONG tid;          //  thread id
    ULONG crirec, regrec;
    ULONG threadNum;

    threadNum = reqThreadNum;

    if (threadNum)
    {
        if (threadNum > nthreads)
        {
            fprintf(stdout, "There are only %x threads\n", nthreads);
            return;
        }
        totalThread = threadNum+1;
        tend = 40*(threadNum - 1);
    }
    else
    {
        totalThread = nthreads;
        tend = 0;
    }

    for (; (ULONG)threadNum<totalThread; threadNum++)
    {
        crirec = 0;
        regrec = 0;
        ptrval = tsum+tend;
        result = (ULONG *)GetVal(ptrval, 4);
        tid = *result;
        ptrval = tsum+tend+12;
        result = (ULONG *)GetVal(ptrval, 4);
        regaddr = *result;
        ptrval = tsum+tend+20;
        result = (ULONG *)GetVal(ptrval, 4);
        urgaddr = *result;
        for (i=0; i<npdrecs; i++)
        {
            if (crirec && regrec)
                i = npdrecs;
            else
            {
                if (daddr[i] == regaddr)
                    crirec = i;
                if (daddr[i] == urgaddr)
                    regrec = i;
            }
        }

        // only display if threadnum not specified
        if (!reqThreadNum)
           fprintf(stdout, "\nRegisters for thread: %08lx\n", tid);

        if (crirec && regrec)
        {
            SEL    cs;
            ULONG  eip;
            CHAR   lnCSEIP[CMDLEN];

            regno = GetReg(regrec, crirec, 1, &flag); /* get eax */
            fprintf(stdout, " EAX=");
            flag == 0 ? fprintf(stdout, "%08lx  EBX=", regno) : fprintf(stdout, "********  EBX=");
            regno = GetReg(regrec, crirec, 2, &flag); /* get ebx */
            flag == 0 ? fprintf(stdout, "%08lx  ECX=", regno) : fprintf(stdout, "********  ECX=");
            regno = GetReg(regrec, crirec, 3, &flag); /* get ecx */
            flag == 0 ? fprintf(stdout, "%08lx  EDX=", regno) : fprintf(stdout, "********  EDX=");
            regno = GetReg(regrec, crirec, 4, &flag); /* get edx */
            flag == 0 ? fprintf(stdout, "%08lx\n", regno) : fprintf(stdout, "********\n");
            regno = GetReg(regrec, crirec, 6, &flag); /* get esi */
            flag == 0 ? fprintf(stdout, " ESI=%08lx  EDI=", regno) : fprintf(stdout, "********");
            regno = GetReg(regrec, crirec, 7, &flag); /* get edi */
            flag == 0 ? fprintf(stdout, "%08lx  DS=", regno) : fprintf(stdout, "********");
            regno = GetReg(regrec, crirec, 8, &flag); /* get ds */
            flag == 0 ? fprintf(stdout, "%04x  ES=", regno) : fprintf(stdout, "****");
            regno = GetReg(regrec, crirec, 9, &flag); /* get es */
            flag == 0 ? fprintf(stdout, "%04x  FS=", regno) : fprintf(stdout, "****");
            regno = GetReg(regrec, crirec, 10, &flag); /* get fs */
            flag == 0 ? fprintf(stdout, "%04x  GS=", regno) : fprintf(stdout, "****");
            regno = GetReg(regrec, crirec, 11, &flag); /* get gs */
            flag == 0 ? fprintf(stdout, "%04x\n", regno) : fprintf(stdout, "****\n");
            regno = GetReg(regrec, crirec, 12, &flag); /* get cs */
            cs=(USHORT)regno;
            flag == 0 ? fprintf(stdout, " CS:EIP=%04x:", regno) : fprintf(stdout, "****");
            regno = GetReg(regrec, crirec, 13, &flag); /* get eip */
            eip=regno;
            flag == 0 ? fprintf(stdout, "%08lx  SS:ESP=", regno) : fprintf(stdout, "********");

            ptrval = tsum+tend+16;
            result = (ULONG *)GetVal(ptrval, 4);
            if (*result == 0x4c)   // the correct client register address
            {
                regno = GetReg(regrec, crirec, 15, &flag); /* get ss */
                flag == 0 ? fprintf(stdout, "%04x:", regno) : fprintf(stdout, "****");
                regno = GetReg(regrec, crirec, 16, &flag); /* get esp */
                flag == 0 ? fprintf(stdout, "%08lx  EBP= ", regno) : fprintf(stdout, "********");
            }
            else
            {
                regno = GetReg(regrec, crirec, 8, &flag); /* hack  ss as ds */
                flag == 0 ? fprintf(stdout, "%04x:", regno) : fprintf(stdout, "****");
                // use esp from the stack address from the process dump
                ptrval = tsum+tend+32;
                result = (ULONG *)GetVal(ptrval, 4);
                regno = *result;
                flag == 0 ? fprintf(stdout, "%08lx  EBP= ", regno) : fprintf(stdout, "********");
            }


            regno = GetReg(regrec, crirec, 5, &flag); /* get ebp */
            flag == 0 ? fprintf(stdout, "%08lx\n", regno) : fprintf(stdout, "********\n");
//            regno = GetReg(regrec, crirec, 17, &flag); /* get cbargs */
//            flag == 0 ? fprintf(stdout, "  CBARGS=%08lx  TRAPNUM= ", regno) : fprintf(stdout, "  CBARGS=********  TRAPNUM= ");
//            regno = GetReg(regrec, crirec, 18, &flag); /* get trapnum */
//            flag == 0 ? fprintf(stdout, "%08lx  ERRCODE= ", regno) : fprintf(stdout, "********  ERRCODE= ");
//            regno = GetReg(regrec, crirec, 19, &flag); /* get errcode */
//            flag == 0 ? fprintf(stdout, "%04x  EFLAG= ", regno) : fprintf(stdout, "****  EFLAG= ");
//            regno = GetReg(regrec, crirec, 14, &flag); /* get eflag */
//            flag == 0 ? fprintf(stdout, "%08lx\n", regno) : fprintf(stdout, "********\n");

            lnCSEIP[0]=0;
            memcpy(&lnCSEIP[1],&eip,sizeof(ULONG));
            memcpy(&lnCSEIP[5],&cs,sizeof(SEL));
            CListNear(lnCSEIP);

        }
        else
            fprintf(stdout, "Register information is not available for this thread\n");

        fflush(stdout);
        tend += 40;
        //   Check for an ESC key (user abort)
        if (CheckESC())
            return;
    }
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetReg(ULONG, ULONG, int, int)                            */
/*  Description:    get register value                                        */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
ULONG GetReg(ULONG regrec, ULONG crirec, int regno, int *flag)
{
    ULONG regflg, reg=0;
    ULONG *regptr;
    int regoff;

    regno = regno*4;
    regptr = (ULONG *)GetVal(doffs[crirec]+regno, 1);
    regflg = *regptr;
    if ((regflg & 0x03) != 0x00)
    {
        *flag = 1;
        return FALSE;
    }
    else
        *flag = 0;
    regptr = (ULONG *)GetVal(doffs[crirec]+regno+2, 2);
    regoff = (int)*regptr;
    regptr = (ULONG *)GetVal(doffs[regrec]+regoff, 4);
    reg = *regptr;
    if ((regflg & 0x04) == 0x04)
        reg = reg & SELECTOR16REG;
    return reg;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       SUMMInfo(int, int)                                        */
/*  Description:    Print summary information                                 */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void SUMMInfo(ULONG posprcd, ULONG posheader)
{
    ULONG ptrval;
    ULONG *result;
    int day, month, year, hour, minute, second;

    /* now start the output */
    fprintf(stdout, "IBM OS/2 Process Dump Formatter for ");
    /* is this a retail or debug kernel dump? */
    /* result = '0000000c'x for RETAIL */
    /* result = '0001000c'x for DEBUG */
    ptrval = posprcd+12;
    result = (ULONG *)GetVal(ptrval, 4);
    if (*result == 0x0000000C)
        fprintf(stdout, "retail kernel\n");
    else if (*result == 0x0001000C)
        fprintf(stdout, "debug kernel\n");

    fprintf(stdout, "Formatter is --> %s\n", ourversion);
    fprintf(stdout, "Dump file is --> ");

    /* get dump version number */
    ptrval = posprcd+20;
    result = (ULONG *)GetVal(ptrval, 4);
//    fprintf(stdout, "Dump version number %08lx\n", *result);
    fprintf(stdout, "%33s\n", &dumpPtr[posheader]);

    fprintf(stdout,"Current thread: %04x\n\n",currThreadnum);
    /* load symbols */
    CActivateMap("1*");
    fprintf(stdout,"\n");

    /* get dump date */
    ptrval = posprcd+28;
    result = (ULONG *)GetVal(ptrval, 1);
    day = (int)*result;
    ptrval += 1;
    result = (ULONG *)GetVal(ptrval, 1);
    month = (int)*result;
    ptrval += 1;
    result = (ULONG *)GetVal(ptrval, 2);
    year = (int)*result;
    ptrval += 4;
    result = (ULONG *)GetVal(ptrval, 1);
    fprintf(stdout, "Dump date:  ");
    switch (*result)
    {
        case 1: fprintf(stdout, "Sun  ");
                break;
        case 2: fprintf(stdout, "Mon  ");
                break;
        case 3: fprintf(stdout, "Tue  ");
                break;
        case 4: fprintf(stdout, "Wed  ");
                break;
        case 5: fprintf(stdout, "Thu  ");
                break;
        case 6: fprintf(stdout, "Fri  ");
                break;
        case 7: fprintf(stdout, "Sat  ");
                break;
    }
    fprintf(stdout, "%02d/%02d/%4d\n", month, day, year);

    /* get dump time */
    ptrval = posprcd+24;
    result = (ULONG *)GetVal(ptrval, 1);
    hour = (int)*result;
    ptrval += 1;
    result = (ULONG *)GetVal(ptrval, 1);
    minute = (int)*result;
    ptrval += 1;
    result = (ULONG *)GetVal(ptrval, 1);
    second = (int)*result;
    ptrval += 1;
    result = (ULONG *)GetVal(ptrval, 1); /* millisecond */
    fprintf(stdout, "Dump time:  %02d:%02d:%02d.%02d\n\n", hour, minute, second, *result);

    /* get trap number */
    ptrval = posprcd+16;
    result = (ULONG *)GetVal(ptrval, 4);
    if (*result == 0xffff)
      fprintf(stdout, "Trap unknown\n\n");
    else
      fprintf(stdout, "Trap %08lx\n\n", *result);


    fflush(stdout);
}

/******************************************************************************/
/*                                                                            */
/*  Function:       TASKCBInfo(int, int)                                      */
/*                  len    : size of dump file                                */
/*                  postcbd: offset in dump file that starts the TCBD record  */
/*  Description:    Print TASKCB information                                  */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void TASKCBInfo(ULONG len, ULONG postcbd)
{
    USHORT i;

#if 0
//    int found=0,tend=0;
//    ULONG threadn;
//    ULONG ptrval;
//    ULONG *result;
#endif

    /* get thread summary information for each thread */
    for (i=1; i<= (USHORT)nthreads; i++)
    {
        fprintf(stdout, "Thread %x summary:\n", i);
        DotPInfo(len, 1, i);
        fprintf(stdout, "\n");
        REGSInfo(i);
        fprintf(stdout, "\n\n");
        fflush(stdout);
        //   Check for an ESC key (user abort)
        if (CheckESC())
            return;
    }


#if 0
    /* report PTDA header information */
    fprintf(stdout, "PTDA process task data area header:\n");
    ptrval = posptda+12;
    result = (ULONG *)GetVal(ptrval, 4);   /* process id */
    fprintf(stdout, "   Process ID:                             %08lx\n", *result);
    ptrval = posptda+8;
    result = (ULONG *)GetVal(ptrval, 4);   /* return code */
    fprintf(stdout, "   Process data return code:               %08lx\n", *result);
    ptrval = posptda+16;
    result = (ULONG *)GetVal(ptrval, 4);   /* process data length */
    fprintf(stdout, "   Process data length:                    %d\n", *result);
    ptrval = posptda+20;
    result = (ULONG *)GetVal(ptrval, 4);   /* process data address */
    fprintf(stdout, "   Process data address:                   %08lx\n", *result);


    /* find out where process data is in the dump */
    found = 0;
    for (i=0; i<npdrecs; i++)
        if (*result == daddr[i])
        {
            found = 1;
            break;
        }

    /* show the process data */
    if (found && ((doffs[i]+dsize[i]) <= (ULONG)len))
    {
        /* show PTDA data part 1 */
        fprintf(stdout, "   Process memory dump entry:              %d\n", i+1);

        /* get PTDA addresses for this task, parent, children, etc. */
        ptrval = doffs[i];
        result = (ULONG *)GetVal(ptrval, 4);   /* Parent PTDA address */
        fprintf(stdout, "   Parent PTDA address:                    %08lx\n", *result);
        ptrval = doffs[i]+4;
        result = (ULONG *)GetVal(ptrval, 4);   /* Current PTDA address */
        fprintf(stdout, "   This PTDA address:                      %08lx\n", *result);
        ptrval = doffs[i]+8;
        result = (ULONG *)GetVal(ptrval, 4);   /* First child PTDA address */
        fprintf(stdout, "   First child PTDA address:               %08lx\n", *result);
        ptrval = doffs[i]+12;
        result = (ULONG *)GetVal(ptrval, 4);   /* New child PTDA address */
        fprintf(stdout, "   New child PTDA address:                 %08lx\n", *result);
        ptrval = doffs[i]+16;
        result = (ULONG *)GetVal(ptrval, 4);   /* Next sibling PTDA address */
        fprintf(stdout, "   Next sibling PTDA address:              %08lx\n", *result);
        ptrval = doffs[i]+20;
        result = (ULONG *)GetVal(ptrval, 4);   /* Previous sibling PTDA address */
        fprintf(stdout, "   Previous sibling PTDA address:          %08lx\n", *result);

        if (CheckESC())
            return;

        /* get TCB and EXE-name addresses */
        ptrval = doffs[i]+24;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Address of this .EXE name:              %08lx\n", *result);
        ptrval = doffs[i]+28;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Next TCB address:                       %08lx\n", *result);
        ptrval = doffs[i]+32;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Address of head of TCB list:            %08lx\n", *result);
        ptrval = doffs[i]+36;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   Number of TCBs in use:                  %d\n", *result);
        ptrval = doffs[i]+38;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   Number of TIBs allocated:               %d\n", *result);

        /* get TIB array addresses: currently there are 4 of them */
        ptrval = doffs[i]+40;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   TIB array 1 address:                    %08lx\n", *result);
        ptrval = doffs[i]+44;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   TIB array 2 address:                    %08lx\n", *result);
        ptrval = doffs[i]+48;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   TIB array 3 address:                    %08lx\n", *result);
        ptrval = doffs[i]+52;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   TIB array 4 address:                    %08lx\n", *result);

        /* get debug control block information */
        ptrval = doffs[i]+56;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Debug control block (DCB) address:      %08lx\n", *result);
        ptrval = doffs[i]+60;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Debug flags:                            %08lx\n", *result);

        /* show PTDA data part 2 */

        //   Check for an ESC key (user abort)
        if (CheckESC())
            return;
        fprintf(stdout, "   VM arena header:\n");

        /* get PTDA's VM arena header data */
        ptrval = doffs[i]+64;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Link to next arena:                   %08lx\n", *result);
        ptrval = doffs[i]+68;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Link to previous arena:               %08lx\n", *result);
        ptrval = doffs[i]+72;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Handle of arena sentinel:             %08lx\n", *result);
        ptrval = doffs[i]+76;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Hint of 1st free block in arena:      %08lx\n", *result);
        ptrval = doffs[i]+80;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Pointer to bitmap directory:          %08lx\n", *result);
        ptrval = doffs[i]+84;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Hash table pointer:                   %08lx\n", *result);
        ptrval = doffs[i]+88;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Pointer to per-type info:             %08lx\n", *result);
        ptrval = doffs[i]+92;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Flags:                                %08lx\n", *result);
        ptrval = doffs[i]+96;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Minimum address currently mapped:     %08lx\n", *result);
        ptrval = doffs[i]+100;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Max address currently mapped:         %08lx\n", *result);
        ptrval = doffs[i]+104;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Count of arena entries:               %d\n", *result);
        ptrval = doffs[i]+108;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Max entry count to need bitmap:       %d\n", *result);
        ptrval = doffs[i]+112;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Max bitmap number:                    %d\n", *result);
        ptrval = doffs[i]+116;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Max bitmap entry number:              %d\n", *result);
        ptrval = doffs[i]+120;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Max hash table index:                 %08lx\n", *result);
        ptrval = doffs[i]+124;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Arena header pseudo-handle:           %08lx\n", *result);
        ptrval = doffs[i]+128;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "     Make structure 4-byte multiple:       %08lx\n", *result);

        /* get & show page data fake string */
        fprintf(stdout, "   Page data fake string:\n     ");
        PrintFake(148, 132, i);
        fprintf(stdout, "     ");
        PrintFake(166, 148, i);

        /* get more PTDA data */
        ptrval = doffs[i]+170;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "     Handle for environment string:        %04x\n", *result);
    }
    else
        fprintf(stdout, "Process data not in the dump\n");
    if (CheckESC())
        return;

    /* get TCB header information */
    fprintf(stdout, "TCB thread control block header:\n");
    fprintf(stdout, "   Number of threads:                      %d\n", nthreads);
    ptrval = postcbd+19;
    result = (ULONG *)GetVal(ptrval, 2);
    fprintf(stdout, "   Number of storage requests:             %d\n", *result);
    ptrval = postcbd+23;
    result = (ULONG *)GetVal(ptrval, 2);
    fprintf(stdout, "   Number of storage request failures:     %d\n", *result);

    /* get thread summary information for each thread */
    for (i=0; i< nthreads; i++)
    {
        ptrval = tsum+tend;
        result = (ULONG *)GetVal(ptrval, 4);
        threadn = *result;
        fprintf(stdout, "Thread %08lx summary:\n", threadn);
        ptrval = tsum+tend+8;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   Current thread:                         %04x\n", *result);
        ptrval = tsum+tend+10;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   Client register type:                   %04x ", *result);
        switch (*result)
        {
            case 0001: fprintf(stdout, "(Interrupt Stack Frame)\n");
                       break;
            case 0002: fprintf(stdout, "(Trap Stack Frame)\n");
                       break;
            case 0003: fprintf(stdout, "(VDM Stack Frame)\n");
                       break;
            case 0004: fprintf(stdout, "(System Entry Stack Frame(C32))\n");
                       break;
            case 0005: fprintf(stdout, "(System Entry Stack Frame(PASCAL32))\n");
                       break;
            case 0006: fprintf(stdout, "(SCI Stack Frame(PASCAL16))\n");
                       break;
            case 0007: fprintf(stdout, "(DevHlp Stack Frame)\n");
                       break;
            case 0111: fprintf(stdout, "(Unknown Stack Frame Not Defined)\n");
                       break;
        }
        ptrval = tsum+tend+12;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Client register address:                %08lx\n", *result);
        ptrval = tsum+tend+16;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   Client register size:                   %x\n", *result);
        ptrval = tsum+tend+20;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   User register address:                  %08lx\n", *result);
        ptrval = tsum+tend+24;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   User register size:                     %x\n", *result);
        ptrval = tsum+tend+28;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   User 16-bit selector:                   %04x\n", *result);
        ptrval = tsum+tend+30;
        result = (ULONG *)GetVal(ptrval, 2);
        fprintf(stdout, "   User 16-bit offset:                     %04x\n", *result);
        ptrval = tsum+tend+32;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   User stack address:                     %08lx\n", *result);
        ptrval = tsum+tend+36;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "   User stack size:                        %lx\n", *result);

        REGSInfo(threadn);
        fprintf(stdout, "\n");

        tend += 40;
        fflush(stdout);
        //   Check for an ESC key (user abort)
        if (CheckESC())
            return;
    }
#endif
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       PrintFake(int, int, int)                                  */
/*                  end  : ending of fake string                              */
/*                  begin: beginning of fake string                           */
/*                  rec  : record number                                      */
/*  Description:    Print page data fake string                               */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void PrintFake(int end, int begin, ULONG rec)
{
    ULONG i, ptrval;
    ULONG *result;

    for (i=end; i>=(ULONG)begin; i -= 4)
    {
        ptrval = doffs[rec]+i;
        result = (ULONG *)GetVal(ptrval, 4);
        fprintf(stdout, "%08lx", *result);
    }
    fprintf(stdout, "\n");
    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       VMARInfo(void)                                            */
/*  Description:    Print VMAR information                                    */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void VMARInfo(void)
{
    ULONG posvmar, ptrval;
    ULONG *result;
    ULONG arenaAddr;
    int numArenaRecs;

    /* get starting positions */
    posvmar = GetPos("VMAR");

    fprintf(stdout, "\nVMAR virtual memory arena header:\n");
    ptrval = posvmar+8;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Length of arena record:              %d\n", *result);
    ptrval = posvmar+12;
    result = (ULONG *)GetVal(ptrval, 4);
    arenaAddr = *result;
    fprintf(stdout, "Address of 1st arena record:         %08lx\n", arenaAddr);
    ptrval = posvmar+16;
    result = (ULONG *)GetVal(ptrval, 4);
    numArenaRecs = (int)*result;
    fprintf(stdout, "Number of arena records in dump:     %d\n", numArenaRecs);
    ptrval = posvmar+20;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Number of storage requests:          %d\n", *result);
    ptrval = posvmar+22;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Number of storage requests failures: %d\n\n", *result);
    if (!PrintVMInfo(arenaAddr, numArenaRecs, 0))
        fprintf(stdout, "Couldn't get offset to dump VMAR at address: %08lx\n",
                arenaAddr);

    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       VMOBInfo(void)                                            */
/*  Description:    Print VMOB information                                    */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
void VMOBInfo(void)
{
    ULONG posvmob, ptrval;
    ULONG *result;
    ULONG objectAddr;
    int numObjectRecs;

    /* get starting positions */
    posvmob = GetPos("VMOB");

    fprintf(stdout, "VMOB virtual memory object header:\n");
    ptrval = posvmob+8;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Length of object record:             %d\n", *result);
    ptrval = posvmob+12;
    result = (ULONG *)GetVal(ptrval, 4);
    objectAddr = *result;
    fprintf(stdout, "Address of 1st object record:        %08lx\n", objectAddr);
    ptrval = posvmob+16;
    result = (ULONG *)GetVal(ptrval, 4);
    numObjectRecs = (int)*result;
    fprintf(stdout, "Number of object records in dump:    %d\n", numObjectRecs);
    ptrval = posvmob+20;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Number of storage requests:          %d\n", *result);
    ptrval = posvmob+22;
    result = (ULONG *)GetVal(ptrval, 4);
    fprintf(stdout, "Number of storage requests failures: %d\n\n", *result);
    if (!PrintVMInfo(objectAddr, numObjectRecs, 1))
        fprintf(stdout, "Couldn't get offset to dump VMOB at address: %08lx\n",
                objectAddr);

    fflush(stdout);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       PrintVMInfo(void)                                         */
/*  Description:    Print VMCB information                                    */
/*  By:             Diem Dang                                                 */
/*  Date:           07/26/94                                                  */
/*                                                                            */
/******************************************************************************/
int PrintVMInfo(ULONG addr, int nRecs, int VMType)
{
    ULONG numRec, offs, i, rc;
    VMAR pVMAR_s;
    VMOB pVMOB_s;
    int ul = 0;
    ULONG va_ipg;

    if (GetOffs(addr, &numRec, &offs))
    {
        for (i=0; i<(ULONG)nRecs; i++)
        {
//              if (ul%12 == 0)
//                  fprintf(stdout, RecHeader);
//              fprintf(stdout, "%02d  %02d    %8lx       %d          %d\n",
//                               i+1, numRec, daddr[numRec], doffs[numRec], dsize[numRec]);
            if (VMType == 0)
                rc = GetPdumpMem(daddr[numRec], sizeof(VMAR), (char *)&pVMAR_s);
            else
                rc = GetPdumpMem(daddr[numRec], sizeof(VMOB), (char *)&pVMOB_s);
            if (rc != ERR_NO_ERROR)
                fprintf(stdout, "Couldn't load VMLinearAddr=%lx\n", daddr[numRec]);
            else
            {
                if (ul%12 == 0)
                {
                    switch (VMType)
                    {
                        case 0: fprintf(stdout, VMARHeader);
                                break;
                        case 1: fprintf(stdout, VMOBHeader);
                                break;
                    }
                }
                if (VMType == 0)
                {
                    va_ipg = pVMAR_s.ar_ipg;
                    fprintf(stdout, VMARFormat,
                                0,                   //   don't know the har... -todo
                                daddr[numRec] + (ULONG)(ul * dsize[numRec]),
                                pVMAR_s.ar_cpg,
                                va_ipg << 12,
                                pVMAR_s.ar_f,
                                pVMAR_s.ar_harnext,
                                pVMAR_s.ar_harprev,
                                pVMAR_s.ar_harlink,
                                pVMAR_s.ar_harhash,
                                pVMAR_s.ar_hob,
                                pVMAR_s.ar_hal,
                                pVMAR_s.ar_sel);
                }
                else
                {
                    fprintf(stdout, VMOBFormat,
                             0,                   //   don't know the hob... -todo
                             pVMOB_s.ob_har,                   /* Arena Record handle */
                             pVMOB_s.ob_hobnext,               /* Associated Object Record handle */
                             pVMOB_s.ob_fs,                    /* Flags */
                             pVMOB_s.ob_hobowner,              /* Owner i.d. */
                             pVMOB_s.ob_hobmte,                /* MTE handle */
                             pVMOB_s.ob_wsemowner,             /* I.d. of thread owning semaphore */
                             pVMOB_s.ob_bsemcnt,               /* Counter and waiting flag */
                             pVMOB_s.ob_cllock,                /* Count of all long-term locks */
                             pVMOB_s.ob_cslock,                /* Count of all short-term locks */
                             pVMOB_s.ob_xflags                 /* Extra flags */
                           );
                }
            }
            //   Check for an ESC key (user abort)
            if (CheckESC())
                return TRUE;
            numRec++;
            ul++;
            fflush(stdout);
        }
        return TRUE;
    }
    else
        return FALSE;
}
/******************************************************************************/
/*                                                                            */
/*  Function:       DotPInfo(ULONG, int, ULONG )                              */
/*                  len  : size of the dump file                              */
/*                  sType: 1(.p), 2(.pb), 4(.pu)                              */
/*  Description:    Get information of processes                              */
/*  By:             Diem Dang                                                 */
/*  Date:           07/20/94                                                  */
/*                                                                            */
/******************************************************************************/
void DotPInfo(ULONG len, int sType, USHORT reqThread)
{
    ULONG *result;
    struct ldrmte_s ldrMTE;
    ULONG ulAddr;
    ULONG recNum, offs, found=FALSE, rc;
    struct tcb_s far *TCBPtr;
    char szPTDABuf[84];
    int numThread=0;
    ushort_t threadCnt;

    result = (ULONG *)GetVal(posmted+11, 4);    //  address pointer to MTE head
    rc = GetPdumpMem(*result, sizeof(struct ldrmte_s), (char *)&ldrMTE);
    if (rc != ERR_NO_ERROR)
    {
        fprintf(stdout, "Couldn't load ulMTELinearAddr=%lx\n", *result);
        return;
    }

//  warp change
#ifdef WARP
    strncpy(szMTEModName,ldrMTE.mte_modname,MTE_NAME_LEN);
    szMTEModName[MTE_NAME_LEN]=NULL;
#else
    //  get MTE module name
    rc = GetPdumpMem(ldrMTE.mte_modname+1, MTE_NAME_LEN, szMTEModName);
    if (rc != ERR_NO_ERROR)
    {
        fprintf(stdout, "Couldn't load ldrMTE.mte_modname=%lx\n", ldrMTE.mte_modname);
        return;
    }
#endif


    result = (ULONG *)GetVal(posptda+20, 4);    //  get process data address
    //  find which record the address belongs to
    found = GetOffs(*result, &recNum, &offs);

    if ((found==TRUE) && ((doffs[recNum] + dsize[recNum]) <= len))
    {
        result = (ULONG *)GetVal(doffs[recNum]+4, 4);    //  get vpPTDA address
        ulAddr = *result;
        rc = GetPdumpMem(ulAddr, sizeof(struct ptda_s), (char *)vpPTDA);
        if (rc != ERR_NO_ERROR)
        {
            fprintf(stdout, "Couldn't load ulPTDALinearAddr=%lx\n", ulAddr);
            return;
        }
        TCBPtr = vpPTDA->ptda_pTCBHead;
        for (threadCnt=0; threadCnt < vpPTDA->ptda_cTCB && TCBPtr; threadCnt++)
        {
          ulAddr = (ULONG)TCBPtr;
          rc = GetPdumpMem(ulAddr, sizeof(struct tcb_s), (char *)vpTCB);
          if (rc != ERR_NO_ERROR)
          {
              fprintf(stdout, "Couldn't load ulTCBLinearAddr=%lx\n", ulAddr);
              return;
          }
          if (( reqThread == 0) || (reqThread == vpTCB->TCBOrdinal ))
          {
            GetProcessState(vpTCB->TCBState, szProcState);
            switch (sType)
            {
                case GET_PROC_NORM:
                    FormatData(vpTCB->TCBNumber, ulAddr, szPTDABuf, sizeof(szPTDABuf));
                    if ((numThread++)%24 == 0)
                        fprintf(stdout, ProcStatHeader1);
                    break;
                case GET_PROC_BLK:
                    FormatBlockData(vpTCB->TCBNumber, szPTDABuf, sizeof(szPTDABuf));
                    if ((numThread++)%24 == 0)
                        fprintf(stdout, ProcStatHeader2);
                    break;
                case GET_PROC_USER:
                    FormatUserData(vpTCB->TCBNumber, szPTDABuf, sizeof(szPTDABuf));
                    if ((numThread++)%24 == 0)
                        fprintf(stdout, ProcStatHeader3);
                    break;
            }

            if ( vpTCB->TCBOrdinal == currThreadnum )
               *(szPTDABuf + POUNDSGN_LOC) = '#';

            if ( vpTCB->TCBOrdinal == defThreadnum )
               *(szPTDABuf + ASTERISK_LOC) = '*';

            fprintf(stdout,"%s\n",szPTDABuf);

          }
          TCBPtr = vpTCB->TCBpTCBNext;
          if (CheckESC())
              return;
        }
          fflush(stdout);
    }
    else
        fprintf(stdout, "Couldn't find PTDA address in DotPInfo\n");
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       ListMTEs( len , listobjs)                                 */
/*                  len  : size of the dump file                              */
/*  Description:    List module table entries                                 */
/*  By:             David Jaramillo                                           */
/*  Date:           09/16/94                                                  */
/*                                                                            */
/******************************************************************************/

void ListMTEs(ULONG len, ULONG listobjs )
{
    ULONG    i;                  //  index
    ULONG  ptrval;
    ULONG *result;
    struct ldrmte_s  ldrMTE;
    struct ldrsmte_s ldrsMTE;
    ULONG  found=FALSE, rc;
    ULONG  mtl1;               //   length of MTE part 1 data
    ULONG  nomte;              //   number of MTEs in dump
    ULONG  mta1, mf2, mnobj;
    int    code;
    ULONG  ment=0;
    ULONG  index;              //   index to number of MTEs
    ULONG  index2;             //   index to object table

    ptrval = posmted+7;
    result = (ULONG *)GetVal(ptrval, 4);
    mtl1 = *result;

    ptrval = posmted+11;
    result = (ULONG *)GetVal(ptrval, 4);
    mta1 = *result;

    ptrval = posmted+23;
    result = (ULONG *)GetVal(ptrval, 4);
    nomte = *result;

//    fprintf(stdout, "   Number of MTEs:                         %d\n", nomte);

    /* find out where MTE part 1 data is in the dump */
    for (i=0; i<npdrecs; i++)
        if (mta1 == daddr[i])
        {
            found = 1;
            break;
        }

    /* if MTE part 1 data is in the dump, show it */
      if (found && ((doffs[i]+dsize[i]) <= (ULONG)len))
      {
        for ( index=1; index<=nomte; index++ )
        {
            if ( dsize[i] != mtl1 )
            {
                fprintf(stdout,  "\n   ERROR: size %d of record %d", dsize[i], i );
                fprintf(stdout,  "\n          does not match expected size of %d.", mtl1 );
                fprintf(stdout,  "\n   ABORTING MTE option...\n" );
                break;
            }  /* end if dsize[i] != mtl1 */

    mta1 = daddr[i];

    rc = GetPdumpMem(mta1, sizeof(struct ldrmte_s), (char *)&ldrMTE);
    if (rc != ERR_NO_ERROR)
    {
        fprintf(stdout, "Couldn't load ulMTELinearAddr=%lx\n", mta1);
        return;
    }

//  warp change
#ifdef WARP
    strncpy(szMTEModName,ldrMTE.mte_modname,8);
    szMTEModName[8]=NULL;
#else
    //  get MTE module name
    rc = GetPdumpMem(ldrMTE.mte_modname+1, MTE_NAME_LEN, szMTEModName);
    if (rc != ERR_NO_ERROR)
    {
        fprintf(stdout, "Couldn't load ldrMTE.mte_modname=%lx\n", ldrMTE.mte_modname);
        return;
    }
#endif

    fprintf(stdout, "hmte=%04x ",ldrMTE.mte_handle);
    fprintf(stdout, "pmte=%08lx ",mta1);
    fprintf(stdout, "mflags=%08lx ",ldrMTE.mte_flags1);
    fprintf(stdout, "%-8s ",szMTEModName);

#ifdef WARP
            fprintf(stdout, "%s\n",GetVal(doffs[i+3], dsize[i+3]));
#else
            fprintf(stdout, "%s\n", GetVal(doffs[i+4], dsize[i+4]));
#endif
            i++;

            ptrval = doffs[i]+32;
            result = (ULONG *)GetVal(ptrval, 4);
            mnobj = *result;
//            fprintf(stdout, "     Number of objects:                     %d\n", mnobj);

    rc = GetPdumpMem((ULONG)ldrMTE.mte_swapmte, sizeof(struct ldrsmte_s), (char *)&ldrsMTE);

    if (rc != ERR_NO_ERROR)
     {
        fprintf(stdout, "Couldn't load ulSMTELinearAddr=%lx\n", ldrMTE.mte_swapmte);
        return;
     }

            /* bump to next record to get object table data */
            i++;


if ( listobjs )
{
            ment = doffs[i];
            if ((mf2 & 0x0003) == 0x0001)
            {
                code = 16;
//                fprintf(stdout, "\n     MTE #%d %d bit Object Table\n", index, code);
                fprintf(stdout, "obj  Sel  hob   Size\n");
            }
            else
            {
//                fprintf(stdout, "\n     MTE #%d %d bit Object Table\n", index, code);
                fprintf(stdout, "obj  Sel    Vbase   hob   vsize    flags\n");
                code = 32;
            }

            if (CheckESC())
              return;

            for (index2=1; index2<=mnobj; index2++)
            {
                if (code == 16)
                {
                    result = (ULONG *)GetVal(ment+10, 2);  //selector
                    fprintf(stdout, "%04ld %04x ", index2, *result);
                    result = (ULONG *)GetVal(ment+8, 2);   // handle
                    fprintf(stdout, "%04x ", *result);
                    result = (ULONG *)GetVal(ment+6, 2);   // size
                    fprintf(stdout, "%04x\n", *result);
                    ment += 16;
                }
                else
                {
                    result = (ULONG *)GetVal(ment+20, 2);            // selector
                    fprintf(stdout, "%04ld %04x ", index2, *result);
                    result = (ULONG *)GetVal(ment+4 , 4);            // virtual addr
                    fprintf(stdout, "%08lx ", *result);
                    result = (ULONG *)GetVal(ment+22, 2);            // handle
                    fprintf(stdout, "%04x ", *result);
                    result = (ULONG *)GetVal(ment, 4);               // size
                    fprintf(stdout, "%08lx ", *result);
                    result = (ULONG *)GetVal(ment+8 , 4);            // virtual addr
                    fprintf(stdout, "%08lx\n", *result);
                    ment += 24;
                }
            }

            fprintf(stdout,"\n");
}
            /* bump record number to next MTE entry */
#ifdef WARP
            i += 2;
#else
            i += 3;
#endif
            fflush(stdout);
            //   Check for an ESC key (user abort)
            if (CheckESC())
               return;
        }
    }
    else
        fprintf(stdout, "\n   MTE entries not in dump\n");
    return;
}


/******************************************************************************/
/*                                                                            */
/*  Function:       FormatData(ushort_t, char*, int)                          */
/*  Description:    Get data for process state                                */
/*  Comment:        Need to specify CurrentSlot or DefaultSlot                */
/*  By:             Diem Dang                                                 */
/*  Date:           07/20/94                                                  */
/*                                                                            */
/******************************************************************************/
void FormatData(ushort_t pSlot, ULONG ulTCBLinearAddr, char *szBuf, int bufLen)
{
    ULONG ulTSDLinearAddr;
    int rc;
    USHORT usDisp;

    ulTSDLinearAddr = (ULONG)vpTCB->TCBpTSD;
    rc = GetPdumpMem(ulTSDLinearAddr, sizeof(struct tsd_s), (char *)vpTSD);
    if (rc != ERR_NO_ERROR)
        sprintf(szBuf, szPTDASumFormat2, pSlot, vpPTDA->ptda_Pid, vpPTDA->ptda_Ppid,
                   vpPTDA->Csid, vpTCB->TCBOrdinal, szProcState, vpTCB->TCBPriority,
                   ulTSDLinearAddr, vpPTDA->pPTDASelf, ulTCBLinearAddr, "    ",
                   vpPTDA->ptda_CurScrnGrp);
    else
    {
        usDisp = (USHORT)(vpTSD->TSDKernelESP - vpTCB->TCBCurrTSD);
        sprintf(szBuf, szPTDASumFormat1, pSlot, vpPTDA->ptda_Pid, vpPTDA->ptda_Ppid,
                       vpPTDA->Csid, vpTCB->TCBOrdinal, szProcState, vpTCB->TCBPriority,
                       ulTSDLinearAddr, vpPTDA->pPTDASelf, ulTCBLinearAddr, usDisp,
                       vpPTDA->ptda_CurScrnGrp);
    }
    strcat(szBuf, szMTEModName);
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       FormatBlockData(ushort_t, char*, int)                     */
/*  Description:    Get data for process state                                */
/*  Comment:        Need to specify CurrentSlot or DefaultSlot                */
/*  By:             Diem Dang                                                 */
/*  Date:           07/20/94                                                  */
/*                                                                            */
/******************************************************************************/
void FormatBlockData(ushort_t pSlot, char *szBuf, int bufLen)
{
    ULONG ulBlockID;
    USHORT blockid_hi;
    char szType[11];
    int usBufLen;

    ulBlockID = (ULONG)vpTCB->TCBSleepID;
    blockid_hi = (USHORT)(SHIFT_RIGHT(ulBlockID, 16));

    //  dumpInfoStruc was not loaded, so assume there are only two szType:
    //  RamSem and MuxWait.  There is no symbol loaded either.
    switch (blockid_hi)
    {
        case RAMSEM_BLOCK_ID:
            strcpy(szType, "RamSem");
            break;
        case MUX_BLOCK_ID:
            strcpy(szType, "MuxWait");
            break;
        default:
            *szType = '\0';
    }
    sprintf(szBuf, szBlockFormat, pSlot, szProcState, ulBlockID, szMTEModName, szType);
    usBufLen = strlen(szBuf);
    if (!strcmp(szType, "RamSem"))
    {
        sprintf(szBuf+usBufLen, "%04x:%04x", SELECTOROF(vpTCB->TCB_SemInfo),
                                             OFFSETOF(vpTCB->TCB_SemInfo));
    }
    else
        sprintf(szBuf+usBufLen, "         ");
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       FormatUserData(ushort_t, char*, int)                      */
/*  Description:    Get data for process state                                */
/*  Comment:        Need to specify CurrentSlot or DefaultSlot                */
/*  By:             Diem Dang                                                 */
/*  Date:           07/20/94                                                  */
/*                                                                            */
/******************************************************************************/
void FormatUserData(ushort_t pSlot, char *szBuf, int bufLen)
{
    int rc;

    if (vpTCB->TCB_pFrameBase == NULL)
    {
        sprintf(szBuf, szUserFormat1, pSlot, vpTCB->TCBProc_ID, vpTCB->TCBOrdinal,
                vpTCB->TCBpPTDA, szMTEModName);
        return;
    }

    sprintf(szBuf, szUserFormat2, pSlot, vpTCB->TCBProc_ID, vpTCB->TCBOrdinal,
            vpTCB->TCBpPTDA, szMTEModName, vpTCB->TCB_pFrameBase);
    rc = GetPdumpMem((ULONG)vpTCB->TCBpTSD, sizeof(struct tsd_s), (char *)vpTSD);
    if (rc == ERR_NO_ERROR)
    {
        if (vpTSD->TSDKernelESP != 0)
        {
            szBuf+=strlen(szBuf);
            sprintf(szBuf, " %s", print_reg(KM_REG_CS));
            szBuf+=strlen(szBuf);
            sprintf(szBuf, ":%s ", print_reg(KM_REG_EIP));
            szBuf+=strlen(szBuf);
            sprintf(szBuf, "%04.4x:%08.8lx %4.4x", vpTSD->TSDUserSS,
                    vpTSD->TSDUserESP, (print_reg(KM_REG_CBARGS) != NULL ?
                    atoi(print_reg(KM_REG_CBARGS)) : 0));
            szBuf+=strlen(szBuf);
        }
    }
    return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetPdumpMem(ULONG, int, char*)                            */
/*                  ulAddr: address used to start dumping                     */
/*                  nBytes: number of bytes to be dumped                      */
/*                  buffer: used to store the dump string                     */
/*  Description:    Dump memory into buffer                                   */
/*  By:             Diem Dang                                                 */
/*  Date:           07/20/94                                                  */
/*                                                                            */
/******************************************************************************/
int GetPdumpMem(ULONG ulAddr, int nBytes, char *buffer)
{
    ULONG i, recNum;
    ULONG offs;
    ULONG found=FALSE;
    char *memChr;

    if ((found = GetOffs(ulAddr, &recNum, &offs)) == TRUE)
    {
        for (i=0; i<(ULONG)nBytes; i++)
        {
            memChr = GetVal(offs, 1);
            buffer[i] = *memChr;
            offs++;
        }
        return ERR_NO_ERROR;
    }
    else
        return 1; //ERROR
}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetOffs(ULONG, int, int)                                  */
/*                  ulAddr: address used to get the offset                    */
/*                  recNum: record number                                     */
/*                  offs  : offset in the dump                                */
/*  Description:    Get offset to dump memory into buffer                     */
/*  By:             Diem Dang                                                 */
/*  Date:           07/21/94                                                  */
/*                                                                            */
/******************************************************************************/
ULONG GetOffs(ULONG ulAddr, ULONG *recNum, ULONG *offs)
{
    ULONG i, j, nRecs, begin, end;
    ULONG addr;
    ULONG endRec;
    int found=FALSE;

    if (npdrecs==0)
        return found;

    if (sort)
    {
        begin = 0;
        i = npdrecs/2;
        end = npdrecs;
        j = seq[i];
        *recNum = j;
        while (ulAddr != daddr[j])
        {
            if (ulAddr > daddr[j])
            {
                if (ulAddr <= (daddr[j] + (ULONG)dsize[j]))
                //  ulAddr in the range of recNum
                {
                    begin = i;
                    end = i + 1;
                    break;
                }
                else
                {
                    begin = i;
                    nRecs = end - begin + 1;
                    i = i + nRecs/2;
                }
            }//  end if ulAddr > daddr[j]
            else    //  if (ulAddr < daddr[j])
            {
                if ((end - begin) == 1)
                    break;
                end = i;
                nRecs = end - begin + 1;
                i = i - nRecs/2;
            }//  end if ulAddr < daddr[j]

//            if ((i >= 0) || (i < npdrecs))
            if (i < npdrecs)
            {
                j = seq[i];
                *recNum = j;
            }
            else
                break;
        }//  end while (ulAddr != daddr[j])

        if (ulAddr == daddr[j])
        {
            found = TRUE;
            *offs = doffs[j];
        }
        else if(ulAddr == daddr[seq[i+1]])
        {
            found = TRUE;
            *recNum = seq[i+1];
            *offs = doffs[*recNum];
        }
    }//  end sort
    else  //  not sort
    {
        begin = 0;
        end = npdrecs;
    }//  end not sort

    if (found == FALSE)
    {
        for (i=begin; i<end; i++)
        {
            if (sort) j = seq[i];
            else      j = i;
            endRec = daddr[j] + (ULONG)dsize[j];
            if (ulAddr <= endRec)
            {
                addr = daddr[j];
                *offs = doffs[j];
                while (addr < endRec)
                {
                    if (addr == ulAddr)
                    {
                        i = end;
                        found = TRUE;
                        *recNum = j;
                        break;
                    }
                    else
                    {
                        addr++;
                        (*offs)++;
                    }
                }//  end while addr < endRec
            }//  end if ulAddr <= endRec
        }//  end for
    }//  end if found = FALSE
    return found;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetPos(char *)                                            */
/*  Description:    Get starting positions for headers in the dump            */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
ULONG GetPos(UCHAR *string)
{
    ULONG position;
    int done=FALSE;
    UCHAR  huge *tmp = dumpPtr;

    while(!done)
    {
        if (*tmp++ == string[0])
            if (strstr(tmp, &string[1]) == tmp)
            {
                done = TRUE;
                position = (ULONG)((--tmp) - dumpPtr);
            }
    }
    if (done)
        return position;
    else
        return FALSE;
}

/******************************************************************************/
/*                                                                            */
/* Function:        GetCmd(char *)                                            */
/* Description:     Get user input command                                    */
/*  By:             Diem Dang, Julie Reese                                    */
/*                                                                            */
/******************************************************************************/
void GetCmd(char far *cmd)
{
    ULONG  rc;
    USHORT numRead;

    memset(cmd, '\0', CMDLEN);

    if (fFrontEnd == TRUE)
    {

//159912       fprintf(stdout,  "#\002\r\n");
       fprintf(stdout,  "#\002");                //159912
       fflush(stdout);

       rc = DosRead( hPipe, cmd, CMDLEN, &numRead );
       cmd[numRead-1]='\0';

//       fprintf(stdout,"\n[%s]\n",cmd);
//       fflush(stdin);

    }
    else
    {

       cmd[0] = ' ';              //  initialize cmd[0]
       while (isspace(cmd[0]))    //   print another prompt if the user press space bar
       {
           fprintf(stdout,  "# ");
           fflush(stdout);
           fflush(stdin);
           cmd[0] = (char)getchar();
       }

       gets(&cmd[1]);          //  get the rest of the input line

    }

    return;

}

/******************************************************************************/
/*                                                                            */
/*  Function:       GetVal(ULONG, int)                                          */
/*  Description:    Get data from the dump file                               */
/*  By:             Diem Dang                                                 */
/*                                                                            */
/******************************************************************************/
char *GetVal(ULONG posstart, ULONG length)
{
    UCHAR huge *valptr;
    ULONG i=0;
    static char num[NUMSIZE];

    memset(num,0,NUMSIZE);

    valptr = dumpPtr+posstart;
    for(i=0; i < length; i++)
    {
        num[i]= valptr[i];
    }
    num[i] = '\0';
    return num;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       CheckESC(void)                                            */
/*  Description:    Check for an ESC key (user abort)                         */
/*  By:             Diem Dang                                                 */
/*  Date:           07/19/94                                                  */
/*                                                                            */
/******************************************************************************/
int CheckESC(void)
{
    KBDKEYINFO kb;                     //   used to get ESC key
    CHAR  ltmpByte;
    USHORT lnumBytes;
    AVAILDATA pipeAvail;
    USHORT pipeState;
    ULONG rc;

    if (fFrontEnd == TRUE )
    {
        rc = DosPeekNmPipe( hPipe, &ltmpByte, 1, &lnumBytes, &pipeAvail, &pipeState );

        if (rc)
            fprintf(stdout, "Error peeking pipe, rc = %ld\n",rc);

        if (( ltmpByte == 3 ) || (ltmpByte == 0x1b ))
            return TRUE;
    }
    else
    {
        KbdCharIn(&kb, 1, 0);
        if (kb.chChar == '\x1b')
           return TRUE;
    }
    return FALSE;
}

#ifdef WARP
void dumpDebug( void )
{
    ULONG  posdebug=0;                           //  starting position for MEM_TABLE_END

    ULONG  ptrval;
    ULONG  *result;
    ULONG  val;


    /* report Debug MEMORY TABLE END */
    fprintf(stdout, "\nDebug MEMORY TABLE END\n");
    posdebug = GetPos("MEM_TAB_END ");

    if (posdebug==0)
    {
      fprintf(stdout, "Memory Table Debug information not present in dump\n");
      return;
    }

    ptrval = posdebug+12;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "Dump Areas Requested  %08lx\n", val);

    ptrval = posdebug+16;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "   VMAR rc             %08lx\n", val);

    ptrval = posdebug+20;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "   VMOB rc             %08lx\n", val);

    ptrval = posdebug+24;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "   MTE rc              %08lx\n", val);

    ptrval = posdebug+28;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "   THREAD rc           %08lx\n", val);

    ptrval = posdebug+32;
    result = (ULONG *)GetVal(ptrval, 4);
    val=*result;
    fprintf(stdout, "   LDT rc              %08lx\n", val);

    return;
}
#endif

#include <time.h>
void ffsthere(char * fname,int line,char *str, unsigned long var1,unsigned long var2)
{
  FILE *ffile;
  char sdate[9];
  char stime[9];
  ffile=fopen("ffsthere.out","a");
  fprintf(ffile,"%s %s file:%s line:%i %s  var1: %ld var2: %ld\n",
          _strdate(sdate),_strtime(stime),fname,line, str, var1,var2);
  fclose(ffile);
  return;
}

/******************************************************************************/
/*                                                                            */
/*  Function:       ReadInDumpFile                                            */
/*  Description:    Reads Process Dump file                                   */
/*  By:             David Jaramillo                                           */
/*  Date:           09/09/94                                                  */
/*                                                                            */
/******************************************************************************/

int ReadInDumpFile( char *szDumpFile, ULONG *numBytes )
{
   FILESTATUS fstsFile;
   UCHAR huge *pchTmp;
   USHORT    usHugeShift;               // segment index shift value                              */
   USHORT    usReturnCode = 0;         // return code from Dos APIs
   USHORT    usAction;                 // open action taken
   ULONG     ulBytesRead;
   HFILE     hFile = 0;                // file handle
   USHORT    usBytes;
   ULONG     ulBytesNeeded;
   USHORT    usMSize = 0;  // not needed here because there is no header
   SEL       sel = 0;                   // selector for file's content
   USHORT Hugeinc=8;                    // hunge increment value (1<<usHugeshift)
   UINT      i;

   if (usReturnCode = DosOpen(szDumpFile,
                              &hFile,
                              &usAction,
                              0L,
                              FILE_NORMAL,
                              FILE_OPEN,
                              OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,
                              0L))
      {
//      fprintf(stdout,"Error openning PDump file (%s)\n", strlwr(szDumpFile));
      return(usReturnCode);
      }

   DosQFileInfo( hFile, 1, &fstsFile, sizeof( FILESTATUS ));

   ulBytesNeeded = usMSize + fstsFile.cbFile;

                                       // get some memory...
   if (usReturnCode = DosAllocHuge((USHORT)(ulBytesNeeded / UINT_MAX),
                                   (USHORT)(ulBytesNeeded % UINT_MAX),
                                   &sel,
                                   0,
                                   SEG_NONSHARED))
      {
      fprintf( stdout, "Error, Could not allocate memory to load symbol file %s, rc=%d",szDumpFile, usReturnCode);
      fflush(stdout);
      DosClose(hFile);
      return(usReturnCode);
      }

//   fprintf(stdout,"allocated selector %d\n",sel);
   DosGetHugeShift(&usHugeShift);

   Hugeinc=(1 << usHugeShift);

//   fprintf( stdout, "Starting to Read in PDump File %s file\n",szDumpFile );
//   fflush(stdout);
   ulBytesRead = 0L;
   i = 0;
   while (ulBytesRead < fstsFile.cbFile)
      {
      usBytes = (fstsFile.cbFile-ulBytesRead) > (ULONG)32768 ?
                        (USHORT)32768 : (USHORT)(fstsFile.cbFile-ulBytesRead);

      pchTmp = (PVOID)MAKEP(sel+( (i / 2) <<usHugeShift),
                            (32768 * (i % 2)) );

      if ( usMSize )
         {
         pchTmp += usMSize;
         if ( usMSize + usBytes > 32768 )
            {
            int   x;
            x = ( usMSize + usBytes ) - (USHORT)32768;
            usBytes -= x;
            }
         usMSize = 0;
         }

      if (usReturnCode = DosRead(hFile,
                                 pchTmp,
                                 usBytes,
                                 &usBytes))
         {
         fprintf( stdout, "Error, Reading PDump File %s file, rc=%d\n",szDumpFile, usReturnCode );
         fflush(stdout);
//         fprintf(stdout,"deallocated selector %d\n",sel);
         DosFreeSeg(sel);
         DosClose(hFile);
         return(usReturnCode);
         }
      ulBytesRead += usBytes;
      i++;
      }

//   fprintf( stdout, "Finished Reading in PDump File %s file\n",szDumpFile );
//   fflush(stdout);

   dumpPtr = MAKEP(sel, 0);

   *numBytes = ulBytesRead;
   pdsize = ulBytesRead;

   fflush(stdout);
   DosClose( hFile );
   return( 0 );
}

void GetNextMTE( ULONG *mteAddr )
{
    ULONG    i;                  //  index
    ULONG  ptrval;
    ULONG *result;
    ULONG  found=FALSE;
    ULONG  mtl1;               //   length of MTE part 1 data
    ULONG  nomte;              //   number of MTEs in dump
    ULONG  mta1;
    ULONG  ment=0;
    ULONG  index;              //   index to number of MTEs

    ptrval = posmted+7;         // mte length
    result = (ULONG *)GetVal(ptrval, 4);
    mtl1 = *result;

    ptrval = posmted+11;        // mte address 1
    result = (ULONG *)GetVal(ptrval, 4);
    mta1 = *result;

    ptrval = posmted+23;        // number of mte's
    result = (ULONG *)GetVal(ptrval, 4);
    nomte = *result;

    if ( *mteAddr == -1 )
    {
        *mteAddr = mta1;
        return;
    }

    /* find out where MTE part 1 data is in the dump */
    for (i=0; i<npdrecs; i++)
        if (mta1 == daddr[i])
        {
            found = 1;
            break;
        }

    /* if MTE part 1 data is in the dump, show it */
    if (found && ((doffs[i]+dsize[i]) <= pdsize))
    {
        for ( index=1; index<=nomte; index++ )
        {
            if ( dsize[i] != mtl1 )
            {
                *mteAddr == 0;
                return;
            }  /* end if dsize[i] != mtl1 */

            if ( index == nomte )
            {
                *mteAddr = 0;
                return;
            }

            mta1 = daddr[i];

            #ifdef WARP
                i += 4;
            #else
                i += 5;
            #endif

            if (mta1 == *mteAddr)
            {
                *mteAddr = daddr[i];
                return;
            }

        }
    }
    else
        *mteAddr=0;
    return;
}


/** eof  **/
