/***    symbols6.c
 *
 * engine routines for C6 symbols. to convert C6 symbols to C7 (CV4) symbols
 *
 */

#include "compact.h"


LOCAL   void    FixupPublics (uchar *, ushort);
LOCAL   uchar  *RemoveComDat (uchar *Symbols);
LOCAL   void    RewritePublics (uchar *, DirEntry *, PMOD);
LOCAL   void    RewriteSrcLnSeg (uchar *, DirEntry *, uchar *, PMOD);
LOCAL   void    RewriteSymbols (uchar *, DirEntry *, char *, PMOD);

// Called through Fixup function table
LOCAL void C6SizeBlockSym16 (void);
LOCAL void C6SizeBlockSym32 (void);
LOCAL void C6SizeEndSym (void);
LOCAL void C6SizeLabSym16 (void);
LOCAL void C6SizeLabSym32 (void);
LOCAL void C6SizeChgDfltSegSym (void);
LOCAL void C6SizeSkipSym (void);
LOCAL void C6SizeBPRelSym16 (void);
LOCAL void C6SizeBPRelSym32 (void);
LOCAL void C6SizeRegSym (void);
LOCAL void C6SizeConstantSym (void);
LOCAL void C6SizeLocalSym16 (void);
LOCAL void C6SizeLocalSym32 (void);
LOCAL void C6SizeProcSym16 (void);
LOCAL void C6SizeProcSym32 (void);

// Called through Rewrite function table
LOCAL void C6RwrtRegSym (void);
LOCAL void C6RwrtDataSym16 (void);
LOCAL void C6RwrtDataSym32 (void);
LOCAL void C6RwrtBPRelSym16 (void);
LOCAL void C6RwrtBPRelSym32 (void);
LOCAL void C6RwrtBlockSym16 (void);
LOCAL void C6RwrtBlockSym32 (void);
LOCAL void C6RwrtLabSym16 (void);
LOCAL void C6RwrtLabSym32 (void);
LOCAL void C6RwrtChgDfltSeg (void);
LOCAL void C6RwrtProcSym16  (void);
LOCAL void C6RwrtProcSym32  (void);
LOCAL void C6RwrtConstantSym    (void);
LOCAL void C6RwrtGenericSym (void);
LOCAL void C6RwrtSkipSym (void);
#ifndef WIN32
#pragma alloc_text (TEXT2, C6RwrtRegSym)
#pragma alloc_text (TEXT2, C6RwrtDataSym16)
#pragma alloc_text (TEXT2, C6RwrtDataSym32)
#pragma alloc_text (TEXT2, C6RwrtBPRelSym16)
#pragma alloc_text (TEXT2, C6RwrtBPRelSym32)
#pragma alloc_text (TEXT2, C6RwrtBlockSym16)
#pragma alloc_text (TEXT2, C6RwrtBlockSym32)
#pragma alloc_text (TEXT2, C6RwrtLabSym16)
#pragma alloc_text (TEXT2, C6RwrtLabSym32)
#pragma alloc_text (TEXT2, C6RwrtChgDfltSeg)
#pragma alloc_text (TEXT2, C6RwrtProcSym16)
#pragma alloc_text (TEXT2, C6RwrtProcSym32)
#pragma alloc_text (TEXT2, C6RwrtConstantSym)
#pragma alloc_text (TEXT2, C6RwrtGenericSym)
#pragma alloc_text (TEXT2, C6RwrtSkipSym)
#endif

LOCAL ushort C6CnvrtRegSym (uchar *, uchar *);
LOCAL ushort C6CnvrtDataSym16 (uchar *, uchar *);
LOCAL ushort C6CnvrtDataSym32 (uchar *, uchar *);
LOCAL ushort C6CnvrtBPRelSym16 (uchar *, uchar *);
LOCAL ushort C6CnvrtBPRelSym32 (uchar *, uchar *);
#ifndef WIN32
#pragma alloc_text (TEXT2, C6CnvrtRegSym)
#pragma alloc_text (TEXT2, C6CnvrtDataSym16)
#pragma alloc_text (TEXT2, C6CnvrtDataSym32)
#pragma alloc_text (TEXT2, C6CnvrtBPRelSym16)
#pragma alloc_text (TEXT2, C6CnvrtBPRelSym32)
#endif



LOCAL void C6RewriteSymbolStrings (uchar * End);

LOCAL short SizeChgNumeric (uchar *);


extern ushort recursive;
extern ushort AddNewSymbols;
extern uchar  Signature[];
extern ulong  cPublics;

extern uchar ptr32;
extern uchar *SymbolSegment;

extern ushort SymbolSizeAdd;
extern ushort SymbolSizeSub;
extern ushort UDTAdd;
extern uchar **ExtraSymbolLink;
extern uchar *ExtraSymbols;
extern ulong InitialSymInfoSize;
extern ulong FinalSymInfoSize;
extern char    *ModAddr;

extern ulong ulCVTypeSignature; // The signature from the modules type segment


// These are shared by the fixup functions
LOCAL uchar *pOldSym;           // Old (C6) symbol to fixup, and calc size for
LOCAL int    iLevel;

// These are shared by the rewrite functions
LOCAL uchar *NewSymbols;        // Where to write next byte of new symbol
LOCAL uchar *StartSymbols;      // Where to write next byte of new symbol
LOCAL uchar *OldSymbols;        // Where to get next byte of old symbol
LOCAL ushort segment;


