/*
 * $Id$
 */

/*
 * Harbour Project source code:
 * Compiler PCode generation functions
 *
 * Copyright 1999 {list of individual authors and e-mail addresses}
 * www - http://www.harbour-project.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version, with one exception:
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
 * their web site at http://www.gnu.org/).
 *
 */

/*
 * The following parts are Copyright of the individual authors.
 * www - http://www.harbour-project.org
 *
 * Copyright 2000 RonPinkas <Ron@Profit-Master.com>
 *    hb_compStrongType()
 *
 * See doc/license.txt for licensing terms.
 *
 */

#include "hbcomp.h"
#include "hbassert.h"

#define HB_PSIZE_FUNC( func ) HB_PCODE_FUNC( func, HB_VOID_PTR )

/*
 * functions for variable size PCODE tracing
 */
static HB_PSIZE_FUNC( hb_p_pushstrshort )
{
   HB_SYMBOL_UNUSED( cargo );
   return 2 + pFunc->pCode[ lPCodePos + 1 ];
}

static HB_PSIZE_FUNC( hb_p_pushstr )
{
   HB_SYMBOL_UNUSED( cargo );
   return 3 + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] );
}

static HB_PSIZE_FUNC( hb_p_pushstrlarge )
{
   HB_SYMBOL_UNUSED( cargo );
   return 4 + HB_PCODE_MKUINT24( &pFunc->pCode[ lPCodePos + 1 ] );
}

static HB_PSIZE_FUNC( hb_p_pushstrhidden )
{
   HB_SYMBOL_UNUSED( cargo );
   return 4 + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 2 ] );
}

static HB_PSIZE_FUNC( hb_p_pushblock )
{
   HB_SYMBOL_UNUSED( cargo );
   return HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] );
}

static HB_PSIZE_FUNC( hb_p_pushblockshort )
{
   HB_SYMBOL_UNUSED( cargo );
   return pFunc->pCode[ lPCodePos + 1 ];
}

static HB_PSIZE_FUNC( hb_p_pushblocklarge )
{
   HB_SYMBOL_UNUSED( cargo );
   return HB_PCODE_MKUINT24( &pFunc->pCode[ lPCodePos + 1 ] );
}

static HB_PSIZE_FUNC( hb_p_localname )
{
   ULONG ulStart = lPCodePos;

   HB_SYMBOL_UNUSED( cargo );
   lPCodePos += 3;
   while( pFunc->pCode[ lPCodePos++ ] );

   return ( lPCodePos - ulStart );
}

static HB_PSIZE_FUNC( hb_p_modulename )
{
   ULONG ulStart = lPCodePos;

   HB_SYMBOL_UNUSED( cargo );
   lPCodePos += 3;
   while( pFunc->pCode[ lPCodePos++ ]);

   return ( lPCodePos - ulStart );
}

static HB_PSIZE_FUNC( hb_p_staticname )
{
   ULONG ulStart = lPCodePos;

   HB_SYMBOL_UNUSED( cargo );
   lPCodePos += 4;
   while( pFunc->pCode[ lPCodePos++ ] );

   return ( lPCodePos - ulStart );
}

