1 message in com.perforce.jammingJam support for VisualAge C++ under NT| From | Sent On | Attachments |
|---|---|---|
| Grae...@digideas.com.au | 13 Aug 1997 17:45 |
| Subject: | Jam support for VisualAge C++ under NT![]() |
|---|---|
| From: | Grae...@digideas.com.au (Grae...@digideas.com.au) |
| Date: | 08/13/1997 05:45:36 PM |
| List: | com.perforce.jamming |
I have an NT machine at home running IBM's Visual Age compiler, so I have set about getting jam running in this environment.
Context diffs of the changes so far follow, based on version 2.1.0.
Changes:
jam.c: I've added a JAMBASE environment variable. I've found this far more convenient that using the -f option all the time.
filent.c: Visual Ages unix libraries don't support _findfirst(), so I've changed the code to use the Win32 equivalent FindFirstFile(). The only difficulty is converting Win32 FILETIME (64 bit 100 nsec since 1601) to time_t (32 bit seconds since 1970). I've separated the Borland stuff out so that it hopefully still works. Perhaps the separate Borland code is no longer necessary ?
execunix.c IBM sticks more closely to the unix style libraries for spawn(), and returns pid's like it should. It doesn't provide a wait() function on NT though, so it is necessary to use the my_wait() function. Since my_wait() uses Win32 functions and these use process handles, it is necessary to convert between pid's and handles. Note that the existing code was leaking process handles.
jambase: I've made the obvious changes here.
NT Things still to do:
There are a lot of common options used in NT that should be specifiable in a way that is independent of the compiler - e.g. build a DLL, compile multithreaded safe, build a debug version into a debug sub-directory, build the release version into the release directory etc. etc. Having these rules would then make a MSVC++ Makefile -> jamfile converter a possibility.
Some projects need to intermix different compilers within the same project. There should be a way to select which compiler to use.
Watcom and gcc compilers should be supported under NT.
Enjoy !
Graeme Gill gra...@digideas.com.au
*** orig/jam.c Wed Jul 9 20:13:18 1997 ---- jam.c Wed Aug 13 18:58:04 1997 *************** *** 115,120 **** ---- 115,121 ---- * 05/04/94 (seiwald) - async multiprocess (-j) support * 02/08/95 (seiwald) - -n implies -d2. * 02/22/95 (seiwald) - -v for version info. + * 03/06/97 (gwg) - Added JAMBASE environment variable */
struct globs globs = { *************** *** 269,275 ****
if( !n ) { ! yyfparse( "+" ); yyparse(); }
---- 270,280 ----
if( !n ) { ! char *jambase; ! if ((jambase = getenv("JAMBASE")) != NULL) ! yyfparse( jambase ); ! else ! yyfparse( "+" ); yyparse(); }
*** orig/filent.c Wed Jul 9 20:13:18 1997 ---- filent.c Wed Aug 13 18:58:04 1997 *************** *** 19,24 **** ---- 19,27 ---- # include <io.h> # include <sys/stat.h>
+ # define WIN32_LEAN_AND_MEAN
+ # include <windows.h>
+
/*
* filent.c - scan directories and archives on NT
*
***************
*** 36,41 ****
---- 39,46 ----
*
* 07/10/95 (taylor) Findfirst() returns the first file on NT.
* 05/03/96 (seiwald) split apart into pathnt.c
+ * 23/06/97 (gwg) Switch to Win32 FindFirstFile & friends so that this
will
+ * compile under VisualAge.
*/
/* *************** *** 42,47 **** ---- 47,53 ---- * file_dirscan() - scan a directory for files */
+ # ifdef __BORLANDC__ void file_dirscan( dir, func ) char *dir; *************** *** 77,83 **** if( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir );
- - # ifdef __BORLANDC__ if ( ret = findfirst( filespec, finfo, FA_NORMAL | FA_DIREC ) ) return;
---- 83,88 ---- *************** *** 95,127 ****
ret = findnext( finfo ); } ! # else ! handle = _findfirst( filespec, finfo );
! if( ret = ( handle < 0L ) ) return;
while( !ret ) { ! f.f_base.ptr = finfo->name; ! f.f_base.len = strlen( finfo->name );
! file_build( &f, filename, 0 );
! (*func)( filename, 1 /* stat()'ed */, finfo->time_write );
! ret = _findnext( handle, finfo ); }
! _findclose( handle ); # endif
- - } - - /* * file_time() - get timestamp of file, if not done by file_dirscan() */
int file_time( filename, time ) char *filename; ---- 100,182 ----
ret = findnext( finfo ); } ! }
! # else /* !__BORLANDC__ */ ! ! time_t TimetFromFt(FILETIME * pft); ! ! void ! file_dirscan( dir, func ) ! char *dir; ! void (*func)(); ! { ! FILENAME f; ! char filespec[ MAXJPATH ]; ! char filename[ MAXJPATH ]; ! HANDLE handle; ! int ret; ! WIN32_FIND_DATA fileinfo[1]; ! ! /* First enter directory itself */ ! ! memset( (char *)&f, '\0', sizeof( f ) ); ! ! f.f_dir.ptr = dir; ! f.f_dir.len = strlen(dir); ! ! dir = *dir ? dir : "."; ! ! /* Special case \ or d:\ : enter it */ ! ! if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' ) ! (*func)( dir, 0 /* not stat()'ed */, (time_t)0 ); ! else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' ) ! (*func)( dir, 0 /* not stat()'ed */, (time_t)0 ); ! ! /* Now enter contents of directory */ ! ! sprintf( filespec, "%s/*", dir ); ! ! if( DEBUG_BINDSCAN ) ! printf( "scan directory %s\n", dir ); ! ! handle = FindFirstFile( filespec, fileinfo ); ! ! if( ret = ( handle == INVALID_HANDLE_VALUE ) ) return;
while( !ret ) { ! time_t st_mtime; ! f.f_base.ptr = fileinfo->cFileName; ! f.f_base.len = strlen( fileinfo->cFileName );
! file_build( &f, filename );
! /* ftLastWriteTime represents 100nsec intervals since */ ! /* Jan 1 1601 in 64 bits, while time_t represents seconds since */ ! /* Jan 1 1970 in 32 bits. */ ! st_mtime = TimetFromFt(&fileinfo->ftLastWriteTime);
! { char *cc; ! for (cc = fileinfo->cFileName; *cc != '\000'; cc++) ! *cc = tolower(*cc); ! } ! (*func)( filename, 1 /* stat()'ed */, st_mtime ); ! ! ret = !FindNextFile( handle, fileinfo ); }
! FindClose( handle ); ! } # endif
/* * file_time() - get timestamp of file, if not done by file_dirscan() */
+ # ifdef __BORLANDC__ int file_time( filename, time ) char *filename; *************** *** 139,144 **** ---- 194,233 ---- return 0; }
+ # else /* !__BORLANDC__ */ + file_time( filename, time ) + char *filename; + time_t *time; + { + HANDLE hFile; + FILETIME CreationTime; + FILETIME LastAccessTime; + FILETIME LastWriteTime; + + hFile = CreateFile( + filename, + GENERIC_READ, /* Access mode */ + FILE_SHARE_READ, /* share mode */ + (LPSECURITY_ATTRIBUTES)NULL, /* Optional security descriptor */ + OPEN_EXISTING, /* how to create */ + FILE_ATTRIBUTE_NORMAL, + (HANDLE)NULL ); /* handle of file with attributes to copy */ + + if (hFile == (HANDLE)NULL) + return -1; + + if (!GetFileTime( + hFile, /* identifies the file */ + &CreationTime, /* address of creation time */ + &LastAccessTime, /* address of last access time */ + &LastWriteTime)) /* address of last write time */ + return -1; + + *time = TimetFromFt(&LastWriteTime); + return 0; + } + #endif /* !__BORLANDC__ */ + /* * file_archscan() - scan an archive for files */ *************** *** 257,260 **** ---- 346,387 ---- close( fd ); }
+ /* Convert NT style FILETIME into time_t */ + /* Note this is correct on NT, but will give local time on Win32 */ + time_t TimetFromFt(FILETIME *pft) { + unsigned long h,l,pl; + unsigned long dh,dl,r,t; + + /* Subtract offset from 1601 to 1970 in 100nsec */ + h = pft->dwHighDateTime; + pl = l = pft->dwLowDateTime; + h += 0xfe624e9e; + l += 0xe4fbaeb0; + if (l < pl) // carry + h++; + + if (h >= 10000000) /* Oops! */ + return (time_t)-1; /* Error */ + + /* Truncate from 100nsec to 1 second using long division */ + dh = 10000000 >> 1; /* Divisor * 0x80000000 */ + dl = 10000000 << 31; + for (t = 0, r = 0x80000000; r != 0; r >>= 1) { + if (dh < h || (dh == h && dl < l)) { /* If dividor is less than dividend */ + t |= r; /* Accumulate result */ + pl = l; /* Subtract divisor */ + h -= dh; + l -= dl; + if (l > pl) // carry + h--; + } + dl >>= 1; /* Divide divisor by 2 */ + dl |= (dh << 31); + dh >>= 1; + } + if (l >= 5000000) /* Round */ + t++; + + return (time_t) t; + } # endif /* NT */ *** orig/execunix.c Wed Jul 9 20:13:18 1997 ---- execunix.c Wed Aug 13 18:58:04 1997 *************** *** 23,28 **** ---- 23,31 ----
# if defined( NT ) || defined( __OS2__ )
+ # define WIN32_LEAN_AND_MEAN + # include <windows.h> /* do the ugly deed */ + # include <process.h>
# if !defined( __BORLANDC__ )
***************
*** 61,66 ****
---- 64,70 ----
* 05/04/94 (seiwald) - async multiprocess interface
* 01/22/95 (seiwald) - $(JAMSHELL) support
* 06/02/97 (gsar) - full async multiprocess support for Win32
+ * 09/07/97 (gwg) - Fix for IBM spawn() returning pid's rather than
handles
*/
static int intr = 0; *************** *** 229,235 **** ---- 233,244 ---- /* Start the command */
# if defined( NT ) || defined( __OS2__ ) + # if defined( __IBMC__ ) /* IBM returns pid's from spawn, just like unix */ + if( ( pid = (int)OpenProcess(PROCESS_ALL_ACCESS,FALSE, + spawnvp( P_NOWAIT, argv[0], argv ) ) ) < 0 ) + # else if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) < 0 ) + # endif { perror( "spawn" ); exit( EXITBAD ); *************** *** 322,331 ****
# if defined( NT ) && !defined( __BORLANDC__ )
- - # define WIN32_LEAN_AND_MEAN - - - - # include <windows.h> /* do the ugly deed */ - - static int my_wait( status ) int *status; ---- 331,336 ---- *************** *** 347,352 **** ---- 352,358 ---- active_handles[num_active++] = (HANDLE)cmdtab[i].pid; else { *status = (int)((exitcode & 0xff) << 8); + CloseHandle((HANDLE)cmdtab[i].pid); return cmdtab[i].pid; } } *************** *** 372,377 **** ---- 378,384 ---- i = waitcode - WAIT_OBJECT_0; if ( GetExitCodeProcess(active_handles[i], &exitcode) ) { *status = (int)((exitcode & 0xff) << 8); + CloseHandle(active_handles[i]); return (int)active_handles[i]; } } *** orig/jambase Wed Jul 9 20:13:18 1997 ---- jambase Wed Aug 13 18:58:06 1997 *************** *** 35,40 **** ---- 35,41 ---- # 04/30/95 (seiwald) - Use install -c flag so that it copies, not moves. # 07/10/95 (taylor) - Support for Microsoft C++. # 11/21/96 (peterk) - Support for BeOS + # 03/06/97 (gwg) - Support for IBM Visual Age.
# Special targets defined in this file: # *************** *** 290,297 **** SUFOBJ default = .obj ; SUFEXE default = .exe ;
! if $(BCCROOT) { ECHO "Compiler is Borland C++" ;
AR default = tlib ; ---- 291,320 ---- SUFOBJ default = .obj ; SUFEXE default = .exe ;
! if $(IPF_PATH32) { + ECHO "Compiler is IBM Visual Age C++" ; + + AR default = ilib /nologo ; + # AS default = masm386 ; + CC default = icc /Q ; + CCFLAGS default = /DNT ; + C++ default = $(CC) ; + C++FLAGS default = $(CCFLAGS) ; + # CRELIB default = true ; # Can't update a lib to create it + LINK default = ilink /NOLogo ; + LINKFLAGS default = ; + LINKLIBS default = ; # $(IPF_PATH32)\\lib\\advapi32.lib + # $(IPF_PATH32)\\lib\\libc.lib + # $(IPF_PATH32)\\lib\\oldnames.lib + # $(IPF_PATH32)\\lib\\kernel32.lib ; + NOARSCAN default = true ; + OPTIM default = ; + STDHDRS default = $(IPF_PATH32)\\include $(IPF_PATH32)\\sdk\\winh ; + UNDEFFLAG default = "/U _" ; + } + else if $(BCCROOT) + { ECHO "Compiler is Borland C++" ;
AR default = tlib ; *************** *** 353,360 **** } else { ! EXIT On NT, set BCCROOT, MSVCNT, or MSVC to the root of the ! Borland or Microsoft directories. ; }
} ---- 376,383 ---- } else { ! EXIT On NT, set IPF_PATH32, BCCROOT, MSVCNT, or MSVC to the root of the ! VisualAge, Borland or Microsoft directories. ; }
} *************** *** 1605,1611 **** } else if $(NT) || $(OS2) { ! if $(BCCROOT) {
actions C++ ---- 1628,1663 ---- } else if $(NT) || $(OS2) { ! ! if $(IPF_PATH32) ! { # IBM Visual Age C++ ! actions updated together piecemeal Archive ! { ! if exist $(<) set _$(<:B)_=$(<) ! $(AR) /out:$(<) %_$(<:B)_% $(>) ! } ! ! # actions As ! # { ! # $(AS) /Ml /p /v /w2 $(>) $(<) ,nul,nul; ! # } ! # ! actions Cc ! { ! $(CC) /c $(CCFLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) $(>) ! } ! ! actions C++ ! { ! $(C++) /c $(C++FLAGS) $(OPTIM) /Fo$(<) /I$(HDRS) /I$(STDHDRS) /Tp$(>) ! } ! ! actions Link bind NEEDLIBS ! { ! $(LINK) $(LINKFLAGS) /out:$(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) ! } ! } ! else if $(BCCROOT) {
actions C++