typedef struct {
    uchar               oldsym;             // Old C6 Symbol record type
    ushort              new16sym;           // New C7 type (16 bit)
    void                (*pfcn16) (void);
    ushort              new32sym;           // New C7 type (32 bit)
    void                (*pfcn32) (void);
} rewritesymfcn;

rewritesymfcn   C6RwrtSymFcn[] = {
        {OSYMBLOCKSTART,
                S_BLOCK16,          C6RwrtBlockSym16,
                S_BLOCK32,          C6RwrtBlockSym32},

        {OSYMPROCSTART,
                S_LPROC16,          C6RwrtProcSym16,
                S_LPROC32,          C6RwrtProcSym32},

        {OSYMEND,
                S_END,              C6RwrtGenericSym,
                S_END,              C6RwrtGenericSym},

        {OSYMBPREL,
                S_BPREL16,          C6RwrtBPRelSym16,
                S_BPREL32,          C6RwrtBPRelSym32},

        {OSYMLOCAL,
                S_LDATA16,          C6RwrtDataSym16,
                S_LDATA32,          C6RwrtDataSym32},

        {OSYMLABEL,
                S_LABEL16,          C6RwrtLabSym16,
                S_LABEL32,          C6RwrtLabSym32},

        {OSYMWITH,
                S_WITH16,           C6RwrtBlockSym16,   // Structure matches Block Start
                S_WITH32,           C6RwrtBlockSym32},  // Structure matches Block Start

        {OSYMREG,
                S_REGISTER,         C6RwrtRegSym,
                S_REGISTER,         C6RwrtRegSym},

        {OSYMCONST,
                S_CONSTANT,         C6RwrtConstantSym,
                S_CONSTANT,         C6RwrtConstantSym},

//M00 Kludge - Fortran Entry may not map this easy.
        {OSYMFORENTRY,
                S_LPROC16,          C6RwrtProcSym16,
                S_LPROC32,          C6RwrtProcSym32},

        {OSYMNOOP,
                0,                  C6RwrtSkipSym,
                0,                  C6RwrtSkipSym},

        {OSYMCHGDFLTSEG,
                0,                  C6RwrtChgDfltSeg,
                0,                  C6RwrtChgDfltSeg},
};


#define C6REWRITESYMCNT (sizeof C6RwrtSymFcn / sizeof (C6RwrtSymFcn[0]))

//  This table is used to convert based pointer symbols.  The only symbol
//  types that can be used as bases are BP relative symbols, data symbols and
//  register symbols.


typedef struct {
    uchar       oldsym;             // Old C6 Symbol record type
    ushort      new16sym;           // New C7 type (16 bit)
    ushort      (*pfcn16) (uchar *, uchar *);
    ushort      new32sym;           // New C7 type (32 bit)
    ushort      (*pfcn32) (uchar *, uchar *);
} cnvrtsymfcn;

cnvrtsymfcn   C6CnvrtSymFcn[] = {
        {OSYMBPREL,
                S_BPREL16,          C6CnvrtBPRelSym16,
                S_BPREL32,          C6CnvrtBPRelSym32},

        {OSYMLOCAL,
                S_LDATA16,          C6CnvrtDataSym16,
                S_LDATA32,          C6CnvrtDataSym32},

        {OSYMREG,
                S_REGISTER,         C6CnvrtRegSym,
                S_REGISTER,         C6CnvrtRegSym},

};


#define C6CNVRTSYMCNT (sizeof C6CnvrtSymFcn / sizeof (C6CnvrtSymFcn[0]))



typedef struct {
    uchar               oldsym;             // Old C6 Symbol record type
    void                (*pfcn16) (void);
    void                (*pfcn32) (void);
} fixupsymfcn;

fixupsymfcn C6SizeSymFcn[] = {
        {OSYMBLOCKSTART,    C6SizeBlockSym16,
                            C6SizeBlockSym32},

        {OSYMPROCSTART,     C6SizeProcSym16,
                            C6SizeProcSym32},

        {OSYMEND,           C6SizeEndSym,
                            C6SizeEndSym},

        {OSYMBPREL,         C6SizeBPRelSym16,
                            C6SizeBPRelSym32},

        {OSYMLOCAL,         C6SizeLocalSym16,
                            C6SizeLocalSym32},

        {OSYMLABEL,         C6SizeLabSym16,
                            C6SizeLabSym32},

        {OSYMWITH,          C6SizeBlockSym16,    // Structure matches Block Start
                            C6SizeBlockSym32},   // Structure matches Block Start

        {OSYMREG,           C6SizeRegSym,
                            C6SizeRegSym},

        {OSYMCONST,         C6SizeConstantSym,
                            C6SizeConstantSym},

//M00 Kludge - Fortran Entry may not map this easy.
        {OSYMFORENTRY,      C6SizeProcSym16,
                            C6SizeProcSym32},

        {OSYMNOOP,          C6SizeSkipSym,
                            C6SizeSkipSym},

        {OSYMCHGDFLTSEG,    C6SizeChgDfltSegSym,
                            C6SizeChgDfltSegSym},

};


#define C6SIZESYMCNT (sizeof C6SizeSymFcn / sizeof (C6SizeSymFcn[0]))