const BYTE hb_comp_pcode_len[] = {
   1,        /* HB_P_AND,                  */
   1,        /* HB_P_ARRAYPUSH,            */
   1,        /* HB_P_ARRAYPOP,             */
   3,        /* HB_P_ARRAYDIM,             */
   3,        /* HB_P_ARRAYGEN,             */
   1,        /* HB_P_EQUAL,                */
   1,        /* HB_P_ENDBLOCK,             */
   1,        /* HB_P_ENDPROC,              */
   1,        /* HB_P_EXACTLYEQUAL,         */
   1,        /* HB_P_FALSE,                */
   1,        /* HB_P_FORTEST,              */
   3,        /* HB_P_FUNCTION,             */
   2,        /* HB_P_FUNCTIONSHORT,        */
   3,        /* HB_P_FRAME,                */
   1,        /* HB_P_FUNCPTR,              */
   1,        /* HB_P_GREATER,              */
   1,        /* HB_P_GREATEREQUAL,         */
   1,        /* HB_P_DEC,                  */
   1,        /* HB_P_DIVIDE,               */
   3,        /* HB_P_DO,                   */
   2,        /* HB_P_DOSHORT,              */
   1,        /* HB_P_DUPLICATE,            */
   1,        /* HB_P_DUPLTWO,              */
   1,        /* HB_P_INC,                  */
   1,        /* HB_P_INSTRING,             */
   2,        /* HB_P_JUMPNEAR,             */
   3,        /* HB_P_JUMP,                 */
   4,        /* HB_P_JUMPFAR,              */
   2,        /* HB_P_JUMPFALSENEAR,        */
   3,        /* HB_P_JUMPFALSE,            */
   4,        /* HB_P_JUMPFALSEFAR,         */
   2,        /* HB_P_JUMPTRUENEAR,         */
   3,        /* HB_P_JUMPTRUE,             */
   4,        /* HB_P_JUMPTRUEFAR,          */
   1,        /* HB_P_LESSEQUAL,            */
   1,        /* HB_P_LESS,                 */
   3,        /* HB_P_LINE,                 */
   0,        /* HB_P_LOCALNAME,            */
   2,        /* HB_P_MACROPOP,             */
   2,        /* HB_P_MACROPOPALIASED,      */
   2,        /* HB_P_MACROPUSH,            */
   3,        /* HB_P_MACROARRAYGEN,        */
   2,        /* HB_P_MACROPUSHLIST,        */
   1,        /* HB_P_MACROPUSHINDEX,       */
   2,        /* HB_P_MACROPUSHPARE,        */
   2,        /* HB_P_MACROPUSHALIASED,     */
   1,        /* HB_P_MACROSYMBOL,          */
   1,        /* HB_P_MACROTEXT,            */
   3,        /* HB_P_MESSAGE,              */
   1,        /* HB_P_MINUS,                */
   1,        /* HB_P_MODULUS,              */
   0,        /* HB_P_MODULENAME,           */
             /* start: pcodes generated by macro compiler */
   3,        /* HB_P_MMESSAGE,             */
   3,        /* HB_P_MPOPALIASEDFIELD,     */
   3,        /* HB_P_MPOPALIASEDVAR,       */
   3,        /* HB_P_MPOPFIELD,            */
   3,        /* HB_P_MPOPMEMVAR,           */
   3,        /* HB_P_MPUSHALIASEDFIELD,    */
   3,        /* HB_P_MPUSHALIASEDVAR,      */
   0,        /* HB_P_MPUSHBLOCK,           */
   3,        /* HB_P_MPUSHFIELD,           */
   3,        /* HB_P_MPUSHMEMVAR,          */
   3,        /* HB_P_MPUSHMEMVARREF,       */
   3,        /* HB_P_MPUSHSYM,             */
   3,        /* HB_P_MPUSHVARIABLE,        */
             /* end: */
   1,        /* HB_P_MULT,                 */
   1,        /* HB_P_NEGATE,               */
   1,        /* HB_P_NOOP,                 */
   1,        /* HB_P_NOT,                  */
   1,        /* HB_P_NOTEQUAL,             */
   1,        /* HB_P_OR,                   */
   4,        /* HB_P_PARAMETER,            */
   1,        /* HB_P_PLUS,                 */
   1,        /* HB_P_POP,                  */
   1,        /* HB_P_POPALIAS,             */
   3,        /* HB_P_POPALIASEDFIELD,      */
   2,        /* HB_P_POPALIASEDFIELDNEAR,  */
   3,        /* HB_P_POPALIASEDVAR,        */
   3,        /* HB_P_POPFIELD,             */
   3,        /* HB_P_POPLOCAL,             */
   2,        /* HB_P_POPLOCALNEAR,         */
   3,        /* HB_P_POPMEMVAR,            */
   3,        /* HB_P_POPSTATIC,            */
   3,        /* HB_P_POPVARIABLE,          */
   1,        /* HB_P_POWER,                */
   1,        /* HB_P_PUSHALIAS,            */
   3,        /* HB_P_PUSHALIASEDFIELD,     */
   2,        /* HB_P_PUSHALIASEDFIELDNEAR, */
   3,        /* HB_P_PUSHALIASEDVAR,       */
   0,        /* HB_P_PUSHBLOCK,            */
   0,        /* HB_P_PUSHBLOCKSHORT,       */
   3,        /* HB_P_PUSHFIELD,            */
   2,        /* HB_P_PUSHBYTE,             */
   3,        /* HB_P_PUSHINT,              */
   3,        /* HB_P_PUSHLOCAL,            */
   2,        /* HB_P_PUSHLOCALNEAR,        */
   3,        /* HB_P_PUSHLOCALREF,         */
   5,        /* HB_P_PUSHLONG,             */
   3,        /* HB_P_PUSHMEMVAR,           */
   3,        /* HB_P_PUSHMEMVARREF,        */
   1,        /* HB_P_PUSHNIL,              */
   1 + sizeof( double ) + sizeof( BYTE ) + sizeof( BYTE ),        /* HB_P_PUSHDOUBLE,           */
   1,        /* HB_P_PUSHSELF,             */
   3,        /* HB_P_PUSHSTATIC,           */
   3,        /* HB_P_PUSHSTATICREF,        */
   0,        /* HB_P_PUSHSTR,              */
   0,        /* HB_P_PUSHSTRSHORT,         */
   3,        /* HB_P_PUSHSYM,              */
   2,        /* HB_P_PUSHSYMNEAR,          */
   3,        /* HB_P_PUSHVARIABLE,         */
   1,        /* HB_P_RETVALUE,             */
   3,        /* HB_P_SEND,                 */
   2,        /* HB_P_SENDSHORT,            */
   4,        /* HB_P_SEQBEGIN,             */
   4,        /* HB_P_SEQEND,               */
   1,        /* HB_P_SEQRECOVER,           */
   3,        /* HB_P_SFRAME,               */
   5,        /* HB_P_STATICS,              */
   0,        /* HB_P_STATICNAME,           */
   1,        /* HB_P_SWAPALIAS,            */
   1,        /* HB_P_TRUE,                 */
   1,        /* HB_P_ZERO,                 */
   1,        /* HB_P_ONE,                  */
   3,        /* HB_P_MACROFUNC,            */
   3,        /* HB_P_MACRODO,              */
   0,        /* HB_P_MPUSHSTR              */
   4,        /* HB_P_LOCALNEARADDINT,      */
   1,        /* HB_P_MACROPUSHREF          */
   9,        /* HB_P_PUSHLONGLONG          */
   3,        /* HB_P_ENUMSTART             */
   1,        /* HB_P_ENUMNEXT              */
   1,        /* HB_P_ENUMPREV              */
   1,        /* HB_P_ENUMEND               */
   3,        /* HB_P_SWITCH                */
   5,        /* HB_P_PUSHDATE,             */
             /* optimalization of inlined math operations */
   1,        /* HB_P_PLUSEQPOP,            */
   1,        /* HB_P_MINUSEQPOP,           */
   1,        /* HB_P_MULTEQPOP,            */
   1,        /* HB_P_DIVEQPOP,             */
   1,        /* HB_P_PLUSEQ,               */
   1,        /* HB_P_MINUSEQ,              */
   1,        /* HB_P_MULTEQ,               */
   1,        /* HB_P_DIVEQ,                */
   1,        /* HB_P_WITHOBJECTSTART,      */
   3,        /* HB_P_WITHOBJECTMESSAGE,    */
   1,        /* HB_P_WITHOBJECTEND,        */
   3,        /* HB_P_MACROSEND,            */
   1,        /* HB_P_PUSHOVARREF,          */
   1,        /* HB_P_ARRAYPUSHREF          */
   3,        /* HB_P_VFRAME                */
   4,        /* HB_P_LARGEFRAME            */
   4,        /* HB_P_LARGEVFRAME           */
   0,        /* HB_P_PUSHSTRHIDDEN         */
   5,        /* HB_P_LOCALADDINT           */
   1,        /* HB_P_MODEQPOP              */
   1,        /* HB_P_EXPEQPOP              */
   1,        /* HB_P_MODEQ                 */
   1,        /* HB_P_EXPEQ                 */
   1,        /* HB_P_DUPLUNREF             */
   0,        /* HB_P_MPUSHBLOCKLARGE,      */
   0,        /* HB_P_MPUSHSTRLARGE         */
   0,        /* HB_P_PUSHBLOCKLAREG,       */
   0,        /* HB_P_PUSHSTRLARGE          */
   2,        /* HB_P_SWAP                  */
   1,        /* HB_P_PUSHVPARAMS           */
   1,        /* HB_P_PUSHUNREF             */
   4,        /* HB_P_SEQALWAYS             */
   4,        /* HB_P_ALWAYSBEGIN           */
   1,        /* HB_P_ALWAYSEND             */
   1,        /* HB_P_DECEQPOP              */
   1,        /* HB_P_INCEQPOP              */
   1,        /* HB_P_DECEQ                 */
   1,        /* HB_P_INCEQ                 */
   3,        /* HB_P_LOCALDEC              */
   3,        /* HB_P_LOCALINC              */
   3,        /* HB_P_LOCALINCPUSH          */
   3,        /* HB_P_PUSHFUNCSYM           */
   3,        /* HB_P_HASHGEN               */
   1         /* HB_P_SEQBLOCK              */
};

