diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 5aa3f2312c..c4e95c0ba6 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,43 @@ +19990914-17:40 EDT David G. Holm + + * include/itemapi.h + * source/rtl/itemapi.c + ! Added a third argument, PBH_ITEM pItemArg1, to the hb_itemDo() + and hb_itemDoC() functions to solve a var-arg problem with the + OS/2 version of GCC. When calling hb_itemDo() or hb_itemDoC() to + evaluate a symbol, function, or code block that does not take + any arguments, use '(PHB_ITEM *) 0' as the third argument. + + * config/win32/bcc32.cf + ! The GNU make system now works with Borland 32-bit compilers. + + * config/win32/gcc.cf + * Removed '-lmoldname' in order to avoid polluting the __CYGWIN__ + build with __MINGW32__ stuff. + + * source/compiler/harbour.l + ! Removed 'extern int _bQuiet', because it conflicts with the + 'extern BOOL _bQuiet' declaration in include/compiler.h. + + * source/rtl/console.c + ! Added __CYGWIN__ to the Unix-style input in HB___ACCEPT() + + * source/rtl/filesys.c + ! Removed the alleged Cygwin mode flag fix, which turned out to + be an incomptibility between the CYGWIN and MINGW32 libraries. + + * source/rtl/inkey.c + ! Applied the Borland Windows fix supplied by Jose Lalin. + ! Changed Cygwin support to use the Unix method in order to + avoid polluting the __CYGWIN__ build with __MINGW32__ stuff. + ! Moved the Unix keyboard input from hb_inkeyPoll() to hb_inkeyGet() + in order to stop blocking the VM when it polls the keyboard. + + * tests/working/inkeytst.prg + + Display a note regarding Unix-style keyboard input. + ! Changed the final keyboard test exit key from ESC to TAB, because + Unix-style keyboard input uses ESC as the lead-in for extended keys. + 19990915-23:20 GMT+3 Alexander Kresin * source/hbpp/hbpp.c * source/hbpp/table.c diff --git a/harbour/config/win32/bcc32.cf b/harbour/config/win32/bcc32.cf index b48590a660..c2793bf33f 100644 --- a/harbour/config/win32/bcc32.cf +++ b/harbour/config/win32/bcc32.cf @@ -2,7 +2,7 @@ # $Id$ # # The Harbour Project -# GNU MAKE file for Borland C/C++ Builder +# GNU MAKE file for Borland C/C++ 3.1 include $(TOP)$(ROOT)config/$(HB_ARCHITECTURE)/global.cf @@ -11,61 +11,45 @@ EXE_EXT = .exe LIB_PREF = LIB_EXT = .lib -$(HB_ARCHITECTURE)_$(HB_COMPILER)_GRANDP = $(subst /,\\,$(GRANDP)) -_HB_INC_COMPILE = $(subst /,\\,$(HB_INC_COMPILE)) +_HB_INC_COMPILE = $(subst /,\,$(HB_INC_COMPILE)) _HL = $(notdir $(HB_LIB_COMPILE)) ifeq ($(_HL),) #there is an ending slash -_HB_LIB_COMPILE = $(subst /,\\,$(HB_LIB_COMPILE)) +_HB_LIB_COMPILE = $(subst /,\,$(HB_LIB_COMPILE)) else -_HB_LIB_COMPILE = $(subst /,\\,$(HB_LIB_COMPILE)/) +_HB_LIB_COMPILE = $(subst /,\,$(HB_LIB_COMPILE)/) endif CC = bcc32 CC_IN = -c CC_OUT = -o -CPPFLAGS = -I$($(HB_ARCHITECTURE)_$(HB_COMPILER)_GRANDP) -I$(_HB_INC_COMPILE) +CPPFLAGS = -I$(GRANDP) -I$(_HB_INC_COMPILE) -DHARBOUR_USE_DOS_GTAPI CFLAGS = -O2 -#Note: The empty line below HAVE TO exist! -define link_file -$(COMSPEC) /E:2048 /Cecho $(file) >> __link__.tmp - -endef - - -define link_exe_file -$(COMSPEC) /E:2048 /Cecho $(LDFLAGS) -e$@ > __link__.tmp -$(foreach file, $^, $(link_file)) -$(COMSPEC) /E:2048 /Cecho $(LINKLIBS) >> __link__.tmp --$(LD) @__link__.tmp -endef - LD = bcc32 LDFLAGS = -O2 +LD_OUT = -e + +# Add all libraries specified in LIBS. ifeq ($(HB_LIB_COMPILE),) -LINKLIBS = $(foreach lib, $(LIBS), $(TOP)$(ROOT)source/$(lib)/$(ARCH)/$(lib)$(LIB_EXT)) +LINKPATHS += $(foreach lib, $(LIBS), -L$(TOP)$(ROOT)source/$(lib)/$(ARCH)) else -LINKLIBS = $(foreach lib, $(LIBS), $(lib)$(LIB_EXT)) +LINKPATHS += -L$(HB_LIB_COMPILE) endif -LD_RULE = $(link_exe_file) -#Note: The empty line below HAVE TO exist! -define lib_object -echo -+$(file) &>> __lib__.tmp +LINKLIBS += $(foreach lib, $(LIBS), $(lib).lib) -endef +# If LIBS specifies the rdd library, add all DB drivers. +ifeq ($(findstring rdd,$(LIBS)),rdd) +LINKPATHS += $(foreach drv, $(HB_DB_DRIVERS), -L$(TOP)$(ROOT)source/rdd/$(drv)/$(ARCH)) +LINKLIBS += $(foreach drv, $(HB_DB_DRIVERS), $(drv).lib) +endif -define create_library -echo $@ &> __lib__.tmp -$(foreach file, $^, $(lib_object)) -echo ,, >> __lib__.tmp -$(AR) @__lib__.tmp -del __lib__.tmp -endef +LDFLAGS = $(LINKPATHS) AR = tlib ARFLAGS = -AR_RULE = $(create_library) +AROBJS = $(foreach file, $^, -+$(file)) +AR_RULE = $(AR) $(ARFLAGS) $@ $(AROBJS),, include $(TOP)$(ROOT)config/rules.cf diff --git a/harbour/config/win32/gcc.cf b/harbour/config/win32/gcc.cf index 1b80d8d356..0aa1bb28a5 100644 --- a/harbour/config/win32/gcc.cf +++ b/harbour/config/win32/gcc.cf @@ -32,9 +32,6 @@ endif LINKLIBS += $(foreach lib, $(LIBS), -l$(lib)) -# This library is needed for kbhit() and getch() support. -LINKLIBS += -lmoldname - # If LIBS specifies the rdd library, add all DB drivers. ifeq ($(findstring rdd,$(LIBS)),rdd) LINKPATHS += $(foreach drv, $(HB_DB_DRIVERS), -L$(TOP)$(ROOT)source/rdd/$(drv)/$(ARCH)) diff --git a/harbour/include/itemapi.h b/harbour/include/itemapi.h index 853dd0d2f5..bdd64484e5 100644 --- a/harbour/include/itemapi.h +++ b/harbour/include/itemapi.h @@ -51,8 +51,8 @@ extern BOOL hb_evalNew ( PEVALINFO pEvalInfo, PHB_ITEM pItem ); extern BOOL hb_evalPutParam ( PEVALINFO pEvalInfo, PHB_ITEM pItem ); extern BOOL hb_evalRelease ( PEVALINFO pEvalInfo ); -extern PHB_ITEM hb_itemDo ( PHB_ITEM pItem, USHORT uiPCount, ... ); -extern PHB_ITEM hb_itemDoC ( char * szFunc, USHORT uiPCount, ... ); +extern PHB_ITEM hb_itemDo ( PHB_ITEM pItem, USHORT uiPCount, PHB_ITEM pItemArg1, ... ); +extern PHB_ITEM hb_itemDoC ( char * szFunc, USHORT uiPCount, PHB_ITEM pItemArg1, ... ); extern PHB_ITEM hb_itemArrayGet ( PHB_ITEM pArray, ULONG ulIndex ); extern PHB_ITEM hb_itemArrayNew ( ULONG ulLen ); diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 80ccc96870..85bd713a94 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -71,7 +71,6 @@ int yy_lex_input( char *, int ); #define YY_INPUT( buf, result, max_size ) result = yy_lex_input( buf, max_size ); /* variables defined in harbour.y */ -extern int _bQuiet; extern int _bRestrictSymbolLength; extern WORD _wSeqCounter; extern WORD _wForCounter; diff --git a/harbour/source/rtl/console.c b/harbour/source/rtl/console.c index fd817be914..8423b35e80 100644 --- a/harbour/source/rtl/console.c +++ b/harbour/source/rtl/console.c @@ -78,6 +78,11 @@ #include #endif +#if defined(OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) + #include + #include +#endif + #define ACCEPT_BUFFER_LEN 256 /*length of input buffer for ACCEPT command */ #if defined(OS_UNIX_COMPATIBLE) @@ -1110,12 +1115,28 @@ HARBOUR HB___ACCEPT( void ) /* Internal Clipper function used in ACCEPT command hb_altout( s_szCrLf, CRLF_BUFFER_LEN - 1 ); hb_altout( szPrompt, len ); } -#ifdef OS_UNIX_COMPATIBLE +#if defined (OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) /* Read the data using fgets(), because hb_inkeyPoll() doesn't support Unix compatible operating systems yet. */ - szResult[ 0 ] = '\0'; /* start with something defined */ - if( fgets( szResult, ACCEPT_BUFFER_LEN, stdin ) ) - strtok( szResult, "\n" ); /* strip off the trailing newline if it exists */ + { + /* Set up for echoed canonical input */ + struct termios ta; + tcgetattr( STDIN_FILENO, &ta ); + ta.c_lflag |= ( ICANON | ECHO ); + tcsetattr( STDIN_FILENO, TCSAFLUSH, &ta ); + + /* Avoid an undefined variable warning */ + input = 0; + + /* Get a line of user input */ + szResult[ 0 ] = '\0'; /* start with something defined */ + if( fgets( szResult, ACCEPT_BUFFER_LEN, stdin ) ) + strtok( szResult, "\n" ); /* strip off the trailing newline if it exists */ + + /* Restore unechoed non-canonical input */ + ta.c_lflag &= ~( ICANON | ECHO ); + tcsetattr( STDIN_FILENO, TCSAFLUSH, &ta ); + } #else len = 0; input = 0; diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index dfdbb93ab3..71fc680a6a 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -165,15 +165,6 @@ extern int rename( const char *, const char * ); #if defined(HAVE_POSIX_IO) || defined(_MSC_VER) -#ifdef __CYGWIN__ -/* TODO: Get Cygwin fixed so that this bug fix won't be needed */ -static inline int FixCygwinIOflags( int flags ) -{ - /* Starting with O_CREAT, the Cygwin I/O flags are 1 bit too high */ - return ( ( flags & 0x1FF00 ) >> 1 ) | ( flags & 0xFF ); -} -#endif - static int convert_open_flags( USHORT uiFlags ) { /* by default FO_READ + FO_COMPAT is set */ @@ -242,11 +233,6 @@ static int convert_open_flags( USHORT uiFlags ) /* DEBUG: printf(" SH_DENYNO"); */ } /* DEBUG: printf(" 0x%04x\n", result_flags); */ -#ifdef __CYGWIN__ -/* TODO: Get Cygwin fixed so that this bug fix won't be needed */ - result_flags = FixCygwinIOflags( result_flags ); -/* DEBUG: printf(" Cygwin fix: 0x%04x\n", result_flags); */ -#endif #endif return result_flags; @@ -287,11 +273,6 @@ static void convert_create_flags( USHORT uiFlags, int * result_flags, unsigned * if( uiFlags & FC_SYSTEM ) *result_flags |= 0; /* DEBUG: printf(" 0x%04x, 0x%04x\n", *result_flags, *result_pmode); */ -#ifdef __CYGWIN__ -/* TODO: Get Cygwin fixed so that this bug fix won't be needed */ - *result_flags = FixCygwinIOflags( *result_flags ); -/* DEBUG: printf(" Cygwin fix: 0x%04x\n", *result_flags); */ -#endif } #endif diff --git a/harbour/source/rtl/inkey.c b/harbour/source/rtl/inkey.c index 86bc5d5f65..b396708270 100644 --- a/harbour/source/rtl/inkey.c +++ b/harbour/source/rtl/inkey.c @@ -32,6 +32,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit their web site at http://www.gnu.org/). + V 1.35 David G. Holm Changed the __CYGWIN__ build to use + the Unix keyboard input method and + modified it to not block the VM. V 1.21 David G. Holm Added OS/2 DosSleep() V 1.15 David G. Holm Tested Borland 3.1 hb_releaseCPU() V 1.5 Paul Tucker ReleaseCPU comments @@ -78,8 +81,6 @@ #elif defined(__IBMCPP__) #include #include -#elif defined(__CYGWIN__) - #include #endif #include @@ -108,7 +109,7 @@ ULONG DosSleep( ULONG ulMilliseconds ); #endif -#if defined(OS_UNIX_COMPATIBLE) +#if defined(OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) #include #include @@ -176,7 +177,7 @@ void hb_releaseCPU( void ) regs.h.ah = 0; regs.h.al ^= 0x80; #endif -#elif defined(OS_UNIX_COMPATIBLE) +#elif defined(OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) #else #endif } @@ -189,6 +190,10 @@ int hb_inkey ( double seconds, HB_inkey_enum event_mask, BOOL wait, BOOL forever /* Check or wait for input events */ if( wait ) end_clock = clock() + seconds * CLOCKS_PER_SEC; s_inkeyPoll = TRUE; /* Force polling */ + +/* As soon as a non-blocking way to do Unix input is implemented, + the #if test can be eliminated, (leaving the code intact) */ +#if ! defined(OS_UINX_COMPATIBLE) && ! defined(__CYGWIN__) while( wait && hb_inkeyNext() == 0 ) { /* Release the CPU between checks */ @@ -198,6 +203,7 @@ int hb_inkey ( double seconds, HB_inkey_enum event_mask, BOOL wait, BOOL forever if( !forever && clock() >= end_clock ) wait = FALSE; } /* Get the current input event or 0 */ +#endif key = hb_inkeyGet(); s_inkeyPoll = FALSE; /* Stop forced polling */ s_eventmask = hb_set.HB_SET_EVENTMASK; /* Restore original input event mask */ @@ -207,6 +213,13 @@ int hb_inkey ( double seconds, HB_inkey_enum event_mask, BOOL wait, BOOL forever int hb_inkeyGet( void ) /* Extract the next key from the keyboard buffer */ { int key; +#if defined(OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) + /* This part of the #if block is temporary and needs to be removed when + non-blocking Unix-style keyboard input is implemented */ + char ch; + read( STDIN_FILENO, &ch, 1 ); + key = ch; +#else hb_inkeyPoll(); if( hb_set.HB_SET_TYPEAHEAD ) { @@ -224,6 +237,7 @@ int hb_inkeyGet( void ) /* Extract the next key from the keyboard buffer * } else key = s_inkeyLast = s_inkeyForce; /* Typeahead support is disabled */ s_inkeyForce = 0; +#endif return key; } @@ -253,7 +267,7 @@ void hb_inkeyPoll( void ) /* Poll the console keyboard to stuff the Harbour if( hb_set.HB_SET_TYPEAHEAD || s_inkeyPoll ) { int ch = 0; -#if defined(OS_DOS_COMPATIBLE) || defined(HARBOUR_GCC_OS2) || defined(__IBMCPP__) || defined(_Windows) +#if ( defined(OS_DOS_COMPATIBLE) || defined(HARBOUR_GCC_OS2) || defined(__IBMCPP__) || defined(_Windows) ) && ! defined(__CYGWIN__) /* The reason for including _Windows here is that kbhit() and getch() appear to work properly in console mode. For true Windows mode, changes are needed. */ #if defined(HARBOUR_GCC_OS2) @@ -404,10 +418,9 @@ void hb_inkeyPoll( void ) /* Poll the console keyboard to stuff the Harbour case 396: /* Alt + F12 */ ch = 349 - ch; } -#elif defined(OS_UNIX_COMPATIBLE) +#elif defined(OS_UNIX_COMPATIBLE) || defined(__CYGWIN__) /* TODO: */ - if( ! read( STDIN_FILENO, &ch, 1 ) ) - return; + /* NOTE: The blocking Unix support has been moved to hb_inkeyGet() */ #else /* TODO: Support for other platforms, such as Mac */ #endif diff --git a/harbour/source/rtl/itemapi.c b/harbour/source/rtl/itemapi.c index 70b51bf7b5..0f5caf647a 100644 --- a/harbour/source/rtl/itemapi.c +++ b/harbour/source/rtl/itemapi.c @@ -163,9 +163,12 @@ BOOL hb_evalRelease( PEVALINFO pEvalInfo ) /* NOTE: Same purpose as hb_evalLaunch(), but simpler, faster and more flexible. It can be used to call symbols, functions names, or blocks, the items don't need to be duplicated when passed as argument, one line is - enough to initiate a call, the number of parameters is not limited. */ + enough to initiate a call, the number of parameters is not limited. -PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, ... ) + NOTE: When calling hb_itemDo() with no arguments for the Harbour item being + evaluated, you must use '(PHB_ITEM *) 0' as the third parameter. */ + +PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, PHB_ITEM pItemArg1, ... ) { PHB_ITEM pResult; @@ -180,10 +183,11 @@ PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, ... ) USHORT uiParam; va_list va; - va_start( va, uiPCount ); + va_start( va, pItemArg1 ); hb_vmPushSymbol( pDynSym->pSymbol ); hb_vmPushNil(); - for( uiParam = 1; uiParam <= uiPCount; uiParam++ ) + if( uiPCount >= 1 ) hb_vmPush( pItemArg1 ); + for( uiParam = 2; uiParam <= uiPCount; uiParam++ ) hb_vmPush( va_arg( va, PHB_ITEM ) ); hb_vmDo( uiPCount ); va_end( va ); @@ -197,10 +201,11 @@ PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, ... ) USHORT uiParam; va_list va; - va_start( va, uiPCount ); + va_start( va, pItemArg1 ); hb_vmPushSymbol( &symEval ); hb_vmPush( pItem ); - for( uiParam = 1; uiParam <= uiPCount; uiParam++ ) + if( uiPCount >= 1 ) hb_vmPush( pItemArg1 ); + for( uiParam = 2; uiParam <= uiPCount; uiParam++ ) hb_vmPush( va_arg( va, PHB_ITEM ) ); hb_vmDo( uiPCount ); va_end( va ); @@ -213,10 +218,11 @@ PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, ... ) USHORT uiParam; va_list va; - va_start( va, uiPCount ); + va_start( va, pItemArg1 ); hb_vmPushSymbol( pItem->item.asSymbol.value ); hb_vmPushNil(); - for( uiParam = 1; uiParam <= uiPCount; uiParam++ ) + if( uiPCount >= 1 ) hb_vmPush( pItemArg1 ); + for( uiParam = 2; uiParam <= uiPCount; uiParam++ ) hb_vmPush( va_arg( va, PHB_ITEM ) ); hb_vmDo( uiPCount ); va_end( va ); @@ -234,9 +240,12 @@ PHB_ITEM hb_itemDo( PHB_ITEM pItem, USHORT uiPCount, ... ) } /* NOTE: Same as hb_itemDo(), but even simpler, since the function name can be - directly passed as a zero terminated string. */ + directly passed as a zero terminated string. -PHB_ITEM hb_itemDoC( char * szFunc, USHORT uiPCount, ... ) + NOTE: When calling hb_itemDoC() with no arguments for the Harbour function + being called, you must use '(PHB_ITEM *) 0' as the third parameter. */ + +PHB_ITEM hb_itemDoC( char * szFunc, USHORT uiPCount, PHB_ITEM pItemArg1, ... ) { PHB_ITEM pResult; @@ -249,10 +258,11 @@ PHB_ITEM hb_itemDoC( char * szFunc, USHORT uiPCount, ... ) USHORT uiParam; va_list va; - va_start( va, uiPCount ); + va_start( va, pItemArg1 ); hb_vmPushSymbol( pDynSym->pSymbol ); hb_vmPushNil(); - for( uiParam = 1; uiParam <= uiPCount; uiParam++ ) + if( uiPCount >= 1 ) hb_vmPush( pItemArg1 ); + for( uiParam = 2; uiParam <= uiPCount; uiParam++ ) hb_vmPush( va_arg( va, PHB_ITEM ) ); hb_vmDo( uiPCount ); va_end( va ); diff --git a/harbour/tests/working/inkeytst.prg b/harbour/tests/working/inkeytst.prg index a547f8d394..97e52c20bf 100644 --- a/harbour/tests/working/inkeytst.prg +++ b/harbour/tests/working/inkeytst.prg @@ -14,6 +14,15 @@ PROCEDURE main( cSkip, cExtended ) LOCAL nKey, nMask, cText IF EMPTY( cSkip ) + /* NOTE: When non-blocking Unix-style keyboard input is implemented, + remove the next few lines... */ + ? + ? "Note: All but the last test will fail for Harbour builds with Unix-style" + ? " keyboard input. The TYPEAHEAD tests will enter an infinite loop." + ? " To run only the last test, break out of this program and run it" + ? " again with any parameter (for example, INKEYTST X)." + + ? ? "Testing the KEYBOARD and CLEAR TYPEAHEAD commands and the" ? "INKEY(), NEXTKEY(), and LASTKEY() functions." ? @@ -122,7 +131,7 @@ LOCAL nKey, nMask, cText ? END IF ? "For the last test, a loop is started and all keyboard and mouse" - ? "events are allowed. Each event will be displayed. Press the ESC" + ? "events are allowed. Each event will be displayed. Press the TAB" ? "key to exit. Try moving the mouse, holding and releasing the mouse" ? "buttons as well as double-clicking the mouse buttons." ? @@ -134,7 +143,7 @@ LOCAL nKey, nMask, cText nMask += INKEY_EXTENDED END IF SET(_SET_EVENTMASK, nMask) - WHILE (nKey := INKEY( 0, nMask )) != K_ESC + WHILE (nKey := INKEY( 0, nMask )) != K_TAB DO CASE CASE nKey == K_MOUSEMOVE ? "The mouse moved." @@ -154,7 +163,7 @@ LOCAL nKey, nMask, cText ? "A keyboard key was pressed: ", nKey, IF( nKey >= 32 .AND. nKey <= 255, CHR( nKey ), "" ) END CASE END WHILE - ? "The ESC key was pressed. Exiting..." + ? "The TAB key ("+LTRIM(STR(nKey))+") was pressed. Exiting..." QUIT PROCEDURE Results()