ushort RegMap[36] = {
    CV_REG_AL,                   //    0
    CV_REG_CL,                   //    1
    CV_REG_DL,                   //    2
    CV_REG_BL,                   //    3
    CV_REG_AH,                   //    4
    CV_REG_CH,                   //    5
    CV_REG_DH,                   //    6
    CV_REG_BH,                   //    7
    CV_REG_AX,                   //    8
    CV_REG_CX,                   //    9
    CV_REG_DX,                   //   10
    CV_REG_BX,                   //   11
    CV_REG_SP,                   //   12
    CV_REG_BP,                   //   13
    CV_REG_SI,                   //   14
    CV_REG_DI,                   //   15
    CV_REG_EAX,                  //   16
    CV_REG_ECX,                  //   17
    CV_REG_EDX,                  //   18
    CV_REG_EBX,                  //   19
    CV_REG_ESP,                  //   20
    CV_REG_EBP,                  //   21
    CV_REG_ESI,                  //   22
    CV_REG_EDI,                  //   23
    CV_REG_ES,                   //   24
    CV_REG_CS,                   //   25
    CV_REG_SS,                   //   26
    CV_REG_DS,                   //   27
    CV_REG_FS,                   //   28
    CV_REG_GS,                   //   29
    CV_REG_ST0,                  //   30
    CV_REG_NONE,                 //   31
    ((CV_REG_DX<<8) | CV_REG_AX),//   32
    ((CV_REG_ES<<8) | CV_REG_BX),//   33
    CV_REG_IP,                   //   34
    CV_REG_FLAGS                 //   35
};




/**
 *
 *  C6 CalcNewSizeOfSymbols
 *
 *  Go through the symbols segment calculating the maximum size increase
 *  from the old C6 symbol segment to the new C7 symbol segment. This
 *  calculation is the maximum. Many symbols will fit into less space
 *  and the actual symbol size will be smaller.
 */


//M00 Document comunication with called functions
void C6CalcNewSizeOfSymbols (uchar *Symbols, ulong SymbolCount)
{
    uchar *         End;
    uchar           type;
    uchar           fFlat32;
    fixupsymfcn    *pFixFcn;
    int             i;

    cSeg = 0;

    pOldSym = Symbols;
    End = pOldSym + SymbolCount;
    while (pOldSym < End)
    {
        type = *(pOldSym + 1);
        if (type & 0x80) {
            fFlat32 = TRUE;
        }
        else {
            fFlat32 = FALSE;
        }
        type &= 0x7f;

        for (pFixFcn = C6SizeSymFcn, i = 0; i < C6SIZESYMCNT; i++, pFixFcn++) {
            if (pFixFcn->oldsym == type) {
                break;      // Ok, found the entry
            }
        }

        DASSERT (i != C6SIZESYMCNT);   // Make sure type was in the table

        if  (i == C6SIZESYMCNT) {
            ErrorExit (ERR_SYMBOL, FormatMod (pCurMod), NULL);
        }

        if (fFlat32) {
            pFixFcn->pfcn32 ();    // Rewrite the symbol
        }
        else {
            pFixFcn->pfcn16 ();    // Rewrite the symbol
        }
        pOldSym += *pOldSym + 1;   // to next record
        DASSERT (!recursive);
        DASSERT (iLevel >= 0);
    }
    InitialSymInfoSize += SymbolCount;
}

////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////


#define FIXEDADD 2  // one for length, one for type

// Also used for OSYMWITH

LOCAL void C6SizeBlockSym16 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (BLOCKSYM16) - 1) - (2 + 4);
    iLevel++;
}

// Also used for OSYMWITH
LOCAL void C6SizeBlockSym32 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (BLOCKSYM32) - 1) - (2 + 6);
    iLevel++;
}


LOCAL void C6SizeEndSym (void)
{
    SymbolSizeAdd += FIXEDADD;  // New sym 4 bytes, no pad necessary
    iLevel--;
}

// Also used for OSYMCHGEXECMODEL
LOCAL void C6SizeLabSym16 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (LABELSYM16) - 1) - (2 + 3);
}

// Also used for OSYMCHGEXECMODEL

LOCAL void C6SizeLabSym32 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (LABELSYM32) - 1) - (2 + 5);
}


LOCAL void C6SizeChgDfltSegSym (void)
{
    // rewrite to start search if necessary

    if (!SegmentPresent (*(ushort *)(pOldSym + 2))) {
        SymbolSizeAdd += MAXPAD + sizeof(SEARCHSYM) - (2 + 4);
        segnum[cSeg++] = *(ushort *)(pOldSym + 2);
        if (cSeg > MAXCDF) {
            ErrorExit (ERR_TOOMANYSEG, FormatMod (pCurMod), NULL);
        }
    }
    else {
        SymbolSizeSub += (2 + 4); // The record will be removed
    }
}






LOCAL void C6SizeSkipSym (void)
{
    // The skip field will be deleted. No need to allocate space for it.
    SymbolSizeSub += *pOldSym + 1;
}


LOCAL void C6SizeBPRelSym16 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (BPRELSYM16) - 1) - (2 + 4);
}

LOCAL void C6SizeBPRelSym32 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (BPRELSYM32) - 1) - (2 + 6);
}


LOCAL void C6SizeRegSym (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (REGSYM) - 1) - (2 + 3);
}


LOCAL void C6SizeConstantSym (void)
{
    // Add one extra because the numeric leaf may grow a byte;
    SymbolSizeAdd += MAXPAD + (sizeof (CONSTSYM) - 2) - (2 + 2) + 1;
}


LOCAL void C6SizeLocalSym16 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (DATASYM16) - 1) - (2 + 6);
}