/*
 * this table has pointers to functions which count
 * real size of variable size PCODEs
 */
static HB_PCODE_FUNC_PTR s_psize_table[] =
{
   NULL,                       /* HB_P_AND,                  */
   NULL,                       /* HB_P_ARRAYPUSH,            */
   NULL,                       /* HB_P_ARRAYPOP,             */
   NULL,                       /* HB_P_ARRAYDIM,             */
   NULL,                       /* HB_P_ARRAYGEN,             */
   NULL,                       /* HB_P_EQUAL,                */
   NULL,                       /* HB_P_ENDBLOCK,             */
   NULL,                       /* HB_P_ENDPROC,              */
   NULL,                       /* HB_P_EXACTLYEQUAL,         */
   NULL,                       /* HB_P_FALSE,                */
   NULL,                       /* HB_P_FORTEST,              */
   NULL,                       /* HB_P_FUNCTION,             */
   NULL,                       /* HB_P_FUNCTIONSHORT,        */
   NULL,                       /* HB_P_FRAME,                */
   NULL,                       /* HB_P_FUNCPTR,              */
   NULL,                       /* HB_P_GREATER,              */
   NULL,                       /* HB_P_GREATEREQUAL,         */
   NULL,                       /* HB_P_DEC,                  */
   NULL,                       /* HB_P_DIVIDE,               */
   NULL,                       /* HB_P_DO,                   */
   NULL,                       /* HB_P_DOSHORT,              */
   NULL,                       /* HB_P_DUPLICATE,            */
   NULL,                       /* HB_P_DUPLTWO,              */
   NULL,                       /* HB_P_INC,                  */
   NULL,                       /* HB_P_INSTRING,             */
   NULL,                       /* HB_P_JUMPNEAR,             */
   NULL,                       /* HB_P_JUMP,                 */
   NULL,                       /* HB_P_JUMPFAR,              */
   NULL,                       /* HB_P_JUMPFALSENEAR,        */
   NULL,                       /* HB_P_JUMPFALSE,            */
   NULL,                       /* HB_P_JUMPFALSEFAR,         */
   NULL,                       /* HB_P_JUMPTRUENEAR,         */
   NULL,                       /* HB_P_JUMPTRUE,             */
   NULL,                       /* HB_P_JUMPTRUEFAR,          */
   NULL,                       /* HB_P_LESSEQUAL,            */
   NULL,                       /* HB_P_LESS,                 */
   NULL,                       /* HB_P_LINE,                 */
   hb_p_localname,             /* HB_P_LOCALNAME,            */
   NULL,                       /* HB_P_MACROPOP,             */
   NULL,                       /* HB_P_MACROPOPALIASED,      */
   NULL,                       /* HB_P_MACROPUSH,            */
   NULL,                       /* HB_P_MACROARRAYGEN,        */
   NULL,                       /* HB_P_MACROPUSHLIST,        */
   NULL,                       /* HB_P_MACROPUSHINDEX,       */
   NULL,                       /* HB_P_MACROPUSHPARE,        */
   NULL,                       /* HB_P_MACROPUSHALIASED,     */
   NULL,                       /* HB_P_MACROSYMBOL,          */
   NULL,                       /* HB_P_MACROTEXT,            */
   NULL,                       /* HB_P_MESSAGE,              */
   NULL,                       /* HB_P_MINUS,                */
   NULL,                       /* HB_P_MODULUS,              */
   hb_p_modulename,            /* HB_P_MODULENAME,           */
                               /* start: pcodes generated by macro compiler */
   NULL,                       /* HB_P_MMESSAGE,             */
   NULL,                       /* HB_P_MPOPALIASEDFIELD,     */
   NULL,                       /* HB_P_MPOPALIASEDVAR,       */
   NULL,                       /* HB_P_MPOPFIELD,            */
   NULL,                       /* HB_P_MPOPMEMVAR,           */
   NULL,                       /* HB_P_MPUSHALIASEDFIELD,    */
   NULL,                       /* HB_P_MPUSHALIASEDVAR,      */
   NULL,                       /* HB_P_MPUSHBLOCK,           */
   NULL,                       /* HB_P_MPUSHFIELD,           */
   NULL,                       /* HB_P_MPUSHMEMVAR,          */
   NULL,                       /* HB_P_MPUSHMEMVARREF,       */
   NULL,                       /* HB_P_MPUSHSYM,             */
   NULL,                       /* HB_P_MPUSHVARIABLE,        */
                               /* end: */
   NULL,                       /* HB_P_MULT,                 */
   NULL,                       /* HB_P_NEGATE,               */
   NULL,                       /* HB_P_NOOP,                 */
   NULL,                       /* HB_P_NOT,                  */
   NULL,                       /* HB_P_NOTEQUAL,             */
   NULL,                       /* HB_P_OR,                   */
   NULL,                       /* HB_P_PARAMETER,            */
   NULL,                       /* HB_P_PLUS,                 */
   NULL,                       /* HB_P_POP,                  */
   NULL,                       /* HB_P_POPALIAS,             */
   NULL,                       /* HB_P_POPALIASEDFIELD,      */
   NULL,                       /* HB_P_POPALIASEDFIELDNEAR,  */
   NULL,                       /* HB_P_POPALIASEDVAR,        */
   NULL,                       /* HB_P_POPFIELD,             */
   NULL,                       /* HB_P_POPLOCAL,             */
   NULL,                       /* HB_P_POPLOCALNEAR,         */
   NULL,                       /* HB_P_POPMEMVAR,            */
   NULL,                       /* HB_P_POPSTATIC,            */
   NULL,                       /* HB_P_POPVARIABLE,          */
   NULL,                       /* HB_P_POWER,                */
   NULL,                       /* HB_P_PUSHALIAS,            */
   NULL,                       /* HB_P_PUSHALIASEDFIELD,     */
   NULL,                       /* HB_P_PUSHALIASEDFIELDNEAR, */
   NULL,                       /* HB_P_PUSHALIASEDVAR,       */
   hb_p_pushblock,             /* HB_P_PUSHBLOCK,            */
   hb_p_pushblockshort,        /* HB_P_PUSHBLOCKSHORT,       */
   NULL,                       /* HB_P_PUSHFIELD,            */
   NULL,                       /* HB_P_PUSHBYTE,             */
   NULL,                       /* HB_P_PUSHINT,              */
   NULL,                       /* HB_P_PUSHLOCAL,            */
   NULL,                       /* HB_P_PUSHLOCALNEAR,        */
   NULL,                       /* HB_P_PUSHLOCALREF,         */
   NULL,                       /* HB_P_PUSHLONG,             */
   NULL,                       /* HB_P_PUSHMEMVAR,           */
   NULL,                       /* HB_P_PUSHMEMVARREF,        */
   NULL,                       /* HB_P_PUSHNIL,              */
   NULL,                       /* HB_P_PUSHDOUBLE,           */
   NULL,                       /* HB_P_PUSHSELF,             */
   NULL,                       /* HB_P_PUSHSTATIC,           */
   NULL,                       /* HB_P_PUSHSTATICREF,        */
   hb_p_pushstr,               /* HB_P_PUSHSTR,              */
   hb_p_pushstrshort,          /* HB_P_PUSHSTRSHORT,         */
   NULL,                       /* HB_P_PUSHSYM,              */
   NULL,                       /* HB_P_PUSHSYMNEAR,          */
   NULL,                       /* HB_P_PUSHVARIABLE,         */
   NULL,                       /* HB_P_RETVALUE,             */
   NULL,                       /* HB_P_SEND,                 */
   NULL,                       /* HB_P_SENDSHORT,            */
   NULL,                       /* HB_P_SEQBEGIN,             */
   NULL,                       /* HB_P_SEQEND,               */
   NULL,                       /* HB_P_SEQRECOVER,           */
   NULL,                       /* HB_P_SFRAME,               */
   NULL,                       /* HB_P_STATICS,              */
   hb_p_staticname,            /* HB_P_STATICNAME,           */
   NULL,                       /* HB_P_SWAPALIAS,            */
   NULL,                       /* HB_P_TRUE,                 */
   NULL,                       /* HB_P_ZERO,                 */
   NULL,                       /* HB_P_ONE,                  */
   NULL,                       /* HB_P_MACROFUNC,            */
   NULL,                       /* HB_P_MACRODO,              */
   NULL,                       /* HB_P_MPUSHSTR,             */
   NULL,                       /* HB_P_LOCALNEARADDINT,      */
   NULL,                       /* HB_P_MACROPUSHREF          */
   NULL,                       /* HB_P_PUSHLONGLONG          */
   NULL,                       /* HB_P_ENUMSTART             */
   NULL,                       /* HB_P_ENUMNEXT              */
   NULL,                       /* HB_P_ENUMPREV              */
   NULL,                       /* HB_P_ENUMEND               */
   NULL,                       /* HB_P_SWITCH                */
   NULL,                       /* HB_P_PUSHDATE              */
                               /* optimalization of inlined math operations */
   NULL,                       /* HB_P_PLUSEQPOP             */
   NULL,                       /* HB_P_MINUSEQPOP            */
   NULL,                       /* HB_P_MULTEQPOP             */
   NULL,                       /* HB_P_DIVEQPOP              */
   NULL,                       /* HB_P_PLUSEQ                */
   NULL,                       /* HB_P_MINUSEQ               */
   NULL,                       /* HB_P_MULTEQ                */
   NULL,                       /* HB_P_DIVEQ                 */
   NULL,                       /* HB_P_WITHOBJECTSTART       */
   NULL,                       /* HB_P_WITHOBJECTMESSAGE     */
   NULL,                       /* HB_P_WITHOBJECTEND         */
   NULL,                       /* HB_P_MACROSEND             */
   NULL,                       /* HB_P_PUSHOVARREF           */
   NULL,                       /* HB_P_ARRAYPUSHREF          */
   NULL,                       /* HB_P_VFRAME                */
   NULL,                       /* HB_P_LARGEFRAME            */
   NULL,                       /* HB_P_LARGEVFRAME           */
   hb_p_pushstrhidden,         /* HB_P_PUSHSTRHIDDEN         */
   NULL,                       /* HB_P_LOCALADDINT           */
   NULL,                       /* HB_P_MODEQPOP              */
   NULL,                       /* HB_P_EXPEQPOP              */
   NULL,                       /* HB_P_MODEQ                 */
   NULL,                       /* HB_P_EXPEQ                 */
   NULL,                       /* HB_P_DUPLUNREF             */
   NULL,                       /* HB_P_MPUSHBLOCKLARGE       */
   NULL,                       /* HB_P_MPUSHSTRLARGE         */
   hb_p_pushblocklarge,        /* HB_P_PUSHBLOCKLARGE,       */
   hb_p_pushstrlarge,          /* HB_P_PUSHSTRLARGE          */
   NULL,                       /* HB_P_SWAP                  */
   NULL,                       /* HB_P_PUSHVPARAMS           */
   NULL,                       /* HB_P_PUSHUNREF             */
   NULL,                       /* HB_P_SEQALWAYS             */
   NULL,                       /* HB_P_ALWAYSBEGIN           */
   NULL,                       /* HB_P_ALWAYSEND             */
   NULL,                       /* HB_P_DECEQPOP              */
   NULL,                       /* HB_P_INCEQPOP              */
   NULL,                       /* HB_P_DECEQ                 */
   NULL,                       /* HB_P_INCEQ                 */
   NULL,                       /* HB_P_LOCALDEC              */
   NULL,                       /* HB_P_LOCALINC              */
   NULL,                       /* HB_P_LOCALINCPUSH          */
   NULL,                       /* HB_P_PUSHFUNCSYM           */
   NULL,                       /* HB_P_HASHGEN               */
   NULL                        /* HB_P_SEQBLOCK              */
};

