diff --git a/harbour/include/hbver.h b/harbour/include/hbver.h index d3b0c4428e..4a32280e9e 100644 --- a/harbour/include/hbver.h +++ b/harbour/include/hbver.h @@ -58,15 +58,20 @@ #else #define HB_VER_LEX "Flex" #endif + +/* NOTE: One of these next three fields can be incremented by the hbverfix program */ + #define HB_VER_MAJOR 0 /* Major version number */ #define HB_VER_MINOR 43 /* Minor version number */ #define HB_VER_REVISION 0 /* Revision number */ -/* TOFIX: Ideally these should be generated dynamically, until - then, they should be updated by the builder. [vszakats] */ +/* NOTE: The next two fields are automatically updated by the hbverfix program */ #define HB_VER_LENTRY "2003-09-29 22:10 UTC+0300 Alexander Kresin " #define HB_VER_CHLCVS "ChangeLog,v 1.4490 2003/09/29 18:07:24 alkresin" + +/* TOFIX: The next three fields need to get updated automatically */ + #define HB_VER_C_USR "" #define HB_VER_L_USR "" #define HB_VER_PRG_USR "" diff --git a/harbour/makefile.bc b/harbour/makefile.bc index ec5e5e7a11..03a09b5d94 100644 --- a/harbour/makefile.bc +++ b/harbour/makefile.bc @@ -112,6 +112,7 @@ HBTEST_DIR = utils\hbtest HBDOC_DIR = utils\hbdoc HBPP_DIR = utils\hbpp HBMAKE_DIR = utils\hbmake +HBVER_DIR = utils\hbver !if $(HB_LEX) == SIMPLEX INCLUDE_DIR = $(INCLUDE_DIR);source\compiler;source\macro @@ -170,6 +171,7 @@ HBRUN_EXE = $(BIN_DIR)\hbrun.exe HBTEST_EXE = $(BIN_DIR)\hbtest.exe HBDOC_EXE = $(BIN_DIR)\hbdoc.exe HBMAKE_EXE = $(BIN_DIR)\hbmake.exe +HBVER_EXE = $(BIN_DIR)\hbverfix.exe # # GT driver list @@ -752,6 +754,9 @@ HBMAKE_EXE_OBJS = \ $(OBJ_DIR)\radios.obj \ $(OBJ_DIR)\hbmlang.obj +HBVER_EXE_OBJS = \ + $(OBJ_DIR)\hbverfix.obj \ + # # Our default target # @@ -777,7 +782,8 @@ all: \ $(HBPP_EXE) \ $(HBTEST_EXE) \ $(HBDOC_EXE) \ - $(HBMAKE_EXE) + $(HBMAKE_EXE) \ + $(HBVER_EXE) # # Library dependencies and build rules # @@ -2951,3 +2957,14 @@ $(OBJ_DIR)\prb_stak.obj : $(OBJ_DIR)\prb_stak.c $(OBJ_DIR)\hbmlang.obj : $(HBMAKE_DIR)\hbmlang.c $(CC) $(CLIBFLAGS) -o$@ $** + +$(HBVER_EXE) : $(HBVER_EXE_OBJS) + + $(ECHO) $(CFLAGS) > make.tmp + $(ECHO) -e$(HBVER_EXE) >> make.tmp + $(ECHO) $(OBJ_DIR)\hbverfix.obj >> make.tmp + $(CC) @make.tmp + $(DEL) make.tmp + +$(OBJ_DIR)\hbverfix.obj : $(HBVER_DIR)\hbverfix.c + $(CC) $(CLIBFLAGS) -o$@ $** diff --git a/harbour/makefile.nt b/harbour/makefile.nt index 1d7cca92ac..39a54f2f2b 100644 --- a/harbour/makefile.nt +++ b/harbour/makefile.nt @@ -172,6 +172,7 @@ HBRUN_EXE = $(BIN_DIR)\hbrun.exe HBTEST_EXE = $(BIN_DIR)\hbtest.exe HBDOC_EXE = $(BIN_DIR)\hbdoc.exe HBMAKE_EXE = $(BIN_DIR)\hbmake.exe +HBVER_EXE = $(BIN_DIR)\hbverfix.exe # # GT driver list @@ -832,7 +833,8 @@ all: \ $(HBPP_EXE) \ $(HBTEST_EXE) \ $(HBDOC_EXE) \ - $(HBMAKE_EXE) + $(HBMAKE_EXE) \ + $(HBVER_EXE) MK_FLAGS = $(MK_FLAGS:A=) @@ -859,7 +861,8 @@ all: \ $(HBPP_EXE) \ $(HBTEST_EXE) \ $(HBDOC_EXE) \ - $(HBMAKE_EXE) + $(HBMAKE_EXE) \ + $(HBVER_EXE) !endif @@ -989,6 +992,15 @@ $(HBMAKE_EXE) : \ $(HBMAKE_DIR)\hbmlang.c \ -o $(HBMAKE_EXE) /link $(LDFLAGS) $(LIBS2) +# +# HBVERFIX.EXE rules +# + +$(HBVER_EXE) : \ + $(HBVER_DIR)\hbverfix.c + $(CC) $(CFLAGS) -Fo$(OBJ_DIR)\ $(HBVER_DIR)\hverfix.c \ + -o $(HBVER_EXE) /link $(LDFLAGS) + # # HARBOUR.EXE rules # diff --git a/harbour/makefile.vc b/harbour/makefile.vc index 740b957479..23d0adbc23 100644 --- a/harbour/makefile.vc +++ b/harbour/makefile.vc @@ -90,6 +90,7 @@ HBTEST_DIR = utils\hbtest HBDOC_DIR = utils\hbdoc HBPP_DIR = utils\hbpp HBMAKE_DIR = utils\hbmake +HBVER_DIR = utils\hbver !ifdef HB_DOC_PDF # don't indent definitions @@ -149,6 +150,7 @@ HBRUN_EXE = $(BIN_DIR)\hbrun.exe HBTEST_EXE = $(BIN_DIR)\hbtest.exe HBDOC_EXE = $(BIN_DIR)\hbdoc.exe HBMAKE_EXE = $(BIN_DIR)\hbmake.exe +HBVER_EXE = $(BIN_DIR)\hbverfix.exe # # GT driver list @@ -796,7 +798,8 @@ all: \ $(HBPP_EXE) \ $(HBTEST_EXE) \ $(HBDOC_EXE) \ - $(HBMAKE_EXE) + $(HBMAKE_EXE) \ + $(HBVER_EXE) MK_FLAGS = $(MK_FLAGS:A=) @@ -823,7 +826,8 @@ all: \ $(HBPP_EXE) \ $(HBTEST_EXE) \ $(HBDOC_EXE) \ - $(HBMAKE_EXE) + $(HBMAKE_EXE) \ + $(HBVER_EXE) !endif @@ -953,6 +957,15 @@ $(HBMAKE_EXE) : \ $(HBMAKE_DIR)\hbmlang.c \ -o $(HBMAKE_EXE) /link $(LDFLAGS) $(LIBS2) +# +# HBVERFIX.EXE rules +# + +$(HBVER_EXE) : \ + $(HBVER_DIR)\hbverfix.c + $(CC) $(CFLAGS) -Fo$(OBJ_DIR)\ $(HBVER_DIR)\hverfix.c \ + -o $(HBVER_EXE) /link $(LDFLAGS) + # # HARBOUR.EXE rules # diff --git a/harbour/utils/Makefile b/harbour/utils/Makefile index a8fd4e213b..e041acf97e 100644 --- a/harbour/utils/Makefile +++ b/harbour/utils/Makefile @@ -6,10 +6,11 @@ ROOT = ../ DIRS=\ hbpp \ + hbver \ hbrun \ hbdoc \ hbtest \ - hbmake \ + hbmake \ # hbextern \ include $(ROOT)config/dir.cf diff --git a/harbour/utils/hbver/Makefile b/harbour/utils/hbver/Makefile new file mode 100644 index 0000000000..1dee657b85 --- /dev/null +++ b/harbour/utils/hbver/Makefile @@ -0,0 +1,13 @@ +# +# $Id$ +# + +ROOT = ../../ + +C_SOURCES=\ + +C_MAIN=hbverfix.c + +LIBS=\ + +include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/utils/hbver/hbverfix.c b/harbour/utils/hbver/hbverfix.c new file mode 100644 index 0000000000..89a3009d89 --- /dev/null +++ b/harbour/utils/hbver/hbverfix.c @@ -0,0 +1,355 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Harbour Version Updater standalone main module + * + * Copyright 2003 David G. Holm + * 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, 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* + * Avoid tracing in preprocessor/compiler. + */ +#if ! defined(HB_TRACE_UTILS) + #if defined(HB_TRACE_LEVEL) + #undef HB_TRACE_LEVEL + #endif +#endif + +#include +#include +#include +#include + +#include "hbcomp.h" + +#define MAX_BUF_LEN 4096 + +char * szIncrementNumber( char * szBuffer, size_t stSkipOver ) +{ + size_t i; + for( i = stSkipOver; i < strlen( szBuffer ) && isspace( szBuffer[ i ] ); i++ ) {} + if( i > stSkipOver && i < strlen( szBuffer ) ) + { + int iVersion; + char szIntBuf[ 8 ]; + size_t stStart = i; + iVersion = atoi( &szBuffer[ stStart ] ) + 1; + sprintf( szIntBuf, "%-7d", iVersion ); + for( i = 0; i < strlen( szIntBuf ); i++ ) + { + szBuffer[ stStart + i ] = szIntBuf[ i ]; + } + } + return szBuffer; +} + +char * szReplaceQuoted( char * szBuffer, const char * new_string ) +{ + char szOldBuf[ MAX_BUF_LEN ]; + char * szOpening = strchr( szBuffer, 34 ); /* Locate starting quote */ + if( szOpening ) + { + char * szClosing = strchr( szOpening + 1, 34 ); /* Locate ending quote */ + if( szClosing ) + { + strncpy( szOldBuf, szClosing + 1, MAX_BUF_LEN ); + szOldBuf[ MAX_BUF_LEN - 1 ] = '\0'; + strncpy( szOpening + 1, new_string, MAX_BUF_LEN - ( szOpening - szBuffer ) ); + szBuffer[ MAX_BUF_LEN - 1 ] = '\0'; + strncat( szBuffer, szOldBuf, MAX_BUF_LEN - strlen( szBuffer ) ); + szBuffer[ MAX_BUF_LEN - 1 ] = '\0'; + return szBuffer; + } + } + return NULL; +} + +int main( int argc, char * argv[] ) +{ + BOOL bBadCmdLine = FALSE; + BOOL bShowHelp = FALSE; + char cIncrement = ' '; + char szErrBuf[ MAX_BUF_LEN ]; + int iDebugLevel = 0; + int iArg = 1; + + while( iArg < argc ) + { + if( HB_ISOPTSEP(argv[ iArg ][ 0 ])) + { + BOOL bInvalid = FALSE; + switch( argv[ iArg ][ 1 ] ) + { + case 'd': + case 'D': + iDebugLevel = atoi( &argv[ iArg ][ 2 ] ); + break; + case 'h': + case 'H': + case '?': + bShowHelp = TRUE; + break; + case 'i': + case 'I': + if( strlen( argv[ iArg ] ) > 2 ) + { + switch( argv[ iArg ][ 2 ] ) + { + case 'v': + case 'V': + case 'm': + case 'M': + case 'r': + case 'R': + cIncrement = tolower( argv[ iArg ][ 2 ] ); + break; + default: + bInvalid = TRUE; + } + break; + } + bInvalid = TRUE; + break; + default: + bInvalid = TRUE; + break; + } + if( bInvalid ) + { + bBadCmdLine = TRUE; + fprintf( stderr, "\nInvalid command line option: %s\n", &argv[ iArg ][ 1 ] ); + } + } + else + { + bBadCmdLine = TRUE; + fprintf( stderr, "\nInvalid command line argument: %s\n", &argv[ iArg ][ 0 ] ); + } + iArg++; + } + + if( bShowHelp ) + { + fprintf( stderr, "\nSyntax: %s [options]" + "\n" + "\nOptions: /d[level] set debug level (-1 == none, 0 == minimal*, 1 == verbose)" + "\n /iv increment major version number+" + "\n /im increment minor version number+" + "\n /ir increment cszRevision number+" + "\n" + "\nAn * indicates a default option. A + indicates mutually exclusive options" + "\n(the last one that is present on the command line will be being used)." + "\n" + , argv[ 0 ] ); + + return 1; + } + else if( bBadCmdLine ) + { + return 2; + } + else + { + const char * cszChangeLogName = "ChangeLog"; + const char * cszVersionName = "include/hbver.h"; + const char * cszRewriteName = "include/hbver.rw"; + char szInputBuffer[ MAX_BUF_LEN ]; + char szNewID[ MAX_BUF_LEN ]; + char szNewLog[ MAX_BUF_LEN ]; + BOOL bFoundID = FALSE; + BOOL bFoundLog = FALSE; + FILE * fhChangeLog; + + sprintf( szErrBuf, "Opening %s", cszChangeLogName ); + fhChangeLog = fopen( cszChangeLogName, "rt" ); + if( fhChangeLog == NULL ) + { + switch( errno ) + { + case ENOFILE: + fprintf( stderr, "\nThis program needs to be run from the directory with the %s file.\n", cszChangeLogName ); + return 3; + default: + perror( szErrBuf ); + return 4; + } + } + while( ! ( bFoundID && bFoundLog ) && ! feof( fhChangeLog ) ) + { + sprintf( szErrBuf, "Reading from %s", cszChangeLogName ); + fgets( szInputBuffer, MAX_BUF_LEN, fhChangeLog ); + if( ferror( fhChangeLog ) ) + { + perror( szErrBuf ); + return 5; + } + if( iDebugLevel > 0 ) fprintf( stderr, "\n==> %u <==> %s <==", strlen( szInputBuffer ), szInputBuffer ); + if( ! bFoundID ) + { + char * szID = strstr( szInputBuffer, "$Id: " ); + if( szID ) + { + size_t stLen; + szID = &szID[ 5 ]; /* Leave out the id markers... */ + stLen = strcspn( szID, "$" ) - 5; /* ...on both ends */ + szID[ stLen ] = '\0'; + bFoundID = TRUE; + strncpy( szNewID, szID, sizeof( szNewID ) ); + szNewID[ sizeof( szNewID ) - 1 ] = '\0'; + if( iDebugLevel >= 0 ) fprintf( stderr, "\nID: %s\n", szID ); + } + } + else if( szInputBuffer[ 4 ] == '-' && szInputBuffer[ 7 ] == '-' && szInputBuffer[ 10 ] == ' ' && szInputBuffer[ 13 ] == ':' ) + { + bFoundLog = TRUE; + strncpy( szNewLog, szInputBuffer, sizeof( szNewLog ) ); + szNewLog[ sizeof( szNewLog ) - 1 ] = '\0'; + if( iDebugLevel >= 0 ) fprintf( stderr, "\nLOG: %s\n", szInputBuffer ); + } + else if( iDebugLevel > 0 ) fprintf( stderr, " ===> %c %c %c %c <===", szInputBuffer[ 4 ], szInputBuffer[ 7 ], szInputBuffer[ 10 ], szInputBuffer[ 13 ] ); + } + fclose( fhChangeLog ); + if( !bFoundID ) + { + fprintf( stderr, "\nUnable to locate %s $Id record.\n", cszChangeLogName ); + return 6; + } + else if( ! bFoundLog ) + { + fprintf( stderr, "\nUnable to locate a %s entry.\n", cszChangeLogName ); + return 7; + } + else + { + const char *cszMajorVersion = "#define HB_VER_MAJOR"; + const char *cszMinorVersion = "#define HB_VER_MINOR"; + const char *cszRevision = "#define HB_VER_REVISION"; + const char *cszLastEntry = "#define HB_VER_LENTRY"; + const char *cszLastID = "#define HB_VER_CHLCVS"; + + FILE * fhRewrite; + FILE * fhVersion; + + sprintf( szErrBuf, "Opening %s", cszVersionName ); + fhVersion = fopen( cszVersionName, "rt" ); + if( fhVersion == NULL ) + { + perror( szErrBuf ); + return 9; + } + sprintf( szErrBuf, "Creating %s", cszRewriteName ); + fhRewrite = fopen( cszRewriteName, "wt" ); + if( fhRewrite == NULL ) + { + perror( szErrBuf ); + return 8; + } + while( ! feof( fhVersion ) ) + { + sprintf( szErrBuf, "Reading from %s", cszVersionName ); + fgets( szInputBuffer, MAX_BUF_LEN, fhVersion ); + if( iDebugLevel > 0 ) fprintf( stderr, "\n==> %u <==> %s <==", strlen( szInputBuffer ), szInputBuffer ); + if( ferror( fhVersion ) ) + { + perror( szErrBuf ); + return 9; + } + if( iDebugLevel > 0 ) fprintf( stderr, "\n==> %u <==> %s <==", strlen( szInputBuffer ), szInputBuffer ); + if( cIncrement == 'v' && strncmp( szInputBuffer, cszMajorVersion, strlen( cszMajorVersion ) ) == 0 ) + { + szIncrementNumber( szInputBuffer, strlen( cszMajorVersion ) ); + if( iDebugLevel >= 0 ) fprintf( stderr, "\nMajor version: %s", szInputBuffer ); + } + if( cIncrement == 'm' && strncmp( szInputBuffer, cszMinorVersion, strlen( cszMinorVersion ) ) == 0 ) + { + szIncrementNumber( szInputBuffer, strlen( cszMinorVersion ) ); + if( iDebugLevel >= 0 ) fprintf( stderr, "\nMinor version: %s", szInputBuffer ); + } + if( cIncrement == 'r' && strncmp( szInputBuffer, cszRevision, strlen( cszRevision ) ) == 0 ) + { + szIncrementNumber( szInputBuffer, strlen( cszRevision ) ); + if( iDebugLevel >= 0 ) fprintf( stderr, "\nRevision level: %s", szInputBuffer ); + } + if( strncmp( szInputBuffer, cszLastEntry, strlen( cszLastEntry ) ) == 0 ) + { + szReplaceQuoted( szInputBuffer, szNewLog ); + if( iDebugLevel >= 0 ) fprintf( stderr, "\nNew log: %s", szInputBuffer ); + } + if( strncmp( szInputBuffer, cszLastID, strlen( cszLastID ) ) == 0 ) + { + szReplaceQuoted( szInputBuffer, szNewID ); + if( iDebugLevel >= 0 ) fprintf( stderr, "\nNew ID: %s", szInputBuffer ); + } + if( !feof( fhVersion ) ) + { + sprintf( szErrBuf, "Writing to %s", cszRewriteName ); + fputs( szInputBuffer, fhRewrite ); + if( ferror( fhRewrite ) ) + { + perror( szErrBuf ); + return 10; + } + } + } + fclose( fhVersion ); + fclose( fhRewrite ); + sprintf( szErrBuf, "Deleting %s", cszVersionName ); + if( remove( cszVersionName ) ) + { + perror( szErrBuf ); + return 11; + } + sprintf( szErrBuf, "Renaming %s to %s", cszRewriteName, cszVersionName ); + if( rename( cszRewriteName, cszVersionName ) ) + { + perror( szErrBuf ); + return 11; + } + } + } + return 0; +}