/* * $Id$ */ /* * Harbour Project source code: * Compiler main file * * Copyright 1999 Antonio Linares * 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. * * 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 * hb_compPrepareOptimize() * hb_compOptimizeJumps() * hb_compOptimizeFrames() * hb_compAutoOpenAdd() * hb_compAutoOpenFind() * hb_compAutoOpen() * hb_compDeclaredParameterAdd() * hb_compClassAdd() * hb_compClassFind() * hb_compMethodAdd() * hb_compMethodFind() * hb_compDeclaredAdd() * hb_compDeclaredInit() * * See doc/license.txt for licensing terms. * */ /* malloc.h has been obsoleted by stdlib.h, which is included via hbcomp.h #include */ /* * Avoid tracing in preprocessor/compiler. */ #if ! defined(HB_TRACE_UTILS) #if defined(HB_TRACE_LEVEL) #undef HB_TRACE_LEVEL #endif #endif #include "hbcomp.h" #include "hbhash.h" #if defined(HB_OS_DOS) && defined(__BORLANDC__) #include extern unsigned _stklen = UINT_MAX; #endif #define HB_COMP_SINGLEFILE 1 #define HB_COMP_AUTOADDFILE 2 #define HB_COMP_MEMBUFFER 3 static int hb_compCompile( HB_COMP_DECL, const char * szPrg, int iFileType ); static int hb_compProcessRSPFile( HB_COMP_DECL, char * ); /* process response file */ static int hb_compAutoOpen( HB_COMP_DECL, const char * szPrg, BOOL * bSkipGen, int iFileType ); static void hb_compDeclaredInit( HB_COMP_DECL ); /* ************************************************************************* */ int hb_compMain( int argc, char * argv[], BYTE ** pBufPtr, ULONG * pulSize, const char * szSource ) { HB_COMP_DECL; int iStatus = EXIT_SUCCESS; BOOL bAnyFiles = FALSE; int i; HB_TRACE(HB_TR_DEBUG, ("hb_compMain()")); HB_COMP_PARAM = hb_comp_new(); HB_COMP_PARAM->pOutPath = NULL; /* First check the environment variables */ hb_compChkCompilerSwitch( HB_COMP_PARAM, 0, NULL ); /* Then check command line arguments This will override duplicated environment settings */ hb_compChkCompilerSwitch( HB_COMP_PARAM, argc, argv ); if( !HB_COMP_PARAM->fExit ) { if( pBufPtr && pulSize ) { HB_COMP_PARAM->iLanguage = HB_LANG_PORT_OBJ_BUF; } if( HB_COMP_PARAM->fLogo ) hb_compPrintLogo( HB_COMP_PARAM ); if( HB_COMP_PARAM->fBuildInfo ) { hb_compOutStd( HB_COMP_PARAM, "\n" ); hb_verBuildInfo(); hb_comp_free( HB_COMP_PARAM ); return iStatus; } if( HB_COMP_PARAM->fCredits ) { hb_compPrintCredits( HB_COMP_PARAM ); hb_comp_free( HB_COMP_PARAM ); return iStatus; } /* Set Search Path */ hb_compChkPaths( HB_COMP_PARAM ); /* Set standard rules */ hb_compInitPP( HB_COMP_PARAM, argc, argv ); /* Prepare the table of identifiers */ hb_compIdentifierOpen( HB_COMP_PARAM ); /* Load standard Declarations. */ if( HB_COMP_PARAM->iWarnings >= 3 ) hb_compDeclaredInit( HB_COMP_PARAM ); } if( szSource ) { bAnyFiles = TRUE; iStatus = hb_compCompile( HB_COMP_PARAM, szSource, HB_COMP_MEMBUFFER ); } else { /* Process all files passed via the command line. */ for( i = 1; i < argc && !HB_COMP_PARAM->fExit; i++ ) { HB_TRACE(HB_TR_DEBUG, ("main LOOP(%i,%s)", i, argv[i])); if( ! HB_ISOPTSEP( argv[ i ][ 0 ] ) ) { bAnyFiles = TRUE; if( argv[ i ][ 0 ] == '@' ) iStatus = hb_compProcessRSPFile( HB_COMP_PARAM, argv[ i ] + 1 ); else iStatus = hb_compCompile( HB_COMP_PARAM, argv[ i ], HB_COMP_SINGLEFILE ); if( iStatus != EXIT_SUCCESS ) break; } } } if( ! bAnyFiles && ! HB_COMP_PARAM->fQuiet ) { hb_compPrintUsage( HB_COMP_PARAM, argv[ 0 ] ); iStatus = EXIT_FAILURE; } if( HB_COMP_PARAM->iErrorCount > 0 ) iStatus = EXIT_FAILURE; if( pBufPtr && pulSize ) { if( iStatus == EXIT_SUCCESS ) { * pBufPtr = HB_COMP_PARAM->pOutBuf; * pulSize = HB_COMP_PARAM->ulOutBufSize; HB_COMP_PARAM->pOutBuf = NULL; HB_COMP_PARAM->ulOutBufSize = 0; } else { * pBufPtr = NULL; * pulSize = 0; } } hb_comp_free( HB_COMP_PARAM ); return iStatus; } static int hb_compProcessRSPFile( HB_COMP_DECL, char * szRspName ) { char szFile[ _POSIX_PATH_MAX + 1 ]; int iStatus = EXIT_SUCCESS; PHB_FNAME pFileName; FILE *inFile; pFileName = hb_fsFNameSplit( szRspName ); if( !pFileName->szExtension ) { pFileName->szExtension = ".clp"; hb_fsFNameMerge( szFile, pFileName ); szRspName = szFile; } inFile = hb_fopen( szRspName, "r" ); if( !inFile ) { char buffer[ _POSIX_PATH_MAX + 80 ]; snprintf( buffer, sizeof( buffer ), "Cannot open input file: %s\n", szRspName ); hb_compOutErr( HB_COMP_PARAM, buffer ); iStatus = EXIT_FAILURE; } else { int i = 0, ch; BOOL bAutoOpen = HB_COMP_PARAM->fAutoOpen; HB_COMP_PARAM->fAutoOpen = TRUE; do { ch = fgetc( inFile ); /* * '"' - quoting file names is Harbour extension - * Clipper does not serve it, [druzus] */ if( ch == '"' ) { while( ( ch = fgetc ( inFile ) ) != EOF && ch != '"' && ch != '\n' ) { if( i < _POSIX_PATH_MAX ) szFile[ i++ ] = (char) ch; } if( ch == '"' ) continue; } while( i == 0 && HB_ISSPACE( ch ) ) ch = fgetc( inFile ); if( ch == EOF || HB_ISSPACE( ch ) || ch == '#' ) { szFile[ i ] = '\0'; if( i > 0 ) hb_compAutoOpenAdd( HB_COMP_PARAM, hb_compIdentifierNew( HB_COMP_PARAM, szFile, HB_IDENT_COPY ) ); i = 0; while( ch != EOF && ch != '\n' ) ch = fgetc( inFile ); } else if( i < _POSIX_PATH_MAX ) szFile[ i++ ] = (char) ch; } while( ch != EOF ); fclose( inFile ); HB_COMP_PARAM->fAutoOpen = bAutoOpen; hb_fsFNameMerge( szFile, pFileName ); hb_compCompile( HB_COMP_PARAM, szFile, HB_COMP_AUTOADDFILE ); } hb_xfree( pFileName ); return iStatus; } /* ------------------------------------------------------------------------- */ /* ACTIONS */ /* ------------------------------------------------------------------------- */ static PCOMSYMBOL hb_compSymbolAdd( HB_COMP_DECL, char * szSymbolName, USHORT * pwPos, BOOL bFunction ) { PCOMSYMBOL pSym; if( szSymbolName[ 0 ] ) { /* Create a symbol for non-empty names only. * NOTE: an empty name is passed for a fake starting function when * '-n' switch is used */ pSym = ( PCOMSYMBOL ) hb_xgrab( sizeof( COMSYMBOL ) ); pSym->szName = szSymbolName; pSym->cScope = 0; pSym->pNext = NULL; pSym->bFunc = bFunction; if( ! HB_COMP_PARAM->symbols.iCount ) { HB_COMP_PARAM->symbols.pFirst = pSym; HB_COMP_PARAM->symbols.pLast = pSym; } else { ( ( PCOMSYMBOL ) HB_COMP_PARAM->symbols.pLast )->pNext = pSym; HB_COMP_PARAM->symbols.pLast = pSym; } HB_COMP_PARAM->symbols.iCount++; if( pwPos ) *pwPos = HB_COMP_PARAM->symbols.iCount -1; /* position number starts form 0 */ } else pSym = NULL; return pSym; } static PCOMSYMBOL hb_compSymbolFind( HB_COMP_DECL, char * szSymbolName, USHORT * pwPos, BOOL bFunction ) { PCOMSYMBOL pSym = HB_COMP_PARAM->symbols.pFirst; USHORT wCnt = 0; if( pwPos ) *pwPos = 0; while( pSym ) { if( ! strcmp( pSym->szName, szSymbolName ) ) { if( bFunction == pSym->bFunc ) { if( pwPos ) *pwPos = wCnt; return pSym; } } if( pSym->pNext ) { pSym = pSym->pNext; ++wCnt; } else return NULL; } return NULL; } /* NOTE: Name of symbols are released in hbident.c on exit */ static PCOMSYMBOL hb_compSymbolKill( PCOMSYMBOL pSym ) { PCOMSYMBOL pNext = pSym->pNext; hb_xfree( ( void * ) pSym ); return pNext; } /* returns a symbol name based on its index on the symbol table * index starts from 0 */ char * hb_compSymbolName( HB_COMP_DECL, USHORT uiSymbol ) { PCOMSYMBOL pSym = HB_COMP_PARAM->symbols.pFirst; while( pSym ) { if( uiSymbol-- == 0 ) return pSym->szName; pSym = pSym->pNext; } return NULL; } static void hb_compCheckDuplVars( HB_COMP_DECL, PVAR pVar, char * szVarName ) { while( pVar ) { if( ! strcmp( pVar->szName, szVarName ) ) { HB_COMP_ERROR_DUPLVAR( szVarName ); break; } else pVar = pVar->pNext; } } static USHORT hb_compVarListAdd( PVAR * pVarLst, PVAR pVar ) { USHORT uiVar = 1; while( *pVarLst ) { pVarLst = &( *pVarLst )->pNext; ++uiVar; } *pVarLst = pVar; return uiVar; } void hb_compVariableAdd( HB_COMP_DECL, char * szVarName, BYTE cValueType ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast; PVAR pVar; BOOL bFreeVar = TRUE; HB_SYMBOL_UNUSED( cValueType ); if( ! HB_COMP_PARAM->fStartProc && HB_COMP_PARAM->functions.iCount <= 1 && ( HB_COMP_PARAM->iVarScope == VS_LOCAL || HB_COMP_PARAM->iVarScope == ( VS_PRIVATE | VS_PARAMETER ) ) ) { /* Variable declaration is outside of function/procedure body. In this case only STATIC and PARAMETERS variables are allowed. */ hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_OUTSIDE, NULL, NULL ); return; } /* check if we are declaring local/static variable after some * executable statements */ if( pFunc->bFlags & FUN_STATEMENTS ) { char * szVarScope; switch( HB_COMP_PARAM->iVarScope ) { case VS_LOCAL: szVarScope = "LOCAL"; break; case VS_STATIC: szVarScope = "STATIC"; break; case VS_FIELD: szVarScope = "FIELD"; break; case VS_MEMVAR: szVarScope = "MEMVAR"; break; default: szVarScope = NULL; } if( szVarScope ) { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FOLLOWS_EXEC, szVarScope, NULL ); return; } } /* Check if a declaration of duplicated variable name is requested */ if( pFunc->szName ) { /* variable defined in a function/procedure */ hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pFields, szVarName ); hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pStatics, szVarName ); /* NOTE: Clipper warns if PARAMETER variable duplicates the MEMVAR * declaration */ if( !( HB_COMP_PARAM->iVarScope == VS_PRIVATE || HB_COMP_PARAM->iVarScope == VS_PUBLIC ) ) hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pMemvars, szVarName ); } else if( pFunc->bFlags & FUN_EXTBLOCK ) { /* variable defined in an extended codeblock */ hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pFields, szVarName ); hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pStatics, szVarName ); } else if( HB_COMP_PARAM->iVarScope != VS_PARAMETER ) { char buffer[ 80 ]; snprintf( buffer, sizeof( buffer ), "Wrong type of codeblock parameter, is: %d, should be: %d\r\n", HB_COMP_PARAM->iVarScope, VS_PARAMETER ); hb_compOutErr( HB_COMP_PARAM, buffer ); /* variable defined in a codeblock */ HB_COMP_PARAM->iVarScope = VS_PARAMETER; } hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pLocals, szVarName ); pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); pVar->szName = szVarName; pVar->szAlias = NULL; pVar->cType = cValueType; pVar->iUsed = VU_NOT_USED; pVar->pNext = NULL; pVar->iDeclLine = HB_COMP_PARAM->currLine; if( toupper( cValueType ) == 'S' ) { /* printf( "\nVariable %s is of Class: %s\n", szVarName, HB_COMP_PARAM->szFromClass ); */ pVar->pClass = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->szFromClass ); if( ! pVar->pClass ) { hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_CLASS_NOT_FOUND, HB_COMP_PARAM->szFromClass, szVarName ); pVar->cType = 'O'; } /* Resetting */ HB_COMP_PARAM->szFromClass = NULL; } if( HB_COMP_PARAM->iVarScope & VS_PARAMETER ) pVar->iUsed = VU_INITIALIZED; if( HB_COMP_PARAM->iVarScope & VS_MEMVAR ) { PCOMSYMBOL pSym; USHORT wPos; if( HB_COMP_PARAM->fAutoMemvarAssume || HB_COMP_PARAM->iVarScope == VS_MEMVAR ) { /* add this variable to the list of MEMVAR variables */ if( pFunc->pMemvars ) hb_compCheckDuplVars( HB_COMP_PARAM, pFunc->pMemvars, szVarName ); hb_compVarListAdd( &pFunc->pMemvars, pVar ); bFreeVar = FALSE; } switch( HB_COMP_PARAM->iVarScope ) { case VS_MEMVAR: /* variable declared in MEMVAR statement */ break; case( VS_PARAMETER | VS_PRIVATE ): if( ++pFunc->wParamNum > pFunc->wParamCount ) pFunc->wParamCount = pFunc->wParamNum; pSym = hb_compSymbolFind( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) pSym = hb_compSymbolAdd( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= HB_FS_MEMVAR; hb_compGenPCode4( HB_P_PARAMETER, HB_LOBYTE( wPos ), HB_HIBYTE( wPos ), HB_LOBYTE( pFunc->wParamNum ), HB_COMP_PARAM ); if( HB_COMP_PARAM->iWarnings >= 3 && bFreeVar ) { PVAR pMemVar = pFunc->pMemvars; while( pMemVar && strcmp( pMemVar->szName, pVar->szName ) != 0 ) pMemVar = pMemVar->pNext; /* Not declared as memvar. */ if( pMemVar == NULL ) { /* add this variable to the list of PRIVATE variables. */ hb_compVarListAdd( &pFunc->pPrivates, pVar ); bFreeVar = FALSE; } } if( bFreeVar ) hb_xfree( pVar ); break; case VS_PRIVATE: pSym = hb_compSymbolFind( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) pSym = hb_compSymbolAdd( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= HB_FS_MEMVAR; if( HB_COMP_PARAM->iWarnings >= 3 && bFreeVar ) { PVAR pMemVar = pFunc->pMemvars; while( pMemVar && strcmp( pMemVar->szName, pVar->szName ) != 0 ) pMemVar = pMemVar->pNext; /* Not declared as memvar. */ if( pMemVar == NULL ) { /* add this variable to the list of PRIVATE variables. */ hb_compVarListAdd( &pFunc->pPrivates, pVar ); bFreeVar = FALSE; } } if( bFreeVar ) hb_xfree( pVar ); break; case VS_PUBLIC: pSym = hb_compSymbolFind( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) pSym = hb_compSymbolAdd( HB_COMP_PARAM, szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= HB_FS_MEMVAR; if( bFreeVar ) hb_xfree( pVar ); break; } } else { switch( HB_COMP_PARAM->iVarScope ) { case VS_LOCAL: case VS_PARAMETER: { USHORT wLocal = hb_compVarListAdd( &pFunc->pLocals, pVar ); if( HB_COMP_PARAM->iVarScope == VS_PARAMETER ) { ++pFunc->wParamCount; pFunc->bFlags |= FUN_USES_LOCAL_PARAMS; } if( HB_COMP_PARAM->fDebugInfo ) { hb_compGenPCode3( HB_P_LOCALNAME, HB_LOBYTE( wLocal ), HB_HIBYTE( wLocal ), HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) szVarName, strlen( szVarName ) + 1, HB_COMP_PARAM ); } break; } case VS_STATIC: hb_compVarListAdd( &pFunc->pStatics, pVar ); break; case VS_FIELD: hb_compVarListAdd( &pFunc->pFields, pVar ); break; } } } /* Set the name of an alias for the list of previously declared FIELDs * * szAlias -> name of the alias * iField -> position of the first FIELD name to change */ void hb_compFieldSetAlias( HB_COMP_DECL, char * szAlias, int iField ) { PVAR pVar; pVar = HB_COMP_PARAM->functions.pLast->pFields; while( iField-- && pVar ) pVar = pVar->pNext; while( pVar ) { pVar->szAlias = szAlias; pVar = pVar->pNext; } } /* This functions counts the number of FIELD declaration in a function * We will required this information in hb_compFieldSetAlias function */ int hb_compFieldsCount( HB_COMP_DECL ) { int iFields = 0; PVAR pVar = HB_COMP_PARAM->functions.pLast->pFields; while( pVar ) { ++iFields; pVar = pVar->pNext; } return iFields; } static PVAR hb_compVariableGet( PVAR pVars, char * szVarName, int * piPos ) { int iVar = 1; while( pVars ) { if( pVars->szName && ! strcmp( pVars->szName, szVarName ) ) { pVars->iUsed |= VU_USED; *piPos = iVar; return pVars; } pVars = pVars->pNext; ++iVar; } return NULL; } /* returns variable pointer if defined or NULL */ static PVAR hb_compVariableGetVar( PVAR pVars, USHORT wOrder ) { while( pVars && --wOrder ) pVars = pVars->pNext; return pVars; } /* returns the order + 1 of a variable if defined or zero */ static USHORT hb_compVariableGetPos( PVAR pVars, char * szVarName ) { USHORT wVar = 1; while( pVars ) { if( pVars->szName && ! strcmp( pVars->szName, szVarName ) ) { pVars->iUsed |= VU_USED; return wVar; } pVars = pVars->pNext; ++wVar; } return 0; } PVAR hb_compVariableFind( HB_COMP_DECL, char * szVarName, int * piPos, int * piScope ) { PFUNCTION pFunc, pGlobal, pOutBlock = NULL; BOOL fStatic = FALSE, fBlock = FALSE, fGlobal = FALSE; PVAR pVar = NULL; int iPos = 0, iScope = 0, iLevel = 0; if( piPos ) *piPos = 0; else piPos = &iPos; if( piScope ) *piScope = HB_VS_UNDECLARED; else piScope = &iScope; /* check current function/codeblock variables */ pFunc = HB_COMP_PARAM->functions.pLast; pGlobal = ( HB_COMP_PARAM->fStartProc || HB_COMP_PARAM->functions.pFirst == pFunc ) ? NULL : HB_COMP_PARAM->functions.pFirst; while( pFunc ) { if( ( pFunc->cScope & HB_FS_INITEXIT ) == HB_FS_INITEXIT ) { /* static initialization function */ fStatic = TRUE; } else if( pFunc->szName ) { /* normal function/procedure */ /* check local parameters */ pVar = hb_compVariableGet( pFunc->pLocals, szVarName, piPos ); if( pVar ) { *piScope = HB_VS_LOCAL_VAR; if( fStatic ) { /* local variable was referenced in a codeblock during * initialization of static variable. This cannot be supported * because static variables are initialized at program * startup when there is no local variables yet - hence we * cannot detach this local variable * For example: * LOCAL locvar * STATIC stavar:={ | x | locvar} * * NOTE: Clipper creates such a codeblock however at the * time of codeblock evaluation it generates a runtime error: * 'bound error: array acccess' * Called from: (b)STATICS$(0) */ hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_ILLEGAL_INIT, "(b)", szVarName ); } else if( fBlock ) { /* We want to access a local variable defined in a function * that owns this codeblock. We cannot access this variable in * a normal way because at runtime the stack base will point * to local variables of EVAL function. */ /* NOTE: The list of local variables defined in a function * and referenced in a codeblock will be stored in a outer * codeblock only. This makes sure that all variables will be * detached properly - the inner codeblock can be created * outside of a function where it was defined when the local * variables are not accessible. */ *piPos = -hb_compVariableGetPos( pOutBlock->pDetached, szVarName ); if( *piPos == 0 ) { /* this variable was not referenced yet - add it to the list */ pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); pVar->szName = szVarName; pVar->szAlias = NULL; pVar->cType = ' '; pVar->iUsed = VU_NOT_USED; pVar->pNext = NULL; pVar->iDeclLine = HB_COMP_PARAM->currLine; /* Use negative order to signal that we are accessing a local * variable from a codeblock */ *piPos = -hb_compVarListAdd( &pOutBlock->pDetached, pVar ); } *piScope = HB_VS_CBLOCAL_VAR; } } else { /* check static variables */ pVar = hb_compVariableGet( pFunc->pStatics, szVarName, piPos ); if( pVar ) { *piScope = HB_VS_STATIC_VAR; *piPos += pFunc->iStaticsBase; } else { /* check FIELDs */ pVar = hb_compVariableGet( pFunc->pFields, szVarName, piPos ); if( pVar ) *piScope = HB_VS_LOCAL_FIELD; else { /* check MEMVARs */ pVar = hb_compVariableGet( pFunc->pMemvars, szVarName, piPos ); if( pVar ) *piScope = HB_VS_LOCAL_MEMVAR; } } } } else { /* codeblock */ fBlock = TRUE; /* check local parameters */ pVar = hb_compVariableGet( pFunc->pLocals, szVarName, piPos ); if( pVar ) { *piScope = HB_VS_LOCAL_VAR; if( iLevel ) { /* this variable is defined in a parent codeblock * It is not possible to access a parameter of a codeblock * in which the current codeblock is defined */ hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_OUTER_VAR, szVarName, NULL ); } } else if( pFunc->bFlags & FUN_EXTBLOCK ) { /* extended codeblock */ /* check static variables */ pVar = hb_compVariableGet( pFunc->pStatics, szVarName, piPos ); if( pVar ) { *piScope = HB_VS_STATIC_VAR; *piPos += pFunc->iStaticsBase; } else { /* check FIELDs */ pVar = hb_compVariableGet( pFunc->pFields, szVarName, piPos ); if( pVar ) *piScope = HB_VS_LOCAL_FIELD; else { /* check MEMVARs */ pVar = hb_compVariableGet( pFunc->pMemvars, szVarName, piPos ); if( pVar ) *piScope = HB_VS_LOCAL_MEMVAR; } } } } if( pVar ) break; pOutBlock = pFunc; pFunc = pFunc->pOwner; if( !pFunc && !fGlobal ) { /* instead of making this trick with pGlobal switching it will be * much cleaner to set pOwner in each compiled function to first * global pseudo function created when -n compiler switch is used * [druzus] */ pFunc = pGlobal; fGlobal = TRUE; } ++iLevel; } if( pVar && fGlobal ) *piScope |= HB_VS_FILEWIDE; return pVar; } /* return local variable name using its order after final fixing */ char * hb_compLocalVariableName( PFUNCTION pFunc, USHORT wVar ) { PVAR pVar; if( pFunc->wParamCount && !( pFunc->bFlags & FUN_USES_LOCAL_PARAMS ) ) wVar -= pFunc->wParamCount; pVar = hb_compVariableGetVar( pFunc->pLocals, wVar ); return pVar ? pVar->szName : NULL; } char * hb_compStaticVariableName( HB_COMP_DECL, USHORT wVar ) { PVAR pVar; PFUNCTION pTmp = HB_COMP_PARAM->functions.pFirst; while( pTmp->pNext && pTmp->pNext->iStaticsBase < wVar ) pTmp = pTmp->pNext; pVar = hb_compVariableGetVar( pTmp->pStatics, wVar - pTmp->iStaticsBase ); return pVar ? pVar->szName : NULL; } int hb_compVariableScope( HB_COMP_DECL, char * szVarName ) { int iScope; hb_compVariableFind( HB_COMP_PARAM, szVarName, NULL, &iScope ); return iScope; } BOOL hb_compIsValidMacroText( HB_COMP_DECL, char * szText, ULONG ulLen ) { BOOL fFound = FALSE; ULONG ul = 0; while( ul < ulLen ) { if( szText[ ul++ ] == '&' ) { char szSymName[ HB_SYMBOL_NAME_LEN + 1 ]; int iSize = 0, iScope; /* Check if macro operator is used inside a string * Macro operator is ignored if it is the last char or * next char is '(' e.g. "this is &(ignored)" * (except if strict Clipper compatibility mode is enabled) * * NOTE: This uses _a-zA-Z pattern to check for * beginning of a variable name */ while( ul < ulLen && iSize < HB_SYMBOL_NAME_LEN ) { char ch = szText[ ul ]; if( ch >= 'a' && ch <= 'z' ) szSymName[ iSize++ ] = ch - ( 'a' - 'A' ); else if( ch == '_' || ( ch >= 'A' && ch <= 'Z' ) || ( ch >= '0' && ch <= '9' ) ) szSymName[ iSize++ ] = ch; else break; ++ul; } if( iSize ) { szSymName[ iSize ] = '\0'; /* NOTE: All variables are assumed memvars in macro compiler - * there is no need to check for a valid name but to be Clipper * compatible we should check if macrotext variable does not refer * to local, static or field and generate error in such case. * Only MEMVAR or undeclared (memvar will be assumed) * variables can be used in macro text. */ fFound = TRUE; iScope = hb_compVariableScope( HB_COMP_PARAM, szSymName ); if( iScope != HB_VS_UNDECLARED && !( iScope & HB_VS_LOCAL_MEMVAR ) ) { hb_compErrorMacro( HB_COMP_PARAM, szText ); break; } } else if( ! HB_SUPPORT_HARBOUR ) fFound = TRUE; /* always macro substitution in Clipper */ } } return fFound; } /* * DECLARATIONS */ PCOMCLASS hb_compClassFind( HB_COMP_DECL, char * szClassName ) { PCOMCLASS pClass = HB_COMP_PARAM->pFirstClass; if( HB_COMP_PARAM->iWarnings < 3 ) return NULL; while( pClass ) { if( ! strcmp( pClass->szName, szClassName ) ) return pClass; pClass = pClass->pNext; } return NULL; } PCOMCLASS hb_compClassAdd( HB_COMP_DECL, char * szClassName, char * szClassFunc ) { PCOMCLASS pClass; PCOMDECLARED pDeclared; /*printf( "Declaring Class: %s\n", szClassName );*/ if( HB_COMP_PARAM->iWarnings < 3 ) return NULL; if( ( pClass = hb_compClassFind( HB_COMP_PARAM, szClassName ) ) != NULL ) { PCOMCLASS * pClassPtr = &HB_COMP_PARAM->pFirstClass; while( *pClassPtr && *pClassPtr != HB_COMP_PARAM->pReleaseClass ) { /* It's predefined class, allow to redefine them */ if( *pClassPtr == pClass ) { *pClassPtr = pClass->pNext; pClass = NULL; break; } pClassPtr = &( *pClassPtr )->pNext; } if( pClass ) { hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_DUP_DECLARATION, "Class", szClassName ); return pClass; } } pClass = ( PCOMCLASS ) hb_xgrab( sizeof( COMCLASS ) ); pClass->szName = szClassName; pClass->pMethod = NULL; pClass->pNext = NULL; if( HB_COMP_PARAM->pFirstClass == NULL ) HB_COMP_PARAM->pFirstClass = pClass; else HB_COMP_PARAM->pLastClass->pNext = pClass; HB_COMP_PARAM->pLastClass = pClass; /* Auto declaration for the Class Function. */ pDeclared = hb_compDeclaredAdd( HB_COMP_PARAM, szClassFunc ? szClassFunc : szClassName ); pDeclared->cType = 'S'; pDeclared->pClass = pClass; if( ! HB_COMP_PARAM->pReleaseClass ) { HB_COMP_PARAM->pReleaseClass = pClass; } return pClass; } PCOMDECLARED hb_compMethodFind( PCOMCLASS pClass, char * szMethodName ) { if( pClass ) { PCOMDECLARED pMethod = pClass->pMethod; while( pMethod ) { if( ! strcmp( pMethod->szName, szMethodName ) ) return pMethod; pMethod = pMethod->pNext; } } return NULL; } PCOMDECLARED hb_compMethodAdd( HB_COMP_DECL, PCOMCLASS pClass, char * szMethodName ) { PCOMDECLARED pMethod; /*printf( "\nDeclaring Method: %s of Class: %s Pointer: %li\n", szMethodName, pClass->szName, pClass );*/ if( HB_COMP_PARAM->iWarnings < 3 ) return NULL; if( ( pMethod = hb_compMethodFind( pClass, szMethodName ) ) != NULL ) { hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_DUP_DECLARATION, "Method", szMethodName ); /* Last Declaration override previous declarations */ pMethod->cParamTypes = NULL; pMethod->iParamCount = 0; pMethod->pParamClasses = NULL; return pMethod; } pMethod = ( PCOMDECLARED ) hb_xgrab( sizeof( COMDECLARED ) ); pMethod->szName = szMethodName; pMethod->cType = ' '; /* Not known yet */ pMethod->cParamTypes = NULL; pMethod->iParamCount = 0; pMethod->pParamClasses = NULL; pMethod->pNext = NULL; if( pClass->pMethod == NULL ) pClass->pMethod = pMethod; else pClass->pLastMethod->pNext = pMethod; pClass->pLastMethod = pMethod; HB_COMP_PARAM->pLastMethod = pMethod; return pMethod; } static void hb_compDeclaredInit( HB_COMP_DECL ) { #define _DECL static COMDECLARED /* \x5c -> ByRef (+60) '-' -> NIL \x7a -> Optional (+90) 'U' -> Undefined ' ' -> AnyType 'A' -> Array 'B' -> Array 'A' -> Array of AnyType 'a' -> Array of Arrays 'b' -> Array of Blocks \x7a -> Optional AnyType \x9b -> Optional Array \x9c -> Optional Block \x94 -> Optional Array of AnyType \xb5 -> Optional Array of Arrays \xb6 -> Optional Array of Blocks 'C' -> Character/String 'D' -> Date 'L' -> Logical 'c' -> Array of Strings 'd' -> Array of Dates 'l' -> Array of Logicals \x9d -> Optional Character \x9e -> Optional Date \xa6 -> Optional Logical \xb7 -> Optional Array of Strings \xb8 -> Optional Array of Dates \xc0 -> Optional Array of Logicals 'N' -> Numeric 'O' -> Object 'S' -> Class 'n' -> Array of Numerics 'o' -> Array of Objects 's' -> Array of Classes \xa8 -> Optional Numeric \xa9 -> Optional Object \xad -> Optional Class \xc2 -> Optional Array of Numerics \xc3 -> Optional Array of Objects \xc7 -> Optional Array of Classes */ /* ------------------------------------------------- Standard Functions -------------------------------------------------- */ /* Name Ret # of Prams Param Types Ret Class Param Classes Next ---------- --- ---------- ------------------------------ --------- ------------- ------ */ _DECL s_001 = { "AADD" , ' ', 2 , (BYTE*)"A " , NULL , NULL , NULL }; _DECL s_002 = { "ABS" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_001}; _DECL s_003 = { "ACHOICE" , 'N', 9 , (BYTE*)"NNNNA\x7a\x9d\xa8\xa8" , NULL , NULL , &s_002}; _DECL s_004 = { "ACLONE" , 'A', 1 , (BYTE*)"A" , NULL , NULL , &s_003}; _DECL s_005 = { "ACOPY" , 'A', 5 , (BYTE*)"AA\xa8\xa8\xa8" , NULL , NULL , &s_004}; _DECL s_006 = { "ADEL" , 'A', 2 , (BYTE*)"AN" , NULL , NULL , &s_005}; _DECL s_007 = { "ADIR" , 'N', 6 , (BYTE*)"\x9d\x9b\x9b\x9b\x9b\x9b" , NULL , NULL , &s_006}; _DECL s_008 = { "AEVAL" , 'A', 4 , (BYTE*)"AB\xa8\xa8" , NULL , NULL , &s_007}; _DECL s_009 = { "AFIELDS" , 'N', 4 , (BYTE*)"A\x9b\x9b\x9b" , NULL , NULL , &s_008}; _DECL s_010 = { "AFILL" , 'A', 4 , (BYTE*)"A \xa8\xa8" , NULL , NULL , &s_009}; _DECL s_011 = { "AINS" , 'A', 2 , (BYTE*)"AN" , NULL , NULL , &s_010}; _DECL s_012 = { "ALERT" , 'N', 4 , (BYTE*)"C\x9b\x9d\xa8" , NULL , NULL , &s_011}; _DECL s_013 = { "ALIAS" , 'C', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_012}; _DECL s_014 = { "ALLTRIM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_013}; _DECL s_015 = { "AMPM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_014}; _DECL s_016 = { "ARRAY" , 'A', 3 , (BYTE*)"N\xa8\xa8" , NULL , NULL , &s_015}; _DECL s_017 = { "ASC" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_016}; _DECL s_018 = { "ASCAN" , 'N', 4 , (BYTE*)"A\xa7\xa8\xa8" , NULL , NULL , &s_017}; _DECL s_019 = { "ASIZE" , 'A', 2 , (BYTE*)"AN" , NULL , NULL , &s_018}; _DECL s_020 = { "ASORT" , 'A', 4 , (BYTE*)"A\xa8\xa8\x9c" , NULL , NULL , &s_019}; _DECL s_021 = { "AT" , 'N', 2 , (BYTE*)"CC" , NULL , NULL , &s_020}; _DECL s_022 = { "ATAIL" , ' ', 1 , (BYTE*)"A" , NULL , NULL , &s_021}; _DECL s_023 = { "BIN2I" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_022}; _DECL s_024 = { "BIN2L" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_023}; _DECL s_025 = { "BIN2U" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_024}; _DECL s_026 = { "BIN2W" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_025}; _DECL s_027 = { "BOF" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_026}; _DECL s_028 = { "BROWSE" , '-', 4 , (BYTE*)"\xa8\xa8\xa8\xa8" , NULL , NULL , &s_027}; _DECL s_029 = { "CDOW" , 'C', 1 , (BYTE*)"D" , NULL , NULL , &s_028}; _DECL s_030 = { "CHR" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_029}; _DECL s_031 = { "CMONTH" , 'C', 1 , (BYTE*)"D" , NULL , NULL , &s_030}; _DECL s_032 = { "COL" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_031}; _DECL s_033 = { "CTOD" , 'D', 1 , (BYTE*)"C" , NULL , NULL , &s_032}; _DECL s_034 = { "CURDIR" , 'C', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_033}; _DECL s_035 = { "DATE" , 'D', 0 , (BYTE*)NULL , NULL , NULL , &s_034}; _DECL s_036 = { "DAY" , 'N', 1 , (BYTE*)"D" , NULL , NULL , &s_035}; _DECL s_037 = { "DAYS" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_036}; _DECL s_038 = { "DBAPPEND" , '-', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_037}; _DECL s_039 = { "DBCLEARFILTER" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_038}; _DECL s_040 = { "DBCLEARINDEX" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_039}; _DECL s_041 = { "DBCLEARRELATION" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_040}; _DECL s_042 = { "DBCLOSEALL" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_041}; _DECL s_043 = { "DBCLOSEAREA" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_042}; _DECL s_044 = { "DBCOMMIT" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_043}; _DECL s_045 = { "DBCOMMITALL" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_044}; _DECL s_046 = { "DBCREATE" , '-', 5 , (BYTE*)"CA\x9d\xa6\x9d" , NULL , NULL , &s_045}; _DECL s_047 = { "DBCREATEINDEX" , '-', 5 , (BYTE*)"C B\xa6\xa6" , NULL , NULL , &s_046}; _DECL s_048 = { "DBDELETE" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_047}; _DECL s_049 = { "DBEDIT" , '-',12 , (BYTE*)"\xa8\xa8\xa8\xa8\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a" , NULL , NULL , &s_048}; _DECL s_050 = { "DBEVAL" , '-', 6 , (BYTE*)"B\x9c\x9cNNL" , NULL , NULL , &s_049}; _DECL s_051 = { "DBF" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_050}; _DECL s_052 = { "DBFILTER" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_051}; _DECL s_053 = { "DBGOBOTTOM" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_052}; _DECL s_054 = { "DBGOTO" , '-', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_053}; _DECL s_055 = { "DBGOTOP" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_054}; _DECL s_056 = { "DBRECALL" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_055}; _DECL s_057 = { "DBREINDEX" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_056}; _DECL s_058 = { "DBRELATION" , ' ', 1 , (BYTE*)"N" , NULL , NULL , &s_057}; _DECL s_059 = { "DBRLOCK" , 'L', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_058}; _DECL s_060 = { "DBRLOCKLIST" , 'A', 0 , (BYTE*)NULL , NULL , NULL , &s_059}; _DECL s_061 = { "DBRSELECT" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_060}; _DECL s_062 = { "DBRUNLOCK" , '-', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_061}; _DECL s_063 = { "DBSEEK" , 'L', 3 , (BYTE*)" \xa6\xa6" , NULL , NULL , &s_062}; _DECL s_064 = { "DBSELECTAREA" , '-', 1 , (BYTE*)" " , NULL , NULL , &s_063}; _DECL s_065 = { "DBSETDRIVER" , 'C', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_064}; _DECL s_066 = { "DBSETFILTER" , '-', 2 , (BYTE*)"B\x9d" , NULL , NULL , &s_065}; _DECL s_067 = { "DBSETINDEX" , '-', 1 , (BYTE*)"C" , NULL , NULL , &s_066}; _DECL s_068 = { "DBSETORDER" , '-', 1 , (BYTE*)"N" , NULL , NULL , &s_067}; _DECL s_069 = { "DBSETRELATION" , '-', 3 , (BYTE*)" BC" , NULL , NULL , &s_068}; _DECL s_070 = { "DBSKIP" , '-', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_069}; _DECL s_071 = { "DBSTRUCT" , 'A', 0 , (BYTE*)NULL , NULL , NULL , &s_070}; _DECL s_072 = { "DBUNLOCK" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_071}; _DECL s_073 = { "DBUNLOCKALL" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_072}; _DECL s_074 = { "DBUSEAREA" , '-', 6 , (BYTE*)"\xa6\x9d""C\x9d\xa6\xa6" , NULL , NULL , &s_073}; _DECL s_075 = { "DELETED" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_074}; _DECL s_076 = { "DESCEND" , ' ', 1 , (BYTE*)" " , NULL , NULL , &s_075}; _DECL s_077 = { "DEVOUT" , '-', 2 , (BYTE*)" \x9d" , NULL , NULL , &s_076}; _DECL s_078 = { "DEVOUTPICT" , '-', 3 , (BYTE*)" C\x9d" , NULL , NULL , &s_077}; _DECL s_079 = { "DEVPOS" , '-', 2 , (BYTE*)"NN" , NULL , NULL , &s_078}; _DECL s_080 = { "DIRECTORY" , 'A', 3 , (BYTE*)"\x9d\x9d\xa6" , NULL , NULL , &s_079}; _DECL s_081 = { "DIRCHANGE" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_080}; _DECL s_082 = { "DIRREMOVE" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_081}; _DECL s_083 = { "DISKSPACE" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_082}; _DECL s_084 = { "DISPBEGIN" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_083}; _DECL s_085 = { "DISPCOUNT" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_084}; _DECL s_086 = { "DISPEND" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_085}; _DECL s_087 = { "DISPOUT" , '-', 2 , (BYTE*)" \x9d" , NULL , NULL , &s_086}; _DECL s_088 = { "DOW" , 'N', 1 , (BYTE*)"D" , NULL , NULL , &s_087}; _DECL s_089 = { "DTOC" , 'C', 1 , (BYTE*)"D" , NULL , NULL , &s_088}; _DECL s_090 = { "DTOS" , 'C', 1 , (BYTE*)"D" , NULL , NULL , &s_089}; _DECL s_091 = { "ELAPTIME" , 'C', 2 , (BYTE*)"CC" , NULL , NULL , &s_090}; _DECL s_092 = { "EMPTY" , 'L', 1 , (BYTE*)" " , NULL , NULL , &s_091}; _DECL s_093 = { "EOF" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_092}; _DECL s_094 = { "ERRORNEW" , 'S', 0 , (BYTE*)NULL , NULL , NULL , &s_093}; _DECL s_095 = { "EVAL" , ' ', 3 , (BYTE*)"B\x7a\x7a" , NULL , NULL , &s_094}; _DECL s_096 = { "EXP" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_095}; _DECL s_097 = { "FCLOSE" , 'L', 1 , (BYTE*)"N" , NULL , NULL , &s_096}; _DECL s_098 = { "FCOUNT" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_097}; _DECL s_099 = { "FCREATE" , 'N', 2 , (BYTE*)"C\xa8" , NULL , NULL , &s_098}; _DECL s_100 = { "FERASE" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_099}; _DECL s_101 = { "FERROR" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_100}; _DECL s_102 = { "FIELD" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_101}; _DECL s_103 = { "FIELDBLOCK" , 'B', 1 , (BYTE*)"C" , NULL , NULL , &s_102}; _DECL s_104 = { "FIELDGET" , ' ', 1 , (BYTE*)"N" , NULL , NULL , &s_103}; _DECL s_105 = { "FIELDNAME" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_104}; _DECL s_106 = { "FIELDPOS" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_105}; _DECL s_107 = { "FIELDPUT" , ' ', 2 , (BYTE*)"N " , NULL , NULL , &s_106}; _DECL s_108 = { "FIELDWBLOCK" , 'B', 2 , (BYTE*)"CN" , NULL , NULL , &s_107}; _DECL s_109 = { "FILE" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_108}; _DECL s_110 = { "FLOCK" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_109}; _DECL s_111 = { "FOPEN" , 'N', 2 , (BYTE*)"C\xa8" , NULL , NULL , &s_110}; _DECL s_112 = { "FOUND" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_111}; _DECL s_113 = { "FREAD" , 'N', 3 , (BYTE*)"N\x5cN" , NULL , NULL , &s_112}; _DECL s_114 = { "FREADSTR" , 'C', 2 , (BYTE*)"NN" , NULL , NULL , &s_113}; _DECL s_115 = { "FRENAME" , 'N', 2 , (BYTE*)"CC" , NULL , NULL , &s_114}; _DECL s_116 = { "FSEEK" , 'N', 3 , (BYTE*)"NN\xa8" , NULL , NULL , &s_115}; _DECL s_117 = { "FWRITE" , 'N', 3 , (BYTE*)"NC\xa8" , NULL , NULL , &s_116}; _DECL s_118 = { "GETACTIVE" , '-', 1 , (BYTE*)"O" , NULL , NULL , &s_117}; _DECL s_119 = { "GETAPPLYKEY" , '-', 2 , (BYTE*)"ON" , NULL , NULL , &s_118}; _DECL s_120 = { "GETDOSETKEY" , '-', 2 , (BYTE*)"BO" , NULL , NULL , &s_119}; _DECL s_121 = { "GETENV" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_120}; _DECL s_122 = { "GETNEW" , 'O', 6 , (BYTE*)"\xa8\xa8\x9c\x9d\x9d\x9d" , NULL , NULL , &s_121}; _DECL s_123 = { "GETPREVALIDATE" , 'L', 1 , (BYTE*)"O" , NULL , NULL , &s_122}; _DECL s_124 = { "GETPOSTVALIDATE" , 'L', 1 , (BYTE*)"O" , NULL , NULL , &s_123}; _DECL s_125 = { "GETREADER" , '-', 1 , (BYTE*)"O" , NULL , NULL , &s_124}; _DECL s_126 = { "HARDCR" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_125}; _DECL s_127 = { "HB_ANSITOOEM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_126}; _DECL s_128 = { "HB_DISKSPACE" , 'N', 2 , (BYTE*)"\x9d\xa8" , NULL , NULL , &s_127}; _DECL s_129 = { "HB_FEOF" , 'L', 1 , (BYTE*)"N" , NULL , NULL , &s_128}; _DECL s_130 = { "HB_OEMTOANSI" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_129}; _DECL s_131 = { "HEADER" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_130}; _DECL s_132 = { "I2BIN" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_131}; _DECL s_133 = { "IF" , ' ', 3 , (BYTE*)"L " , NULL , NULL , &s_132}; _DECL s_134 = { "INDEXEXT" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_133}; _DECL s_135 = { "INDEXKEY" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_134}; _DECL s_136 = { "INDEXORD" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_135}; _DECL s_137 = { "INKEY" , 'N', 2 , (BYTE*)"\xa8\xa8" , NULL , NULL , &s_136}; _DECL s_138 = { "INT" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_137}; _DECL s_139 = { "ISAFFIRM" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_138}; _DECL s_140 = { "ISALPHA" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_139}; _DECL s_141 = { "ISDIGIT" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_140}; _DECL s_142 = { "ISDISK" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_141}; _DECL s_143 = { "ISLOWER" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_142}; _DECL s_144 = { "ISNEGATIVE" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_143}; _DECL s_145 = { "ISUPPER" , 'L', 1 , (BYTE*)"C" , NULL , NULL , &s_144}; _DECL s_146 = { "L2BIN" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_145}; _DECL s_147 = { "LASTKEY" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_146}; _DECL s_148 = { "LASTREC" , 'N', 1 , (BYTE*)" " , NULL , NULL , &s_147}; _DECL s_149 = { "LEFT" , 'C', 2 , (BYTE*)"CN" , NULL , NULL , &s_148}; _DECL s_150 = { "LEN" , 'N', 1 , (BYTE*)" " , NULL , NULL , &s_149}; _DECL s_151 = { "LOG" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_150}; _DECL s_152 = { "LOWER" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_151}; _DECL s_153 = { "LTRIM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_152}; _DECL s_154 = { "LUPDATE" , 'D', 0 , (BYTE*)NULL , NULL , NULL , &s_153}; _DECL s_155 = { "MAKEDIR" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_154}; _DECL s_156 = { "MAX" , ' ', 2 , (BYTE*)" " , NULL , NULL , &s_155}; _DECL s_157 = { "MAXCOL" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_156}; _DECL s_158 = { "MAXROW" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_157}; _DECL s_159 = { "MCOL" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_158}; _DECL s_160 = { "MEMOEDIT" , 'C',13 , (BYTE*)"\x9d\xa8\xa8\xa8\xa8\xa6\x9d\xa8\xa8\xa8\xa8\xa8\xa8" , NULL , NULL , &s_159}; _DECL s_161 = { "MEMOTRAN" , 'C', 3 , (BYTE*)"C\x9d\x9d" , NULL , NULL , &s_160}; _DECL s_162 = { "MEMOLINE" , 'C', 5 , (BYTE*)"C\xa8\xa8\xa8\xa6" , NULL , NULL , &s_161}; _DECL s_163 = { "MEMORY" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_162}; _DECL s_164 = { "MEMOREAD" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_163}; _DECL s_165 = { "MEMOTRAN" , 'C', 3 , (BYTE*)"C\x9d\x9d" , NULL , NULL , &s_164}; _DECL s_166 = { "MEMOWRIT" , 'L', 2 , (BYTE*)"CC" , NULL , NULL , &s_165}; _DECL s_167 = { "MEMVARBLOCK" , 'B', 1 , (BYTE*)"C" , NULL , NULL , &s_166}; _DECL s_168 = { "MIN" , ' ', 2 , (BYTE*)" " , NULL , NULL , &s_167}; _DECL s_169 = { "MLCOUNT" , 'N', 4 , (BYTE*)"C\xa8\xa8\xa6" , NULL , NULL , &s_168}; _DECL s_170 = { "MLCTOPOS" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_169}; _DECL s_171 = { "MLPOS" , 'N', 5 , (BYTE*)"CNN\xa8\xa6" , NULL , NULL , &s_170}; _DECL s_172 = { "MOD" , 'N', 2 , (BYTE*)"NN" , NULL , NULL , &s_171}; _DECL s_173 = { "MONTH" , 'N', 1 , (BYTE*)"D" , NULL , NULL , &s_172}; _DECL s_174 = { "MPOSTOLC" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_173}; _DECL s_175 = { "MROW" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_174}; _DECL s_176 = { "NATIONMSG" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_175}; _DECL s_177 = { "NETERR" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_176}; _DECL s_178 = { "NETNAME" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_177}; _DECL s_179 = { "NEXTKEY" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_178}; _DECL s_180 = { "ORDBAGEXT" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_179}; _DECL s_181 = { "ORDBAGNAME" , 'C', 1 , (BYTE*)" " , NULL , NULL , &s_180}; _DECL s_182 = { "ORDCREATE" , '-', 5 , (BYTE*)"C\x9d \x9c\xa6" , NULL , NULL , &s_181}; _DECL s_183 = { "ORDDESTROY" , '-', 2 , (BYTE*)"C\x9d" , NULL , NULL , &s_182}; _DECL s_184 = { "ORDFOR" , 'C', 2 , (BYTE*)" \x9d" , NULL , NULL , &s_183}; _DECL s_185 = { "ORDKEY" , 'C', 2 , (BYTE*)" \x9d" , NULL , NULL , &s_184}; _DECL s_186 = { "ORDLISTADD" , '-', 2 , (BYTE*)"C\x9d" , NULL , NULL , &s_185}; _DECL s_187 = { "ORDLISTCLEAR" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_186}; _DECL s_188 = { "ORDLISTREBUILD" , '-', 0 , (BYTE*)NULL , NULL , NULL , &s_187}; _DECL s_189 = { "ORDNAME" , 'C', 2 , (BYTE*)"N\x9d" , NULL , NULL , &s_188}; _DECL s_190 = { "ORDNUMBER" , 'N', 2 , (BYTE*)"C\x9d" , NULL , NULL , &s_189}; _DECL s_191 = { "ORDSETFOCUS" , 'C', 2 , (BYTE*)"\x7a\x9d" , NULL , NULL , &s_190}; _DECL s_192 = { "OS" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_191}; _DECL s_193 = { "OUTERR" , '-', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_192}; _DECL s_194 = { "OUTSTD" , '-', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_193}; _DECL s_195 = { "PADC" , 'C', 3 , (BYTE*)" N\x9d" , NULL , NULL , &s_194}; _DECL s_196 = { "PADL" , 'C', 3 , (BYTE*)" N\x9d" , NULL , NULL , &s_195}; _DECL s_197 = { "PADR" , 'C', 3 , (BYTE*)" N\x9d" , NULL , NULL , &s_196}; _DECL s_198 = { "PCOL" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_197}; _DECL s_199 = { "PCOUNT" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_198}; _DECL s_200 = { "PROCFILE" , 'C', 1 , (BYTE*)"\x7a" , NULL , NULL , &s_199}; _DECL s_201 = { "PROCLINE" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_200}; _DECL s_202 = { "PROCNAME" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_201}; _DECL s_203 = { "PROW" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_202}; /* * Both QOUT and QQOUT can take from 0 to as many parameters as you like * of any type, so including them in the parameter checking is of no use, * because the list requires an upper limit and a type declaration for all * of the parameters. So instead of trying to fix the unfixable, I have * commented them out and fixed the linkage for s_206 to point to s_203. * - David G. Holm * * _DECL s_204 = { "QOUT" , '-', 2 , (BYTE*)"\x7a\x7a" , NULL , NULL , &s_203}; * _DECL s_205 = { "QQOUT" , '-', 2 , (BYTE*)"\x7a\x7a" , NULL , NULL , &s_204}; */ _DECL s_206 = { "RAT" , 'N', 2 , (BYTE*)"CC" , NULL , NULL , &s_203}; _DECL s_207 = { "RDDLIST" , 'A', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_206}; _DECL s_208 = { "RDDNAME" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_207}; _DECL s_209 = { "RDDSETDEFAULT" , 'C', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_208}; _DECL s_210 = { "READEXIT" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_209}; _DECL s_211 = { "READUPDATED" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_210}; _DECL s_212 = { "READINSERT" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_211}; _DECL s_213 = { "READKEY" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_212}; _DECL s_214 = { "READFORMAT" , 'B', 1 , (BYTE*)"B" , NULL , NULL , &s_213}; _DECL s_215 = { "READKILL" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_214}; _DECL s_216 = { "READMODAL" , 'L', 2 , (BYTE*)"A\xa8" , NULL , NULL , &s_215}; _DECL s_217 = { "READUPDATED" , 'L', 1 , (BYTE*)"\xa6" , NULL , NULL , &s_216}; _DECL s_218 = { "READVAR" , 'C', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_217}; _DECL s_219 = { "RECCOUNT" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_218}; _DECL s_220 = { "RECNO" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_219}; _DECL s_221 = { "RECSIZE" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_220}; _DECL s_222 = { "REPLICATE" , 'C', 2 , (BYTE*)"CN" , NULL , NULL , &s_221}; _DECL s_223 = { "RESTSCREEN" , '-', 5 , (BYTE*)"\xa8\xa8\xa8\xa8\x9d" , NULL , NULL , &s_222}; _DECL s_224 = { "RIGHT" , 'C', 2 , (BYTE*)"CN" , NULL , NULL , &s_223}; _DECL s_225 = { "RLOCK" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_224}; _DECL s_226 = { "ROUND" , 'N', 2 , (BYTE*)"NN" , NULL , NULL , &s_225}; _DECL s_227 = { "ROW" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_226}; _DECL s_228 = { "RTRIM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_227}; _DECL s_229 = { "SAVESCREEN" , '-', 4 , (BYTE*)"\xa8\xa8\xa8\xa8" , NULL , NULL , &s_228}; _DECL s_230 = { "SCROLL" , '-', 6 , (BYTE*)"\xa8\xa8\xa8\xa8\xa8\xa8" , NULL , NULL , &s_229}; _DECL s_231 = { "SECONDS" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_230}; _DECL s_232 = { "SECS" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_231}; _DECL s_233 = { "SELECT" , 'N', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_232}; _DECL s_234 = { "SET" , ' ', 3 , (BYTE*)"N\x7a\xa6" , NULL , NULL , &s_233}; _DECL s_235 = { "SETCOLOR" , 'C', 1 , (BYTE*)"\x9d" , NULL , NULL , &s_234}; _DECL s_236 = { "SETCURSOR" , 'N', 1 , (BYTE*)"\xa8" , NULL , NULL , &s_235}; _DECL s_237 = { "SETKEY" , ' ', 3 , (BYTE*)"N\x9c\x9c" , NULL , NULL , &s_236}; _DECL s_238 = { "SETMODE" , 'L', 2 , (BYTE*)"NN" , NULL , NULL , &s_237}; _DECL s_239 = { "SETPOS" , '-', 2 , (BYTE*)"NN" , NULL , NULL , &s_238}; _DECL s_240 = { "SETPRC" , '-', 2 , (BYTE*)"NN" , NULL , NULL , &s_239}; _DECL s_241 = { "SETTYPEAHEAD" , '-', 1 , (BYTE*)"N" , NULL , NULL , &s_240}; _DECL s_242 = { "SPACE" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_241}; _DECL s_243 = { "SQRT" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_242}; _DECL s_244 = { "STR" , 'C', 3 , (BYTE*)"N\xa8\xa8" , NULL , NULL , &s_243}; _DECL s_245 = { "STRTRAN" , 'C', 5 , (BYTE*)"CC\x9d\xa8\xa8" , NULL , NULL , &s_244}; _DECL s_246 = { "STRZERO" , 'C', 3 , (BYTE*)"N\xa8\xa8" , NULL , NULL , &s_245}; _DECL s_247 = { "STUFF" , 'C', 4 , (BYTE*)"CNNC" , NULL , NULL , &s_246}; _DECL s_248 = { "SUBSTR" , 'C', 3 , (BYTE*)"CN\xa8" , NULL , NULL , &s_247}; _DECL s_249 = { "TBROWSENEW" , 'O', 4 , (BYTE*)"NNNN" , NULL , NULL , &s_248}; _DECL s_250 = { "TBROWSEDB" , 'O', 4 , (BYTE*)"NNNN" , NULL , NULL , &s_249}; _DECL s_251 = { "TBCOLUMNNEW" , 'O', 2 , (BYTE*)"CB" , NULL , NULL , &s_250}; _DECL s_252 = { "TIME" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_251}; _DECL s_253 = { "TONE" , '-', 2 , (BYTE*)"NN" , NULL , NULL , &s_252}; _DECL s_254 = { "TRANSFORM" , 'C', 2 , (BYTE*)" C" , NULL , NULL , &s_253}; _DECL s_255 = { "TRIM" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_254}; _DECL s_256 = { "TYPE" , 'C', 1 , (BYTE*)" " , NULL , NULL , &s_255}; _DECL s_257 = { "U2BIN" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_256}; _DECL s_258 = { "UPDATED" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_257}; _DECL s_259 = { "UPPER" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_258}; _DECL s_260 = { "USED" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_259}; _DECL s_261 = { "VAL" , 'N', 1 , (BYTE*)"C" , NULL , NULL , &s_260}; _DECL s_262 = { "VALTYPE" , ' ', 1 , (BYTE*)" " , NULL , NULL , &s_261}; _DECL s_263 = { "VERSION" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_262}; _DECL s_264 = { "W2BIN" , 'C', 1 , (BYTE*)"N" , NULL , NULL , &s_263}; _DECL s_265 = { "WORD" , 'N', 1 , (BYTE*)"N" , NULL , NULL , &s_264}; _DECL s_266 = { "HB_FNAMESPLIT" , '-', 5 , (BYTE*)"C\x5c\x5c\x5c\x5c" , NULL , NULL , &s_265}; _DECL s_267 = { "HB_FNAMEMERGE" , 'C', 4 , (BYTE*)"CCCC" , NULL , NULL , &s_266}; /* TODO: Rest of Standard Functions. */ /* -------------------------------------------------- Standard Classes --------------------------------------------------- */ static COMCLASS s_ERROR = { "ERROR" , NULL, NULL, NULL }; static COMCLASS s_GET = { "GET" , NULL, NULL, NULL }; static COMCLASS s_TBCOLUMN = { "TBCOLUMN", NULL, NULL, NULL }; static COMCLASS s_TBROWSE = { "TBROWSE" , NULL, NULL, NULL }; /* Name Ret # of Prams Param Types Ret Class Param Classes Next --------------- --- ---------- -------------------- --------- ------------- --------------- */ _DECL s_ERROR_01 = { "ARGS" , 'A', 0 , (BYTE*)NULL , NULL , NULL , NULL }; _DECL s_ERROR_02 = { "CANDEFAULT" , 'B', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_01 }; _DECL s_ERROR_03 = { "CANRETRY" , 'B', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_02 }; _DECL s_ERROR_04 = { "CANSUBSTITUTE", 'B', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_03 }; _DECL s_ERROR_05 = { "CARGO" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_04 }; _DECL s_ERROR_06 = { "DESCRIPTION" , 'S', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_05 }; _DECL s_ERROR_07 = { "FILENAME" , 'S', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_06 }; _DECL s_ERROR_08 = { "GENCODE" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_07 }; _DECL s_ERROR_09 = { "OPERATION" , 'S', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_08 }; _DECL s_ERROR_10 = { "OSCODE" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_09 }; _DECL s_ERROR_11 = { "SEVERITY" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_10 }; _DECL s_ERROR_12 = { "SUBCODE" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_11 }; _DECL s_ERROR_13 = { "SUBSYSTEM" , 'S', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_12 }; _DECL s_ERROR_14 = { "TRIES" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_ERROR_13 }; /* Name Ret # of Prams Param Types Ret Class Param Classes Next --------------- --- ---------- -------------------- --------- ------------- --------------- */ _DECL s_GET_01 = { "ASSIGN" , ' ', 0 , (BYTE*)NULL , NULL , NULL , NULL }; _DECL s_GET_02 = { "COLORDISP" , 'S', 1 , (BYTE*)"\x9d" , &s_GET , NULL , &s_GET_01 }; _DECL s_GET_03 = { "DISPLAY" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_02 }; _DECL s_GET_04 = { "KILLFOCUS" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_03 }; _DECL s_GET_05 = { "PARSEPICT" , 'C', 1 , (BYTE*)"C" , NULL , NULL , &s_GET_04 }; _DECL s_GET_06 = { "RESET" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_05 }; _DECL s_GET_07 = { "SETFOCUS" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_06 }; _DECL s_GET_08 = { "UNDO" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_07 }; _DECL s_GET_09 = { "UNTRANSFORM" , 'S', 1 , (BYTE*)"\x9d" , &s_GET , NULL , &s_GET_08 }; _DECL s_GET_10 = { "UPDATEBUFFER" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_09 }; _DECL s_GET_11 = { "VARGET" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_GET_10 }; _DECL s_GET_12 = { "VARPUT" , ' ', 1 , (BYTE*)" " , NULL , NULL , &s_GET_11 }; _DECL s_GET_13 = { "END" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_12 }; _DECL s_GET_14 = { "HOME" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_13 }; _DECL s_GET_15 = { "LEFT" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_14 }; _DECL s_GET_16 = { "RIGHT" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_15 }; _DECL s_GET_17 = { "TODECPOS" , 'S', 0 , (BYTE*)"L" , &s_GET , NULL , &s_GET_16 }; _DECL s_GET_18 = { "WORDLEFT" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_17 }; _DECL s_GET_19 = { "WORDRIGHT" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_18 }; _DECL s_GET_20 = { "BACKSPACE" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_19 }; _DECL s_GET_21 = { "DELETE" , 'S', 1 , (BYTE*)"\xa6" , &s_GET , NULL , &s_GET_20 }; _DECL s_GET_22 = { "DELEND" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_21 }; _DECL s_GET_23 = { "DELLEFT" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_22 }; _DECL s_GET_24 = { "DELRIGHT" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_23 }; _DECL s_GET_25 = { "DELWORDLEFT" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_24 }; _DECL s_GET_26 = { "DELWORDRIGHT" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_25 }; _DECL s_GET_27 = { "INSERT" , 'S', 1 , (BYTE*)"C" , &s_GET , NULL , &s_GET_26 }; _DECL s_GET_28 = { "OVERSTRIKE" , 'S', 1 , (BYTE*)"C" , &s_GET , NULL , &s_GET_27 }; _DECL s_GET_29 = { "DELETEALL" , 'S', 0 , (BYTE*)NULL , &s_GET , NULL , &s_GET_28 }; _DECL s_GET_30 = { "ISEDITABLE" , 'L', 1 , (BYTE*)"N" , NULL , NULL , &s_GET_29 }; _DECL s_GET_31 = { "INPUT" , 'C', 0 , (BYTE*)"C" , NULL , NULL , &s_GET_30 }; _DECL s_GET_32 = { "PUTMASK" , 'C', 2 , (BYTE*)"CL" , NULL , NULL , &s_GET_31 }; _DECL s_GET_33 = { "HASSCROLL" , 'L', 0 , (BYTE*)NULL , NULL , NULL , &s_GET_32 }; /* Name Ret # of Prams Param Types Ret Class Param Classes Next --------------- --- ---------- -------------------- --------- ------------- --------------- */ _DECL s_TBCOLUMN_01 = { "BLOCK" , ' ', 0 , (BYTE*)NULL , NULL , NULL , NULL }; _DECL s_TBCOLUMN_02 = { "CARGO" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_01 }; _DECL s_TBCOLUMN_03 = { "COLORBLOCK" , 'A', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_02 }; _DECL s_TBCOLUMN_04 = { "COLSEP" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_03 }; _DECL s_TBCOLUMN_05 = { "DEFCOLOR" , 'A', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_04 }; _DECL s_TBCOLUMN_06 = { "FOOTING" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_05 }; _DECL s_TBCOLUMN_07 = { "FOOTSEP" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_06 }; _DECL s_TBCOLUMN_08 = { "HEADING" , 'C', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_07 }; _DECL s_TBCOLUMN_09 = { "PICTURE" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_08 }; _DECL s_TBCOLUMN_10 = { "WIDTH" , 'N', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_09 }; _DECL s_TBCOLUMN_11 = { "COLPOS" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_10 }; _DECL s_TBCOLUMN_12 = { "HEADSEP" , ' ', 0 , (BYTE*)NULL , NULL , NULL , &s_TBCOLUMN_11 }; /* TODO: Finish definition of GET, and add definitions for TBROWSE. */ #undef _DECL /* ------- */ /* First (bottom) Method */ s_ERROR.pMethod = &s_ERROR_14; /* Last (top) Method. */ s_ERROR.pLastMethod = &s_ERROR_01; /* Next class definition pointer */ s_ERROR.pNext = NULL; /* ------- */ /* First (bottom) Method */ s_GET.pMethod = &s_GET_33; /* Change to BOTTOM Method. */ /* Last (top) Method. */ s_GET.pLastMethod = &s_GET_01; /* Next class definition pointer */ s_GET.pNext = &s_ERROR; /* ------- */ /* First (bottom) Method */ s_TBCOLUMN.pMethod = &s_TBCOLUMN_12; /* Change to BOTTOM Method. */ /* Last (top) Method. */ s_TBCOLUMN.pLastMethod = &s_TBCOLUMN_01; /* Next class definition pointer */ s_TBCOLUMN.pNext = &s_GET; /* ------- */ /* First (bottom) Method */ s_TBROWSE.pMethod = NULL; /* Change to BOTTOM Method. */ /* Last (top) Method. */ s_TBROWSE.pLastMethod = NULL; /* Next class definition pointer */ s_TBROWSE.pNext = &s_TBCOLUMN; /* ------- */ HB_COMP_PARAM->pFirstDeclared = &s_267; /* Change to BOTTOM Function. */ HB_COMP_PARAM->pLastDeclared = &s_001; HB_COMP_PARAM->pReleaseDeclared = NULL; HB_COMP_PARAM->pFirstClass = &s_TBROWSE; HB_COMP_PARAM->pLastClass = &s_ERROR; HB_COMP_PARAM->pReleaseClass = NULL; } /* returns a symbol pointer from the symbol table * and sets its position in the symbol table. * NOTE: symbol's position number starts from 0 */ static PCOMDECLARED hb_compDeclaredFind( HB_COMP_DECL, char * szDeclaredName ) { PCOMDECLARED pSym = HB_COMP_PARAM->pFirstDeclared; while( pSym ) { if( ! strcmp( pSym->szName, szDeclaredName ) ) return pSym; pSym = pSym->pNext; } return NULL; } PCOMDECLARED hb_compDeclaredAdd( HB_COMP_DECL, char * szDeclaredName ) { PCOMDECLARED pDeclared; if( HB_COMP_PARAM->iWarnings < 3 ) return NULL; /*printf( "\nDeclaring Function: %s\n", szDeclaredName, NULL );*/ if( ( pDeclared = hb_compDeclaredFind( HB_COMP_PARAM, szDeclaredName ) ) != NULL ) { hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_DUP_DECLARATION, "Function", szDeclaredName ); /* Last declaration will take effect. */ pDeclared->cType = ' '; /* Not known yet */ pDeclared->cParamTypes = NULL; pDeclared->iParamCount = 0; pDeclared->pParamClasses = NULL; return pDeclared; } pDeclared = ( PCOMDECLARED ) hb_xgrab( sizeof( COMDECLARED ) ); pDeclared->szName = szDeclaredName; pDeclared->cType = ' '; /* Not known yet */ pDeclared->cParamTypes = NULL; pDeclared->iParamCount = 0; pDeclared->pParamClasses = NULL; pDeclared->pNext = NULL; HB_COMP_PARAM->pLastDeclared->pNext = pDeclared; HB_COMP_PARAM->pLastDeclared = pDeclared; if( ! HB_COMP_PARAM->pReleaseDeclared ) { HB_COMP_PARAM->pReleaseDeclared = pDeclared; } return pDeclared; } void hb_compDeclaredParameterAdd( HB_COMP_DECL, char * szVarName, BYTE cValueType ) { /* Nothing to do since no warnings requested.*/ if( HB_COMP_PARAM->iWarnings < 3 ) { HB_SYMBOL_UNUSED( szVarName ); return; } /* Either a Declared Function Parameter or a Declared Method Parameter. */ if( HB_COMP_PARAM->szDeclaredFun ) { /* Find the Declared Function owner of this parameter. */ PCOMDECLARED pDeclared = hb_compDeclaredFind( HB_COMP_PARAM, HB_COMP_PARAM->szDeclaredFun ); if( pDeclared ) { pDeclared->iParamCount++; /* TOFIX: these allocations causes memory leaks */ if( pDeclared->cParamTypes ) { pDeclared->cParamTypes = ( BYTE * ) hb_xrealloc( pDeclared->cParamTypes, pDeclared->iParamCount ); pDeclared->pParamClasses = ( PCOMCLASS * ) hb_xrealloc( pDeclared->pParamClasses, pDeclared->iParamCount * sizeof( PCOMCLASS ) ); } else { pDeclared->cParamTypes = ( BYTE * ) hb_xgrab( 1 ); pDeclared->pParamClasses = ( PCOMCLASS * ) hb_xgrab( sizeof( PCOMCLASS ) ); } pDeclared->cParamTypes[ pDeclared->iParamCount - 1 ] = cValueType; if( toupper( cValueType ) == 'S' ) { pDeclared->pParamClasses[ pDeclared->iParamCount - 1 ] = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->szFromClass ); /* Resetting */ HB_COMP_PARAM->szFromClass = NULL; } } } else /* Declared Method Parameter */ { /* printf( "\nAdding parameter: %s Type: %c In Method: %s Class: %s FROM CLASS: %s\n", szVarName, cValueType, HB_COMP_PARAM->pLastMethod->szName, HB_COMP_PARAM->pLastClass->szName, HB_COMP_PARAM->szFromClass ); */ HB_COMP_PARAM->pLastMethod->iParamCount++; /* TOFIX: these allocations causes memory leaks */ if( HB_COMP_PARAM->pLastMethod->cParamTypes ) { HB_COMP_PARAM->pLastMethod->cParamTypes = ( BYTE * ) hb_xrealloc( HB_COMP_PARAM->pLastMethod->cParamTypes, HB_COMP_PARAM->pLastMethod->iParamCount ); HB_COMP_PARAM->pLastMethod->pParamClasses = ( PCOMCLASS * ) hb_xrealloc( HB_COMP_PARAM->pLastMethod->pParamClasses, HB_COMP_PARAM->pLastMethod->iParamCount * sizeof( COMCLASS ) ); } else { HB_COMP_PARAM->pLastMethod->cParamTypes = ( BYTE * ) hb_xgrab( 1 ); HB_COMP_PARAM->pLastMethod->pParamClasses = ( PCOMCLASS * ) hb_xgrab( sizeof( COMCLASS ) ); } HB_COMP_PARAM->pLastMethod->cParamTypes[ HB_COMP_PARAM->pLastMethod->iParamCount - 1 ] = cValueType; if( toupper( cValueType ) == 'S' ) { HB_COMP_PARAM->pLastMethod->pParamClasses[ HB_COMP_PARAM->pLastMethod->iParamCount - 1 ] = hb_compClassFind( HB_COMP_PARAM, HB_COMP_PARAM->szFromClass ); /* printf( "\nParameter: %s FROM CLASS: %s\n", szVarName, HB_COMP_PARAM->pLastMethod->pParamClasses[ HB_COMP_PARAM->pLastMethod->iParamCount - 1 ]->szName ); */ /* Resetting */ HB_COMP_PARAM->szFromClass = NULL; } } } /* * FUNCTIONS */ static int hb_compSort_ULONG( const void * pLeft, const void * pRight ) { ULONG ulLeft = *( ( ULONG * ) ( pLeft ) ); ULONG ulRight = *( ( ULONG * ) ( pRight ) ); if( ulLeft == ulRight ) return 0 ; else if( ulLeft < ulRight ) return -1; else return 1; } /* Jump Optimizer and dummy code eliminator */ static void hb_compOptimizeJumps( HB_COMP_DECL ) { BYTE * pCode = HB_COMP_PARAM->functions.pLast->pCode; ULONG * pNOOPs, * pJumps; ULONG ulOptimized, ulNextByte, ulBytes2Copy, ulJumpAddr, iNOOP, iJump; BOOL fLineStrip = !HB_COMP_PARAM->fDebugInfo && HB_COMP_PARAM->fLineNumbers; int iPass; if( ! HB_COMP_ISSUPPORTED(HB_COMPFLAG_OPTJUMP) ) return; hb_compOptimizePCode( HB_COMP_PARAM, HB_COMP_PARAM->functions.pLast ); hb_compCodeTraceMarkDead( HB_COMP_PARAM, HB_COMP_PARAM->functions.pLast ); for( iPass = 0; iPass < 4 && !HB_COMP_PARAM->fExit; ++iPass ) { LONG lOffset; if( iPass == 3 && fLineStrip ) { hb_compStripFuncLines( HB_COMP_PARAM->functions.pLast ); fLineStrip = FALSE; } if( HB_COMP_PARAM->functions.pLast->iJumps > 0 ) { pJumps = HB_COMP_PARAM->functions.pLast->pJumps; iJump = HB_COMP_PARAM->functions.pLast->iJumps - 1; do { ulJumpAddr = pJumps[ iJump ]; /* * optimize existing jumps, it will be good to also join * unconditional jump chain calculating total jump offset but * it will be necessary to add some code to protect against * infinite loop which will appear when we add optimization * for the PCODE sequences like: * * HB_P_{FALSE|TRUE}, * [ no jump targets or stack modification here ] * HB_P_JUMP{FALSE|TRUE}*, * * I'll think about sth like that later, [druzus] */ switch( pCode[ ulJumpAddr ] ) { case HB_P_JUMPNEAR: if( ( signed char ) pCode[ ulJumpAddr + 1 ] == 2 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 2, FALSE, FALSE ); break; case HB_P_JUMPFALSENEAR: case HB_P_JUMPTRUENEAR: if( ( signed char ) pCode[ ulJumpAddr + 1 ] == 2 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 2, TRUE, FALSE ); break; case HB_P_JUMP: lOffset = HB_PCODE_MKSHORT( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 3 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 3, FALSE, FALSE ); else if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPNEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 1, FALSE, FALSE ); } break; case HB_P_JUMPFALSE: lOffset = HB_PCODE_MKSHORT( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 3 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 3, TRUE, FALSE ); else if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPFALSENEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 1, FALSE, FALSE ); } break; case HB_P_JUMPTRUE: lOffset = HB_PCODE_MKSHORT( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 3 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 3, TRUE, FALSE ); else if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPTRUENEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 1, FALSE, FALSE ); } break; case HB_P_JUMPFAR: lOffset = HB_PCODE_MKINT24( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 4 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 4, FALSE, FALSE ); else if( iPass > 0 && HB_LIM_INT16( lOffset ) ) { if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPNEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 2, FALSE, FALSE ); } else { pCode[ ulJumpAddr ] = HB_P_JUMP; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 3, 1, FALSE, FALSE ); } } break; case HB_P_JUMPFALSEFAR: lOffset = HB_PCODE_MKINT24( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 4 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 4, TRUE, FALSE ); else if( iPass > 0 && HB_LIM_INT16( lOffset ) ) { if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPFALSENEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 2, FALSE, FALSE ); } else { pCode[ ulJumpAddr ] = HB_P_JUMPFALSE; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 3, 1, FALSE, FALSE ); } } break; case HB_P_JUMPTRUEFAR: lOffset = HB_PCODE_MKINT24( &pCode[ ulJumpAddr + 1 ] ); if( lOffset == 4 ) hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr, 4, TRUE, FALSE ); else if( iPass > 0 && HB_LIM_INT16( lOffset ) ) { if( HB_LIM_INT8( lOffset ) ) { pCode[ ulJumpAddr ] = HB_P_JUMPTRUENEAR; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 2, 2, FALSE, FALSE ); } else { pCode[ ulJumpAddr ] = HB_P_JUMPTRUE; hb_compNOOPfill( HB_COMP_PARAM->functions.pLast, ulJumpAddr + 3, 1, FALSE, FALSE ); } } break; } /* remove dummy jumps (over dead code) */ if( pCode[ ulJumpAddr ] == HB_P_NOOP || pCode[ ulJumpAddr ] == HB_P_POP ) { if( HB_COMP_PARAM->functions.pLast->iJumps > iJump + 1 ) memmove( &pJumps[ iJump ], &pJumps[ iJump + 1 ], ( HB_COMP_PARAM->functions.pLast->iJumps - iJump - 1 ) * sizeof( ULONG ) ); HB_COMP_PARAM->functions.pLast->iJumps--; } } while( iJump-- ); if( HB_COMP_PARAM->functions.pLast->iJumps == 0 ) { hb_xfree( HB_COMP_PARAM->functions.pLast->pJumps ); HB_COMP_PARAM->functions.pLast->pJumps = NULL; } } if( HB_COMP_PARAM->functions.pLast->iNOOPs == 0 ) { if( iPass == 0 ) continue; if( fLineStrip ) hb_compStripFuncLines( HB_COMP_PARAM->functions.pLast ); if( HB_COMP_PARAM->functions.pLast->iNOOPs == 0 ) return; } pNOOPs = HB_COMP_PARAM->functions.pLast->pNOOPs; /* Needed so the pasting of PCODE pieces below will work correctly */ qsort( ( void * ) pNOOPs, HB_COMP_PARAM->functions.pLast->iNOOPs, sizeof( ULONG ), hb_compSort_ULONG ); if( HB_COMP_PARAM->functions.pLast->iJumps ) { LONG * plSizes, * plShifts; ULONG ulSize; pJumps = HB_COMP_PARAM->functions.pLast->pJumps; ulSize = sizeof( LONG ) * HB_COMP_PARAM->functions.pLast->iJumps; plSizes = ( LONG * ) hb_xgrab( ulSize ); plShifts = ( LONG * ) hb_xgrab( ulSize ); for( iJump = 0; iJump < HB_COMP_PARAM->functions.pLast->iJumps; iJump++ ) plSizes[ iJump ] = plShifts[ iJump ] = 0; /* First Scan NOOPS - Adjust Jump addresses. */ for( iNOOP = 0; iNOOP < HB_COMP_PARAM->functions.pLast->iNOOPs; iNOOP++ ) { /* Adjusting preceding jumps that pooint to code beyond the current NOOP or trailing backward jumps pointing to lower address. */ for( iJump = 0; iJump < HB_COMP_PARAM->functions.pLast->iJumps ; iJump++ ) { ulJumpAddr = pJumps[ iJump ]; switch( pCode[ ulJumpAddr ] ) { case HB_P_JUMPNEAR: case HB_P_JUMPFALSENEAR: case HB_P_JUMPTRUENEAR: lOffset = ( signed char ) pCode[ ulJumpAddr + 1 ]; break; case HB_P_JUMP: case HB_P_JUMPFALSE: case HB_P_JUMPTRUE: lOffset = HB_PCODE_MKSHORT( &pCode[ ulJumpAddr + 1 ] ); break; case HB_P_JUMPFAR: case HB_P_JUMPTRUEFAR: case HB_P_JUMPFALSEFAR: case HB_P_ALWAYSBEGIN: case HB_P_SEQALWAYS: case HB_P_SEQBEGIN: case HB_P_SEQEND: lOffset = HB_PCODE_MKINT24( &pCode[ ulJumpAddr + 1 ] ); break; default: hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_NOT_FOUND, NULL, NULL ); continue; } /* update jump size */ if( lOffset > 0 ) /* forward (positive) jump */ { /* Only if points to code beyond the current fix. */ if( pNOOPs[ iNOOP ] > ulJumpAddr && pNOOPs[ iNOOP ] < ( ULONG ) ( ulJumpAddr + lOffset ) ) plSizes[ iJump ]--; } else /* if( lOffset < 0 ) - backword (negative) jump */ { /* Only if points to code prior the current fix. */ if( pNOOPs[ iNOOP ] < ulJumpAddr && pNOOPs[ iNOOP ] >= ( ULONG ) ( ulJumpAddr + lOffset ) ) plSizes[ iJump ]++; } /* update jump address */ if( pNOOPs[ iNOOP ] < ulJumpAddr ) plShifts[ iJump ]++; } } for( iJump = 0; iJump < HB_COMP_PARAM->functions.pLast->iJumps; iJump++ ) { lOffset = plSizes[ iJump ]; if( lOffset != 0 ) { ulJumpAddr = pJumps[ iJump ]; switch( pCode[ ulJumpAddr ] ) { case HB_P_JUMPNEAR: case HB_P_JUMPFALSENEAR: case HB_P_JUMPTRUENEAR: lOffset += ( signed char ) pCode[ ulJumpAddr + 1 ]; pCode[ ulJumpAddr + 1 ] = HB_LOBYTE( lOffset ); break; case HB_P_JUMP: case HB_P_JUMPFALSE: case HB_P_JUMPTRUE: lOffset += HB_PCODE_MKSHORT( &pCode[ ulJumpAddr + 1 ] ); HB_PUT_LE_UINT16( &pCode[ ulJumpAddr + 1 ], lOffset ); break; default: lOffset += HB_PCODE_MKINT24( &pCode[ ulJumpAddr + 1 ] ); HB_PUT_LE_UINT24( &pCode[ ulJumpAddr + 1 ], lOffset ); break; } } pJumps[ iJump ] -= plShifts[ iJump ]; } hb_xfree( plSizes ); hb_xfree( plShifts ); } ulOptimized = ulNextByte = 0; /* Second Scan, after all adjustements been made, we can copy the optimized code. */ for( iNOOP = 0; iNOOP < HB_COMP_PARAM->functions.pLast->iNOOPs; iNOOP++ ) { ulBytes2Copy = ( pNOOPs[ iNOOP ] - ulNextByte ) ; memmove( pCode + ulOptimized, pCode + ulNextByte, ulBytes2Copy ); ulOptimized += ulBytes2Copy; ulNextByte += ulBytes2Copy; /* Skip the NOOP and point to next valid byte */ ulNextByte++; } ulBytes2Copy = ( HB_COMP_PARAM->functions.pLast->lPCodePos - ulNextByte ) ; memmove( pCode + ulOptimized, pCode + ulNextByte, ulBytes2Copy ); ulOptimized += ulBytes2Copy; HB_COMP_PARAM->functions.pLast->lPCodePos = ulOptimized; HB_COMP_PARAM->functions.pLast->lPCodeSize = ulOptimized; hb_xfree( HB_COMP_PARAM->functions.pLast->pNOOPs ); HB_COMP_PARAM->functions.pLast->pNOOPs = NULL; HB_COMP_PARAM->functions.pLast->iNOOPs = 0; if( iPass <= 1 ) { hb_compOptimizePCode( HB_COMP_PARAM, HB_COMP_PARAM->functions.pLast ); hb_compCodeTraceMarkDead( HB_COMP_PARAM, HB_COMP_PARAM->functions.pLast ); } } } static void hb_compOptimizeFrames( HB_COMP_DECL, PFUNCTION pFunc ) { USHORT w; if( pFunc == NULL ) return; if( pFunc == HB_COMP_PARAM->pInitFunc ) { if( pFunc->pCode[ 0 ] == HB_P_STATICS && pFunc->pCode[ 5 ] == HB_P_SFRAME ) { hb_compSymbolFind( HB_COMP_PARAM, HB_COMP_PARAM->pInitFunc->szName, &w, HB_SYM_FUNCNAME ); pFunc->pCode[ 1 ] = HB_LOBYTE( w ); pFunc->pCode[ 2 ] = HB_HIBYTE( w ); pFunc->pCode[ 6 ] = HB_LOBYTE( w ); pFunc->pCode[ 7 ] = HB_HIBYTE( w ); /* Remove the SFRAME pcode if there's no global static initialization: */ /* NOTE: For some reason this will not work for the static init function, so I'm using an ugly hack instead. [vszakats] */ /* if( !( pFunc->bFlags & FUN_USES_STATICS ) ) */ if( pFunc->pCode[ 8 ] == HB_P_ENDPROC ) { pFunc->lPCodePos -= 3; memmove( pFunc->pCode + 5, pFunc->pCode + 8, pFunc->lPCodePos - 5 ); } else /* Check Global Statics. */ { /* PVAR pVar = pFunc->pStatics; */ PVAR pVar = HB_COMP_PARAM->functions.pFirst->pStatics; while( pVar ) { /*printf( "\nChecking: %s Used: %i\n", pVar->szName, pVar->iUsed );*/ if( ! ( pVar->iUsed & VU_USED ) && (pVar->iUsed & VU_INITIALIZED) ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_VAL_NOT_USED, pVar->szName, NULL ); /* May have been initialized in previous execution of the function. else if( ( pVar->iUsed & VU_USED ) && ! ( pVar->iUsed & VU_INITIALIZED ) ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_NOT_INITIALIZED, pVar->szName, NULL ); */ pVar = pVar->pNext; } } } } else if( pFunc->pCode[ 0 ] == HB_P_FRAME && pFunc->pCode[ 3 ] == HB_P_SFRAME ) { PVAR pLocal; int iLocals = 0, iOffset = 0; BOOL bSkipFRAME; BOOL bSkipSFRAME; pLocal = pFunc->pLocals; while( pLocal ) { pLocal = pLocal->pNext; iLocals++; } if( pFunc->bFlags & FUN_USES_STATICS ) { hb_compSymbolFind( HB_COMP_PARAM, HB_COMP_PARAM->pInitFunc->szName, &w, HB_SYM_FUNCNAME ); pFunc->pCode[ 4 ] = HB_LOBYTE( w ); pFunc->pCode[ 5 ] = HB_HIBYTE( w ); bSkipSFRAME = FALSE; } else bSkipSFRAME = TRUE; if( iLocals || pFunc->wParamCount ) { /* Parameters declared with PARAMETERS statement are not * placed in the local variable list. */ if( pFunc->bFlags & FUN_USES_LOCAL_PARAMS ) iLocals -= pFunc->wParamCount; if( iLocals > 255 ) { /* more then 255 local variables, * make a room for HB_P_LARGE[V]FRAME */ hb_compGenPCode1( 0, HB_COMP_PARAM ); memmove( pFunc->pCode + 4, pFunc->pCode + 3, pFunc->lPCodePos - 4 ); pFunc->pCode[ 0 ] = HB_P_LARGEFRAME; pFunc->pCode[ 1 ] = HB_LOBYTE( iLocals ); pFunc->pCode[ 2 ] = HB_HIBYTE( iLocals ); pFunc->pCode[ 3 ] = ( BYTE )( pFunc->wParamCount ); iOffset = 1; } else { pFunc->pCode[ 1 ] = ( BYTE )( iLocals ); pFunc->pCode[ 2 ] = ( BYTE )( pFunc->wParamCount ); } bSkipFRAME = FALSE; } else /* Skip LOCALs frame only when function is not declared with * variable number of parameters (HB_P_[LARGE]VFRAME) */ bSkipFRAME = !pFunc->fVParams; /* Remove the frame pcodes if they are not needed */ if( bSkipFRAME ) { if( bSkipSFRAME ) { pFunc->lPCodePos -= 6; memmove( pFunc->pCode, pFunc->pCode + 6, pFunc->lPCodePos ); } else { pFunc->lPCodePos -= 3; memmove( pFunc->pCode, pFunc->pCode + 3, pFunc->lPCodePos ); } } else { if( pFunc->fVParams ) pFunc->pCode[ 0 ] = iOffset ? HB_P_LARGEVFRAME : HB_P_VFRAME; if( bSkipSFRAME ) { pFunc->lPCodePos -= 3; memmove( pFunc->pCode + 3 + iOffset, pFunc->pCode + 6 + iOffset, pFunc->lPCodePos - 3 - iOffset ); } } } } static void hb_compFinalizeFunction( HB_COMP_DECL ) /* fixes all last defined function returns jumps offsets */ { PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast; if( pFunc ) { if( ( pFunc->bFlags & FUN_WITH_RETURN ) == 0 ) { /* The last statement in a function/procedure was not a RETURN * Generate end-of-procedure pcode */ hb_compGenPCode1( HB_P_ENDPROC, HB_COMP_PARAM ); } hb_compCheckUnclosedStru( HB_COMP_PARAM, pFunc ); hb_compRTVariableKill( HB_COMP_PARAM, pFunc ); hb_compSwitchKill( HB_COMP_PARAM, pFunc ); hb_compElseIfKill( pFunc ); hb_compLoopKill( pFunc ); if( !pFunc->bError ) { if( pFunc->wParamCount && !( pFunc->bFlags & FUN_USES_LOCAL_PARAMS ) ) { /* There was a PARAMETERS statement used. * NOTE: This fixes local variables references in a case when * there is PARAMETERS statement after a LOCAL variable declarations. * All local variables are numbered from 1 - which means use first * item from the eval stack. However if PARAMETERS statement is used * then there are additional items on the eval stack - the * function arguments. Then first local variable is at the position * (1 + ). We cannot fix this numbering * because the PARAMETERS statement can be used even at the end * of function body when all local variables are already created. */ hb_compFixFuncPCode( HB_COMP_PARAM, pFunc ); } hb_compOptimizeJumps( HB_COMP_PARAM ); } if( HB_COMP_PARAM->iWarnings ) { PVAR pVar; pVar = pFunc->pLocals; while( pVar ) { if( pVar->szName && pFunc->szName && pFunc->szName[0] && (! ( pVar->iUsed & VU_USED )) ) { char szFun[ 256 ]; snprintf( szFun, sizeof( szFun ), "%s(%i)", pFunc->szName, pVar->iDeclLine ); hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_VAR_NOT_USED, pVar->szName, szFun ); } pVar = pVar->pNext; } pVar = pFunc->pStatics; while( pVar ) { if( pVar->szName && pFunc->szName && pFunc->szName[0] && ! ( pVar->iUsed & VU_USED ) ) { char szFun[ 256 ]; snprintf( szFun, sizeof( szFun ), "%s(%i)", pFunc->szName, pVar->iDeclLine ); hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_VAR_NOT_USED, pVar->szName, szFun ); } pVar = pVar->pNext; } /* Check if the function returned some value */ if( (pFunc->bFlags & FUN_WITH_RETURN) == 0 && (pFunc->bFlags & FUN_PROCEDURE) == 0 ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_FUN_WITH_NO_RETURN, pFunc->szName, NULL ); } } } /* * This function creates and initialises the _FUNC structure */ static PFUNCTION hb_compFunctionNew( HB_COMP_DECL, char * szName, HB_SYMBOLSCOPE cScope ) { PFUNCTION pFunc; pFunc = ( PFUNCTION ) hb_xgrab( sizeof( _FUNC ) ); memset( pFunc, 0, sizeof( _FUNC ) ); pFunc->szName = szName; pFunc->cScope = cScope; pFunc->iStaticsBase = HB_COMP_PARAM->iStaticCnt; pFunc->bLateEval = TRUE; pFunc->fVParams = FALSE; pFunc->bError = FALSE; return pFunc; } static PINLINE hb_compInlineNew( HB_COMP_DECL, char * szName, int iLine ) { PINLINE pInline; pInline = ( PINLINE ) hb_xgrab( sizeof( _INLINE ) ); pInline->szName = szName; pInline->pCode = NULL; pInline->lPCodeSize = 0; pInline->pNext = NULL; pInline->szFileName = hb_compIdentifierNew( HB_COMP_PARAM, hb_pp_fileName( HB_COMP_PARAM->pLex->pPP ), HB_IDENT_COPY ); pInline->iLine = iLine; return pInline; } /* NOTE: Names of variables and functions are released in hbident.c on exit */ static PFUNCTION hb_compFunctionKill( HB_COMP_DECL, PFUNCTION pFunc ) { PFUNCTION pNext = pFunc->pNext; HB_ENUMERATOR_PTR pEVar; PVAR pVar; hb_compRTVariableKill( HB_COMP_PARAM, pFunc ); hb_compSwitchKill( HB_COMP_PARAM, pFunc ); hb_compElseIfKill( pFunc ); hb_compLoopKill( pFunc ); while( pFunc->pLocals ) { pVar = pFunc->pLocals; pFunc->pLocals = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pStatics ) { pVar = pFunc->pStatics; pFunc->pStatics = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pFields ) { pVar = pFunc->pFields; pFunc->pFields = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pMemvars ) { pVar = pFunc->pMemvars; pFunc->pMemvars = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pDetached ) { pVar = pFunc->pDetached; pFunc->pDetached = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pPrivates ) { pVar = pFunc->pPrivates; pFunc->pPrivates = pVar->pNext; hb_xfree( ( void * ) pVar ); } while( pFunc->pEnum ) { pEVar = pFunc->pEnum; pFunc->pEnum = pEVar->pNext; hb_xfree( pEVar ); } /* Release the NOOP array. */ if( pFunc->pNOOPs ) hb_xfree( ( void * ) pFunc->pNOOPs ); /* Release the Jumps array. */ if( pFunc->pJumps ) hb_xfree( ( void * ) pFunc->pJumps ); hb_xfree( ( void * ) pFunc->pCode ); hb_xfree( ( void * ) pFunc ); return pNext; } /* * This function adds the name of called function into the list * as they have to be placed on the symbol table later than the * first public symbol */ static PFUNCALL hb_compFunCallAdd( HB_COMP_DECL, char * szFunctionName ) { PFUNCALL pFunc = ( PFUNCALL ) hb_xgrab( sizeof( _FUNCALL ) ); pFunc->szName = szFunctionName; pFunc->pNext = NULL; if( ! HB_COMP_PARAM->funcalls.iCount ) { HB_COMP_PARAM->funcalls.pFirst = pFunc; HB_COMP_PARAM->funcalls.pLast = pFunc; } else { HB_COMP_PARAM->funcalls.pLast->pNext = pFunc; HB_COMP_PARAM->funcalls.pLast = pFunc; } HB_COMP_PARAM->funcalls.iCount++; return pFunc; } /* * This function adds the name of external symbol into the list of externals * as they have to be placed on the symbol table later than the first * public symbol */ void hb_compExternAdd( HB_COMP_DECL, char * szExternName, HB_SYMBOLSCOPE cScope ) /* defines a new extern name */ { PEXTERN pExtern = ( PEXTERN ) hb_xgrab( sizeof( _EXTERN ) ), pLast; if( strcmp( "_GET_", szExternName ) == 0 ) { /* special function to implement @ GET statement */ hb_compExternAdd( HB_COMP_PARAM, "__GETA", 0 ); pExtern->szName = "__GET"; } else { pExtern->szName = szExternName; } pExtern->cScope = cScope; pExtern->pNext = NULL; if( HB_COMP_PARAM->externs == NULL ) HB_COMP_PARAM->externs = pExtern; else { pLast = HB_COMP_PARAM->externs; while( pLast->pNext ) pLast = pLast->pNext; pLast->pNext = pExtern; } } static void hb_compAddFunc( HB_COMP_DECL, PFUNCTION pFunc ) { while( HB_COMP_PARAM->functions.pLast && !HB_COMP_PARAM->functions.pLast->szName ) { PFUNCTION pBlock = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->functions.pLast = pBlock->pOwner; hb_compFunctionKill( HB_COMP_PARAM, pBlock ); } if( HB_COMP_PARAM->functions.iCount == 0 ) HB_COMP_PARAM->functions.pFirst = pFunc; else HB_COMP_PARAM->functions.pLast->pNext = pFunc; HB_COMP_PARAM->functions.pLast = pFunc; HB_COMP_PARAM->functions.iCount++; } /* * Stores a Clipper defined function/procedure * szFunName - name of a function * cScope - scope of a function * iType - FUN_PROCEDURE if a procedure or 0 */ void hb_compFunctionAdd( HB_COMP_DECL, char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) { PCOMSYMBOL pSym; PFUNCTION pFunc; char * szFunction; hb_compFinalizeFunction( HB_COMP_PARAM ); /* fix all previous function returns offsets */ if( cScope & (HB_FS_INIT | HB_FS_EXIT) ) { char szNewName[ HB_SYMBOL_NAME_LEN + 1 ]; int iLen; iLen = strlen( szFunName ); if( iLen >= HB_SYMBOL_NAME_LEN ) iLen = HB_SYMBOL_NAME_LEN - 1; memcpy( szNewName, szFunName, iLen ); szNewName[ iLen ] ='$'; szNewName[ iLen + 1 ] = '\0'; szFunName = hb_compIdentifierNew( HB_COMP_PARAM, szNewName, HB_IDENT_COPY ); } pFunc = hb_compFunctionFind( HB_COMP_PARAM, szFunName ); if( pFunc ) { /* The name of a function/procedure is already defined */ if( pFunc != HB_COMP_PARAM->functions.pFirst || HB_COMP_PARAM->fStartProc ) /* it is not a starting procedure that was automatically created */ hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_FUNC_DUPL, szFunName, NULL ); } szFunction = hb_compReservedName( szFunName ); if( szFunction && !( HB_COMP_PARAM->functions.iCount == 0 && !HB_COMP_PARAM->fStartProc ) ) { /* We are ignoring it when it is the name of PRG file and we are * not creating implicit starting procedure */ hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_FUNC_RESERVED, szFunction, szFunName ); } HB_COMP_PARAM->iFunctionCnt++; pSym = hb_compSymbolFind( HB_COMP_PARAM, szFunName, NULL, HB_SYM_FUNCNAME ); if( ! pSym ) { /* there is not a symbol on the symbol table for this function name */ pSym = hb_compSymbolAdd( HB_COMP_PARAM, szFunName, NULL, HB_SYM_FUNCNAME ); } if( pSym ) pSym->cScope |= cScope | HB_FS_LOCAL; pFunc = hb_compFunctionNew( HB_COMP_PARAM, szFunName, cScope ); pFunc->bFlags |= iType; hb_compAddFunc( HB_COMP_PARAM, pFunc ); HB_COMP_PARAM->lastLinePos = 0; /* optimization of line numbers opcode generation */ HB_COMP_PARAM->ilastLineErr = 0; /* position of last syntax error (line number) */ hb_compGenPCode3( HB_P_FRAME, 0, 0, HB_COMP_PARAM ); /* frame for locals and parameters */ hb_compGenPCode3( HB_P_SFRAME, 0, 0, HB_COMP_PARAM ); /* frame for statics variables */ if( HB_COMP_PARAM->fDebugInfo ) hb_compGenModuleName( HB_COMP_PARAM, szFunName ); else HB_COMP_PARAM->lastLine = -1; } PINLINE hb_compInlineAdd( HB_COMP_DECL, char * szFunName, int iLine ) { PINLINE pInline; PCOMSYMBOL pSym; if( szFunName ) { pSym = hb_compSymbolFind( HB_COMP_PARAM, szFunName, NULL, HB_SYM_FUNCNAME ); if( ! pSym ) { pSym = hb_compSymbolAdd( HB_COMP_PARAM, szFunName, NULL, HB_SYM_FUNCNAME ); } if( pSym ) { pSym->cScope |= HB_FS_STATIC | HB_FS_LOCAL; } } pInline = hb_compInlineNew( pComp, szFunName, iLine ); if( HB_COMP_PARAM->inlines.iCount == 0 ) { HB_COMP_PARAM->inlines.pFirst = pInline; HB_COMP_PARAM->inlines.pLast = pInline; } else { HB_COMP_PARAM->inlines.pLast->pNext = pInline; HB_COMP_PARAM->inlines.pLast = pInline; } HB_COMP_PARAM->inlines.iCount++; return pInline; } /* create an ANNOUNCEd procedure */ void hb_compAnnounce( HB_COMP_DECL, char * szFunName ) { PFUNCTION pFunc; pFunc = hb_compFunctionFind( HB_COMP_PARAM, szFunName ); if( pFunc ) { /* there is a function/procedure defined already - ANNOUNCEd procedure * have to be a public symbol - check if existing symbol is public */ if( pFunc->cScope & HB_FS_STATIC ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_FUNC_ANNOUNCE, szFunName, NULL ); } else { PCOMSYMBOL pSym; /* create a new procedure */ pSym = hb_compSymbolAdd( HB_COMP_PARAM, szFunName, NULL, HB_SYM_FUNCNAME ); pSym->cScope = HB_FS_PUBLIC | HB_FS_LOCAL; pFunc = hb_compFunctionNew( HB_COMP_PARAM, szFunName, pSym->cScope ); pFunc->bFlags |= FUN_PROCEDURE; hb_compAddFunc( HB_COMP_PARAM, pFunc ); HB_COMP_PARAM->iFunctionCnt++; /* this function have a very limited functionality */ hb_compGenPCode1( HB_P_ENDPROC, HB_COMP_PARAM ); } } void hb_compGenBreak( HB_COMP_DECL ) { hb_compGenPushFunCall( "BREAK", HB_COMP_PARAM ); } void hb_compExternGen( HB_COMP_DECL ) /* generates the symbols for the EXTERN names */ { PEXTERN pDelete; if( HB_COMP_PARAM->fDebugInfo ) hb_compExternAdd( HB_COMP_PARAM, "__DBGENTRY", 0 ); while( HB_COMP_PARAM->externs ) { PCOMSYMBOL pSym = hb_compSymbolFind( HB_COMP_PARAM, HB_COMP_PARAM->externs->szName, NULL, HB_SYM_FUNCNAME ); if( pSym ) { if( ! hb_compFunCallFind( HB_COMP_PARAM, HB_COMP_PARAM->externs->szName ) ) hb_compFunCallAdd( HB_COMP_PARAM, HB_COMP_PARAM->externs->szName ); } else { pSym = hb_compSymbolAdd( HB_COMP_PARAM, HB_COMP_PARAM->externs->szName, NULL, HB_SYM_FUNCNAME ); hb_compFunCallAdd( HB_COMP_PARAM, HB_COMP_PARAM->externs->szName ); } pSym->cScope |= HB_COMP_PARAM->externs->cScope; pDelete = HB_COMP_PARAM->externs; HB_COMP_PARAM->externs = HB_COMP_PARAM->externs->pNext; hb_xfree( ( void * ) pDelete ); } } PFUNCALL hb_compFunCallFind( HB_COMP_DECL, char * szFunctionName ) /* returns a previously called defined function */ { PFUNCALL pFunc = HB_COMP_PARAM->funcalls.pFirst; while( pFunc ) { if( ! strcmp( pFunc->szName, szFunctionName ) ) break; pFunc = pFunc->pNext; } return pFunc; } PFUNCTION hb_compFunctionFind( HB_COMP_DECL, char * szFunctionName ) /* returns a previously defined function */ { PFUNCTION pFunc = HB_COMP_PARAM->functions.pFirst; while( pFunc ) { if( ! strcmp( pFunc->szName, szFunctionName ) ) break; pFunc = pFunc->pNext; } return pFunc; } PINLINE hb_compInlineFind( HB_COMP_DECL, char * szFunctionName ) { PINLINE pInline = HB_COMP_PARAM->inlines.pFirst; while( pInline ) { if( pInline->szName && strcmp( pInline->szName, szFunctionName ) == 0 ) break; pInline = pInline->pNext; } return pInline; } /* check if function exists, ignore case of letters in function name */ static BOOL hb_compIsFunction( HB_COMP_DECL, char * szFunctionName ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pFirst; while( pFunc ) { if( ! hb_stricmp( pFunc->szName, szFunctionName ) ) break; pFunc = pFunc->pNext; } return pFunc != NULL; } static void hb_compNOOPadd( PFUNCTION pFunc, ULONG ulPos ) { pFunc->pCode[ ulPos ] = HB_P_NOOP; if( pFunc->iNOOPs ) pFunc->pNOOPs = ( ULONG * ) hb_xrealloc( pFunc->pNOOPs, sizeof( ULONG ) * ( pFunc->iNOOPs + 1 ) ); else pFunc->pNOOPs = ( ULONG * ) hb_xgrab( sizeof( ULONG ) ); pFunc->pNOOPs[ pFunc->iNOOPs++ ] = ulPos; } /* NOTE: To disable jump optimization, just make this function a dummy one. [vszakats] */ static void hb_compPrepareOptimize( HB_COMP_DECL ) { if( HB_COMP_ISSUPPORTED(HB_COMPFLAG_OPTJUMP) ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast; if( pFunc->iJumps ) pFunc->pJumps = ( ULONG * ) hb_xrealloc( pFunc->pJumps, sizeof( ULONG ) * ( pFunc->iJumps + 1 ) ); else pFunc->pJumps = ( ULONG * ) hb_xgrab( sizeof( ULONG ) ); pFunc->pJumps[ pFunc->iJumps++ ] = ( ULONG ) ( pFunc->lPCodePos - 4 ); } } ULONG hb_compGenJump( LONG lOffset, HB_COMP_DECL ) { if( !HB_LIM_INT24( lOffset ) ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); hb_compGenPCode4( HB_P_JUMPFAR, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), ( BYTE ) ( ( lOffset >> 16 ) & 0xFF ), HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } ULONG hb_compGenJumpFalse( LONG lOffset, HB_COMP_DECL ) { if( !HB_LIM_INT24( lOffset ) ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); hb_compGenPCode4( HB_P_JUMPFALSEFAR, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), ( BYTE ) ( ( lOffset >> 16 ) & 0xFF ), HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } ULONG hb_compGenJumpTrue( LONG lOffset, HB_COMP_DECL ) { if( !HB_LIM_INT24( lOffset ) ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); hb_compGenPCode4( HB_P_JUMPTRUEFAR, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), ( BYTE ) ( ( lOffset >> 16 ) & 0xFF ), HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo, HB_COMP_DECL ) { BYTE * pCode = HB_COMP_PARAM->functions.pLast->pCode; LONG lOffset = ulTo - ulFrom + 1; if( HB_LIM_INT24( lOffset ) ) { HB_PUT_LE_UINT24( &pCode[ ulFrom ], lOffset ); } else hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_JUMP_TOO_LONG, NULL, NULL ); } void hb_compGenJumpHere( ULONG ulOffset, HB_COMP_DECL ) { hb_compGenJumpThere( ulOffset, HB_COMP_PARAM->functions.pLast->lPCodePos, HB_COMP_PARAM ); } void hb_compLinePush( HB_COMP_DECL ) /* generates the pcode with the currently compiled source code line */ { if( HB_COMP_PARAM->fLineNumbers ) { if( HB_COMP_PARAM->fDebugInfo && HB_COMP_PARAM->lastModule != HB_COMP_PARAM->currModule ) { if( HB_COMP_PARAM->functions.pLast->pCode[ HB_COMP_PARAM->lastLinePos ] == HB_P_LINE && HB_COMP_PARAM->functions.pLast->lPCodePos - HB_COMP_PARAM->lastLinePos == 3 ) HB_COMP_PARAM->functions.pLast->lPCodePos -= 3; hb_compGenModuleName( HB_COMP_PARAM, NULL ); } if( HB_COMP_PARAM->currLine != HB_COMP_PARAM->lastLine ) { if( HB_COMP_PARAM->functions.pLast->lPCodePos - HB_COMP_PARAM->lastLinePos == 3 && HB_COMP_PARAM->functions.pLast->pCode[ HB_COMP_PARAM->lastLinePos ] == HB_P_LINE ) { HB_COMP_PARAM->functions.pLast->pCode[ HB_COMP_PARAM->lastLinePos + 1 ] = HB_LOBYTE( HB_COMP_PARAM->currLine ); HB_COMP_PARAM->functions.pLast->pCode[ HB_COMP_PARAM->lastLinePos + 2 ] = HB_HIBYTE( HB_COMP_PARAM->currLine ); } else { HB_COMP_PARAM->lastLinePos = HB_COMP_PARAM->functions.pLast->lPCodePos; hb_compGenPCode3( HB_P_LINE, HB_LOBYTE( HB_COMP_PARAM->currLine ), HB_HIBYTE( HB_COMP_PARAM->currLine ), HB_COMP_PARAM ); } HB_COMP_PARAM->lastLine = HB_COMP_PARAM->currLine; } } if( HB_COMP_PARAM->functions.pLast->bFlags & FUN_BREAK_CODE ) { /* previous line contained RETURN/BREAK/LOOP/EXIT statement */ hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_UNREACHABLE, NULL, NULL ); /* clear RETURN/BREAK flag */ HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( /*FUN_WITH_RETURN |*/ FUN_BREAK_CODE ); } } /* * Test if we can generate statement (without line pushing) */ void hb_compStatmentStart( HB_COMP_DECL ) { if( ( HB_COMP_PARAM->functions.pLast->bFlags & FUN_STATEMENTS ) == 0 ) { if( ! HB_COMP_PARAM->fStartProc && HB_COMP_PARAM->functions.iCount <= 1 && HB_COMP_PARAM->functions.pLast != HB_COMP_PARAM->pInitFunc && HB_COMP_PARAM->functions.pLast->szName ) { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_OUTSIDE, NULL, NULL ); return; } HB_COMP_PARAM->functions.pLast->bFlags |= FUN_STATEMENTS; } } void hb_compLinePushIfInside( HB_COMP_DECL ) /* generates the pcode with the currently compiled source code line */ { hb_compStatmentStart( HB_COMP_PARAM ); hb_compLinePush( HB_COMP_PARAM ); } /* Generates the pcode with the currently compiled source code line * if debug code was requested only */ void hb_compLinePushIfDebugger( HB_COMP_DECL ) { hb_compStatmentStart( HB_COMP_PARAM ); if( HB_COMP_PARAM->fDebugInfo ) hb_compLinePush( HB_COMP_PARAM ); else { if( HB_COMP_PARAM->functions.pLast->bFlags & FUN_BREAK_CODE ) { /* previous line contained RETURN/BREAK/LOOP/EXIT statement */ hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_UNREACHABLE, NULL, NULL ); } HB_COMP_PARAM->functions.pLast->bFlags &= ~ ( /*FUN_WITH_RETURN |*/ FUN_BREAK_CODE ); /* clear RETURN flag */ } } /* generates the pcode with the currently compiled module and function name */ void hb_compGenModuleName( HB_COMP_DECL, char * szFunName ) { hb_compGenPCode1( HB_P_MODULENAME, HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) HB_COMP_PARAM->currModule, strlen( HB_COMP_PARAM->currModule ), HB_COMP_PARAM ); hb_compGenPCode1( ':', HB_COMP_PARAM ); if( szFunName && *szFunName ) hb_compGenPCodeN( ( BYTE * ) szFunName, strlen( szFunName ) + 1, HB_COMP_PARAM ); else /* special version "filename:" when the file changes within function */ hb_compGenPCode1( '\0', HB_COMP_PARAM ); HB_COMP_PARAM->lastModule = HB_COMP_PARAM->currModule; HB_COMP_PARAM->lastLine = -1; } #if 0 void hb_compGenStaticName( char *szVarName, HB_COMP_DECL ) { if( HB_COMP_PARAM->fDebugInfo ) { BYTE bGlobal = 0; PFUNCTION pFunc; int iVar; if( ! HB_COMP_PARAM->fStartProc && HB_COMP_PARAM->functions.iCount <= 1 ) { /* Variable declaration is outside of function/procedure body. File-wide static variable */ hb_compStaticDefStart( HB_COMP_PARAM ); bGlobal = 1; } pFunc = HB_COMP_PARAM->functions.pLast; iVar = hb_compStaticGetPos( szVarName, pFunc ); hb_compGenPCode4( HB_P_STATICNAME, bGlobal, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) szVarName, strlen( szVarName ) + 1, HB_COMP_PARAM ); if( bGlobal ) hb_compStaticDefEnd( HB_COMP_PARAM ); } } #endif /* * Function generates passed pcode for passed runtime variable * (field or memvar) */ static void hb_compGenVarPCode( BYTE bPCode, char * szVarName, HB_COMP_DECL ) { USHORT wVar; PCOMSYMBOL pSym; /* Check if this variable name is placed into the symbol table */ pSym = hb_compSymbolFind( HB_COMP_PARAM, szVarName, &wVar, HB_SYM_MEMVAR ); if( ! pSym ) pSym = hb_compSymbolAdd( HB_COMP_PARAM, szVarName, &wVar, HB_SYM_MEMVAR ); pSym->cScope |= HB_FS_MEMVAR; if( bPCode == HB_P_PUSHALIASEDFIELD && wVar <= 255 ) hb_compGenPCode2( HB_P_PUSHALIASEDFIELDNEAR, ( BYTE ) wVar, HB_COMP_PARAM ); else if( bPCode == HB_P_POPALIASEDFIELD && wVar <= 255 ) hb_compGenPCode2( HB_P_POPALIASEDFIELDNEAR, ( BYTE ) wVar, HB_COMP_PARAM ); else hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ), HB_COMP_PARAM ); } /* * Function generates pcode for undeclared variable */ static void hb_compGenVariablePCode( HB_COMP_DECL, BYTE bPCode, char * szVarName ) { BOOL bGenCode; /* * NOTE: * Clipper always assumes a memvar variable if undeclared variable * is popped (a value is asssigned to a variable). */ if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_HARBOUR ) ) bGenCode = HB_COMP_PARAM->fForceMemvars; /* harbour compatibility */ else bGenCode = ( HB_COMP_PARAM->fForceMemvars || bPCode == HB_P_POPVARIABLE ); if( bGenCode ) { /* -v switch was used -> assume it is a memvar variable */ hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL ); if( bPCode == HB_P_POPVARIABLE ) bPCode = HB_P_POPMEMVAR; else if( bPCode == HB_P_PUSHVARIABLE ) bPCode = HB_P_PUSHMEMVAR; else bPCode = HB_P_PUSHMEMVARREF; } else hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, szVarName, NULL ); hb_compGenVarPCode( bPCode, szVarName, HB_COMP_PARAM ); } /* Generate a pcode for a field variable */ static void hb_compGenFieldPCode( HB_COMP_DECL, BYTE bPCode, PVAR pField ) { if( pField->szAlias ) { /* the alias was specified in FIELD declaration * Push alias symbol before the field symbol */ if( bPCode == HB_P_POPFIELD ) bPCode = HB_P_POPALIASEDFIELD; else if( bPCode == HB_P_PUSHFIELD ) bPCode = HB_P_PUSHALIASEDFIELD; hb_compGenPushSymbol( pField->szAlias, HB_SYM_ALIAS, HB_COMP_PARAM ); } hb_compGenVarPCode( bPCode, pField->szName, HB_COMP_PARAM ); } /* sends a message to an object */ /* bIsObject = TRUE if we are sending a message to real object bIsObject is FALSE if we are sending a message to an object specified with WITH OBJECT statement. */ void hb_compGenMessage( char * szMsgName, BOOL bIsObject, HB_COMP_DECL ) { USHORT wSym; PCOMSYMBOL pSym; if( szMsgName ) { pSym = hb_compSymbolFind( HB_COMP_PARAM, szMsgName, &wSym, HB_SYM_MSGNAME ); if( ! pSym ) /* the symbol was not found on the symbol table */ pSym = hb_compSymbolAdd( HB_COMP_PARAM, szMsgName, &wSym, HB_SYM_MSGNAME ); pSym->cScope |= HB_FS_MESSAGE; if( bIsObject ) hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), HB_COMP_PARAM ); else hb_compGenPCode3( HB_P_WITHOBJECTMESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), HB_COMP_PARAM ); } else { wSym = 0xFFFF; hb_compGenPCode3( HB_P_WITHOBJECTMESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), HB_COMP_PARAM ); } } void hb_compGenMessageData( char * szMsg, BOOL bIsObject, HB_COMP_DECL ) /* generates an underscore-symbol name for a data assignment */ { char szResult[ HB_SYMBOL_NAME_LEN + 1 ]; int iLen = strlen( szMsg ); if( iLen >= HB_SYMBOL_NAME_LEN ) iLen = HB_SYMBOL_NAME_LEN - 1; szResult[ 0 ] = '_'; memcpy( szResult + 1, szMsg, iLen ); szResult[ iLen + 1 ] = '\0'; hb_compGenMessage( hb_compIdentifierNew( HB_COMP_PARAM, szResult, HB_IDENT_COPY ), bIsObject, HB_COMP_PARAM ); } static void hb_compCheckEarlyMacroEval( HB_COMP_DECL, char *szVarName ) { int iScope = hb_compVariableScope( HB_COMP_PARAM, szVarName ); if( iScope == HB_VS_CBLOCAL_VAR || iScope == HB_VS_STATIC_VAR || iScope == HB_VS_GLOBAL_STATIC || iScope == HB_VS_LOCAL_FIELD || iScope == HB_VS_GLOBAL_FIELD || iScope == HB_VS_LOCAL_MEMVAR || iScope == HB_VS_GLOBAL_MEMVAR ) { hb_compErrorCodeblock( HB_COMP_PARAM, szVarName ); } } /* Check variable in the following order: * LOCAL variable * local STATIC variable * local FIELD variable * local MEMVAR variable * global STATIC variable * global FIELD variable * global MEMVAR variable * (if not found - it is an undeclared variable) */ void hb_compGenPopVar( char * szVarName, HB_COMP_DECL ) /* generates the pcode to pop a value from the virtual machine stack onto a variable */ { int iVar, iScope; PVAR pVar; if( ! HB_COMP_PARAM->functions.pLast->bLateEval ) { /* pseudo-generation of pcode for a codeblock with macro symbol */ hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName ); return; } pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope ); if( pVar ) { switch( iScope ) { case HB_VS_LOCAL_VAR: case HB_VS_CBLOCAL_VAR: /* local variable */ /* local variables used in a coddeblock will not be adjusted * if PARAMETERS statement will be used then it is safe to * use 2 bytes for LOCALNEAR */ if( HB_LIM_INT8( iVar ) && !HB_COMP_PARAM->functions.pLast->szName && !( HB_COMP_PARAM->functions.pLast->bFlags & FUN_EXTBLOCK ) ) hb_compGenPCode2( HB_P_POPLOCALNEAR, ( BYTE ) iVar, HB_COMP_PARAM ); else hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); break; case HB_VS_STATIC_VAR: case HB_VS_GLOBAL_STATIC: /* Static variable */ hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); { PFUNCTION pFunc; /* Check if we are generating a pop code for static variable * initialization function - if YES then we have to switch to a function * where the static variable was declared */ pFunc = HB_COMP_PARAM->functions.pLast; if( ( HB_COMP_PARAM->functions.pLast->cScope & HB_FS_INITEXIT ) == HB_FS_INITEXIT ) pFunc = pFunc->pOwner; pFunc->bFlags |= FUN_USES_STATICS; } break; case HB_VS_LOCAL_FIELD: case HB_VS_GLOBAL_FIELD: /* declared field */ hb_compGenFieldPCode( HB_COMP_PARAM, HB_P_POPFIELD, pVar ); break; case HB_VS_LOCAL_MEMVAR: case HB_VS_GLOBAL_MEMVAR: /* declared memvar variable */ hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName, HB_COMP_PARAM ); break; default: /* undeclared variable */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName ); break; } } else { /* undeclared variable */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName ); } } /* generates the pcode to pop a value from the virtual machine stack onto a memvar variable */ void hb_compGenPopMemvar( char * szVarName, HB_COMP_DECL ) { if( ( hb_compVariableScope( HB_COMP_PARAM, szVarName ) & HB_VS_LOCAL_MEMVAR ) == 0 ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL ); hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName, HB_COMP_PARAM ); } /* generates the pcode to push a nonaliased variable value to the virtual * machine stack * bMacroVar is TRUE if macro &szVarName context */ void hb_compGenPushVar( char * szVarName, BOOL bMacroVar, HB_COMP_DECL ) { int iVar, iScope; PVAR pVar; if( ! HB_COMP_PARAM->functions.pLast->bLateEval && ! bMacroVar ) { /* pseudo-generation of pcode for a codeblock with macro symbol */ hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName ); return; } pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope ); if( pVar ) { switch( iScope ) { case HB_VS_LOCAL_VAR: case HB_VS_CBLOCAL_VAR: /* local variable */ /* local variables used in a coddeblock will not be adjusted * if PARAMETERS statement will be used then it is safe to * use 2 bytes for LOCALNEAR */ if( HB_LIM_INT8( iVar ) && !HB_COMP_PARAM->functions.pLast->szName && !( HB_COMP_PARAM->functions.pLast->bFlags & FUN_EXTBLOCK ) ) hb_compGenPCode2( HB_P_PUSHLOCALNEAR, ( BYTE ) iVar, HB_COMP_PARAM ); else hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); break; case HB_VS_STATIC_VAR: case HB_VS_GLOBAL_STATIC: /* Static variable */ hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->bFlags |= FUN_USES_STATICS; break; case HB_VS_LOCAL_FIELD: case HB_VS_GLOBAL_FIELD: /* declared field */ hb_compGenFieldPCode( HB_COMP_PARAM, HB_P_PUSHFIELD, pVar ); break; case HB_VS_LOCAL_MEMVAR: case HB_VS_GLOBAL_MEMVAR: /* declared memvar variable */ hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName, HB_COMP_PARAM ); break; default: /* undeclared variable */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName ); break; } } else { /* undeclared variable */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName ); } } void hb_compGenPushVarRef( char * szVarName, HB_COMP_DECL ) /* generates the pcode to push a variable by reference to the virtual machine stack */ { int iVar, iScope; PVAR pVar; if( ! HB_COMP_PARAM->functions.pLast->bLateEval ) { /* pseudo-generation of pcode for a codeblock with macro symbol */ hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName ); return; } pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope ); if( pVar ) { switch( iScope ) { case HB_VS_LOCAL_VAR: case HB_VS_CBLOCAL_VAR: /* local variable */ hb_compGenPCode3( HB_P_PUSHLOCALREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); break; case HB_VS_STATIC_VAR: case HB_VS_GLOBAL_STATIC: /* Static variable */ hb_compGenPCode3( HB_P_PUSHSTATICREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); HB_COMP_PARAM->functions.pLast->bFlags |= FUN_USES_STATICS; break; case HB_VS_LOCAL_FIELD: case HB_VS_GLOBAL_FIELD: /* pushing fields by reference is not allowed */ hb_compErrorRefer( HB_COMP_PARAM, NULL, szVarName ); break; case HB_VS_LOCAL_MEMVAR: case HB_VS_GLOBAL_MEMVAR: /* declared memvar variable */ hb_compGenVarPCode( HB_P_PUSHMEMVARREF, szVarName, HB_COMP_PARAM ); break; default: /* undeclared variable */ /* field cannot be passed by the reference - assume the memvar */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName ); break; } } else { /* undeclared variable */ /* field cannot be passed by the reference - assume the memvar */ hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName ); } } void hb_compGenPushMemvarRef( char * szVarName, HB_COMP_DECL ) /* generates the pcode to push memvar variable by reference to the virtual machine stack */ { hb_compGenVarPCode( HB_P_PUSHMEMVARREF, szVarName, HB_COMP_PARAM ); } /* generates the pcode to pop a value from the virtual machine stack onto * an aliased variable */ void hb_compGenPopAliasedVar( char * szVarName, BOOL bPushAliasValue, char * szAlias, HB_LONG lWorkarea, HB_COMP_DECL ) { if( bPushAliasValue ) { if( szAlias ) { int iLen = strlen( szAlias ); if( szAlias[ 0 ] == 'M' && ( iLen == 1 || ( iLen >= 4 && iLen <= 6 && memcmp( szAlias, "MEMVAR", iLen ) == 0 ) ) ) { /* M->variable or MEMV[A[R]]->variable */ hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName, HB_COMP_PARAM ); } else if( iLen >= 4 && iLen <= 5 && memcmp( szAlias, "FIELD", iLen ) == 0 ) { /* FIEL[D]->variable */ hb_compGenVarPCode( HB_P_POPFIELD, szVarName, HB_COMP_PARAM ); } else { /* database alias */ hb_compGenPushSymbol( szAlias, HB_SYM_ALIAS, HB_COMP_PARAM ); hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else { hb_compGenPushLong( lWorkarea, HB_COMP_PARAM ); hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else /* Alias is already placed on stack * NOTE: An alias will be determined at runtime then we cannot decide * here if passed name is either a field or a memvar */ hb_compGenVarPCode( HB_P_POPALIASEDVAR, szVarName, HB_COMP_PARAM ); } /* generates the pcode to push an aliased variable value to the virtual * machine stack */ void hb_compGenPushAliasedVar( char * szVarName, BOOL bPushAliasValue, char * szAlias, HB_LONG lWorkarea, HB_COMP_DECL ) { if( bPushAliasValue ) { if( szAlias ) { int iLen = strlen( szAlias ); /* myalias->var * FIELD->var * MEMVAR->var */ if( szAlias[ 0 ] == 'M' && ( iLen == 1 || ( iLen >= 4 && iLen <= 6 && memcmp( szAlias, "MEMVAR", iLen ) == 0 ) ) ) { /* M->variable or MEMV[A[R]]->variable */ hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName, HB_COMP_PARAM ); } else if( iLen >= 4 && iLen <= 5 && memcmp( szAlias, "FIELD", iLen ) == 0 ) { /* FIEL[D]->variable */ hb_compGenVarPCode( HB_P_PUSHFIELD, szVarName, HB_COMP_PARAM ); } else { /* database alias */ hb_compGenPushSymbol( szAlias, HB_SYM_ALIAS, HB_COMP_PARAM ); hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else { hb_compGenPushLong( lWorkarea, HB_COMP_PARAM ); hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else /* Alias is already placed on stack * NOTE: An alias will be determined at runtime then we cannot decide * here if passed name is either a field or a memvar */ hb_compGenVarPCode( HB_P_PUSHALIASEDVAR, szVarName, HB_COMP_PARAM ); } void hb_compGenPushLogical( int iTrueFalse, HB_COMP_DECL ) /* pushes a logical value on the virtual machine stack */ { hb_compGenPCode1( iTrueFalse ? HB_P_TRUE : HB_P_FALSE, HB_COMP_PARAM ); } void hb_compGenPushNil( HB_COMP_DECL ) { hb_compGenPCode1( HB_P_PUSHNIL, HB_COMP_PARAM ); } /* generates the pcode to push a double number on the virtual machine stack */ void hb_compGenPushDouble( double dNumber, BYTE bWidth, BYTE bDec, HB_COMP_DECL ) { BYTE pBuffer[ sizeof( double ) + sizeof( BYTE ) + sizeof( BYTE ) + 1 ]; pBuffer[ 0 ] = HB_P_PUSHDOUBLE; HB_PUT_LE_DOUBLE( &( pBuffer[ 1 ] ), dNumber ); pBuffer[ 1 + sizeof( double ) ] = bWidth; pBuffer[ 1 + sizeof( double ) + sizeof( BYTE ) ] = bDec; hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } void hb_compGenPushFunCall( char * szFunName, HB_COMP_DECL ) { char * szFunction; USHORT wSym; /* if abbreviated function name was used - change it for whole name */ szFunction = hb_compReservedName( szFunName ); if( szFunction ) szFunName = szFunction; if( hb_compSymbolFind( HB_COMP_PARAM, szFunName, &wSym, HB_SYM_FUNCNAME ) != NULL ) { if( ! hb_compFunCallFind( HB_COMP_PARAM, szFunName ) ) hb_compFunCallAdd( HB_COMP_PARAM, szFunName ); } else { hb_compSymbolAdd( HB_COMP_PARAM, szFunName, &wSym, HB_SYM_FUNCNAME ); hb_compFunCallAdd( HB_COMP_PARAM, szFunName ); } hb_compGenPCode3( HB_P_PUSHFUNCSYM, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), HB_COMP_PARAM ); } void hb_compGenPushFunSym( char * szFunName, HB_COMP_DECL ) { char * szFunction; /* if abbreviated function name was used - change it for whole name */ szFunction = hb_compReservedName( szFunName ); hb_compGenPushSymbol( szFunction ? szFunction : szFunName, HB_SYM_FUNCNAME, HB_COMP_PARAM ); } void hb_compGenPushFunRef( char * szFunName, HB_COMP_DECL ) { char * szFunction; /* if abbreviated function name was used - change it for whole name */ szFunction = hb_compReservedName( szFunName ); hb_compGenPushSymbol( szFunction ? szFunction : szFunName, HB_SYM_FUNCNAME, HB_COMP_PARAM ); } /* generates the pcode to push a symbol on the virtual machine stack */ void hb_compGenPushSymbol( char * szSymbolName, BOOL bFunction, HB_COMP_DECL ) { USHORT wSym; if( hb_compSymbolFind( HB_COMP_PARAM, szSymbolName, &wSym, bFunction ) != NULL ) /* the symbol was found on the symbol table */ { if( bFunction && ! hb_compFunCallFind( HB_COMP_PARAM, szSymbolName ) ) hb_compFunCallAdd( HB_COMP_PARAM, szSymbolName ); } else { hb_compSymbolAdd( HB_COMP_PARAM, szSymbolName, &wSym, bFunction ); if( bFunction ) hb_compFunCallAdd( HB_COMP_PARAM, szSymbolName ); } if( wSym > 255 ) hb_compGenPCode3( HB_P_PUSHSYM, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), HB_COMP_PARAM ); else hb_compGenPCode2( HB_P_PUSHSYMNEAR, ( BYTE ) wSym, HB_COMP_PARAM ); } /* generates the pcode to push a long number on the virtual machine stack */ void hb_compGenPushLong( HB_LONG lNumber, HB_COMP_DECL ) { if( HB_COMP_PARAM->fLongOptimize ) { if( lNumber == 0 ) hb_compGenPCode1( HB_P_ZERO, HB_COMP_PARAM ); else if( lNumber == 1 ) hb_compGenPCode1( HB_P_ONE, HB_COMP_PARAM ); else if( HB_LIM_INT8( lNumber ) ) hb_compGenPCode2( HB_P_PUSHBYTE, (BYTE) lNumber, HB_COMP_PARAM ); else if( HB_LIM_INT16( lNumber ) ) hb_compGenPCode3( HB_P_PUSHINT, HB_LOBYTE( lNumber ), HB_HIBYTE( lNumber ), HB_COMP_PARAM ); else if( HB_LIM_INT32( lNumber ) ) { BYTE pBuffer[ 5 ]; pBuffer[ 0 ] = HB_P_PUSHLONG; HB_PUT_LE_UINT32( pBuffer + 1, lNumber ); hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } else { BYTE pBuffer[ 9 ]; pBuffer[ 0 ] = HB_P_PUSHLONGLONG; HB_PUT_LE_UINT64( pBuffer + 1, lNumber ); hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } } else { if( HB_LIM_INT32( lNumber ) ) { BYTE pBuffer[ 5 ]; pBuffer[ 0 ] = HB_P_PUSHLONG; HB_PUT_LE_UINT32( pBuffer + 1, lNumber ); hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } else { BYTE pBuffer[ 9 ]; pBuffer[ 0 ] = HB_P_PUSHLONGLONG; HB_PUT_LE_UINT64( pBuffer + 1, lNumber ); hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } } } void hb_compGenPushDate( HB_LONG lNumber, HB_COMP_DECL ) { BYTE pBuffer[ 5 ]; pBuffer[ 0 ] = HB_P_PUSHDATE; HB_PUT_LE_UINT32( pBuffer + 1, lNumber ); hb_compGenPCodeN( pBuffer, sizeof( pBuffer ), HB_COMP_PARAM ); } /* generates the pcode to push a string on the virtual machine stack */ void hb_compGenPushString( char * szText, ULONG ulStrLen, HB_COMP_DECL ) { if( HB_COMP_PARAM->iHidden ) { --ulStrLen; szText = hb_compEncodeString( HB_COMP_PARAM->iHidden, szText, &ulStrLen ); hb_compGenPCode4( HB_P_PUSHSTRHIDDEN, ( BYTE ) HB_COMP_PARAM->iHidden, HB_LOBYTE( ulStrLen ), HB_HIBYTE( ulStrLen ), HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) szText, ulStrLen, HB_COMP_PARAM ); hb_xfree( szText ); } else { if( ulStrLen > UINT24_MAX ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_STRING_TOO_LONG, NULL, NULL ); else { if( ulStrLen > USHRT_MAX ) hb_compGenPCode4( HB_P_PUSHSTRLARGE, HB_LOBYTE( ulStrLen ), HB_HIBYTE( ulStrLen ), HB_ULBYTE( ulStrLen ), HB_COMP_PARAM ); else if( ulStrLen > UCHAR_MAX ) hb_compGenPCode3( HB_P_PUSHSTR, HB_LOBYTE( ulStrLen ), HB_HIBYTE( ulStrLen ), HB_COMP_PARAM ); else hb_compGenPCode2( HB_P_PUSHSTRSHORT, ( BYTE ) ulStrLen, HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) szText, ulStrLen, HB_COMP_PARAM ); } } } void hb_compNOOPfill( PFUNCTION pFunc, ULONG ulFrom, int iCount, BOOL fPop, BOOL fCheck ) { ULONG ul; while( iCount-- ) { if( fPop ) { pFunc->pCode[ ulFrom ] = HB_P_POP; fPop = FALSE; } else if( fCheck && pFunc->pCode[ ulFrom ] == HB_P_NOOP && pFunc->iNOOPs ) { for( ul = 0; ul < pFunc->iNOOPs; ++ul ) { if( pFunc->pNOOPs[ ul ] == ulFrom ) break; } if( ul == pFunc->iNOOPs ) hb_compNOOPadd( pFunc, ulFrom ); } else hb_compNOOPadd( pFunc, ulFrom ); ++ulFrom; } } /* * Warning - when jump optimization is disabled this function can be used * _ONLY_ in very limited situations when there is no jumps over the * removed block */ static void hb_compRemovePCODE( HB_COMP_DECL, ULONG ulPos, ULONG ulCount, BOOL fCanMove ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast; ULONG ul; if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_OPTJUMP ) || !fCanMove ) { /* * We can safely remove the dead code when Jump Optimization * is enabled by replacing it with HB_P_NOOP opcodes - which * will be later eliminated and jump data updated. */ hb_compNOOPfill( pFunc, ulPos, ulCount, FALSE, TRUE ); } else { memmove( pFunc->pCode + ulPos, pFunc->pCode + ulPos + ulCount, pFunc->lPCodePos - ulPos - ulCount ); pFunc->lPCodePos -= ulCount; for( ul = pFunc->iNOOPs; ul; --ul ) { if( pFunc->pNOOPs[ ul ] >= ulPos ) { if( pFunc->pNOOPs[ ul ] < ulPos + ulCount ) { memmove( &pFunc->pNOOPs[ ul ], &pFunc->pNOOPs[ ul + 1 ], pFunc->iNOOPs - ul ); pFunc->iNOOPs--; } else { pFunc->pNOOPs[ ul ] -= ulCount; } } } } } BOOL hb_compIsJump( HB_COMP_DECL, PFUNCTION pFunc, ULONG ulPos ) { ULONG iJump; /* * Do not allow any optimization (code striping) when Jump Optimization * is disabled and we do not have any information about jump addreses */ if( ! HB_COMP_ISSUPPORTED( HB_COMPFLAG_OPTJUMP ) ) return TRUE; for( iJump = 0; iJump < pFunc->iJumps; iJump++ ) { ULONG ulJumpAddr = pFunc->pJumps[ iJump ]; switch( pFunc->pCode[ ulJumpAddr ] ) { case HB_P_JUMPNEAR: case HB_P_JUMPFALSENEAR: case HB_P_JUMPTRUENEAR: ulJumpAddr += ( signed char ) pFunc->pCode[ ulJumpAddr + 1 ]; break; case HB_P_JUMP: case HB_P_JUMPFALSE: case HB_P_JUMPTRUE: ulJumpAddr += HB_PCODE_MKSHORT( &pFunc->pCode[ ulJumpAddr + 1 ] ); break; /* Jump can be replaced by series of NOOPs or POP and NOOPs * and not stripped yet */ case HB_P_NOOP: case HB_P_POP: ulJumpAddr = ulPos + 1; break; default: ulJumpAddr += HB_PCODE_MKINT24( &pFunc->pCode[ ulJumpAddr + 1 ] ); break; } if( ulJumpAddr == ulPos ) return TRUE; } return FALSE; } /* Generate the opcode to open BEGIN/END sequence * This code is simmilar to JUMP opcode - the offset will be filled with * - either the address of HB_P_SEQEND opcode if there is no RECOVER clause * - or the address of RECOVER code */ ULONG hb_compSequenceBegin( HB_COMP_DECL ) { hb_compGenPCode4( HB_P_SEQALWAYS, 0, 0, 0, HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); hb_compGenPCode4( HB_P_SEQBEGIN, 0, 0, 0, HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } /* Generate the opcode to close BEGIN/END sequence * This code is simmilar to JUMP opcode - the offset will be filled with * the address of first line after END SEQUENCE * This opcode will be executed if recover code was not requested (as the * last statement in code beetwen BEGIN ... RECOVER) or if BREAK was requested * and there was no matching RECOVER clause. */ ULONG hb_compSequenceEnd( HB_COMP_DECL ) { hb_compGenPCode4( HB_P_SEQEND, 0, 0, 0, HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } ULONG hb_compSequenceAlways( HB_COMP_DECL ) { hb_compGenPCode4( HB_P_ALWAYSBEGIN, 0, 0, 0, HB_COMP_PARAM ); hb_compPrepareOptimize( HB_COMP_PARAM ); return HB_COMP_PARAM->functions.pLast->lPCodePos - 3; } /* Remove unnecessary opcodes in case there were no executable statements * beetwen BEGIN and RECOVER sequence */ void hb_compSequenceFinish( HB_COMP_DECL, ULONG ulStartPos, ULONG ulEndPos, ULONG ulAlways, BOOL fUsualStmts, BOOL fRecover, BOOL fCanMove ) { --ulStartPos; /* HB_P_SEQBEGIN address */ if( !fUsualStmts && fCanMove && !HB_COMP_PARAM->fDebugInfo ) { ulStartPos -= 4; if( ulAlways ) { /* remove HB_P_ALWAYSEND opcode */ HB_COMP_PARAM->functions.pLast->lPCodePos--; /* remove HB_P_SEQALWAYS ... HB_P_ALWAYSBEGIN opcodes */ hb_compRemovePCODE( HB_COMP_PARAM, ulStartPos, ulAlways - ulStartPos + 4, fCanMove ); } else { hb_compRemovePCODE( HB_COMP_PARAM, ulStartPos, HB_COMP_PARAM->functions.pLast->lPCodePos - ulStartPos, fCanMove ); } HB_COMP_PARAM->lastLinePos = ulStartPos - 3; } else if( !ulAlways ) { /* remove HB_P_SEQALWAYS opcode */ hb_compRemovePCODE( HB_COMP_PARAM, ulStartPos - 4, 4, fCanMove ); } else { if( !fRecover ) { /* remove HB_P_SEQBEGIN and HB_P_SEQEND */ hb_compRemovePCODE( HB_COMP_PARAM, ulEndPos - 1, 4, fCanMove ); hb_compRemovePCODE( HB_COMP_PARAM, ulStartPos, 4, fCanMove ); if( ! HB_COMP_ISSUPPORTED( HB_COMPFLAG_OPTJUMP ) ) { /* Fix ALWAYS address in HB_P_SEQALWAYS opcode */ ulAlways -= 8; hb_compGenJumpThere( ulStartPos - 3, ulAlways, HB_COMP_PARAM ); } } /* empty always block? */ if( HB_COMP_PARAM->functions.pLast->lPCodePos - ulAlways == 5 && !HB_COMP_PARAM->fDebugInfo ) { /* remove HB_P_ALWAYSBEGIN and HB_P_ALWAYSEND opcodes */ hb_compRemovePCODE( HB_COMP_PARAM, ulAlways, 5, TRUE ); /* remove HB_P_SEQALWAYS opcode */ hb_compRemovePCODE( HB_COMP_PARAM, ulStartPos - 4, 4, fCanMove ); } } } /* * Start of definition of static variable * We are using here the special function HB_COMP_PARAM->pInitFunc which will store * pcode needed to initialize all static variables declared in PRG module. * pOwner member will point to a function where the static variable is * declared: */ void hb_compStaticDefStart( HB_COMP_DECL ) { HB_COMP_PARAM->functions.pLast->bFlags |= FUN_USES_STATICS; if( ! HB_COMP_PARAM->pInitFunc ) { BYTE pBuffer[ 5 ]; HB_COMP_PARAM->pInitFunc = hb_compFunctionNew( HB_COMP_PARAM, "(_INITSTATICS)", HB_FS_INITEXIT ); HB_COMP_PARAM->pInitFunc->pOwner = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->pInitFunc->bFlags = FUN_USES_STATICS | FUN_PROCEDURE; HB_COMP_PARAM->pInitFunc->cScope = HB_FS_INITEXIT | HB_FS_LOCAL; HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pInitFunc; pBuffer[ 0 ] = HB_P_STATICS; pBuffer[ 1 ] = 0; pBuffer[ 2 ] = 0; pBuffer[ 3 ] = 1; /* the number of static variables is unknown now */ pBuffer[ 4 ] = 0; hb_compGenPCodeN( pBuffer, 5, HB_COMP_PARAM ); hb_compGenPCode3( HB_P_SFRAME, 0, 0, HB_COMP_PARAM ); /* frame for statics variables */ if( HB_COMP_PARAM->fDebugInfo ) { /* uncomment this if you want to always set main module name not the one where first static variable was declared */ /* HB_COMP_PARAM->currModule = HB_COMP_PARAM->szFile; */ hb_compGenModuleName( HB_COMP_PARAM, HB_COMP_PARAM->pInitFunc->szName ); } } else { HB_COMP_PARAM->pInitFunc->pOwner = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pInitFunc; } } /* * End of definition of static variable * Return to previously pcoded function. */ void hb_compStaticDefEnd( HB_COMP_DECL, char * szVarName ) { HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pInitFunc->pOwner; HB_COMP_PARAM->pInitFunc->pOwner = NULL; ++HB_COMP_PARAM->iStaticCnt; if( HB_COMP_PARAM->fDebugInfo ) { BYTE bGlobal = 0; int iVar; if( ! HB_COMP_PARAM->fStartProc && HB_COMP_PARAM->functions.iCount <= 1 ) { /* Variable declaration is outside of function/procedure body. * File-wide static variable */ HB_COMP_PARAM->pInitFunc->pOwner = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pInitFunc; bGlobal = 1; } iVar = HB_COMP_PARAM->iStaticCnt; hb_compGenPCode4( HB_P_STATICNAME, bGlobal, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) szVarName, strlen( szVarName ) + 1, HB_COMP_PARAM ); if( bGlobal ) { HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pInitFunc->pOwner; HB_COMP_PARAM->pInitFunc->pOwner = NULL; } } } /* * Start of stop line number info generation */ static void hb_compLineNumberDefStart( HB_COMP_DECL ) { if( ! HB_COMP_PARAM->pLineFunc ) { HB_COMP_PARAM->pLineFunc = hb_compFunctionNew( HB_COMP_PARAM, "(_INITLINES)", HB_FS_INITEXIT ); HB_COMP_PARAM->pLineFunc->pOwner = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->pLineFunc->bFlags = 0; HB_COMP_PARAM->pLineFunc->cScope = HB_FS_INITEXIT | HB_FS_LOCAL; HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pLineFunc; if( HB_COMP_PARAM->fDebugInfo ) { /* set main module name */ HB_COMP_PARAM->currModule = HB_COMP_PARAM->szFile; hb_compGenModuleName( HB_COMP_PARAM, HB_COMP_PARAM->pLineFunc->szName ); } } else { HB_COMP_PARAM->pLineFunc->pOwner = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pLineFunc; } } /* * End of stop line number info generation * Return to previously pcoded function. */ static void hb_compLineNumberDefEnd( HB_COMP_DECL ) { HB_COMP_PARAM->functions.pLast = HB_COMP_PARAM->pLineFunc->pOwner; HB_COMP_PARAM->pLineFunc->pOwner = NULL; } /* * Start a new fake-function that will hold pcodes for a codeblock */ void hb_compCodeBlockStart( HB_COMP_DECL, BOOL bLateEval ) { PFUNCTION pBlock; pBlock = hb_compFunctionNew( HB_COMP_PARAM, NULL, HB_FS_STATIC | HB_FS_LOCAL ); pBlock->pOwner = HB_COMP_PARAM->functions.pLast; pBlock->bLateEval = bLateEval; HB_COMP_PARAM->functions.pLast = pBlock; HB_COMP_PARAM->lastLinePos = 0; } void hb_compCodeBlockEnd( HB_COMP_DECL ) { PFUNCTION pCodeblock; /* pointer to the current codeblock */ PFUNCTION pFunc; /* pointer to a function that owns a codeblock */ char * pFuncName; ULONG ulSize; USHORT wLocals = 0; /* number of referenced local variables */ USHORT wLocalsCnt, wLocalsLen; USHORT wPos; int iLocalPos; PVAR pVar; pCodeblock = HB_COMP_PARAM->functions.pLast; /* Check if the extended codeblock has return statement */ if( ( pCodeblock->bFlags & FUN_EXTBLOCK ) && !( pCodeblock->bFlags & FUN_WITH_RETURN ) ) { if( HB_COMP_PARAM->iWarnings >= 1 ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_FUN_WITH_NO_RETURN, "{||...}", NULL ); /* finish the codeblock without popping the return value from HVM stack */ hb_compGenPCode1( HB_P_ENDPROC, HB_COMP_PARAM ); } hb_compGenPCode1( HB_P_ENDBLOCK, HB_COMP_PARAM ); /* finish the codeblock */ if( !pCodeblock->bError ) { if( pCodeblock->wParamCount && !( pCodeblock->bFlags & FUN_USES_LOCAL_PARAMS ) ) /* PARAMETERs were used after LOCALs in extended codeblock * fix generated local indexes */ hb_compFixFuncPCode( HB_COMP_PARAM, pCodeblock ); hb_compOptimizeJumps( HB_COMP_PARAM ); } /* return to pcode buffer of function/codeblock in which the current * codeblock was defined */ HB_COMP_PARAM->functions.pLast = pCodeblock->pOwner; /* find the function that owns the codeblock */ pFunc = pCodeblock->pOwner; pFuncName = pFunc->szName; while( pFunc->pOwner ) { pFunc = pFunc->pOwner; if( pFunc->szName && *pFunc->szName ) pFuncName = pFunc->szName; } pFunc->bFlags |= ( pCodeblock->bFlags & FUN_USES_STATICS ); /* generate a proper codeblock frame with a codeblock size and with * a number of expected parameters */ /* Count the number of referenced local variables */ wLocalsLen = 0; pVar = pCodeblock->pDetached; while( pVar ) { if( HB_COMP_PARAM->fDebugInfo ) wLocalsLen += 4 + strlen( pVar->szName ); pVar = pVar->pNext; ++wLocals; } wLocalsCnt = wLocals; ulSize = pCodeblock->lPCodePos + 2; if( HB_COMP_PARAM->fDebugInfo ) { ulSize += 3 + strlen( HB_COMP_PARAM->currModule ) + strlen( pFuncName ); ulSize += wLocalsLen; } if( ulSize <= 255 && pCodeblock->wParamCount == 0 && wLocals == 0 ) { /* NOTE: 2 = HB_P_PUSHBLOCK + BYTE( size ) */ hb_compGenPCode2( HB_P_PUSHBLOCKSHORT, ( BYTE ) ulSize, HB_COMP_PARAM ); } else { /* NOTE: 8 = HB_P_PUSHBLOCK + USHORT( size ) + USHORT( wParams ) + USHORT( wLocals ) + _ENDBLOCK */ ulSize += 5 + wLocals * 2; if( ulSize <= USHRT_MAX ) hb_compGenPCode3( HB_P_PUSHBLOCK, HB_LOBYTE( ulSize ), HB_HIBYTE( ulSize ), HB_COMP_PARAM ); else if( ulSize < UINT24_MAX ) { ++ulSize; hb_compGenPCode4( HB_P_PUSHBLOCKLARGE, HB_LOBYTE( ulSize ), HB_HIBYTE( ulSize ), HB_ULBYTE( ulSize ), HB_COMP_PARAM ); } else hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_BLOCK_TOO_BIG, NULL, NULL ); /* generate the number of local parameters */ hb_compGenPCode2( HB_LOBYTE( pCodeblock->wParamCount ), HB_HIBYTE( pCodeblock->wParamCount ), HB_COMP_PARAM ); /* generate the number of referenced local variables */ hb_compGenPCode2( HB_LOBYTE( wLocals ), HB_HIBYTE( wLocals ), HB_COMP_PARAM ); /* generate the table of referenced local variables */ pVar = pCodeblock->pDetached; while( wLocals-- ) { wPos = hb_compVariableGetPos( pFunc->pLocals, pVar->szName ); hb_compGenPCode2( HB_LOBYTE( wPos ), HB_HIBYTE( wPos ), HB_COMP_PARAM ); pVar = pVar->pNext; } } if( HB_COMP_PARAM->fDebugInfo ) { hb_compGenModuleName( HB_COMP_PARAM, pFuncName ); /* generate the name of referenced local variables */ pVar = pCodeblock->pDetached; iLocalPos = -1; while( wLocalsCnt-- ) { hb_compGenPCode3( HB_P_LOCALNAME, HB_LOBYTE( iLocalPos ), HB_HIBYTE( iLocalPos ), HB_COMP_PARAM ); hb_compGenPCodeN( ( BYTE * ) pVar->szName, strlen( pVar->szName ) + 1, HB_COMP_PARAM ); iLocalPos--; pVar = pVar->pNext; } } hb_compGenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos, HB_COMP_PARAM ); if( HB_COMP_PARAM->iWarnings ) { pVar = pCodeblock->pLocals; while( pVar ) { if( HB_COMP_PARAM->iWarnings && pFunc->szName && pVar->szName && ! ( pVar->iUsed & VU_USED ) ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_BLOCKVAR_NOT_USED, pVar->szName, pFunc->szName ); pVar = pVar->pNext; } pVar = pCodeblock->pStatics; while( pVar ) { if( HB_COMP_PARAM->iWarnings && pFunc->szName && pVar->szName && ! ( pVar->iUsed & VU_USED ) ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_VAR_NOT_USED, pVar->szName, "{||...}" ); pVar = pVar->pNext; } } hb_compFunctionKill( HB_COMP_PARAM, pCodeblock ); } void hb_compCodeBlockStop( HB_COMP_DECL ) { PFUNCTION pCodeblock; /* pointer to the current codeblock */ pCodeblock = HB_COMP_PARAM->functions.pLast; /* return to pcode buffer of function/codeblock in which the current * codeblock was defined */ HB_COMP_PARAM->functions.pLast = pCodeblock->pOwner; hb_compGenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos, HB_COMP_PARAM ); if( HB_COMP_PARAM->iWarnings ) { PVAR pVar = pCodeblock->pLocals; /* find the function that owns the codeblock */ PFUNCTION pFunc = pCodeblock->pOwner; while( pFunc->pOwner ) pFunc = pFunc->pOwner; while( pVar ) { if( pFunc->szName && pVar->szName && ! ( pVar->iUsed & VU_USED ) ) hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_BLOCKVAR_NOT_USED, pVar->szName, pFunc->szName ); pVar = pVar->pNext; } } hb_compFunctionKill( HB_COMP_PARAM, pCodeblock ); } void hb_compCodeBlockRewind( HB_COMP_DECL ) { PFUNCTION pCodeblock; /* pointer to the current codeblock */ pCodeblock = HB_COMP_PARAM->functions.pLast; pCodeblock->lPCodePos = 0; /* Release the NOOP array. */ if( pCodeblock->pNOOPs ) { hb_xfree( ( void * ) pCodeblock->pNOOPs ); pCodeblock->pNOOPs = NULL; pCodeblock->iNOOPs = 0; } /* Release the Jumps array. */ if( pCodeblock->pJumps ) { hb_xfree( ( void * ) pCodeblock->pJumps ); pCodeblock->pJumps = NULL; pCodeblock->iJumps = 0; } } /* ============================ I18N ============================ */ static PHB_I18NTABLE hb_compI18nCreate( void ) { PHB_I18NTABLE pI18n; pI18n = ( PHB_I18NTABLE ) hb_xgrab( sizeof( HB_I18NTABLE ) ); pI18n->pString = NULL; pI18n->uiCount = 0; pI18n->uiAllocated = 0; return pI18n; } static void hb_compI18nFree( PHB_I18NTABLE pI18n ) { UINT ui; if( pI18n->pString ) { for( ui = 0; ui < pI18n->uiCount; ui++ ) { if( pI18n->pString[ ui ].szText ) hb_xfree( pI18n->pString[ ui ].szText ); if( pI18n->pString[ ui ].szContext ) hb_xfree( pI18n->pString[ ui ].szContext ); if( pI18n->pString[ ui ].pLine ) hb_xfree( pI18n->pString[ ui ].pLine ); } hb_xfree( pI18n->pString ); } hb_xfree( pI18n ); } static int hb_compI18nCompare( PHB_I18NSTRING pString, const char* pText, const char* pContext ) { int i; i = strcmp( pString->szText, pText ); if( i == 0 ) { if( pContext ) { if( pString->szContext ) return strcmp( pString->szContext, pContext ); else return -1; } else { if( pString->szContext ) return 1; else return 0; } } return i; } void hb_compI18nAdd( HB_COMP_DECL, const char* szText, const char* szContext, UINT uiLine ) { PHB_I18NTABLE pI18n; PHB_I18NSTRING pString; UINT uiLeft, uiRight, uiMiddle; int iCompare; pI18n = HB_COMP_PARAM->pI18n; if( ! pI18n ) return; if( pI18n->uiCount >= pI18n->uiAllocated ) { if( pI18n->pString ) { pI18n->uiAllocated += 32; pI18n->pString = ( PHB_I18NSTRING ) hb_xrealloc( pI18n->pString, sizeof( HB_I18NSTRING ) * pI18n->uiAllocated ); } else { pI18n->pString = ( PHB_I18NSTRING ) hb_xgrab( sizeof( HB_I18NSTRING ) * 32 ); pI18n->uiAllocated = 32; } } uiLeft = 0; uiRight = pI18n->uiCount; while( uiLeft < uiRight ) { uiMiddle = ( uiLeft + uiRight ) >> 1; iCompare = hb_compI18nCompare( & pI18n->pString[ uiMiddle ], szText, szContext ); if( iCompare == 0 ) { pString = & pI18n->pString[ uiMiddle ]; if( pString->pLine ) { pString->pLine = ( UINT* ) hb_xrealloc( pString->pLine, ( pString->uiLineCount + 1 ) * sizeof( UINT ) ); pString->pLine[ pString->uiLineCount ] = uiLine; pString->uiLineCount++; } else { pString->pLine = ( UINT* ) hb_xgrab( sizeof( UINT ) ); pString->pLine[ 0 ] = uiLine; pString->uiLineCount = 1; } return; } else if( iCompare < 0 ) uiLeft = uiMiddle + 1; else uiRight = uiMiddle; } memmove( &pI18n->pString[ uiLeft + 1 ], &pI18n->pString[ uiLeft ], ( pI18n->uiCount - uiLeft ) * sizeof( HB_I18NSTRING ) ); pString = & pI18n->pString[ uiLeft ]; pString->szText = hb_strdup( szText ); if( szContext ) pString->szContext = hb_strdup( szContext ); else pString->szContext = NULL; pString->uiLine = uiLine; pString->pLine = NULL; pString->uiLineCount = 0; pI18n->uiCount++; } static void hb_compI18nEscapeString( FILE* file, char* szText ) { while( * szText ) { if( (unsigned char) * szText < ' ' ) { if( * szText == '\t' ) fprintf( file, "\\t" ); else if( * szText == '\n' ) fprintf( file, "\\n" ); else if( * szText == '\r' ) fprintf( file, "\\r" ); else fprintf( file, "\\x%02X", * szText ); } else if( * szText == '"' ) { fprintf( file, "\\\"" ); } else if( * szText == '\\' ) { fprintf( file, "\\\\" ); } else { fprintf( file, "%c", * szText ); } szText++; } } static BOOL hb_compI18nSave( HB_COMP_DECL ) { PHB_I18NTABLE pI18n; PHB_I18NSTRING pString; HB_FNAME FileName; char szFileName[ _POSIX_PATH_MAX + 1 ]; char* szText; UINT uiIndex, uiLine; FILE* file; pI18n = HB_COMP_PARAM->pI18n; FileName.szPath = FileName.szName = FileName.szExtension = FileName.szDrive = NULL; if( HB_COMP_PARAM->pOutPath ) { FileName.szDrive = HB_COMP_PARAM->pOutPath->szDrive; FileName.szPath = HB_COMP_PARAM->pOutPath->szPath; } if( HB_COMP_PARAM->pI18nFileName ) { if( HB_COMP_PARAM->pI18nFileName->szName ) FileName.szName = HB_COMP_PARAM->pI18nFileName->szName; if( HB_COMP_PARAM->pI18nFileName->szExtension ) FileName.szExtension = HB_COMP_PARAM->pI18nFileName->szExtension; if( HB_COMP_PARAM->pI18nFileName->szPath ) { FileName.szDrive = HB_COMP_PARAM->pI18nFileName->szDrive; FileName.szPath = HB_COMP_PARAM->pI18nFileName->szPath; } } if( ! FileName.szName ) FileName.szName = HB_COMP_PARAM->pFileName->szName; if( ! FileName.szExtension ) FileName.szExtension = ".pot"; hb_fsFNameMerge( szFileName, &FileName ); file = hb_fopen( szFileName, "wb" ); if( ! file ) { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_CREATE_OUTPUT, szFileName, NULL ); return FALSE; } szText = hb_verHarbour(); fprintf( file, "#\n# This file is generated by %s\n#\n\n", szText ); hb_xfree( szText ); hb_strncpy( szFileName, HB_COMP_PARAM->pFileName->szName, _POSIX_PATH_MAX ); for( uiIndex = 0; uiIndex < pI18n->uiCount; uiIndex++ ) { pString = & pI18n->pString[ uiIndex ]; fprintf( file, "#: %s:%d", szFileName, pString->uiLine ); for( uiLine = 0; uiLine < pString->uiLineCount; uiLine++ ) fprintf( file, " %s:%d", szFileName, pString->pLine[ uiLine ] ); fprintf( file, "\n#, c-format\n" ); if( pString->szContext ) { fprintf( file, "msgctxt \"" ); hb_compI18nEscapeString( file, pString->szContext ); fprintf( file, "\"\n" ); } fprintf( file, "msgid \"" ); hb_compI18nEscapeString( file, pString->szText ); fprintf( file, "\"\nmsgstr \"\"\n\n" ); } fclose( file ); return TRUE; } /* ************************************************************************* */ /* initialize support variables */ static void hb_compInitVars( HB_COMP_DECL ) { if( HB_COMP_PARAM->iErrorCount != 0 ) hb_compExprLstDealloc( HB_COMP_PARAM ); HB_COMP_PARAM->functions.iCount = 0; HB_COMP_PARAM->functions.pFirst = NULL; HB_COMP_PARAM->functions.pLast = NULL; HB_COMP_PARAM->funcalls.iCount = 0; HB_COMP_PARAM->funcalls.pFirst = NULL; HB_COMP_PARAM->funcalls.pLast = NULL; HB_COMP_PARAM->szAnnounce = NULL; HB_COMP_PARAM->fTextSubst = ( HB_COMP_PARAM->supported & HB_COMPFLAG_MACROTEXT ) != 0; HB_COMP_PARAM->fLongOptimize = TRUE; HB_COMP_PARAM->symbols.iCount = 0; HB_COMP_PARAM->symbols.pFirst = NULL; HB_COMP_PARAM->symbols.pLast = NULL; HB_COMP_PARAM->pInitFunc = NULL; HB_COMP_PARAM->pLineFunc = NULL; HB_COMP_PARAM->fAnyWarning = FALSE; HB_COMP_PARAM->iFunctionCnt = 0; HB_COMP_PARAM->iErrorCount = 0; HB_COMP_PARAM->cVarType = ' '; HB_COMP_PARAM->lastLinePos = 0; HB_COMP_PARAM->iStaticCnt = 0; HB_COMP_PARAM->iVarScope = VS_LOCAL; HB_COMP_PARAM->inlines.iCount = 0; HB_COMP_PARAM->inlines.pFirst = NULL; HB_COMP_PARAM->inlines.pLast = NULL; } static void hb_compGenOutput( HB_COMP_DECL, int iLanguage ) { HB_TRACE(HB_TR_DEBUG, ("hb_compGenOutput()")); switch( iLanguage ) { case HB_LANG_C: hb_compGenCCode( HB_COMP_PARAM, HB_COMP_PARAM->pFileName ); break; case HB_LANG_OBJ32: hb_compGenObj32( HB_COMP_PARAM, HB_COMP_PARAM->pFileName ); break; case HB_LANG_PORT_OBJ: hb_compGenPortObj( HB_COMP_PARAM, HB_COMP_PARAM->pFileName ); break; case HB_LANG_PORT_OBJ_BUF: hb_compGenBufPortObj( HB_COMP_PARAM, &HB_COMP_PARAM->pOutBuf, &HB_COMP_PARAM->ulOutBufSize ); break; case HB_LANG_OBJ_MODULE: hb_compGenCObj( HB_COMP_PARAM, HB_COMP_PARAM->pFileName ); break; } } static void hb_compPpoFile( HB_COMP_DECL, const char * szPrg, const char * szExt, char * szPpoName ) { PHB_FNAME pFilePpo = hb_fsFNameSplit( szPrg ); pFilePpo->szExtension = ( char * ) szExt; if( HB_COMP_PARAM->pPpoPath ) { pFilePpo->szPath = HB_COMP_PARAM->pPpoPath->szPath; if( HB_COMP_PARAM->pPpoPath->szName ) { pFilePpo->szName = HB_COMP_PARAM->pPpoPath->szName; pFilePpo->szExtension = HB_COMP_PARAM->pPpoPath->szExtension; } } hb_fsFNameMerge( szPpoName, pFilePpo ); hb_xfree( pFilePpo ); } static void hb_compOutputFile( HB_COMP_DECL ) { HB_TRACE(HB_TR_DEBUG, ("hb_compOutputFile()")); HB_COMP_PARAM->pFileName->szPath = NULL; HB_COMP_PARAM->pFileName->szExtension = NULL; /* we create the output file name */ if( HB_COMP_PARAM->pOutPath ) { if( HB_COMP_PARAM->pOutPath->szPath ) HB_COMP_PARAM->pFileName->szPath = HB_COMP_PARAM->pOutPath->szPath; if( HB_COMP_PARAM->pOutPath->szName ) { HB_COMP_PARAM->pFileName->szName = HB_COMP_PARAM->pOutPath->szName; if( HB_COMP_PARAM->pOutPath->szExtension ) HB_COMP_PARAM->pFileName->szExtension = HB_COMP_PARAM->pOutPath->szExtension; } } } static void hb_compAddInitFunc( HB_COMP_DECL, PFUNCTION pFunc ) { PCOMSYMBOL pSym = hb_compSymbolAdd( HB_COMP_PARAM, pFunc->szName, NULL, HB_SYM_FUNCNAME ); pSym->cScope |= pFunc->cScope; hb_compAddFunc( HB_COMP_PARAM, pFunc ); hb_compGenPCode1( HB_P_ENDPROC, HB_COMP_PARAM ); } void hb_compCompileEnd( HB_COMP_DECL ) { if( HB_COMP_PARAM->pI18n ) { hb_compI18nFree( HB_COMP_PARAM->pI18n ); HB_COMP_PARAM->pI18n = NULL; } if( HB_COMP_PARAM->pI18nFileName ) { hb_xfree( HB_COMP_PARAM->pI18nFileName ); HB_COMP_PARAM->pI18nFileName = NULL; } if( HB_COMP_PARAM->pMainFileName ) { if( HB_COMP_PARAM->pFileName != HB_COMP_PARAM->pMainFileName ) /* currently compiled file was autoopened - close also * the main module */ hb_xfree( HB_COMP_PARAM->pMainFileName ); HB_COMP_PARAM->pMainFileName = NULL; } if( HB_COMP_PARAM->pFileName ) { hb_xfree( HB_COMP_PARAM->pFileName ); HB_COMP_PARAM->pFileName = NULL; } while( HB_COMP_PARAM->functions.pLast && !HB_COMP_PARAM->functions.pLast->szName ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pLast; HB_COMP_PARAM->functions.pLast = pFunc->pOwner; hb_compFunctionKill( HB_COMP_PARAM, pFunc ); } HB_COMP_PARAM->functions.pLast = NULL; if( HB_COMP_PARAM->functions.pFirst ) { PFUNCTION pFunc = HB_COMP_PARAM->functions.pFirst; while( pFunc ) pFunc = hb_compFunctionKill( HB_COMP_PARAM, pFunc ); HB_COMP_PARAM->functions.pFirst = NULL; } while( HB_COMP_PARAM->funcalls.pFirst ) { PFUNCALL pFunc = HB_COMP_PARAM->funcalls.pFirst; HB_COMP_PARAM->funcalls.pFirst = pFunc->pNext; hb_xfree( ( void * ) pFunc ); } while( HB_COMP_PARAM->externs ) { PEXTERN pExtern = HB_COMP_PARAM->externs; HB_COMP_PARAM->externs = HB_COMP_PARAM->externs->pNext; hb_xfree( pExtern ); } while( HB_COMP_PARAM->inlines.pFirst ) { PINLINE pInline = HB_COMP_PARAM->inlines.pFirst; HB_COMP_PARAM->inlines.pFirst = pInline->pNext; if( pInline->pCode ) hb_xfree( pInline->pCode ); hb_xfree( ( void * ) pInline ); } while( HB_COMP_PARAM->pReleaseDeclared ) { PCOMDECLARED pDeclared = HB_COMP_PARAM->pReleaseDeclared; HB_COMP_PARAM->pReleaseDeclared = pDeclared->pNext; if( pDeclared->cParamTypes ) hb_xfree( ( void * ) pDeclared->cParamTypes ); if( pDeclared->pParamClasses ) hb_xfree( ( void * ) pDeclared->pParamClasses ); hb_xfree( ( void * ) pDeclared ); } HB_COMP_PARAM->pFirstDeclared = HB_COMP_PARAM->pLastDeclared = NULL; while( HB_COMP_PARAM->pReleaseClass ) { PCOMCLASS pClass = HB_COMP_PARAM->pReleaseClass; HB_COMP_PARAM->pReleaseClass = pClass->pNext; while( pClass->pMethod ) { PCOMDECLARED pDeclared = pClass->pMethod; pClass->pMethod = pDeclared->pNext; if( pDeclared->cParamTypes ) hb_xfree( ( void * ) pDeclared->cParamTypes ); if( pDeclared->pParamClasses ) hb_xfree( ( void * ) pDeclared->pParamClasses ); hb_xfree( ( void * ) pDeclared ); } hb_xfree( ( void * ) pClass ); } HB_COMP_PARAM->pFirstClass = HB_COMP_PARAM->pLastClass = NULL; if( HB_COMP_PARAM->symbols.pFirst ) { PCOMSYMBOL pSym = HB_COMP_PARAM->symbols.pFirst; while( pSym ) pSym = hb_compSymbolKill( pSym ); HB_COMP_PARAM->symbols.pFirst = NULL; } } static int hb_compCompile( HB_COMP_DECL, const char * szPrg, int iFileType ) { const char * szBuffer = NULL; int iStatus = EXIT_SUCCESS; HB_TRACE(HB_TR_DEBUG, ("hb_compCompile(%s,%d)", szPrg, iFileType)); if( iFileType == HB_COMP_MEMBUFFER ) { szBuffer = szPrg; szPrg = "{SOURCE}"; } HB_COMP_PARAM->pMainFileName = hb_fsFNameSplit( szPrg ); HB_COMP_PARAM->pFileName = HB_COMP_PARAM->pMainFileName; if( HB_COMP_PARAM->pFileName->szName ) { char szFileName[ _POSIX_PATH_MAX + 1 ]; /* filename to parse */ char szPpoName[ _POSIX_PATH_MAX + 1 ]; char buffer[ _POSIX_PATH_MAX * 2 + 80 ]; /* Add /D command line or envvar defines */ /* hb_compChkDefines( argc, argv ); */ /* Initialize support variables */ hb_compInitVars( HB_COMP_PARAM ); /* Clear and reinitialize preprocessor state */ hb_pp_reset( HB_COMP_PARAM->pLex->pPP ); if( !HB_COMP_PARAM->pFileName->szExtension ) HB_COMP_PARAM->pFileName->szExtension = ".prg"; hb_fsFNameMerge( szFileName, HB_COMP_PARAM->pFileName ); if( iFileType == HB_COMP_MEMBUFFER ) { if( !hb_pp_inBuffer( HB_COMP_PARAM->pLex->pPP, szBuffer, strlen( szBuffer ) ) ) { hb_compOutErr( HB_COMP_PARAM, "Cannot create preprocessor buffer." ); iStatus = EXIT_FAILURE; } } else if( !hb_pp_inFile( HB_COMP_PARAM->pLex->pPP, szFileName, FALSE, NULL, FALSE ) ) { snprintf( buffer, sizeof( buffer ), "Cannot open input file: %s\n", szFileName ); hb_compOutErr( HB_COMP_PARAM, buffer ); iStatus = EXIT_FAILURE; } else if( iFileType == HB_COMP_SINGLEFILE ) { if( HB_COMP_PARAM->fPPT ) { hb_compPpoFile( HB_COMP_PARAM, szPrg, ".ppt", szPpoName ); if( !hb_pp_traceFile( HB_COMP_PARAM->pLex->pPP, szPpoName, NULL ) ) iStatus = EXIT_FAILURE; } if( HB_COMP_PARAM->fPPO && iStatus == EXIT_SUCCESS ) { hb_compPpoFile( HB_COMP_PARAM, szPrg, ".ppo", szPpoName ); if( !hb_pp_outFile( HB_COMP_PARAM->pLex->pPP, szPpoName, NULL ) ) iStatus = EXIT_FAILURE; } } if( iStatus == EXIT_SUCCESS && !HB_COMP_PARAM->fExit ) { BOOL bSkipGen = FALSE ; HB_COMP_PARAM->szFile = HB_COMP_PARAM->currModule = hb_compIdentifierNew( HB_COMP_PARAM, szFileName, HB_IDENT_COPY ); HB_COMP_PARAM->currLine = 1; if( iFileType == HB_COMP_MEMBUFFER ) { hb_compFunctionAdd( HB_COMP_PARAM, "", 0, FUN_PROCEDURE ); hb_compparse( HB_COMP_PARAM ); } else if( iFileType == HB_COMP_SINGLEFILE ) { if( ! HB_COMP_PARAM->fQuiet ) { if( HB_COMP_PARAM->fPPO ) snprintf( buffer, sizeof( buffer ), "Compiling '%s' and generating preprocessed output to '%s'...\n", szFileName, szPpoName ); else snprintf( buffer, sizeof( buffer ), "Compiling '%s'...\n", szFileName ); hb_compOutStd( HB_COMP_PARAM, buffer ); } if( HB_COMP_PARAM->fI18n ) { HB_COMP_PARAM->pI18n = hb_compI18nCreate(); } /* Generate the starting procedure frame */ if( HB_COMP_PARAM->fStartProc ) { hb_compFunctionAdd( HB_COMP_PARAM, hb_compIdentifierNew( HB_COMP_PARAM, hb_strupr( hb_strdup( HB_COMP_PARAM->pFileName->szName ) ), HB_IDENT_FREE ), HB_FS_PUBLIC, FUN_PROCEDURE ); } else { /* Don't pass the name of module if the code for starting procedure * will be not generated. The name cannot be placed as first symbol * because this symbol can be used as function call or memvar's name. */ hb_compFunctionAdd( HB_COMP_PARAM, "", 0, FUN_PROCEDURE ); } if( !HB_COMP_PARAM->fExit ) { hb_compparse( HB_COMP_PARAM ); } } else { snprintf( buffer, sizeof( buffer ), "Reading '%s'...\n", szFileName ); hb_compOutStd( HB_COMP_PARAM, buffer ); } /* Open refernced modules (using DO ... WITh statement * or from @.clp command line option */ while( HB_COMP_PARAM->autoopen && !HB_COMP_PARAM->fExit ) { PAUTOOPEN pAutoOpen = HB_COMP_PARAM->autoopen; if( ! hb_compIsFunction( HB_COMP_PARAM, pAutoOpen->szName ) ) hb_compAutoOpen( HB_COMP_PARAM, pAutoOpen->szName, &bSkipGen, iFileType ); HB_COMP_PARAM->autoopen = HB_COMP_PARAM->autoopen->pNext; hb_xfree( pAutoOpen ); } /* Begin of finalization phase. */ /* fix all previous function returns offsets */ hb_compFinalizeFunction( HB_COMP_PARAM ); hb_compExternGen( HB_COMP_PARAM ); /* generates EXTERN symbols names */ if( HB_COMP_PARAM->pInitFunc ) { char szNewName[ 25 ]; /* Fix the number of static variables */ HB_COMP_PARAM->pInitFunc->pCode[ 3 ] = HB_LOBYTE( HB_COMP_PARAM->iStaticCnt ); HB_COMP_PARAM->pInitFunc->pCode[ 4 ] = HB_HIBYTE( HB_COMP_PARAM->iStaticCnt ); HB_COMP_PARAM->pInitFunc->iStaticsBase = HB_COMP_PARAM->iStaticCnt; /* Update pseudo function name */ snprintf( szNewName, sizeof( szNewName ), "(_INITSTATICS%05d)", HB_COMP_PARAM->iStaticCnt ); HB_COMP_PARAM->pInitFunc->szName = hb_compIdentifierNew( HB_COMP_PARAM, szNewName, HB_IDENT_COPY ); hb_compAddInitFunc( HB_COMP_PARAM, HB_COMP_PARAM->pInitFunc ); } if( HB_COMP_PARAM->fLineNumbers && HB_COMP_PARAM->fDebugInfo ) { PHB_DEBUGINFO pInfo = hb_compGetDebugInfo( HB_COMP_PARAM ), pNext; if( pInfo ) { int iModules = 0; hb_compLineNumberDefStart( HB_COMP_PARAM ); do { ULONG ulSkip = pInfo->ulFirstLine >> 3; ULONG ulLen = ( ( pInfo->ulLastLine + 7 ) >> 3 ) - ulSkip; hb_compGenPushString( pInfo->pszModuleName, strlen( pInfo->pszModuleName ) + 1, HB_COMP_PARAM ); hb_compGenPushLong( ulSkip << 3, HB_COMP_PARAM ); hb_compGenPushString( ( char * ) pInfo->pLineMap + ulSkip, ulLen + 1, HB_COMP_PARAM ); hb_compGenPCode3( HB_P_ARRAYGEN, 3, 0, HB_COMP_PARAM ); iModules++; pNext = pInfo->pNext; hb_xfree( pInfo->pszModuleName ); hb_xfree( pInfo->pLineMap ); hb_xfree( pInfo ); pInfo = pNext; } while( pInfo ); hb_compGenPCode3( HB_P_ARRAYGEN, HB_LOBYTE( iModules ), HB_HIBYTE( iModules ), HB_COMP_PARAM ); hb_compGenPCode1( HB_P_RETVALUE, HB_COMP_PARAM ); hb_compLineNumberDefEnd( HB_COMP_PARAM ); hb_compAddInitFunc( HB_COMP_PARAM, HB_COMP_PARAM->pLineFunc ); } } if( HB_COMP_PARAM->szAnnounce ) hb_compAnnounce( HB_COMP_PARAM, HB_COMP_PARAM->szAnnounce ); /* End of finalization phase. */ if( HB_COMP_PARAM->iErrorCount || HB_COMP_PARAM->fAnyWarning ) { if( HB_COMP_PARAM->iErrorCount ) { iStatus = EXIT_FAILURE; bSkipGen = TRUE; snprintf( buffer, sizeof( buffer ), "\r%i error%s\n\nNo code generated\n", HB_COMP_PARAM->iErrorCount, HB_COMP_PARAM->iErrorCount > 1 ? "s" : "" ); hb_compOutStd( HB_COMP_PARAM, buffer ); } else if( HB_COMP_PARAM->iExitLevel == HB_EXITLEVEL_SETEXIT ) { iStatus = EXIT_FAILURE; } else if( HB_COMP_PARAM->iExitLevel == HB_EXITLEVEL_DELTARGET ) { iStatus = EXIT_FAILURE; bSkipGen = TRUE; hb_compOutStd( HB_COMP_PARAM, "\nNo code generated.\n" ); } } if( ! HB_COMP_PARAM->fSyntaxCheckOnly && ! bSkipGen && HB_COMP_PARAM->iErrorCount == 0 ) { char * szFirstFunction = NULL; PFUNCTION *pFunPtr; /* we create the output file name */ hb_compOutputFile( HB_COMP_PARAM ); pFunPtr = &HB_COMP_PARAM->functions.pFirst; if( ! HB_COMP_PARAM->fStartProc ) { /* skip first non-startup procedure */ hb_compOptimizeFrames( HB_COMP_PARAM, *pFunPtr ); pFunPtr = &(*pFunPtr)->pNext; HB_COMP_PARAM->iFunctionCnt--; } while( *pFunPtr && !HB_COMP_PARAM->fExit ) { /* remove function frames with no names */ if( ! HB_COMP_PARAM->fStartProc && ! (*pFunPtr)->szName[0] ) { *pFunPtr = hb_compFunctionKill( HB_COMP_PARAM, *pFunPtr ); HB_COMP_PARAM->functions.iCount--; HB_COMP_PARAM->iFunctionCnt--; } else { hb_compOptimizeFrames( HB_COMP_PARAM, *pFunPtr ); if( szFirstFunction == NULL && ! ( ( *pFunPtr )->cScope & (HB_FS_INIT | HB_FS_EXIT) ) ) { szFirstFunction = ( *pFunPtr )->szName; } pFunPtr = &(*pFunPtr)->pNext; } } if( szFirstFunction ) { PCOMSYMBOL pSym = hb_compSymbolFind( HB_COMP_PARAM, szFirstFunction, NULL, HB_SYM_FUNCNAME ); if( pSym ) pSym->cScope |= HB_FS_FIRST; } if( ! HB_COMP_PARAM->fQuiet ) { snprintf( buffer, sizeof( buffer ), "\rLines %i, Functions/Procedures %i\n", hb_pp_lineTot( HB_COMP_PARAM->pLex->pPP ), HB_COMP_PARAM->iFunctionCnt ); hb_compOutStd( HB_COMP_PARAM, buffer ); } hb_compGenOutput( HB_COMP_PARAM, HB_COMP_PARAM->iLanguage ); if( HB_COMP_PARAM->pI18n ) { hb_compI18nSave( HB_COMP_PARAM ); } } } } else { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_BADFILENAME, szPrg, NULL ); iStatus = EXIT_FAILURE; } hb_compCompileEnd( HB_COMP_PARAM ); return HB_COMP_PARAM->fExit ? EXIT_FAILURE : iStatus; } static BOOL hb_compAutoOpenFind( HB_COMP_DECL, const char * szName ) { PAUTOOPEN pLast = HB_COMP_PARAM->autoopen; HB_TRACE(HB_TR_DEBUG, ("hb_compAutoOpenFind(%s)", szName)); if( pLast == NULL ) return FALSE; if( hb_stricmp( pLast->szName, szName ) == 0 ) return TRUE; else { while( pLast->pNext ) { pLast = pLast->pNext; if( strcmp( pLast->szName, szName ) == 0 ) return TRUE; } } return FALSE; } void hb_compAutoOpenAdd( HB_COMP_DECL, const char * szName ) { HB_TRACE(HB_TR_DEBUG, ("hb_compAutoOpenAdd(%p,%s)", HB_COMP_PARAM, szName)); if( HB_COMP_PARAM->fAutoOpen && ! hb_compAutoOpenFind( HB_COMP_PARAM, szName ) ) { PAUTOOPEN pAutoOpen = ( PAUTOOPEN ) hb_xgrab( sizeof( AUTOOPEN ) ), pLast; pAutoOpen->szName = ( char * ) szName; pAutoOpen->pNext = NULL; if( HB_COMP_PARAM->autoopen == NULL ) HB_COMP_PARAM->autoopen = pAutoOpen; else { pLast = HB_COMP_PARAM->autoopen; while( pLast->pNext ) pLast = pLast->pNext; pLast->pNext = pAutoOpen; } } } static int hb_compAutoOpen( HB_COMP_DECL, const char * szPrg, BOOL * pbSkipGen, int iFileType ) { int iStatus = EXIT_SUCCESS; PHB_FNAME pMainFileName = HB_COMP_PARAM->pFileName; HB_COMP_PARAM->pFileName = hb_fsFNameSplit( szPrg ); if( HB_COMP_PARAM->pFileName->szName ) { char szFileName[ _POSIX_PATH_MAX + 1 ]; /* filename to parse */ char szPpoName[ _POSIX_PATH_MAX + 1 ]; char buffer[ _POSIX_PATH_MAX * 2 + 80 ]; /* Clear and reinitialize preprocessor state */ hb_pp_reset( HB_COMP_PARAM->pLex->pPP ); if( !HB_COMP_PARAM->pFileName->szExtension ) HB_COMP_PARAM->pFileName->szExtension = ".prg"; hb_fsFNameMerge( szFileName, HB_COMP_PARAM->pFileName ); if( !hb_pp_inFile( HB_COMP_PARAM->pLex->pPP, szFileName, FALSE, NULL, FALSE ) ) { snprintf( buffer, sizeof( buffer ), "Cannot open %s, assumed external\n", szFileName ); hb_compOutErr( HB_COMP_PARAM, buffer ); iStatus = EXIT_FAILURE; } else if( HB_COMP_PARAM->fPPT ) { HB_COMP_PARAM->pFileName->szExtension = ".ppt"; hb_fsFNameMerge( szPpoName, HB_COMP_PARAM->pFileName ); if( !hb_pp_traceFile( HB_COMP_PARAM->pLex->pPP, szPpoName, NULL ) ) iStatus = EXIT_FAILURE; } if( HB_COMP_PARAM->fPPO && iStatus == EXIT_SUCCESS ) { HB_COMP_PARAM->pFileName->szExtension = ".ppo"; hb_fsFNameMerge( szPpoName, HB_COMP_PARAM->pFileName ); if( !hb_pp_outFile( HB_COMP_PARAM->pLex->pPP, szPpoName, NULL ) ) iStatus = EXIT_FAILURE; } if( iStatus == EXIT_SUCCESS && !HB_COMP_PARAM->fExit ) { HB_COMP_PARAM->currModule = hb_compIdentifierNew( HB_COMP_PARAM, szFileName, HB_IDENT_COPY ); HB_COMP_PARAM->currLine = 1; if( ! HB_COMP_PARAM->fQuiet ) { if( HB_COMP_PARAM->fPPO ) snprintf( buffer, sizeof( buffer ), "Compiling module '%s' and generating preprocessed output to '%s'...\n", szFileName, szPpoName ); else snprintf( buffer, sizeof( buffer ), "Compiling module '%s'...\n", szFileName ); hb_compOutStd( HB_COMP_PARAM, buffer ); } /* Generate the starting procedure frame */ if( HB_COMP_PARAM->fStartProc ) hb_compFunctionAdd( HB_COMP_PARAM, hb_compIdentifierNew( HB_COMP_PARAM, hb_strupr( hb_strdup( HB_COMP_PARAM->pFileName->szName ) ), HB_IDENT_FREE ), HB_FS_PUBLIC, FUN_PROCEDURE ); else if( iFileType != HB_COMP_SINGLEFILE ) hb_compFunctionAdd( HB_COMP_PARAM, "", 0, FUN_PROCEDURE ); if( !HB_COMP_PARAM->fExit ) { int i = HB_COMP_PARAM->iExitLevel ; BOOL b = HB_COMP_PARAM->fAnyWarning; hb_compparse( HB_COMP_PARAM ); HB_COMP_PARAM->iExitLevel = ( i > HB_COMP_PARAM->iExitLevel ? i : HB_COMP_PARAM->iExitLevel ); HB_COMP_PARAM->fAnyWarning = ( b ? b : HB_COMP_PARAM->fAnyWarning ); } if( HB_COMP_PARAM->fAnyWarning ) { if( HB_COMP_PARAM->iExitLevel == HB_EXITLEVEL_SETEXIT ) { iStatus = EXIT_FAILURE; } else if( HB_COMP_PARAM->iExitLevel == HB_EXITLEVEL_DELTARGET ) { iStatus = EXIT_FAILURE; *pbSkipGen = TRUE; hb_compOutStd( HB_COMP_PARAM, "\nNo code generated.\n" ); } } } } else { hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'F', HB_COMP_ERR_BADFILENAME, szPrg, NULL ); iStatus = EXIT_FAILURE; } hb_xfree( HB_COMP_PARAM->pFileName ); HB_COMP_PARAM->pFileName = pMainFileName; return HB_COMP_PARAM->fExit ? EXIT_FAILURE : iStatus; }