LONG hb_compPCodeSize( PFUNCTION pFunc, ULONG ulOffset )
{
   LONG lSize = 0;
   BYTE opcode = pFunc->pCode[ ulOffset ];

   if( opcode < HB_P_LAST_PCODE )
   {
      lSize = hb_comp_pcode_len[ opcode ];

      if( lSize == 0 )
      {
         HB_PCODE_FUNC_PTR pCall = s_psize_table[ opcode ];

         if( pCall != NULL )
            lSize = pCall( pFunc, ulOffset, NULL );
      }
   }
   return lSize;
}

void hb_compPCodeEval( PFUNCTION pFunc, const HB_PCODE_FUNC_PTR * pFunctions, void * cargo )
{
   ULONG ulPos = 0;
   ULONG ulSkip;
   BYTE opcode;

   /* Make sure that table is correct */
   assert( sizeof( hb_comp_pcode_len ) == HB_P_LAST_PCODE );
   assert( sizeof( s_psize_table ) / sizeof( HB_PCODE_FUNC_PTR ) == HB_P_LAST_PCODE );

   while( ulPos < pFunc->lPCodePos )
   {
      opcode = pFunc->pCode[ ulPos ];
      if( opcode < HB_P_LAST_PCODE )
      {
         HB_PCODE_FUNC_PTR pCall = pFunctions[ opcode ];
         ulSkip = pCall ? pCall( pFunc, ulPos, cargo ) : 0;
         if( ulSkip == 0 )
         {
            ulSkip = hb_comp_pcode_len[ opcode ];
            if( ulSkip == 0 )
            {
               pCall = s_psize_table[ opcode ];
               if( pCall != NULL )
                  ulSkip = pCall( pFunc, ulPos, NULL );
            }
         }

         if( ulSkip == 0 )
         {
            char szOpcode[ 16 ];
            snprintf( szOpcode, sizeof( szOpcode ), "%i", opcode );
            hb_errInternal( HB_EI_COMPBADOPSIZE, "Invalid (zero) opcode %s size in hb_compPCodeEval()", szOpcode, NULL );
            ++ulPos;
         }
#if 0
         /*
          * Test code to validate return values by PCODE eval functions,
          * in some cases the eval functions can return intentionally differ
          * values so it's not enabled by default. [druzus]
          */
         if( hb_comp_pcode_len[ opcode ] != 0 && hb_comp_pcode_len[ opcode ] != ulSkip )
         {
            char szMsg[ 100 ];
            snprintf( szMsg, sizeof( szMsg ), "Wrong PCODE (%d) size (%ld!=%d)", opcode, ulSkip, hb_comp_pcode_len[ opcode ] );
            hb_errInternal( HB_EI_COMPBADOPSIZE, szMsg, NULL, NULL );
         }
#endif
         ulPos += ulSkip;
      }
      else
      {
         char szOpcode[ 16 ];
         snprintf( szOpcode, sizeof( szOpcode ), "%i", opcode );
         hb_errInternal( HB_EI_COMPBADOPCODE, "Invalid opcode: %s in hb_compPCodeEval()", szOpcode, NULL );
         ++ulPos;
      }
   }
}