LOCAL void C6SizeLocalSym32 (void)
{
    SymbolSizeAdd += MAXPAD + (sizeof (DATASYM32) - 1) - (2 + 8);
}

LOCAL void C6SizeProcSym16 (void)
{
    iLevel++;
    SymbolSizeAdd += MAXPAD + (sizeof (PROCSYM16) - 1) - (2 + 13);
}

LOCAL void C6SizeProcSym32 (void)
{
    iLevel++;
    SymbolSizeAdd += MAXPAD + (sizeof (PROCSYM32) - 1) - (2 + 15);
}







/**
 *
 *  FixupPublicsC6
 *
 *  Fixup type indices in the publics segment similar to symbols segment.
 *  Not called through Fixup function tables.
 *
 */

void FixupPublicsC6 (uchar *Publics, ulong PublicCount)
{
    register uchar *End;
    register uchar Offset = 4;

    if (fLinearExe) {
        Offset += 2;                // another 2 bytes
    }
    End = Publics + PublicCount;
    while (Publics < End) {
        switch (ulCVTypeSignature){
            case CV_SIGNATURE_C6:
                if (delete == TRUE) {
                    *(ushort *) (Publics + Offset) = T_NOTYPE;
                }
                else {
                    *(ushort *) (Publics + Offset) =
                      C6GetCompactedIndex(*(ushort *) (Publics + Offset));
                }
                break;

            case CV_SIGNATURE_C7:
                if (delete == TRUE) {
                    *(ushort *) (Publics + Offset) = T_NOTYPE;
                }
                else {
                    *(ushort *) (Publics + Offset) =
                      C7GetCompactedIndex(*(ushort *) (Publics + Offset));
                }
                break;

            default:
                *(ushort *) (Publics + Offset) = 0;
        }
        Publics += Offset + 2;          // skip over index
        Publics += *Publics + 1;        // skip over name
        DASSERT (!recursive);
    }
}




////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

/**     RewriteSymbols - reformat symbols to new format and store in VM
 *
 *      RewriteSymbols (addr, pDir, psstMod);
 *
 *      Entry   addr = address of publics table
 *              pDir = address of directory entry
 *              psstMod = pointer to the module table entry
 *              pMod = module table entry
 *
 *      Exit    pDir->lfo = address of rewritten table
 *              pDir->Size = size of rewritten table
 *
 *      Return  none
 *
 */


void C6RewriteAndFixupSymbols (uchar *OldSym, OMFDirEntry *pDir, char *psstMod, PMOD pMod)
{
    uchar      *End;
    _vmhnd_t    NewSymbolsAddr;
    unsigned int cbNewSymbol;       // Count of bytes used by new symbols
    unsigned int cbAllocSymbol;     // Count of bytes allocate for new symbols
    SYMPTR      pSym;
    ushort      i;
    uchar      *pStartSym;

    OldSymbols = OldSym;

    if (cSeg == 0) {
        // probably asm file without Change Default Segment; pick up
        // data from module entry

        SymbolSizeAdd += sizeof (SEARCHSYM) + 3;  // 3 is maximum amount of pad to add
        segnum[cSeg++] = (ushort)((OMFModule *)psstMod)->SegInfo[0].Seg;
    }

    // Make space for the signature
    SymbolSizeAdd += sizeof (ulong);

    segment = segnum[0];
    End = OldSymbols + pDir->cb;
    cbAllocSymbol =
      (unsigned int)(pDir->cb + SymbolSizeAdd - SymbolSizeSub + UDTAdd);
    if ((NewSymbolsAddr = (_vmhnd_t)VmAlloc (cbAllocSymbol)) == _VM_NULL) {
        ErrorExit (ERR_NOVM, NULL, NULL);
    }
    if ((NewSymbols = (uchar *)VmLock (NewSymbolsAddr)) == NULL) {
        ErrorExit (ERR_NOVM, NULL, NULL);
    }
    pStartSym = NewSymbols;

    // Add CV4/C7 debug info format signature.

    *((ulong *)NewSymbols)++ = CV_SIGNATURE_C7;

    for (i = 0; i < cSeg; i++) {
        NewSymbols += AddSearchSym (NewSymbols, segnum[i]);
    }

    // Rewrite all the symbols from OldSymbols to NewSymbols
    C6RewriteSymbolStrings (End);

    // ExtraSymbols points to a linked list of symbols.
    // Each entry consists of a pointer to the next symbol followed by
    // a C7 style symbol.
    while (ExtraSymbols != NULL) {
        pSym = (SYMPTR)(ExtraSymbols + sizeof (uchar *));
        memcpy (NewSymbols, (uchar *)pSym, pSym->reclen + LNGTHSZ);
        NewSymbols += pSym->reclen + LNGTHSZ;
        End = ExtraSymbols;
        ExtraSymbols = *(uchar **)ExtraSymbols; // Get next symbol address
        free (End);                             // Free the symbol just copied
    }

    // Because we allocated more space than required, calculate true
    // symbol segment size.

    cbNewSymbol = NewSymbols - pStartSym;
    if (LinkScope (pStartSym, cbNewSymbol) == FALSE) {
        // error linking scopes, delete symbol table
        Warn (WARN_SCOPE, FormatMod (pCurMod), NULL);
        cbNewSymbol = 0;
    }

    pDir->lfo = (ulong)NewSymbolsAddr;
    pDir->cb = cbNewSymbol;

    //M00 - If a VmRealloc exists it could be used here to free the
    //M00   extra memory allocated
    VmUnlock (NewSymbolsAddr, _VM_DIRTY);
    FinalSymInfoSize += cbNewSymbol;
    pMod->SymbolSize = cbNewSymbol;
    pMod->SymbolsAddr = (ulong)NewSymbolsAddr;
}


