2010-08-05 15:58 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)

* utils/hbmk2/hbmk2.prg
    % Implemented optimized header parser code created by Przemek.
      With these additions/modifications from previous algorithm:
        + Use FindHeader() to locate the referenced headers.
        + Use different algorithm to find C vc PRG headers.
        % Completely skip known standard system headers.
        % Do not go down to headers included as system (using <>)
          IOW Check their timestamp but don't parse it for sub-headers.
      Please review it, it was quite a tough task, so I may have
      missed something. Here my reference build time went down
      from ~4 to ~2.5secs.
    ! Above implementation had the nice side effect that it fixed
      -autohbc feature in -inc mode.
    ! Fixed header finder code to always look in parent dir
      (and don't look in current dir in such case).
      I'd appreciate if this function (FindHeader() would be peer-reviewed
      to verify if it really matches the way how Harbour and C compilers
      try to find headers.

  * config/postinst.hbs
    ! Fixed typo in a recent commit causing RTE.

  * config/hbextern.hbs
    * Hide stderr in lib listing call.

  * contrib/hbcurl/hbcurl.c
    % Use '#include <>' to refer to curl header.
This commit is contained in:
Viktor Szakats
2010-08-05 14:00:33 +00:00
parent d2f2bc6fe3
commit f38b2832df
5 changed files with 327 additions and 216 deletions

View File

@@ -16,6 +16,35 @@
The license applies to all entries newer than 2009-04-28.
*/
2010-08-05 15:58 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* utils/hbmk2/hbmk2.prg
% Implemented optimized header parser code created by Przemek.
With these additions/modifications from previous algorithm:
+ Use FindHeader() to locate the referenced headers.
+ Use different algorithm to find C vc PRG headers.
% Completely skip known standard system headers.
% Do not go down to headers included as system (using <>)
IOW Check their timestamp but don't parse it for sub-headers.
Please review it, it was quite a tough task, so I may have
missed something. Here my reference build time went down
from ~4 to ~2.5secs.
! Above implementation had the nice side effect that it fixed
-autohbc feature in -inc mode.
! Fixed header finder code to always look in parent dir
(and don't look in current dir in such case).
I'd appreciate if this function (FindHeader() would be peer-reviewed
to verify if it really matches the way how Harbour and C compilers
try to find headers.
* config/postinst.hbs
! Fixed typo in a recent commit causing RTE.
* config/hbextern.hbs
* Hide stderr in lib listing call.
* contrib/hbcurl/hbcurl.c
% Use '#include <>' to refer to curl header.
2010-08-05 08:40 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
* config/hbextern.hbs
% Synced extern extractor regex queries between compilers.

View File

@@ -39,7 +39,7 @@
STATIC FUNCTION __hb_extern_get_list( cInputName )
LOCAL aExtern := NIL
LOCAL cStdOut
LOCAL cStdOut, cStdErr
LOCAL cTempFile
LOCAL hRegex
LOCAL aResult
@@ -73,7 +73,7 @@ STATIC FUNCTION __hb_extern_get_list( cInputName )
FClose( hb_FTempCreateEx( @cTempFile,,, ".tmp" ) )
cCommand := StrTran( cCommand, "{T}", cTempFile )
ENDIF
IF hb_processRun( cCommand,, @cStdOut ) == 0
IF hb_processRun( cCommand, @cStdErr, @cStdOut ) == 0
IF ! Empty( cTempFile )
cStdOut := MemoRead( cTempFile )
ENDIF

View File

@@ -544,7 +544,7 @@ STATIC FUNCTION mk_extern_core()
! Empty( GetEnv( "HB_DYNLIB_ST" ) )
/* TOFIX: Use list of libs instead of dynamic lib */
IF ( aExtern := __hb_extern_get_list( PathToSelf( GetEnv( "HB_DYNLIB_DIR" ) ) + hb_ps() + GetEnv( "HB_DYNLIB_ST" ) + GetEnv( "HB_DYNLIB_EXT" ) ) ) != NIL
IF ( aExtern := __hb_extern_get_list( PathSepToSelf( GetEnv( "HB_DYNLIB_DIR" ) ) + hb_ps() + GetEnv( "HB_DYNLIB_ST" ) + GetEnv( "HB_DYNLIB_EXT" ) ) ) != NIL
OutStd( "! Generating core extern headers..." + hb_eol() )

View File

@@ -52,9 +52,9 @@
*
*/
#include "curl/curl.h"
#include "curl/types.h"
#include "curl/easy.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include "hbapi.h"
#include "hbapiitm.h"

View File

@@ -37,6 +37,7 @@
* rtlink/blinker link script parsers.
* POTMerge(), LoadPOTFilesAsHash(), GenHBL() and AutoTrans().
* (with local modifications by hbmk2 author)
* optimized header time scan algorithm
*
* See COPYING for licensing terms.
*
@@ -99,8 +100,6 @@
/* TODO: Use hashes instead of arrays for input files, options */
/* TODO: Avoid adding certain options and input files twice */
/* TOFIX: -autohbc with -inc mode */
/* TODO: Next gen compiler autodetection:
1. Gather supported compilers by Harbour installation
(look for lib/<plat>/*[/<name>] subdirs)
@@ -416,13 +415,14 @@ REQUEST hbmk_KEYW
#define _HBMK_lAutoHBM 120 /* Toggles processing of hbmk.hbm file in current directory */
#define _HBMK_lContainer 121 /* Target type: container */
#define _HBMK_lShowLevel 122 /* Show project nesting level in all output lines */
#define _HBMK_hFiles 123 /* Cache for the header parser (common for C and Harbour) */
#define _HBMK_aArgs 123
#define _HBMK_nArgTarget 124
#define _HBMK_lPause 125
#define _HBMK_nLevel 126
#define _HBMK_aArgs 124
#define _HBMK_nArgTarget 125
#define _HBMK_lPause 126
#define _HBMK_nLevel 127
#define _HBMK_MAX_ 126
#define _HBMK_MAX_ 127
#define _HBMK_DEP_CTRL_MARKER ".control." /* must be an invalid path */
@@ -817,7 +817,6 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
LOCAL lTargetUpToDate
LOCAL cDir, cName, cExt
LOCAL headstate
LOCAL cDL_Version_Alter
LOCAL cDL_Version
@@ -4446,8 +4445,6 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! lSkipBuild .AND. ! hbmk[ _HBMK_lStopAfterInit ] .AND. ! hbmk[ _HBMK_lStopAfterHarbour ] .AND. ! lDumpInfo
headstate := NIL
IF hbmk[ _HBMK_lINC ] .AND. ! hbmk[ _HBMK_lREBUILD ]
l_aC_TODO := {}
FOR EACH tmp IN hbmk[ _HBMK_aC ]
@@ -4457,7 +4454,7 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! hb_FGetDateTime( FNameDirExtSet( tmp, hbmk[ _HBMK_cWorkDir ], cObjExt ), @tmp2 ) .OR. ;
! hb_FGetDateTime( tmp, @tmp1 ) .OR. ;
tmp1 > tmp2 .OR. ;
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, NIL, .F., tmp2, .T., cBin_CompC, @headstate ) )
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, tmp2, .T., cBin_CompC ) )
AAdd( l_aC_TODO, tmp )
ENDIF
NEXT
@@ -4470,8 +4467,6 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! lSkipBuild .AND. ! hbmk[ _HBMK_lStopAfterInit ] .AND. ! hbmk[ _HBMK_lStopAfterHarbour ] .AND. ! lDumpInfo
headstate := NIL
IF hbmk[ _HBMK_lINC ] .AND. ! hbmk[ _HBMK_lREBUILD ]
l_aCPP_TODO := {}
FOR EACH tmp IN hbmk[ _HBMK_aCPP ]
@@ -4481,7 +4476,7 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! hb_FGetDateTime( FNameDirExtSet( tmp, hbmk[ _HBMK_cWorkDir ], cObjExt ), @tmp2 ) .OR. ;
! hb_FGetDateTime( tmp, @tmp1 ) .OR. ;
tmp1 > tmp2 .OR. ;
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, NIL, .F., tmp2, .T., cBin_CompCPP, @headstate ) )
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, tmp2, .T., cBin_CompCPP ) )
AAdd( l_aCPP_TODO, tmp )
ENDIF
NEXT
@@ -4523,14 +4518,14 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! hb_FGetDateTime( FNameDirExtSet( tmp3, cHarbourOutputDir, cHarbourOutputExt ), @tmp2 ) .OR. ;
! hb_FGetDateTime( tmp3, @tmp1 ) .OR. ;
tmp1 > tmp2 .OR. ;
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, NIL, .F., tmp2, .F., cBin_CompC, @headstate ) )
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, tmp2, .F., cBin_CompC ) )
AAdd( l_aPRG_TODO, tmp )
ENDIF
NEXT
ELSE
IF ! Empty( hbmk[ _HBMK_hAUTOHBC ] )
FOR EACH tmp IN hbmk[ _HBMK_aPRG ]
FindNewerHeaders( hbmk, tmp, NIL, .F., NIL, .F., cBin_CompC, @headstate )
FindNewerHeaders( hbmk, tmp, NIL, .F., cBin_CompC )
NEXT
ENDIF
@@ -5099,7 +5094,7 @@ FUNCTION hbmk2( aArgs, nArgTarget, /* @ */ lPause, nLevel )
IF ! hb_FGetDateTime( FNameDirExtSet( tmp, hbmk[ _HBMK_cWorkDir ], cResExt ), @tmp2 ) .OR. ;
! hb_FGetDateTime( tmp, @tmp1 ) .OR. ;
tmp1 > tmp2 .OR. ;
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, NIL, .F., tmp2, .T., cBin_CompC, @headstate ) )
( hbmk[ _HBMK_nHEAD ] != _HEAD_OFF .AND. FindNewerHeaders( hbmk, tmp, tmp2, .T., cBin_CompC ) )
AAdd( l_aRESSRC_TODO, tmp )
ENDIF
NEXT
@@ -6328,17 +6323,11 @@ STATIC FUNCTION SetupForGT( cGT_New, /* @ */ cGT, /* @ */ lGUI )
feel free to update the code.
[vszakats] */
#define _HEADSTATE_hFiles 1
#define _HEADSTATE_lAnyNewer 2
#define _HEADSTATE_MAX_ 2
STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tTimeParent, lCMode, cBin_CompC, /* @ */ headstate, nNestingLevel )
LOCAL cFile
STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, tTimeParent, lCMode, cBin_CompC )
LOCAL tTimeSelf
LOCAL tTimeDependency
LOCAL tmp
LOCAL cExt
LOCAL cHeader
LOCAL cModule
LOCAL cDependency
LOCAL aCommand
@@ -6346,142 +6335,11 @@ STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tT
STATIC s_hRegexInclude := NIL
STATIC s_hExclStd := NIL
DEFAULT nNestingLevel TO 1
DEFAULT cParentDir TO FNameDirGet( cFileName )
IF nNestingLevel == 1
headstate := Array( _HEADSTATE_MAX_ )
headstate[ _HEADSTATE_hFiles ] := { => }
headstate[ _HEADSTATE_lAnyNewer ] := .F.
ENDIF
IF hbmk[ _HBMK_nHEAD ] == _HEAD_OFF
RETURN .F.
ENDIF
IF nNestingLevel > _HBMK_HEAD_NEST_MAX
RETURN .F.
ENDIF
/* Don't spend time on known system headers */
IF lSystemHeader
IF s_hExclStd == NIL
s_hExclStd := {;
"assert.h" => NIL ,; /* Standard C */
"ctype.h" => NIL ,;
"errno.h" => NIL ,;
"float.h" => NIL ,;
"limits.h" => NIL ,;
"locale.h" => NIL ,;
"math.h" => NIL ,;
"setjmp.h" => NIL ,;
"signal.h" => NIL ,;
"stdarg.h" => NIL ,;
"stddef.h" => NIL ,;
"stdio.h" => NIL ,;
"stdlib.h" => NIL ,;
"string.h" => NIL ,;
"time.h" => NIL ,;
"iso646.h" => NIL ,; /* ISO C NA1 */
"wchar.h" => NIL ,;
"wctype.h" => NIL ,;
"complex.h" => NIL ,; /* ISO C C99 */
"fenv.h" => NIL ,;
"inttypes.h" => NIL ,;
"stdbool.h" => NIL ,;
"stdint.h" => NIL ,;
"tgmath.h" => NIL ,;
"unistd.h" => NIL ,; /* Standard C POSIX */
"aio.h" => NIL ,;
"arpa/inet.h" => NIL ,;
"cpio.h" => NIL ,;
"dirent.h" => NIL ,;
"dlfcn.h" => NIL ,;
"fcntl.h" => NIL ,;
"fmtmsg.h" => NIL ,;
"fnmatch.h" => NIL ,;
"ftw.h" => NIL ,;
"glob.h" => NIL ,;
"grp.h" => NIL ,;
"iconv.h" => NIL ,;
"langinfo.h" => NIL ,;
"libgen.h" => NIL ,;
"monetary.h" => NIL ,;
"mqueue.h" => NIL ,;
"ndbm.h" => NIL ,;
"net/if.h" => NIL ,;
"netdb.h" => NIL ,;
"netinet/in.h" => NIL ,;
"netinet/tcp.h" => NIL ,;
"nl_types.h" => NIL ,;
"poll.h" => NIL ,;
"pthread.h" => NIL ,;
"pwd.h" => NIL ,;
"regex.h" => NIL ,;
"sched.h" => NIL ,;
"search.h" => NIL ,;
"semaphore.h" => NIL ,;
"spawn.h" => NIL ,;
"strings.h" => NIL ,;
"stropts.h" => NIL ,;
"sys/ipc.h" => NIL ,;
"sys/mman.h" => NIL ,;
"sys/msg.h" => NIL ,;
"sys/resource.h" => NIL ,;
"sys/select.h" => NIL ,;
"sys/sem.h" => NIL ,;
"sys/shm.h" => NIL ,;
"sys/socket.h" => NIL ,;
"sys/stat.h" => NIL ,;
"sys/statvfs.h" => NIL ,;
"sys/time.h" => NIL ,;
"sys/times.h" => NIL ,;
"sys/types.h" => NIL ,;
"sys/uio.h" => NIL ,;
"sys/un.h" => NIL ,;
"sys/utsname.h" => NIL ,;
"sys/wait.h" => NIL ,;
"syslog.h" => NIL ,;
"tar.h" => NIL ,;
"termios.h" => NIL ,;
"trace.h" => NIL ,;
"ulimit.h" => NIL ,;
"unistd.h" => NIL ,;
"utime.h" => NIL ,;
"utmpx.h" => NIL ,;
"wordexp.h" => NIL ,;
"windows.h" => NIL ,; /* OS (win) */
"winspool.h" => NIL ,;
"shellapi.h" => NIL ,;
"ole2.h" => NIL ,;
"dos.h" => NIL ,; /* OS (dos) */
"os2.h" => NIL } /* OS (os2) */
ENDIF
IF StrTran( Lower( cFileName ), "\", "/" ) $ s_hExclStd
RETURN .F.
ENDIF
ENDIF
IF nNestingLevel > 1
cFileName := FindHeader( hbmk, cFileName, cParentDir, lSystemHeader, lSystemHeader )
IF Empty( cFileName )
RETURN .F.
ENDIF
ENDIF
IF cFileName $ headstate[ _HEADSTATE_hFiles ]
RETURN .F.
ENDIF
headstate[ _HEADSTATE_hFiles ][ cFileName ] := .T.
IF hbmk[ _HBMK_lDEBUGINC ]
hbmk_OutStd( hbmk, hb_StrFormat( "debuginc: HEADER %1$s", cFileName ) )
ENDIF
IF tTimeParent != NIL .AND. hb_FGetDateTime( cFileName, @tTimeSelf ) .AND. tTimeSelf > tTimeParent
headstate[ _HEADSTATE_lAnyNewer ] := .T.
RETURN .T.
ENDIF
@@ -6492,18 +6350,6 @@ STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tT
RETURN .F.
ENDIF
IF cFileName $ hbmk[ _HBMK_hDEPTS ]
FOR EACH cDependency IN hbmk[ _HBMK_hDEPTS ][ cFileName ]
IF hb_FGetDateTime( cDependency, @tTimeDependency ) .AND. tTimeDependency > tTimeParent
headstate[ _HEADSTATE_lAnyNewer ] := .T.
RETURN .T.
ENDIF
NEXT
RETURN headstate[ _HEADSTATE_lAnyNewer ]
ENDIF
IF ! lCMode .AND. hbmk[ _HBMK_nHEAD ] == _HEAD_NATIVE .AND. hbmk[ _HBMK_nHBMODE ] == _HBMODE_NATIVE
IF hbmk[ _HBMK_lDEBUGINC ]
@@ -6532,7 +6378,6 @@ STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tT
hbmk_OutStd( hbmk, hb_StrFormat( "debuginc: HEADER (NATIVE) %1$s", cDependency ) )
ENDIF
IF hb_FGetDateTime( cDependency, @tTimeDependency ) .AND. tTimeDependency > tTimeParent
headstate[ _HEADSTATE_lAnyNewer ] := .T.
IF Empty( hbmk[ _HBMK_hAUTOHBC ] )
RETURN .T.
ENDIF
@@ -6554,7 +6399,6 @@ STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tT
hbmk_OutStd( hbmk, hb_StrFormat( "debuginc: HEADER (CLP) %1$s", cDependency ) )
ENDIF
IF hb_FGetDateTime( cDependency, @tTimeDependency ) .AND. tTimeDependency > tTimeParent
headstate[ _HEADSTATE_lAnyNewer ] := .T.
RETURN .T.
ENDIF
ENDIF
@@ -6585,61 +6429,298 @@ STATIC FUNCTION FindNewerHeaders( hbmk, cFileName, cParentDir, lSystemHeader, tT
hbmk_OutStd( hbmk, hb_StrFormat( "debuginc: C HEADER (NATIVE) %1$s", cDependency ) )
ENDIF
IF hb_FGetDateTime( cDependency, @tTimeDependency ) .AND. tTimeDependency > tTimeParent
headstate[ _HEADSTATE_lAnyNewer ] := .T.
RETURN .T.
RETURN .T.
ENDIF
ENDIF
NEXT
ENDIF
NEXT
ELSE
/* TODO: Add filter based on extension to avoid binary files */
/* NOTE: Beef up this section if you need a more intelligent source
parser. Notice that this code is meant to process both
.prg, .c and .res sources. Please try to keep it simple,
as speed and maintainability is also important. [vszakats] */
cFile := MemoRead( cFileName )
/* NOTE:
http://en.wikipedia.org/wiki/PCRE
http://www.pcre.org/pcre.txt */
IF s_hRegexInclude == NIL
/* NOTE: #import is Objective C specific directive */
s_hRegexInclude := hb_regexComp( '^[[:blank:]]*#[[:blank:]]*(include|import)[[:blank:]]*(\".+?\"|<.+?>)', .F. /* lCaseSensitive */, .T. /* lNewLine */ )
IF Empty( s_hRegexInclude )
hbmk_OutErr( hbmk, I_( "Internal Error: Regular expression engine missing or unsupported. Please check your Harbour build settings." ) )
s_hRegexInclude := {} /* To show the error only once by setting to non-NIL empty value */
ENDIF
IF getNewestTime( hbmk, cFileName, @hbmk[ _HBMK_hFiles ], lCMode ) > tTimeParent
RETURN .T.
ENDIF
ENDIF
IF ! Empty( s_hRegexInclude )
RETURN .F.
FOR EACH tmp IN hb_regexAll( s_hRegexInclude, cFile, NIL /* lCaseSensitive */, NIL /* lNewLine */, NIL, NIL /* nGetMatch */, .T. /* lOnlyMatch */ )
#define _HBMK_HEADER_cHeader 1
#define _HBMK_HEADER_lSystemHeader 2
#define _HBMK_HEADER_LEN_ 2
STATIC FUNCTION s_getIncludedFiles( hbmk, cFile, cParentDir, lCMode )
STATIC s_hRegexInclude
STATIC s_hExclStd
LOCAL aDeps
LOCAL cFileBody
LOCAL lSystemHeader
LOCAL cHeader
LOCAL aDep
LOCAL tmp
/* NOTE:
http://en.wikipedia.org/wiki/PCRE
http://www.pcre.org/pcre.txt */
IF s_hRegexInclude == NIL
s_hRegexInclude := hb_regexComp( '^[[:blank:]]*#[[:blank:]]*(include|import)[[:blank:]]*(\".+?\"|<.+?>'+"|'.+?'|`.+?'"+')',;
.F. /* lCaseSensitive */,;
.T. /* lNewLine */ )
IF Empty( s_hRegexInclude )
hbmk_OutErr( hbmk, I_( "Internal Error: Regular expression engine missing or unsupported. Please check your Harbour build settings." ) )
s_hRegexInclude := {} /* To show the error only once by setting to non-NIL empty value */
ENDIF
ENDIF
aDeps := {}
IF ! Empty( s_hRegexInclude )
cFileBody := MemoRead( cFile )
IF ! Empty( cFileBody )
FOR EACH tmp IN hb_regexAll( s_hRegexInclude, cFileBody, ;
NIL /* lCaseSensitive */, ;
NIL /* lNewLine */, NIL, ;
NIL /* nGetMatch */, ;
.T. /* lOnlyMatch */ )
cHeader := tmp[ 3 ] /* First match marker */
lSystemHeader := ( Left( cHeader, 1 ) == "<" )
cHeader := SubStr( cHeader, 2, Len( cHeader ) - 2 )
IF FindNewerHeaders( hbmk, cHeader, iif( lCMode, FNameDirGet( cFileName ), cParentDir ), lSystemHeader, tTimeParent, lCMode, cBin_CompC, @headstate, nNestingLevel + 1 )
headstate[ _HEADSTATE_lAnyNewer ] := .T.
IF lCMode .OR. Empty( hbmk[ _HBMK_hAUTOHBC ] )
RETURN .T.
/* Don't spend time on known system headers */
IF lSystemHeader
IF s_hExclStd == NIL
s_hExclStd := {;
"assert.h" => NIL ,; /* Standard C */
"ctype.h" => NIL ,;
"errno.h" => NIL ,;
"float.h" => NIL ,;
"limits.h" => NIL ,;
"locale.h" => NIL ,;
"math.h" => NIL ,;
"setjmp.h" => NIL ,;
"signal.h" => NIL ,;
"stdarg.h" => NIL ,;
"stddef.h" => NIL ,;
"stdio.h" => NIL ,;
"stdlib.h" => NIL ,;
"string.h" => NIL ,;
"time.h" => NIL ,;
"iso646.h" => NIL ,; /* ISO C NA1 */
"wchar.h" => NIL ,;
"wctype.h" => NIL ,;
"complex.h" => NIL ,; /* ISO C C99 */
"fenv.h" => NIL ,;
"inttypes.h" => NIL ,;
"stdbool.h" => NIL ,;
"stdint.h" => NIL ,;
"tgmath.h" => NIL ,;
"unistd.h" => NIL ,; /* Standard C POSIX */
"aio.h" => NIL ,;
"arpa/inet.h" => NIL ,;
"cpio.h" => NIL ,;
"dirent.h" => NIL ,;
"dlfcn.h" => NIL ,;
"fcntl.h" => NIL ,;
"fmtmsg.h" => NIL ,;
"fnmatch.h" => NIL ,;
"ftw.h" => NIL ,;
"glob.h" => NIL ,;
"grp.h" => NIL ,;
"iconv.h" => NIL ,;
"langinfo.h" => NIL ,;
"libgen.h" => NIL ,;
"monetary.h" => NIL ,;
"mqueue.h" => NIL ,;
"ndbm.h" => NIL ,;
"net/if.h" => NIL ,;
"netdb.h" => NIL ,;
"netinet/in.h" => NIL ,;
"netinet/tcp.h" => NIL ,;
"nl_types.h" => NIL ,;
"poll.h" => NIL ,;
"pthread.h" => NIL ,;
"pwd.h" => NIL ,;
"regex.h" => NIL ,;
"sched.h" => NIL ,;
"search.h" => NIL ,;
"semaphore.h" => NIL ,;
"spawn.h" => NIL ,;
"strings.h" => NIL ,;
"stropts.h" => NIL ,;
"sys/ipc.h" => NIL ,;
"sys/mman.h" => NIL ,;
"sys/msg.h" => NIL ,;
"sys/resource.h" => NIL ,;
"sys/select.h" => NIL ,;
"sys/sem.h" => NIL ,;
"sys/shm.h" => NIL ,;
"sys/socket.h" => NIL ,;
"sys/stat.h" => NIL ,;
"sys/statvfs.h" => NIL ,;
"sys/time.h" => NIL ,;
"sys/times.h" => NIL ,;
"sys/types.h" => NIL ,;
"sys/uio.h" => NIL ,;
"sys/un.h" => NIL ,;
"sys/utsname.h" => NIL ,;
"sys/wait.h" => NIL ,;
"syslog.h" => NIL ,;
"tar.h" => NIL ,;
"termios.h" => NIL ,;
"trace.h" => NIL ,;
"ulimit.h" => NIL ,;
"unistd.h" => NIL ,;
"utime.h" => NIL ,;
"utmpx.h" => NIL ,;
"wordexp.h" => NIL ,;
"windows.h" => NIL ,; /* OS (win) */
"winspool.h" => NIL ,;
"shellapi.h" => NIL ,;
"ole2.h" => NIL ,;
"dos.h" => NIL ,; /* OS (dos) */
"os2.h" => NIL } /* OS (os2) */
ENDIF
IF StrTran( Lower( cHeader ), "\", "/" ) $ s_hExclStd
LOOP
ENDIF
ENDIF
IF ! lCMode .AND. cHeader $ hbmk[ _HBMK_hAUTOHBC ]
hbmk[ _HBMK_hAUTOHBCFOUND ][ cHeader ] := hbmk[ _HBMK_hAUTOHBC ][ cHeader ]
hb_HDel( hbmk[ _HBMK_hAUTOHBC ], cHeader )
ENDIF
IF ( cHeader := FindHeader( hbmk, cHeader, cParentDir, lSystemHeader, lSystemHeader ) ) != NIL
IF hbmk[ _HBMK_lDEBUGINC ]
hbmk_OutStd( hbmk, hb_StrFormat( "debuginc: HEADER %1$s %2$s", cHeader, iif( lSystemHeader, "(system)", "" ) ) )
ENDIF
aDep := Array( _HBMK_HEADER_LEN_ )
aDep[ _HBMK_HEADER_cHeader ] := cHeader
aDep[ _HBMK_HEADER_lSystemHeader ] := lSystemHeader
AAdd( aDeps, aDep )
ENDIF
NEXT
ENDIF
ENDIF
RETURN headstate[ _HEADSTATE_lAnyNewer ]
RETURN aDeps
/* optimized time scan algorithm */
#define _HBMK_FILEDEF_aINCFILES 1
#define _HBMK_FILEDEF_tFILETIME 2
#define _HBMK_FILEDEF_tNEWESTTIME 3
#define _HBMK_FILEDEF_lCANSCAN 4
#define _HBMK_FILEDEF_LEN_ 4
STATIC PROCEDURE s_getFilesDep( hbmk, cFile, hFiles, cParentDir, lSystemHeader, lCMode )
LOCAL aDep, tTime, aDeps, aFile
IF ! cFile $ hFiles
IF lSystemHeader
/* Don't scan into system headers */
aDeps := {}
ELSE
aDeps := s_getIncludedFiles( hbmk, cFile, iif( lCMode, FNameDirGet( cFile ), cParentDir ), lCMode )
ENDIF
IF ! hb_FGetDateTime( cFile, @tTime )
tTime := t"00:00"
ENDIF
aFile := Array( _HBMK_FILEDEF_LEN_ )
aFile[ _HBMK_FILEDEF_aINCFILES ] := aDeps
aFile[ _HBMK_FILEDEF_tFILETIME ] := tTime
aFile[ _HBMK_FILEDEF_tNEWESTTIME ] := NIL
aFile[ _HBMK_FILEDEF_lCANSCAN ] := .T.
hFiles[ cFile ] := aFile
FOR EACH aDep IN aDeps
s_getFilesDep( hbmk, aDep[ _HBMK_HEADER_cHeader ],;
hFiles,;
cParentDir,;
aDep[ _HBMK_HEADER_lSystemHeader ],;
lCMode )
NEXT
ENDIF
RETURN
static function s_getNewestTime( cFile, hFiles, lFileReq )
local aFile, tTime, aDep, tDep, lReq
tTime := t"00:00"
if cFile $ hFiles
aFile := hFiles[ cFile ]
if aFile[ _HBMK_FILEDEF_tNEWESTTIME ] != NIL
/* this file does not have any cross references other then to self
* and the time of the newest included file is already calculated
* so we can simply use it
*/
tTime := aFile[ _HBMK_FILEDEF_tNEWESTTIME ]
elseif aFile[ _HBMK_FILEDEF_lCANSCAN ]
lReq := .f.
aFile[ _HBMK_FILEDEF_lCANSCAN ] := .f.
tTime := aFile[ _HBMK_FILEDEF_tFILETIME ]
for each aDep in aFile[ _HBMK_FILEDEF_aINCFILES ]
tDep := s_getNewestTime( aDep[ _HBMK_HEADER_cHeader ], hFiles, @lReq )
if tDep > tTime
tTime := tDep
endif
next
if lReq
/* This file has references to some other files already
* scanned. It's possible that these are circular references
* and the time of files with such references is not fully
* calculated yet (they are now process on higher recursion
* levels) so we cannot store calculated time as the final
* newest time of this file
*/
lFileReq := .t.
else
/* we do not have any circular references to files with
* undefined yet time so we can safely set the time of the
* newest included file to not repeat the scan when this
* file is reused
*/
aFile[ _HBMK_FILEDEF_lCANSCAN ] := .t.
aFile[ _HBMK_FILEDEF_tNEWESTTIME ] := tTime
endif
else
lFileReq := .t.
endif
endif
return tTime
static function getNewestTime( hbmk, cFile, hFiles, lCMode )
local aFile, tTime
if hFiles == NIL
hFiles := { => }
/* for easier visualization the scan steps in debug mode */
/* hb_hKeepOrder( hFiles, .t. ) */
endif
s_getFilesDep( hbmk, cFile, hFiles, FNameDirGet( cFile ), .F., lCMode )
tTime := s_getNewestTime( cFile, hFiles )
/* we calculated the newest time of this file and all included files
* so we can set it for future reuse if this file included also by
* some other ones.
*/
hFiles[ cFile, _HBMK_FILEDEF_tNEWESTTIME ] := tTime
/* mark all files with cross references as scanable so we can
* repeat the scan process for other files
*/
for each aFile in hFiles
aFile[ _HBMK_FILEDEF_lCANSCAN ] := .t.
next
return tTime
STATIC FUNCTION clpfile_read( cFileName )
LOCAL cFileBody := MemoRead( cFileName )
@@ -7087,17 +7168,18 @@ STATIC FUNCTION FindHeader( hbmk, cFileName, cParentDir, lSystemHeader, lSkipDep
LOCAL cDir
LOCAL tmp
/* Check in current dir */
IF ! lSystemHeader .AND. hb_FileExists( PathSepToSelf( cFileName ) )
RETURN PathSepToSelf( cFileName )
ENDIF
/* Check in parent dir */
IF ! lSystemHeader
tmp := DirAddPathSep( PathSepToSelf( cParentDir ) ) + PathSepToSelf( cFileName )
IF hb_FileExists( tmp )
RETURN tmp
IF Empty( cParentDir )
/* Check in current dir */
IF hb_FileExists( PathSepToSelf( cFileName ) )
RETURN PathSepToSelf( cFileName )
ENDIF
ELSE
/* Check in parent dir */
tmp := DirAddPathSep( PathSepToSelf( cParentDir ) ) + PathSepToSelf( cFileName )
IF hb_FileExists( tmp )
RETURN tmp
ENDIF
ENDIF
ENDIF