void hb_compPCodeTrace( PFUNCTION pFunc, const HB_PCODE_FUNC_PTR * pFunctions, void * cargo )
{
   ULONG ulPos = 0;

   /* Make sure that table is correct */
   assert( sizeof( hb_comp_pcode_len ) == HB_P_LAST_PCODE );

   while( ulPos < pFunc->lPCodePos )
   {
      BYTE opcode = pFunc->pCode[ ulPos ];
      if( opcode < HB_P_LAST_PCODE )
      {
         HB_PCODE_FUNC_PTR pCall = pFunctions[ opcode ];
         if( pCall )
            ulPos = pCall( pFunc, ulPos, cargo );
         else
            ulPos += hb_comp_pcode_len[ opcode ];
      }
      else
      {
         char szOpcode[ 16 ];
         snprintf( szOpcode, sizeof( szOpcode ), "%i", opcode );
         hb_errInternal( HB_EI_COMPBADOPCODE, "Invalid opcode: %s in hb_compPCodeTrace()", szOpcode, NULL );
         ++ulPos;
      }
   }
}

void hb_compGenPCode1( BYTE byte, HB_COMP_DECL )
{
   PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;   /* get the currently defined Clipper function */

   if( ! pFunc->pCode )   /* has been created the memory block to hold the pcode ? */
   {
      pFunc->pCode      = ( BYTE * ) hb_xgrab( HB_PCODE_CHUNK );
      pFunc->lPCodeSize = HB_PCODE_CHUNK;
      pFunc->lPCodePos  = 0;
   }
   else if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 1 )
      pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_CHUNK );

   pFunc->pCode[ pFunc->lPCodePos++ ] = byte;
}