// In TEXT2 segment rather than _TEXT
LOCAL void C6RewriteSymbolStrings (uchar * End)
{
    uchar type;
    rewritesymfcn *     pSymFcn;
    uchar       fFlat32;
    ushort      i;

    while (OldSymbols < End) {
        type = OldSymbols[1];
        if (type & 0x80) {
            fFlat32 = TRUE;
        }
        else {
            fFlat32 = FALSE;
        }
        type &= 0x7f;               // clear highest bit

        for (pSymFcn = C6RwrtSymFcn, i = 0; i < C6REWRITESYMCNT; i++, pSymFcn++) {
            if (pSymFcn->oldsym == type) {
                break;      // Ok, found the entry
            }
        }

        //Note: Fixup should have caught bad input
        DASSERT (i != C6REWRITESYMCNT); // Make sure type was in the table

        if (fFlat32) {
            if (pSymFcn->new32sym != 0) {
                ((SYMTYPE *)NewSymbols)->rectyp = pSymFcn->new32sym;
            }
            pSymFcn->pfcn32 ();    // Rewrite the symbol
        }
        else {
            if (pSymFcn->new16sym != 0) {
                ((SYMTYPE *)NewSymbols)->rectyp = pSymFcn->new16sym;
            }
            pSymFcn->pfcn16 ();    // Rewrite the symbol
        }
    }
}







/**     C6CnvtSymbol - reformat a C6 symbol into the buffer passed.
 *
 *      This routine is called only to rewrite a based pointer symbol
 *      into a type record.  The conversion routines do not convert
 *      the type indices.
 *
 *      C6CnvtSymbol (pC7Sym, pC6Sym);
 *
 *      Entry   pC7Sym = A buffer to store the new C7 Symbol in.
 *              pC6Sym = C6 format symbol to be converted.
 *
 *      Exit    OldSymbols - modified, WARNING this will interfere with
 *                           RewriteSymbolsC6 if this routine is called
 *                           a symbols rewrite.
 *              NewSymbols - modified, WARNING this will interfere with
 *                           RewriteSymbolsC6 if this routine is called
 *                           a symbols rewrite.
 *
 *      Return  Size of the new C7 symbol.
 *
 */

ushort C6CnvtSymbol (uchar *pC7Sym, uchar *pC6Sym)
{
    ushort          i;
    uchar           type;
    uchar           fFlat32;
    cnvrtsymfcn    *pSymFcn;

    type = pC6Sym[1];
    if (type & 0x80) {
        fFlat32 = TRUE;
    }
    else {
        fFlat32 = FALSE;
    }
    type &= 0x7f;               // clear highest bit


    for (pSymFcn = C6CnvrtSymFcn, i = 0; i < C6CNVRTSYMCNT; i++, pSymFcn++) {
        if (pSymFcn->oldsym == type) {
            break;      // Ok, found the entry
        }
    }
    DASSERT (i != C6CNVRTSYMCNT); // Make sure type was in the table

    if (fFlat32) {
        return (pSymFcn->pfcn32 (pC7Sym, pC6Sym));
    }
    else {
        return (pSymFcn->pfcn16 (pC7Sym, pC6Sym));
    }
}



LOCAL ushort C6CnvrtRegSym (uchar *NewSym, uchar *OldSym)
{
    ushort      length;
    REGPTR      pSym = (REGPTR)NewSym;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name (including length prefix)
    length = (ushort)OldSym[0] - 1 - 3;

    // calculate new length
    usNTotal = sizeof (REGSYM) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pSym->rectyp = S_REGISTER;
    iPad = PAD4 (usNTotal);

    // Copy data from old symbol

    OldSym += 2;
    pSym->typind = *((ushort *)OldSym)++;
    pSym->reg = *((uchar *) OldSym)++;

    // Copy the name

    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSym++;
    }
    PADLOOP (iPad, pName);
    DASSERT (pName == NewSym + pSym->reclen + LNGTHSZ);
    return ((ushort)(pName - NewSym));
}