void hb_compGenPCode2( BYTE byte1, BYTE byte2, HB_COMP_DECL )
{
   PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;   /* get the currently defined Clipper function */

   if( ! pFunc->pCode )   /* has been created the memory block to hold the pcode ? */
   {
      pFunc->pCode      = ( BYTE * ) hb_xgrab( HB_PCODE_CHUNK );
      pFunc->lPCodeSize = HB_PCODE_CHUNK;
      pFunc->lPCodePos  = 0;
   }
   else if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 2 )
      pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_CHUNK );

   pFunc->pCode[ pFunc->lPCodePos++ ] = byte1;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte2;
}

void hb_compGenPCode3( BYTE byte1, BYTE byte2, BYTE byte3, HB_COMP_DECL )
{
   PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;   /* get the currently defined Clipper function */

   if( ! pFunc->pCode )   /* has been created the memory block to hold the pcode ? */
   {
      pFunc->pCode      = ( BYTE * ) hb_xgrab( HB_PCODE_CHUNK );
      pFunc->lPCodeSize = HB_PCODE_CHUNK;
      pFunc->lPCodePos  = 0;
   }
   else if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 3 )
      pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_CHUNK );

   pFunc->pCode[ pFunc->lPCodePos++ ] = byte1;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte2;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte3;
}