LOCAL ushort C6CnvrtBPRelSym16 (uchar *NewSym, uchar *OldSym)
{
    BPRELPTR16      pSym = (BPRELPTR16)NewSym;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;

    length = OldSym[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pSym->rectyp = S_BPREL16;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes

    OldSym += 2;
    NewSym += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    for  (; length > 0; length --) {
        *NewSym++ = *OldSym++;
    }
    PADLOOP (pad, NewSym);
    DASSERT (NewSym == (uchar *)pSym + pSym->reclen + LNGTHSZ);
    return (NewSym - (uchar *)pSym);
}




LOCAL ushort C6CnvrtBPRelSym32 (uchar *NewSym, uchar *OldSym)
{
    BPRELPTR32      pSym = (BPRELPTR32)NewSym;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;

    length = OldSym[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pSym->rectyp = S_BPREL32;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes

    OldSym += 2;
    NewSym += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    for  (; length > 0; length --) {
        *NewSym++ = *OldSym++;
    }
    PADLOOP (pad, NewSym);
    DASSERT (NewSym == (uchar *)pSym + pSym->reclen + LNGTHSZ);
    return (NewSym - (uchar *)pSym);
}



LOCAL ushort C6CnvrtDataSym16 (uchar *NewSym, uchar *OldSym)
{
    DATAPTR16       pSym = (DATAPTR16)NewSym;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;

    length = OldSym[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pSym->rectyp = S_LDATA16;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes

    OldSym += 2;
    NewSym += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    for  (; length > 0; length --) {
        *NewSym++ = *OldSym++;
    }
    PADLOOP (pad, NewSym);
    DASSERT (NewSym == (uchar *)pSym + pSym->reclen + LNGTHSZ);
    return (NewSym - (uchar *)pSym);
}




LOCAL ushort C6CnvrtDataSym32 (uchar *NewSym, uchar *OldSym)
{
    DATAPTR32       pSym = (DATAPTR32)NewSym;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;

    length = OldSym[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pSym->rectyp = S_LDATA32;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes

    OldSym += 2;
    NewSym += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    for  (; length > 0; length --) {
        *NewSym++ = *OldSym++;
    }
    PADLOOP (pad, NewSym);
    DASSERT (NewSym == (uchar *)pSym + pSym->reclen + LNGTHSZ);
    return (NewSym - (uchar *)pSym);
}





LOCAL void C6RwrtRegSym (void)
{
    ushort  length;
    REGPTR  pSym = (REGPTR)NewSymbols;
    uchar  *pName;
    ushort  usNTotal;          // New length of symbol including length field
    int     iPad;
    ushort  reg;

    // get length of name (including length prefix)
    length = OldSymbols[0] - 1 - 3;

    // calculate new length
    usNTotal = sizeof (REGSYM) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);


    // Copy data from old symbol
    OldSymbols += 2;
    pSym->typind = *((ushort *) OldSymbols)++;
    if ((reg = *((uchar *) OldSymbols)++) <= CV_REG_FLAGS) {
        reg = RegMap[reg];
    }
    pSym->reg = reg;

    // Copy the name
    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
    NewSymbols = pName;
}




LOCAL void C6RwrtConstantSym    (void)
{
    ushort      length;
    CONSTPTR    pSym = (CONSTPTR)NewSymbols;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    ushort      usOldSymSize;
    int         iPad;

    // get length of all variable length data
    length = OldSymbols[0] - 1 - 2;

    // calculate new length
    usNTotal = sizeof (CONSTSYM) - 2 + length + SizeChgNumeric (OldSymbols + 4);
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->typind =      *((ushort *) OldSymbols)++;
    pName = (uchar *)&(pSym->value);

    // Copies the Numeric field and advances the pointers
    ConvertNumeric (&OldSymbols, &pName, &usOldSymSize);

    // Copy the name
    for  (length -= usOldSymSize; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
    NewSymbols = pName;
}









LOCAL void C6RwrtBlockSym16 (void)
{
    BLOCKPTR16  pSym = (BLOCKPTR16)NewSymbols;
    uchar      *pName;
    ushort      length;
    int         fNamePresent = TRUE;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name (including length of the length prefix)
    length = OldSymbols[0] - 1 - 4;
    if (!length) {
        // Niether name nor prefix present, prepare to add a 0 length prefix.
        fNamePresent = FALSE;
        length = 1;
    }

    // calculate new length
    usNTotal = sizeof (BLOCKSYM16) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);

    // Set fixed fields of new symbol
    pSym->pParent = 0L;
    pSym->pEnd = 0L;
    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off = *((ushort *) OldSymbols)++;
    pSym->len = *((ushort *) OldSymbols)++;

    // Copy the optional block name
    pName = pSym->name;
    if (fNamePresent) {
        for  (; length > 0; length --) {
            *pName++ = *OldSymbols++;
        }
    }
    else {
        *pName++ = 0;   // Create a length prefixed name
    }

    PADLOOP (iPad, pName);

    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    NewSymbols = pName;

}




LOCAL void C6RwrtBlockSym32 (void)
{
    ushort      length;
    BLOCKPTR32  pSym = (BLOCKPTR32)NewSymbols;
    uchar      *pName;
    int         fNamePresent = TRUE;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name
    length = OldSymbols[0] - 1 - 6;
    if (!length) {
        // Niether name nor prefix present, prepare to add a 0 length prefix.
        fNamePresent = FALSE;
        length = 1;
    }

    // calculate new length
    usNTotal = sizeof (BLOCKSYM32) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);


    // Set fixed fields of new symbol
    pSym->pParent = 0L;
    pSym->pEnd = 0L;
    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off = *((ulong *) OldSymbols)++;
    pSym->len = *((ushort *) OldSymbols)++;

    // Copy the optional block name
    pName = pSym->name;
    if (fNamePresent) {
        for  (; length > 0; length --) {
            *pName++ = *OldSymbols++;
        }
    }
    else {
        *pName++ = 0;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    NewSymbols = pName;
}



LOCAL void C6RwrtLabSym16 (void)
{
    ushort      length;
    LABELPTR16  pSym = (LABELPTR16)NewSymbols;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name (including length prefix)
    length = OldSymbols[0] - 1 - 3;

    // calculate new length
    usNTotal = sizeof (LABELSYM16) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);


    // Set fixed fields of new symbol
    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off = *((ushort *) OldSymbols)++;
    pSym->rtntyp = *((uchar *) OldSymbols)++;

    // Copy the name
    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    NewSymbols = pName;
}


LOCAL void C6RwrtLabSym32 (void)
{
    ushort      length;
    LABELPTR32  pSym = (LABELPTR32)NewSymbols;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;


    // get length of name
    length = OldSymbols[0] - 1 - 5;

    // calculate new length
    usNTotal = sizeof (LABELSYM32) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);

    // Set fixed fields of new symbol
    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off = *((ulong *) OldSymbols)++;
    pSym->rtntyp = *((uchar *) OldSymbols)++;

    // Copy the name
    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    NewSymbols = pName;
}


LOCAL void C6RwrtChgDfltSeg (void)
{
    segment = * (ushort *) (OldSymbols + 2);     // Record new segment
    OldSymbols += OldSymbols[0] + 1;             // Advance to next symbol
}



LOCAL void C6RwrtProcSym16  (void)
{
    ushort      length;
    PROCPTR16   pSym = (PROCPTR16)NewSymbols;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name (including length prefix)
    length = OldSymbols[0] - 1 - 13;

    // calculate new length
    usNTotal = sizeof (PROCSYM16) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);


    // Set fixed fields of new symbol
    pSym->pParent = 0L;
    pSym->pEnd = 0L;
    pSym->pNext = 0L;

    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off =         *((ushort *) OldSymbols)++;
    pSym->typind =      *((ushort *) OldSymbols)++;
    pSym->len =         *((ushort *) OldSymbols)++;
    pSym->DbgStart =    *((ushort *) OldSymbols)++;
    pSym->DbgEnd =      *((ushort *) OldSymbols)++;
    // skip reserved
    OldSymbols += 2;
    pSym->rtntyp = *((uchar *) OldSymbols)++;

    // Copy the name
    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
    NewSymbols = pName;
}