void hb_compGenPCode4( BYTE byte1, BYTE byte2, BYTE byte3, BYTE byte4, HB_COMP_DECL )
{
   PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;   /* get the currently defined Clipper function */

   if( ! pFunc->pCode )   /* has been created the memory block to hold the pcode ? */
   {
      pFunc->pCode      = ( BYTE * ) hb_xgrab( HB_PCODE_CHUNK );
      pFunc->lPCodeSize = HB_PCODE_CHUNK;
      pFunc->lPCodePos  = 0;
   }
   else if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 4 )
      pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_CHUNK );

   pFunc->pCode[ pFunc->lPCodePos++ ] = byte1;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte2;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte3;
   pFunc->pCode[ pFunc->lPCodePos++ ] = byte4;
}

void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize, HB_COMP_DECL )
{
   PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast;   /* get the currently defined Clipper function */

   if( ! pFunc->pCode )   /* has been created the memory block to hold the pcode ? */
   {
      pFunc->lPCodeSize = ( ( ulSize / HB_PCODE_CHUNK ) + 1 ) * HB_PCODE_CHUNK;
      pFunc->pCode      = ( BYTE * ) hb_xgrab( pFunc->lPCodeSize );
      pFunc->lPCodePos  = 0;
   }
   else if( pFunc->lPCodePos + ulSize > pFunc->lPCodeSize )
   {
      /* not enough free space in pcode buffer - increase it */
      pFunc->lPCodeSize += ( ( ( ulSize / HB_PCODE_CHUNK ) + 1 ) * HB_PCODE_CHUNK );
      pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize );
   }

   memcpy( pFunc->pCode + pFunc->lPCodePos, pBuffer, ulSize );
   pFunc->lPCodePos += ulSize;
}