LOCAL void C6RwrtProcSym32  (void)
{
    ushort      length;
    PROCPTR32   pSym = (PROCPTR32)NewSymbols;
    uchar      *pName;
    ushort      usNTotal;          // New length of symbol including length field
    int         iPad;

    // get length of name (including length prefix)
    length = OldSymbols[0] - 1 - 15;

    // calculate new length
    usNTotal = sizeof (PROCSYM32) - 1 + length;
    pSym->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    iPad = PAD4 (usNTotal);

    // Set fixed fields of new symbol
    pSym->pParent = 0L;
    pSym->pEnd = 0L;
    pSym->pNext = 0L;

    pSym->seg = segment;

    // Copy data from old symbol
    OldSymbols += 2;
    pSym->off =         *((ulong  *) OldSymbols)++;
    pSym->typind =      *((ushort *) OldSymbols)++;
    pSym->len =         *((ushort *) OldSymbols)++;
    pSym->DbgStart =    *((ushort *) OldSymbols)++;
    pSym->DbgEnd =      *((ushort *) OldSymbols)++;
    // skip reserved
    OldSymbols += 2;
    pSym->rtntyp = *((uchar *) OldSymbols)++;

    // Copy the name
    for  (pName = pSym->name; length > 0; length --) {
        *pName++ = *OldSymbols++;
    }

    PADLOOP (iPad, pName);
    DASSERT (pName == NewSymbols + pSym->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
    NewSymbols = pName;
}



// Skip fields are removed
LOCAL void C6RwrtSkipSym (void)
{
    // delete skip record
    OldSymbols += OldSymbols[0] + 1;
}


LOCAL void C6RwrtGenericSym (void)
{
    ushort      usNTotal;            // New length of symbol including length field
    ushort      length;
    int         pad;
    uchar      *pStartNew;


    pStartNew = NewSymbols;
    length = OldSymbols[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    ((SYMTYPE *)NewSymbols)->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes
    OldSymbols += 2;
    NewSymbols += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    //M00SPEED - This may be faster using a memcpy
    for  (; length > 0; length --) {
        *NewSymbols++ = *OldSymbols++;
    }

    PADLOOP (pad, NewSymbols);
    DASSERT (NewSymbols == pStartNew + ((SYMTYPE *)pStartNew)->reclen + LNGTHSZ);
}



LOCAL void C6RwrtBPRelSym16 (void)
{
    BPRELPTR16      pSym = (BPRELPTR16)NewSymbols;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;
    uchar          *pStartNew;


    pStartNew = NewSymbols;
    length = OldSymbols[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    ((SYMTYPE *)NewSymbols)->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes
    OldSymbols += 2;
    NewSymbols += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    //M00SPEED - This may be faster using a memcpy
    for  (; length > 0; length --) {
        *NewSymbols++ = *OldSymbols++;
    }

    PADLOOP (pad, NewSymbols);
    DASSERT (NewSymbols == pStartNew + ((SYMTYPE *)pStartNew)->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
}




LOCAL void C6RwrtBPRelSym32 (void)
{
    BPRELPTR32      pSym = (BPRELPTR32)NewSymbols;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;
    uchar          *pStartNew;


    pStartNew = NewSymbols;
    length = OldSymbols[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    ((SYMTYPE *)NewSymbols)->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes
    OldSymbols += 2;
    NewSymbols += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    //M00SPEED - This may be faster using a memcpy
    for  (; length > 0; length --) {
        *NewSymbols++ = *OldSymbols++;
    }

    PADLOOP (pad, NewSymbols);
    DASSERT (NewSymbols == pStartNew + ((SYMTYPE *)pStartNew)->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
}



LOCAL void C6RwrtDataSym16 (void)
{
    DATAPTR16       pSym = (DATAPTR16)NewSymbols;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;
    uchar          *pStartNew;


    pStartNew = NewSymbols;
    length = OldSymbols[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    ((SYMTYPE *)NewSymbols)->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes
    OldSymbols += 2;
    NewSymbols += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    //M00SPEED - This may be faster using a memcpy
    for  (; length > 0; length --) {
        *NewSymbols++ = *OldSymbols++;
    }

    PADLOOP (pad, NewSymbols);
    DASSERT (NewSymbols == pStartNew + ((SYMTYPE *)pStartNew)->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
}




LOCAL void C6RwrtDataSym32 (void)
{
    DATAPTR32       pSym = (DATAPTR32)NewSymbols;
    ushort          usNTotal;            // New length of symbol including length field
    ushort          length;
    int             pad;
    uchar          *pStartNew;


    pStartNew = NewSymbols;
    length = OldSymbols[0];
    usNTotal = length + 1 + 2;  // 1 = size of old len field, 2 = larger size of len and leaf

    ((SYMTYPE *)NewSymbols)->reclen = ALIGN4 (usNTotal) - LNGTHSZ;
    pad = PAD4 (usNTotal);

    // Move past length and type bytes
    OldSymbols += 2;
    NewSymbols += sizeof (SYMTYPE);
    length--;       // Don't copy old type field

    //M00SPEED - This may be faster using a memcpy
    for  (; length > 0; length --) {
        *NewSymbols++ = *OldSymbols++;
    }

    PADLOOP (pad, NewSymbols);
    DASSERT (NewSymbols == pStartNew + ((SYMTYPE *)pStartNew)->reclen + LNGTHSZ);
    pSym->typind = C6GetCompactedIndex (pSym->typind);
}




/**     RewritePublics - reformat publics to new format and store in VM
 *
 *      RewritePublics (addr, pDir, pMod);
 *
 *      Entry   addr = address of publics table
 *              pDir = address of directory entry
 *              pMod = module table entry
 *
 *      Exit    pDir->lfo = address of rewritten table
 *              pDir->Size = size of rewritten table
 *
 *      Return  none
 *
 *      Note    Not called through Symbol Rewrite funtion table.
 */


void RewritePublicsC6 (uchar *OldPublics, OMFDirEntry *pDir)
{
    uchar       *NewPublics;
    uchar       *End;
    uchar       Offset = 4;
    uchar       length;
    ushort      usNTotal;       // New length of symbol including length field
    int         iPad;
    uchar       buf[512];


    if ((pDir->cb) == 0) {
        // if publics directory entry but no data
        return;
    }
    if (fLinearExe) {
        Offset += 2;
    }
    End = OldPublics + pDir->cb;
    while (OldPublics < End) {
        NewPublics = buf;
        // add in offset, type, name length, name length prefix
        length = (uchar)(Offset + 2 + OldPublics[Offset + 2] + 1);

        // calculate new length; length size, record type size, length of data
        usNTotal = LNGTHSZ + RECTYPSZ + length;
        *((ushort *)NewPublics)++ = ALIGN4 (usNTotal) - LNGTHSZ;
        iPad = PAD4 (usNTotal);

        if (fLinearExe) {
            *((ushort *)NewPublics)++ = S_PUB32;
        }
        else{
            *((ushort *)NewPublics)++ = S_PUB16;
        }
        for (; length > 0; length--) {
            *NewPublics++ = *OldPublics++;
        }
        *NewPublics = 0;
        PADLOOP (iPad, NewPublics);
#ifdef NB09
        PackPublic ((SYMPTR)buf, DWordXorLrl);
#else
        PackPublic ((SYMPTR)buf, SumUCChar);
#endif
    }
}






LOCAL uchar *RemoveComDat (uchar *Symbols)
{
    int level = 1;

    SymbolSizeSub += Symbols[0] + 1;
    Symbols[1] = OSYMRESERVED;
    Symbols += Symbols[0] + 1;

    while (level) {
        switch (Symbols[1] & 0x7f) {
        case OSYMWITH:
        case OSYMBLOCKSTART:
        case OSYMTHUNK:
        case OSYMCV4BLOCK:
        case OSYMCV4WITH:
        case OSYMPROCSTART:
        case OSYMLOCALPROC:
            level++;
            break;
        case OSYMEND:
            level--;
            break;
        default:
            break;
        }

        SymbolSizeSub += Symbols[0] + 1;
        Symbols[1] = OSYMRESERVED;
        Symbols += Symbols[0] + 1;
    }
    return (Symbols);
}



/**
 *
 *  SizeChgNumeric
 *
 *  Calculates the difference in size between an old style numeric leaf and
 *  a new (C7) style numeric leaf. Below is is the table of the old vs new size.
 *      Type            Range           Old         New         Change
 *      unsigned        0-127           1           2           1
 *      unsigned        127-0x7fff      3           2           -1
 *      unsigned        0x8000-0xffff   3           4           1
 *      unsigned long                   5           6           1
 *      signed short                    3           4           1
 *      signed long                     5           6           1
 *
 *  Input:  pOld - Pointer to the old Numeric Leaf
 *  Output: Return value is how many more bytes the new format will occupy
 *          than the old format. May be a negative number.
 */

short SizeChgNumeric (uchar *pOld)
{
    if (*pOld == 133 && *((ushort *)(pOld + 1)) < LF_NUMERIC){
        // An unsigned short that will fit in the leaf indicy
        return(2-3);    // old takes 24bits, new takes 16bits
    }
    if (*pOld > 138){
        ErrorExit (ERR_INVALIDMOD, FormatMod (pCurMod), NULL);
    }
    return (1);
}