# HG changeset patch # User Jan Vrany # Date 1477395302 -3600 # Node ID 83c74234945e35340db9f4feddd2783200553bed # Parent fb8c5591428bd8953a7db6b649e53079692479c5# Parent f6a11f77b23032fb236a5828ae159ba5fd8c70b3 Merge diff -r fb8c5591428b -r 83c74234945e AbstractOperatingSystem.st --- a/AbstractOperatingSystem.st Tue Oct 25 12:31:42 2016 +0100 +++ b/AbstractOperatingSystem.st Tue Oct 25 12:35:02 2016 +0100 @@ -1,3 +1,5 @@ +"{ Encoding: utf8 }" + " COPYRIGHT (c) 1988 by Claus Gittinger All Rights Reserved @@ -1302,6 +1304,29 @@ "Modified: / 10.11.1998 / 20:54:37 / cg" ! +executeCommand:aCommandString inDirectory:aDirectory showWindow:showWindow + "execute the unix command specified by the argument, aCommandString. + If aCommandString is a String, the commandString is passed to a shell for execution + - see the description of 'sh -c' in your UNIX manual ('cmd.com' in your MSDOS manual). + If aCommandString is an Array, the first element is the command to be executed, + and the other elements are the arguments to the command. No shell is invoked in this case. + Return true if successful, false otherwise." + + ^ self + executeCommand:aCommandString + inputFrom:nil + outputTo:nil + errorTo:nil + auxFrom:nil + environment:nil + inDirectory:aDirectory + lineWise:false + showWindow:showWindow + onError:[:exitStatus| false] + + "Created: / 18-10-2016 / 15:55:29 / cg" +! + executeCommand:aCommandString inputFrom:anInStream outputTo:anOutStream errorTo:anErrStream "execute the unix command specified by the argument, aCommandString. If aCommandString is a String, the commandString is passed to a shell for execution diff -r fb8c5591428b -r 83c74234945e Collection.st --- a/Collection.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Collection.st Tue Oct 25 12:35:02 2016 +0100 @@ -275,6 +275,7 @@ ^ self newWithSize:n ! ! + !Collection class methodsFor:'Signal constants'! emptyCollectionSignal @@ -549,6 +550,7 @@ "Created: / 22-10-2008 / 21:29:27 / cg" ! ! + !Collection methodsFor:'accessing'! anElement @@ -2517,12 +2519,13 @@ individualResult := aBlock value:element. result isNil ifTrue:[ - result := individualResult speciesForAdding new. + result := individualResult speciesForCollecting new. ]. result addAll:individualResult. ]. - ^ result ? #() + "do not answer an empty - possibly immutable - Array" + ^ result ? self speciesForCollecting new. " #(1 2 3 4) collectAll:[:n | Array new:n withAll:n ] @@ -2541,10 +2544,7 @@ result := collectionClass new. self do:[:element | - |individualResult| - - individualResult := aBlock value:element. - result addAll:individualResult. + result addAll:(aBlock value:element). ]. ^ result @@ -6001,6 +6001,7 @@ ^ aVisitor visitCollection:self with:aParameter ! ! + !Collection class methodsFor:'documentation'! version diff -r fb8c5591428b -r 83c74234945e ExternalStream.st --- a/ExternalStream.st Tue Oct 25 12:31:42 2016 +0100 +++ b/ExternalStream.st Tue Oct 25 12:35:02 2016 +0100 @@ -1,3 +1,5 @@ +"{ Encoding: utf8 }" + " COPYRIGHT (c) 1988 by Claus Gittinger All Rights Reserved @@ -2121,23 +2123,22 @@ OBJ _handle = __INST(handle); if (_handle != nil) { - if ((__INST(handleType) == @symbol(fileHandle)) - || (__INST(handleType) == @symbol(socketHandle))) { - RETURN (_handle); - } - if ((__INST(handleType) == nil) - || (__INST(handleType) == @symbol(filePointer)) - || (__INST(handleType) == @symbol(socketFilePointer)) - || (__INST(handleType) == @symbol(pipeFilePointer))) { + if ((__INST(handleType) == @symbol(fileHandle)) + || (__INST(handleType) == @symbol(socketHandle))) { + RETURN (_handle); + } + if ((__INST(handleType) == nil) + || (__INST(handleType) == @symbol(filePointer)) + || (__INST(handleType) == @symbol(socketFilePointer)) + || (__INST(handleType) == @symbol(pipeFilePointer))) { #ifdef __win32__ - RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle))))); + RETURN(__MKEXTERNALADDRESS(_get_osfhandle(fileno(__FILEVal(_handle))))); #else - RETURN (__MKINT(fileno(__FILEVal(_handle)))); + RETURN (__MKINT(fileno(__FILEVal(_handle)))); #endif - } + } } %}. - handle isNil ifTrue:[^ self errorNotOpen]. ^ handle ! @@ -2217,6 +2218,15 @@ !ExternalStream methodsFor:'closing'! +abortAndClose + "close the stream - added for protocol compatibility with Socket and PipeStream. + see comment there" + + self close. + + "Modified: 30.8.1996 / 00:39:21 / cg" +! + close "Close the stream. No error if the stream is not open." @@ -2230,7 +2240,7 @@ ! shutDown - "close the stream - added for protocol compatibility with PipeStream. + "close the stream - added for protocol compatibility with Socket. see comment there" self close. @@ -2521,10 +2531,7 @@ finalize "some Stream has been collected - close the file if not already done" - "/ with timeout to avoid blocking in a bad pty/socket - [ - self closeFile - ] valueWithTimeout:30 seconds. + self closeFile ! reRegisterForFinalization @@ -4627,7 +4634,7 @@ " (FileStream newTemporary nextPutUtf16:$B; - nextPutUtf16:$Ä; + nextPutUtf16:$Ä; nextPutUtf16:(Character codePoint:16r10CCCC); reset; binary; @@ -4666,7 +4673,9 @@ clearEOF hitEOF := false -! +! ! + +!ExternalStream protectedMethodsFor:'private'! closeFile "low level close - may be redefined in subclasses @@ -4674,81 +4683,79 @@ |fp error| + handle isNil ifTrue:[ + ^ self. + ]. fp := handle. "/ (didWrite==true and:[binary ~~ true and:[eolMode = #crlf]]) ifTrue: [ self breakPoint:#sr ]. %{ int rslt; - if (fp == nil) { - error = @symbol(errorNotOpen); - goto out; - } - if (__INST(handleType) == @symbol(socketHandle)) { - SOCKET sock = (SOCKET)(__FILEVal(fp)); - - if (@global(FileOpenTrace) == true) { - fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock); - } - - // whether the close() will be successful or not - the handle is invalid now! - __INST(handle) = nil; - do { + SOCKET sock = (SOCKET)(__FILEVal(fp)); + + if (@global(FileOpenTrace) == true) { + fprintf(stderr, "close socket [ExternalStream] %"_lx_"\n", (INT)sock); + } + + // whether the close() will be successful or not - the handle is invalid now! + __INST(handle) = nil; + do { #ifdef __win32__ - rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock); + rslt = __STX_WSA_NOINT_CALL1("closesocket", closesocket, sock); #else - rslt = close(sock); + rslt = close(sock); #endif - } while((rslt < 0) && (__threadErrno == EINTR)); + } while((rslt < 0) && (__threadErrno == EINTR)); } else if ((__INST(handleType) == nil) - || (__INST(handleType) == @symbol(filePointer)) - || (__INST(handleType) == @symbol(socketFilePointer)) - || (__INST(handleType) == @symbol(pipeFilePointer))) + || (__INST(handleType) == @symbol(filePointer)) + || (__INST(handleType) == @symbol(socketFilePointer)) + || (__INST(handleType) == @symbol(pipeFilePointer))) { - FILEPOINTER f = __FILEVal(fp); - - if (@global(FileOpenTrace) == true) { - fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f); - } - // whether the close() will be successful or not - the handle is invalid now! - __INST(handle) = nil; + FILEPOINTER f = __FILEVal(fp); + + if (@global(FileOpenTrace) == true) { + fprintf(stderr, "fclose [ExternalStream] %"_lx_"\n", (INT)f); + } + // whether the close() will be successful or not - the handle is invalid now! + __INST(handle) = nil; #ifdef __win32__ - if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) { - // do a fflush() first, so that fclose() doesn't block - // we suspect, that EINTR causes problems in fclose() - do { - __threadErrno = 0; - rslt = __STX_C_CALL1("fflush", fflush, f); - } while((rslt < 0) && (__threadErrno == EINTR)); - } - do { - __threadErrno = 0; - rslt = __STX_C_NOINT_CALL1("fclose", fclose, f); - } while((rslt < 0) && (__threadErrno == EINTR)); + if (__INST(mode) != @symbol(readonly) && __INST(buffered) != false) { + // do a fflush() first, so that fclose() doesn't block + // we suspect, that EINTR causes problems in fclose() + do { + __threadErrno = 0; + rslt = __STX_C_CALL1("fflush", fflush, f); + } while((rslt < 0) && (__threadErrno == EINTR)); + } + do { + __threadErrno = 0; + rslt = __STX_C_NOINT_CALL1("fclose", fclose, f); + } while((rslt < 0) && (__threadErrno == EINTR)); #else - // cg: the pre Nov2014 code always did the fclose interruptable; - // I am not sure, if fclose is actually prepared to do this; - // at least when only reading, this should not block, and we - // should be ableto do it without being interruptable. - // Must watch this - if it leads to blockings, change and think about it. - if (__INST(mode) != @symbol(readonly)) { - __BEGIN_INTERRUPTABLE__ - rslt = fclose(f); - __END_INTERRUPTABLE__ - } else { - rslt = fclose(f); - } + // cg: the pre Nov2014 code always did the fclose interruptable; + // I am not sure, if fclose is actually prepared to do this; + // at least when only reading, this should not block, and we + // should be ableto do it without being interruptable. + // Must watch this - if it leads to blockings, change and think about it. + if (__INST(mode) != @symbol(readonly)) { + __BEGIN_INTERRUPTABLE__ + rslt = fclose(f); + __END_INTERRUPTABLE__ + } else { + rslt = fclose(f); + } #endif } else { - error = @symbol(badHandleType); - goto out; + error = @symbol(badHandleType); + goto out; } if (rslt < 0) { - error = __mkSmallInteger(__threadErrno); - goto out; + error = __mkSmallInteger(__threadErrno); + goto out; } RETURN (self); @@ -4756,30 +4763,29 @@ %}. error notNil ifTrue:[ - error == #errorNotOpen ifTrue:[ - self errorNotOpen. - ]. - error isInteger ifTrue:[ - lastErrorNumber := error. - mode == #readonly ifTrue:[ - self ioError:error. - ] ifFalse:[ - self writeError:error. - ]. - ^ self. - ]. - self primitiveFailed:error. - ^ self. + error isInteger ifTrue:[ + lastErrorNumber := error. + mode == #readonly ifTrue:[ + self ioError:error. + ] ifFalse:[ + self writeError:error. + ]. + ^ self. + ]. + self primitiveFailed:error. + ^ self. ]. "/ fallback for rel5 fp := handle. fp notNil ifTrue:[ - handle := nil. - self closeFile:fp + handle := nil. + self closeFile:fp ] -! +! ! + +!ExternalStream methodsFor:'private'! closeFile:handle "for rel5 only" @@ -4870,6 +4876,9 @@ |fd dupFd| fd := self fileHandle. + fd isNil ifTrue:[ + ^ self errorNotOpen. + ]. dupFd := OperatingSystem dup:fd. self setFileHandle:dupFd mode:self fopenMode. ! @@ -5150,18 +5159,18 @@ STObject handle = self.instVarAt(I_handle); if (handle != STObject.Nil) { - STObject next; - - if (self.instVarAt(I_binary) == STObject.True) { - next = handle.nextByte(); - } else { - next = handle.nextChar(); - } - if (next != STObject.EOF) { - self.instVarAt_put(I_position, STObject.Nil); - return __c__._RETURN( next ); - } - self.instVarAt_put(I_hitEOF, STObject.True); + STObject next; + + if (self.instVarAt(I_binary) == STObject.True) { + next = handle.nextByte(); + } else { + next = handle.nextChar(); + } + if (next != STObject.EOF) { + self.instVarAt_put(I_position, STObject.Nil); + return __c__._RETURN( next ); + } + self.instVarAt_put(I_hitEOF, STObject.True); } #else FILEPOINTER f; @@ -5175,65 +5184,63 @@ || (__INST(handleType) == @symbol(socketFilePointer)) || (__INST(handleType) == @symbol(socketHandle)) || (__INST(handleType) == @symbol(pipeFilePointer))) { - if (((fp = __INST(handle)) != nil) - && (__INST(mode) != @symbol(writeonly)) - ) { - f = __FILEVal(fp); - - _buffered = (__INST(buffered) == true); - if (_buffered) { - __READING__(f) - } - __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); - - if (ret > 0) { - pos = __INST(position); - if (__isSmallInteger(pos)) { - OBJ t; - - t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); - } else { - __INST(position) = nil; /* i.e. do not know */ - } - if (__INST(binary) == true) { - RETURN ( __mkSmallInteger(ch) ); - } - RETURN ( __MKCHARACTER(ch) ); - } - - __INST(position) = nil; - if ((ret < 0) -# ifdef ECONNRESET - && (__threadErrno != ECONNRESET) -# endif - ){ - error = __mkSmallInteger(__threadErrno); - } else /* ret == 0 */ { - __INST(hitEOF) = true; - } - } + if (((fp = __INST(handle)) != nil) + && (__INST(mode) != @symbol(writeonly)) + ) { + f = __FILEVal(fp); + + _buffered = (__INST(buffered) == true); + if (_buffered) { + __READING__(f) + } + __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); + + if (ret > 0) { + pos = __INST(position); + if (__isSmallInteger(pos)) { + OBJ t; + + t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); + } else { + __INST(position) = nil; /* i.e. do not know */ + } + if (__INST(binary) == true) { + RETURN ( __mkSmallInteger(ch) ); + } + RETURN ( __MKCHARACTER(ch) ); + } + + __INST(position) = nil; + if (ret < 0) { + error = __mkSmallInteger(__threadErrno); + } else /* ret == 0 */ { + __INST(hitEOF) = true; + } + } } #endif /* not SCHTEAM */ %}. hitEOF == true ifTrue:[^ self pastEndRead]. error notNil ifTrue:[ - lastErrorNumber := error. - ^ self readError:error + lastErrorNumber := error. + ^ self readError:error ]. handle isNil ifTrue:[^ self errorNotOpen]. (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. readAhead notNil ifTrue:[ - c := readAhead. - readAhead := nil. - ^ c. + c := readAhead. + readAhead := nil. + ^ c. ]. + + "unknown handleType - future" c := self nextByteFromFile:handle. c isNil ifTrue:[ - ^ self pastEndRead. + ^ self pastEndRead. ]. binary == true ifTrue:[ - ^ c + ^ c ]. ^ Character value:c ! @@ -5276,64 +5283,62 @@ || (__INST(handleType) == @symbol(socketFilePointer)) || (__INST(handleType) == @symbol(socketHandle)) || (__INST(handleType) == @symbol(pipeFilePointer))) { - if (((fp = __INST(handle)) != nil) - && (__INST(mode) != @symbol(writeonly)) - ) { - f = __FILEVal(fp); - - _buffered = (__INST(buffered) == true); - if (_buffered) { - __READING__(f) - } - __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); - - if (ret > 0) { - pos = __INST(position); - if (__isSmallInteger(pos)) { - OBJ t; - - t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); - } else { - __INST(position) = nil; /* i.e. do not know */ - } - if (__INST(binary) == true) { - RETURN ( __mkSmallInteger(ch) ); - } - RETURN ( __MKCHARACTER(ch) ); - } - - __INST(position) = nil; - if ((ret < 0) -#ifdef ECONNRESET - && (__threadErrno != ECONNRESET) -#endif - ){ - error = __mkSmallInteger(__threadErrno); - } else /* ret == 0 */ { - __INST(hitEOF) = true; - } - } + if (((fp = __INST(handle)) != nil) + && (__INST(mode) != @symbol(writeonly)) + ) { + f = __FILEVal(fp); + + _buffered = (__INST(buffered) == true); + if (_buffered) { + __READING__(f) + } + __READBYTE__(ret, f, &ch, _buffered, __INST(handleType)); + + if (ret > 0) { + pos = __INST(position); + if (__isSmallInteger(pos)) { + OBJ t; + + t = __MKINT(__intVal(pos) + 1); __INST(position) = t; __STORE(self, t); + } else { + __INST(position) = nil; /* i.e. do not know */ + } + if (__INST(binary) == true) { + RETURN ( __mkSmallInteger(ch) ); + } + RETURN ( __MKCHARACTER(ch) ); + } + + __INST(position) = nil; + if (ret < 0) { + error = __mkSmallInteger(__threadErrno); + } else /* ret == 0 */ { + __INST(hitEOF) = true; + } + } } %}. hitEOF == true ifTrue:[^ nil]. error notNil ifTrue:[ - lastErrorNumber := error. - ^ self readError:error. + lastErrorNumber := error. + ^ self readError:error. ]. handle isNil ifTrue:[^ self errorNotOpen]. (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. readAhead notNil ifTrue:[ - c := readAhead. - readAhead := nil. - ^ c. + c := readAhead. + readAhead := nil. + ^ c. ]. + + "unknown handleType - future" c := self nextByteFromFile:handle. c isNil ifTrue:[ - ^ nil. + ^ nil. ]. binary == true ifTrue:[ - ^ c + ^ c ]. ^ Character value:c ! @@ -5353,11 +5358,11 @@ OBJ ra; if ((ra = __INST(readAhead)) != nil) { - if (__INST(binary) == true) { - RETURN ( ra ); - } - c = __intVal(ra); - RETURN ( __MKCHARACTER(c) ); + if (__INST(binary) == true) { + RETURN ( ra ); + } + c = __intVal(ra); + RETURN ( __MKCHARACTER(c) ); } __INST(lastErrorNumber) = nil; @@ -5367,49 +5372,45 @@ || (__INST(handleType) == @symbol(socketFilePointer)) || (__INST(handleType) == @symbol(socketHandle)) || (__INST(handleType) == @symbol(pipeFilePointer))) { - if (((fp = __INST(handle)) != nil) - && (__INST(mode) != @symbol(writeonly)) - ) { - f = __FILEVal(fp); - _buffered = (__INST(buffered) == true); - if (_buffered) { - __READING__(f) - } - __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); - - if (ret > 0) { - __UNGETC__(c, f, _buffered); - - if (__INST(binary) == true) { - RETURN ( __mkSmallInteger(c) ); - } - RETURN ( __MKCHARACTER(c) ); - } - if ((ret < 0) -#ifdef ECONNRESET - && (__threadErrno != ECONNRESET) -#endif - ){ - error = __mkSmallInteger(__threadErrno); - } else /* ret == 0 */ { - __INST(hitEOF) = true; - } - } + if (((fp = __INST(handle)) != nil) + && (__INST(mode) != @symbol(writeonly)) + ) { + f = __FILEVal(fp); + _buffered = (__INST(buffered) == true); + if (_buffered) { + __READING__(f) + } + __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); + + if (ret > 0) { + __UNGETC__(c, f, _buffered); + + if (__INST(binary) == true) { + RETURN ( __mkSmallInteger(c) ); + } + RETURN ( __MKCHARACTER(c) ); + } + if (ret < 0) { + error = __mkSmallInteger(__threadErrno); + } else /* ret == 0 */ { + __INST(hitEOF) = true; + } + } } %}. hitEOF == true ifTrue:[^ self pastEndRead]. error notNil ifTrue:[ - lastErrorNumber := error. - ^ self readError:error. + lastErrorNumber := error. + ^ self readError:error. ]. handle isNil ifTrue:[^ self errorNotOpen]. (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. readAhead isNil ifTrue:[ - readAhead := self nextOrNil. - readAhead isNil ifTrue:[ - ^ self pastEndRead. - ]. + readAhead := self nextOrNil. + readAhead isNil ifTrue:[ + ^ self pastEndRead. + ]. ]. ^ readAhead ! @@ -5429,11 +5430,11 @@ OBJ ra; if ((ra = __INST(readAhead)) != nil) { - if (__INST(binary) == true) { - RETURN ( ra ); - } - c = __intVal(ra); - RETURN ( __MKCHARACTER(c) ); + if (__INST(binary) == true) { + RETURN ( ra ); + } + c = __intVal(ra); + RETURN ( __MKCHARACTER(c) ); } __INST(lastErrorNumber) = nil; @@ -5443,46 +5444,42 @@ || (__INST(handleType) == @symbol(socketFilePointer)) || (__INST(handleType) == @symbol(socketHandle)) || (__INST(handleType) == @symbol(pipeFilePointer))) { - if (((fp = __INST(handle)) != nil) - && (__INST(mode) != @symbol(writeonly)) - ) { - f = __FILEVal(fp); - _buffered = (__INST(buffered) == true); - if (_buffered) { - __READING__(f) - } - __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); - - if (ret > 0) { - __UNGETC__(c, f, _buffered); - - if (__INST(binary) == true) { - RETURN ( __mkSmallInteger(c) ); - } - RETURN ( __MKCHARACTER(c) ); - } - if ((ret < 0) -#ifdef ECONNRESET - && (__threadErrno != ECONNRESET) -#endif - ){ - error = __mkSmallInteger(__threadErrno); - } else /* ret == 0 */ { - __INST(hitEOF) = true; - } - } + if (((fp = __INST(handle)) != nil) + && (__INST(mode) != @symbol(writeonly)) + ) { + f = __FILEVal(fp); + _buffered = (__INST(buffered) == true); + if (_buffered) { + __READING__(f) + } + __READBYTE__(ret, f, &c, _buffered, __INST(handleType)); + + if (ret > 0) { + __UNGETC__(c, f, _buffered); + + if (__INST(binary) == true) { + RETURN ( __mkSmallInteger(c) ); + } + RETURN ( __MKCHARACTER(c) ); + } + if (ret < 0) { + error = __mkSmallInteger(__threadErrno); + } else /* ret == 0 */ { + __INST(hitEOF) = true; + } + } } %}. hitEOF == true ifTrue:[^ nil]. error notNil ifTrue:[ - lastErrorNumber := error. - ^ self readError:error. + lastErrorNumber := error. + ^ self readError:error. ]. handle isNil ifTrue:[^ self errorNotOpen]. (mode == #writeonly) ifTrue:[^ self errorWriteOnly]. readAhead isNil ifTrue:[ - readAhead := self nextOrNil. + readAhead := self nextOrNil. ]. ^ readAhead ! @@ -5565,7 +5562,9 @@ !ExternalStream methodsFor:'testing'! atEnd - "return true, if position is at end" + "return true, if position is at end. + A stream is at the end, if the next read operation + would return immediately without waiting." %{ OBJ fp, pos, lim; @@ -5635,26 +5634,17 @@ __INST(hitEOF) = true; RETURN (true); } -#ifdef ECONNRESET - // connection reset by peer is also an EOF - if (__threadErrno == ECONNRESET) { - __INST(hitEOF) = true; - RETURN (true); - } -#endif - /* ret < 0 */ + /* ret < 0 -> error */ __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno); } + // we do not raise an error here - the next read operation will raise the error. + RETURN(false); } %}. - lastErrorNumber notNil ifTrue:[^ self readError]. - handle isNil ifTrue:[^ self errorNotOpen]. - mode == #writeonly ifTrue:[^ self errorWriteOnly]. - readAhead notNil ifTrue:[^ false]. - + + "/ we come here if the handle type is unknown "/ migration support - ^ self - atEndFile:handle + ^ self atEndFile:handle "Modified: / 30.10.1998 / 20:16:06 / cg" ! @@ -5695,7 +5685,7 @@ ! gotErrorOrEOF - "answerv true, if amn error or eof has been occurred on the stream" + "answer true, if amn error or eof has been occurred on the stream" ^ hitEOF == true or:[lastErrorNumber notNil] ! @@ -6579,7 +6569,7 @@ ]. " - 'Bönnigheim' asUnicode16String errorPrintCR + 'Bönnigheim' asUnicode16String errorPrintCR " ! diff -r fb8c5591428b -r 83c74234945e Filename.st --- a/Filename.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Filename.st Tue Oct 25 12:35:02 2016 +0100 @@ -2522,6 +2522,30 @@ "Modified: / 12-09-2010 / 15:43:22 / cg" ! +recursiveDirectoryContentsAsFilenamesDo:aBlock filterForVisitingDirectories:filterOrNil + "evaluate aBlock for all files and directories found under the receiver. + The block is invoked with the filenames as argument. + The walk is bread-first. + This excludes any entries for '.' or '..'. + Subdirectory files are included with a relative pathname. + If filterOrNil is nonNil, it is passed every directory about to be walked into; + if it returns false, that directory is not entered. + Warning: this may take a long time to execute + (especially with deep and/or remote fileSystems)." + + self + recursiveDirectoryContentsDo:[:relFn | + aBlock value:(self construct:relFn) + ] + filterForVisitingDirectories:filterOrNil. + + " + '.' asFilename recursiveDirectoryContentsAsFilenamesDo:[:f | Transcript showCR:f] + " + + "Modified: / 12-09-2010 / 15:43:22 / cg" +! + recursiveDirectoryContentsDo:aBlock "evaluate aBlock for all files and directories found under the receiver. The block is invoked with the relative filenames as string-argument. @@ -2562,13 +2586,64 @@ " ! +recursiveDirectoryContentsDo:aBlock filterForVisitingDirectories:filterOrNil + "evaluate aBlock for all files and directories found under the receiver. + The block is invoked with the relative filenames as string-argument. + The walk is bread-first. + This excludes any entries for '.' or '..'. + Subdirectory files are included with a relative pathname. + If filterOrNil is nonNil, it is passed every directory about to be walked into; + if it returns false, that directory is not entered. + Warning: this may take a long time to execute + (especially with deep and/or remote fileSystems)." + + self + recursiveDirectoryContentsWithPrefix:'' + filesDo:aBlock + directoriesDo:aBlock + filterForVisitingDirectories:filterOrNil + + " + '.' asFilename recursiveDirectoryContentsDo:[:f | Transcript showCR:f] + " + + "Modified: / 12-09-2010 / 15:43:22 / cg" +! + recursiveDirectoryContentsWithPrefix:aPrefix filesDo:fileBlock directoriesDo:dirBlock "evaluate aBlock for all files and directories found under the receiver. The blocks are invoked with a relative pathname as string-argument. The walk is breadth-first (first files, then directories). This excludes any entries for '.' or '..'. A proceedable exception is raised for non-accessible directories. - Warning: this may take a long time to execute (especially with deep and/or remote fileSystems)." + Warning: this may take a long time to execute + (especially with deep and/or remote fileSystems)." + + self + recursiveDirectoryContentsWithPrefix:aPrefix + filesDo:fileBlock + directoriesDo:dirBlock + filterForVisitingDirectories:nil + + " + '.' asFilename + recursiveDirectoryContentsWithPrefix:'bla' + filesDo:[:f | Transcript show:'file: '; showCR:f] + directoriesDo:[:f | Transcript show:'dir: '; showCR:f] + " +! + +recursiveDirectoryContentsWithPrefix:aPrefix filesDo:fileBlock directoriesDo:dirBlock filterForVisitingDirectories:filterOrNil + "evaluate aBlock for all files and directories found under the receiver. + The blocks are invoked with a relative pathname as string-argument. + The walk is breadth-first (first files, then directories). + This excludes any entries for '.' or '..'. + A proceedable exception is raised for non-accessible directories. + If filterOrNil is nonNil, it is passed every directory about to be walked into; + if it returns false, that directory is not entered. + Warning: this may take a long time to execute + (especially with deep and/or remote fileSystems). + " |fileNames dirNames p| @@ -2579,9 +2654,11 @@ self directoryContentsDo:[:f | |t| t := self construct:f. t isDirectory ifTrue:[ - dirBlock notNil ifTrue:[ - t isSymbolicLink ifFalse:[ - dirNames add:f + (filterOrNil isNil or:[filterOrNil value:t]) ifTrue:[ + dirBlock notNil ifTrue:[ + t isSymbolicLink ifFalse:[ + dirNames add:f + ] ] ] ] ifFalse:[ @@ -2602,10 +2679,15 @@ ]. dirBlock notNil ifTrue:[ dirNames do:[:dN | - dirBlock value:(p , dN). - (self construct:dN) - recursiveDirectoryContentsWithPrefix:(p , dN) - filesDo:fileBlock directoriesDo:dirBlock + |subDir| + + subDir := (self construct:dN). + (filterOrNil isNil or:[filterOrNil value:subDir]) ifTrue:[ + dirBlock value:(p , dN). + subDir + recursiveDirectoryContentsWithPrefix:(p , dN) + filesDo:fileBlock directoriesDo:dirBlock + ]. ]. ]. @@ -4418,30 +4500,44 @@ on unix, an xterm is opened." OperatingSystem isOSXlike ifTrue:[ - "/ I dont know yet how to tell the terminal to - "/ go to a particular directory. - "/ therefore, use the built in terminal - VT100TerminalView openShellIn:self pathName. - ^ self. + "/ I dont know yet how to tell the terminal to + "/ go to a particular directory. + "/ therefore, use the built in terminal + VT100TerminalView openShellIn:self pathName. + ^ self. + ]. + "/ using the code below seems to close the window immediately + "/ at least on win7. + "/ use out own terminal, to make sure. + (OperatingSystem isMSWINDOWSlike + and:[OperatingSystem isWin7Like]) ifTrue:[ + "/ I dont know yet how to tell the terminal to + "/ go to a particular directory. + "/ therefore, use the built in terminal + VT100TerminalView openShellIn:self pathName. + ^ self. ]. [ - |cmd| - - OperatingSystem isOSXlike ifTrue:[ - cmd := '/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal ' - ] ifFalse:[ - OperatingSystem isMSWINDOWSlike ifTrue:[ - cmd := 'c:\windows\System32\cmd.exe' - ] ifFalse:[ - "/ VT100TerminalView openShellIn:self pathName - cmd := 'xterm' - ] - ]. - OperatingSystem - executeCommand:cmd - inDirectory:self pathName. + |cmd| + + OperatingSystem isOSXlike ifTrue:[ + cmd := '/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal ' + ] ifFalse:[ + OperatingSystem isMSWINDOWSlike ifTrue:[ + cmd := #('c:\windows\System32\cmd.exe') + ] ifFalse:[ + "/ VT100TerminalView openShellIn:self pathName + cmd := 'xterm' + ] + ]. + OperatingSystem + executeCommand:cmd + inDirectory:self pathName + showWindow:#default. ] fork + + "Modified: / 18-10-2016 / 16:08:15 / cg" ! ! !Filename methodsFor:'printing & storing'! diff -r fb8c5591428b -r 83c74234945e Integer.st --- a/Integer.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Integer.st Tue Oct 25 12:35:02 2016 +0100 @@ -818,6 +818,7 @@ "Modified: 18.7.1996 / 12:26:38 / cg" ! ! + !Integer class methodsFor:'prime numbers'! flushPrimeCache @@ -1195,25 +1196,9 @@ ^ self == Integer ! ! + !Integer methodsFor:'Compatibility-Dolphin'! -& aNumber - "return the bitwise-and of the receiver and the argument, anInteger. - Same as bitAnd: - added for compatibility with Dolphin Smalltalk. - Notice: - PLEASE DO NOT USE & for integers in new code; it makes the code harder - to understand, as it may be not obvious, whether a boolean-and a bitWise-and is intended. - For integers, use bitAnd: to make the intention explicit. - Also, consider using and: for booleans, which is does not evaluate the right part if the left is false." - - ^ self bitAnd:aNumber - - " - 14 | 1 - 9 & 8 - " -! - highWord "return the high 16 bits of a 32 bit value" @@ -1459,6 +1444,8 @@ " ! ! + + !Integer methodsFor:'bcd conversion'! decodeFromBCD @@ -4853,6 +4840,7 @@ "Created: / 09-01-2012 / 17:18:06 / cg" ! ! + !Integer methodsFor:'special modulo arithmetic'! add_32:anInteger diff -r fb8c5591428b -r 83c74234945e Method.st --- a/Method.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Method.st Tue Oct 25 12:35:02 2016 +0100 @@ -1059,6 +1059,7 @@ "Modified (format): / 18-11-2011 / 14:47:06 / cg" ! ! + !Method methodsFor:'accessing-visibility'! isIgnored @@ -2725,6 +2726,16 @@ ^ self externalLibraryFunction notNil ! +isForCompatibility + "returns true, if this method only used for compatibility + and should use only when porting foreign code but not otherwise" + + |res| + + ^ self package == #'stx:libcompat' + or:[(res := self resources) notNil and:[res includesKey:#compatibility]] +! + isInvalid "return true, if this method is not executable due to a (re)-compilation error. Since invalidation is by patching the @@ -3073,16 +3084,6 @@ "Created: / 9.11.1998 / 06:15:08 / cg" ! -overrides: aMethod - - - self obsoleteMethodWarning: 'Use overwrites: instead, stupid naming'. - self overwrites: aMethod. - - "Modified: / 18-06-2009 / 12:15:53 / Jan Vrany " - "Modified: / 05-07-2012 / 10:52:38 / Jan Vrany " -! - overwrites:aMethod |mth| @@ -3760,6 +3761,7 @@ "Created: / 23-07-2012 / 11:16:36 / cg" ! ! + !Method methodsFor:'source management'! revisionInfo diff -r fb8c5591428b -r 83c74234945e NonPositionableExternalStream.st --- a/NonPositionableExternalStream.st Tue Oct 25 12:31:42 2016 +0100 +++ b/NonPositionableExternalStream.st Tue Oct 25 12:35:02 2016 +0100 @@ -1,3 +1,5 @@ +"{ Encoding: utf8 }" + " COPYRIGHT (c) 1989 by Claus Gittinger All Rights Reserved @@ -206,25 +208,6 @@ ]. ! ! -!NonPositionableExternalStream methodsFor:'closing'! - -close - "Close the stream. - No error if the stream is not open." - - |semasToSignal| - - self isOpen ifTrue:[ - "make sure, that no select is performed on closed file descriptors" - semasToSignal := Processor disableFd:self fileHandle doSignal:false. - super close. - "tell the waiters that they must not wait any longer" - semasToSignal do:[:eachSema| - eachSema signalForAll. - ]. - ]. -! ! - !NonPositionableExternalStream methodsFor:'error handling'! positionError @@ -421,6 +404,23 @@ super storeOn:aStream ! ! +!NonPositionableExternalStream protectedMethodsFor:'private'! + +closeFile + |semasToSignal| + + handle notNil ifTrue:[ + "make sure, that no select is performed on closed file descriptors" + semasToSignal := Processor disableFd:self fileHandle doSignal:false. + super closeFile. + + "tell the waiters that they must not wait any longer" + semasToSignal do:[:eachSema| + eachSema signalForAll. + ]. + ]. +! ! + !NonPositionableExternalStream methodsFor:'private'! handleForStderr @@ -549,12 +549,14 @@ ] ]. - "first, wait to avoid blocking on the read. - On end of stream or error, readWait will return" + handle notNil ifTrue:[ + "first, wait to avoid blocking on the read. + On end of stream or error, readWait will return" - self readWaitWithTimeoutMs:nil. + self readWaitWithTimeoutMs:nil. + ]. handle isNil ifTrue:[ - "we were closed while waiting - so we are at the end" + "we are closed or were closed while waiting - so we are at the end" ^ true. ]. ^ super atEnd. @@ -652,7 +654,11 @@ Redefined, to wait on pipes and sockets" - self atEnd ifTrue:[^ nil]. + self readWaitWithTimeoutMs:nil. + handle isNil ifTrue:[ + "we were closed while waiting - so we are at the end" + ^ nil. + ]. ^ super nextOrNil ! @@ -670,7 +676,11 @@ Redefined, to wait on pipes and sockets" - self atEnd ifTrue:[^ nil]. + self readWaitWithTimeoutMs:nil. + handle isNil ifTrue:[ + "we were closed while waiting - so we are at the end" + ^ nil. + ]. ^ self peek ! diff -r fb8c5591428b -r 83c74234945e PCFilename.st --- a/PCFilename.st Tue Oct 25 12:31:42 2016 +0100 +++ b/PCFilename.st Tue Oct 25 12:35:02 2016 +0100 @@ -1,3 +1,5 @@ +"{ Encoding: utf8 }" + " COPYRIGHT (c) 1997 by eXept Software AG All Rights Reserved @@ -601,7 +603,7 @@ ^ true. ]. - (self suffix asLowercase = 'bat') ifTrue:[ + (#('bat' 'cmd') includes:self suffix asLowercase) ifTrue:[ ^ (OperatingSystem isValidPath:osName) and:[(OperatingSystem isDirectory:osName) not]. ]. diff -r fb8c5591428b -r 83c74234945e PipeStream.st --- a/PipeStream.st Tue Oct 25 12:31:42 2016 +0100 +++ b/PipeStream.st Tue Oct 25 12:35:02 2016 +0100 @@ -489,7 +489,7 @@ !PipeStream methodsFor:'closing'! -shutDown +abortAndClose "close the Stream and terminate the command" self unregisterForFinalization. @@ -506,6 +506,31 @@ self terminatePipeCommand. ! +close + "low level close + This waits for the command to finish. + Use abortAndClose for a fast (nonBlocking) close." + + handle notNil ifTrue:[ + super close. + pid notNil ifTrue:[ + "/ wait for the pipe-command to terminate. + self waitForPipeCommandWithTimeout:nil. + ]. + ]. + + "Modified: / 12.9.1998 / 16:51:04 / cg" +! + +shutDown + + "this is a historic leftover kept for backward compatibility. + The name collides wuth the same name in Socket, which does + not hard terminate the connection." + + self abortAndClose. +! + shutDownOutput "signal to the pipestream's command, that no more data will be sent" @@ -524,30 +549,7 @@ finalize "redefined to avoid blocking in close." - self shutDown -! ! - -!PipeStream protectedMethodsFor:'private'! - -closeFile - "low level close - This waits for the command to finish. - Use shutDown for a fast (nonBlocking) close." - - handle notNil ifTrue:[ - super closeFile. -"/ OperatingSystem isMSDOSlike ifTrue:[ -"/ self terminatePipeCommand. -"/ ]. - - handle := nil. - pid notNil ifTrue:[ - "/ wait for the pipe-command to terminate. - self waitForPipeCommandWithTimeout:nil. - ]. - ]. - - "Modified: / 12.9.1998 / 16:51:04 / cg" + self abortAndClose ! ! !PipeStream methodsFor:'private'! diff -r fb8c5591428b -r 83c74234945e Process.st --- a/Process.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Process.st Tue Oct 25 12:35:02 2016 +0100 @@ -2195,7 +2195,8 @@ ! threadVariableValueOf:aKey - "return the value of a thread local variable, or nil if no such variable exists" + "return the value of a thread local variable, + or nil if no such variable exists" ^ self environmentAt:aKey ifAbsent:nil @@ -2236,42 +2237,46 @@ |var oldValue result| environment isNil ifTrue:[ - environment := IdentityDictionary new + environment := IdentityDictionary new ]. var := environment at:variableNameSymbol ifAbsent:nil. var isNil ifTrue:[ - var := ValueHolder new. - environment at:variableNameSymbol put:var. + var := ValueHolder new. + environment at:variableNameSymbol put:var. ]. oldValue := var value. [ - var value:aValue. - result := aBlock value. + var value:aValue. + result := aBlock value. ] ensure:[ - oldValue isNil - ifTrue:[ environment removeKey:variableNameSymbol] - ifFalse:[ var value:oldValue ] + oldValue isNil + ifTrue:[ environment removeKey:variableNameSymbol] + ifFalse:[ var value:oldValue ] ]. ^ result " |printIt| - printIt := [ Transcript showCR:'foo is now ',(Processor activeProcess threadVariableValueOf:#foo) printString ]. + printIt := [ + Transcript + showCR:'foo is now ', + (Processor activeProcess threadVariableValueOf:#foo) printString + ]. Processor activeProcess - withThreadVariable:#foo - boundTo:1234 - do:[ - printIt value. - Processor activeProcess - withThreadVariable:#foo - boundTo:2345 - do:[ - printIt value - ]. - ] + withThreadVariable:#foo + boundTo:1234 + do:[ + printIt value. + Processor activeProcess + withThreadVariable:#foo + boundTo:2345 + do:[ + printIt value + ]. + ] " ! ! diff -r fb8c5591428b -r 83c74234945e String.st --- a/String.st Tue Oct 25 12:31:42 2016 +0100 +++ b/String.st Tue Oct 25 12:35:02 2016 +0100 @@ -519,6 +519,8 @@ ! ! + + !String class methodsFor:'queries'! defaultPlatformClass @@ -539,6 +541,11 @@ ! ! + + + + + !String methodsFor:'accessing'! at:index @@ -2412,30 +2419,6 @@ !String methodsFor:'converting'! -asArrayOfSubstrings - "Answer an array with all the substrings of the receiver separated by - separator characters (space, cr, tab, linefeed, formfeed, etc). - CG: This is ported Squeak code, and I am not sure if it is more efficient than - the inherited one... after all: who added it anyway ?" - - | substrings start end stop | - - substrings := OrderedCollection new. - start := 1. - stop := self size. - [start <= stop] whileTrue: [ - (self at: start) isSeparator ifFalse: [ - end := start + 1. - [end <= stop and: [(self at: end) isSeparator not]] - whileTrue: [end := end + 1]. - substrings add: (self copyFrom: start to: end - 1). - start := end - 1 - ]. - start := start + 1 - ]. - ^ substrings asArray -! - asAsciiZ "if the receiver does not end with a 0-valued character, return a copy of it, with an additional 0-character. Otherwise return the receiver. This is sometimes @@ -4276,6 +4259,7 @@ ^ super reverse ! ! + !String methodsFor:'substring searching'! indexOfSubCollection:aSubString startingAt:startIndex ifAbsent:exceptionValue caseSensitive:caseSensitive @@ -4952,6 +4936,7 @@ ! ! + !String class methodsFor:'documentation'! version diff -r fb8c5591428b -r 83c74234945e Win32OperatingSystem.st --- a/Win32OperatingSystem.st Tue Oct 25 12:31:42 2016 +0100 +++ b/Win32OperatingSystem.st Tue Oct 25 12:35:02 2016 +0100 @@ -18,8 +18,8 @@ AbstractOperatingSystem subclass:#Win32OperatingSystem instanceVariableNames:'' - classVariableNames:'Initialized HostName DomainName CurrentDirectory LastOsTimeLow - LastOsTimeHi LastTimeInfoIsLocal LastTimeInfo' + classVariableNames:'CurrentDirectory DomainName HostName Initialized LastOsTimeHi + LastOsTimeLow LastTimeInfo LastTimeInfoIsLocal' poolDictionaries:'Win32Constants' category:'OS-Windows' ! @@ -3675,67 +3675,71 @@ ! exec:aCommandPath withArguments:argString environment:environment fileDescriptors:fdArray fork:doFork - newPgrp:newPgrp inDirectory:aDirectory - showWindow:showWindowBooleanOrNil + newPgrp:newPgrp inDirectory:aDirectory + showWindow:showWindowBooleanOrNil "Internal lowLevel entry for combined fork & exec for WIN32 If fork is false (chain a command): - execute the OS command specified by the argument, aCommandPath, with - arguments in argArray (no arguments, if nil). - If successful, this method does not return and smalltalk is gone. - If not successful, it does return. - Normal use is with forkForCommand. + execute the OS command specified by the argument, aCommandPath, with + arguments in argArray (no arguments, if nil). + If successful, this method does not return and smalltalk is gone. + If not successful, it does return. + Normal use is with forkForCommand. If fork is true (subprocess command execution): - fork a child to do the above. - The Win32ProcessHandle of the child process is returned; nil if the fork failed. + fork a child to do the above. + The Win32ProcessHandle of the child process is returned; nil if the fork failed. fdArray contains the filedescriptors, to be used for the child (if fork is true). - fdArray[1] = 15 -> use fd 15 as stdin. - If an element of the array is set to nil, the corresponding filedescriptor - will be closed for the child. - fdArray[0] == StdIn for child - fdArray[1] == StdOut for child - fdArray[2] == StdErr for child + fdArray[1] = 15 -> use fd 15 as stdin. + If an element of the array is set to nil, the corresponding filedescriptor + will be closed for the child. + fdArray[0] == StdIn for child + fdArray[1] == StdOut for child + fdArray[2] == StdErr for child NOTE that in WIN32 the fds are HANDLES. If newPgrp is true, the subprocess will be established in a new process group. - The processgroup will be equal to id. - newPgrp is not used on WIN32 and VMS systems. + The processgroup will be equal to id. + newPgrp is not used on WIN32 and VMS systems. showWindowOrBoolean may be: - true - a window is shown on start of the command - false - the command window is hidden - nil - the nCmdShown parameter of the commans's winmain function determins, - if a window is shown." + true - a window is shown on start of the command + false - the command window is hidden + nil - the nCmdShown parameter of the commans's winmain function determins, + if a window is shown. + #default + - same as nil + " |dirPath rslt| aDirectory notNil ifTrue:[ - dirPath := aDirectory asFilename asAbsoluteFilename osNameForDirectory. - (dirPath endsWith:':') ifTrue:[ - dirPath := dirPath , '\'. - ]. + dirPath := aDirectory asFilename asAbsoluteFilename osNameForDirectory. + (dirPath endsWith:':') ifTrue:[ + dirPath := dirPath , '\'. + ]. ]. rslt := self - primExec:aCommandPath - commandLine:argString - fileDescriptors:fdArray - fork:doFork - newPgrp:newPgrp - inPath:dirPath - createFlags:nil - inheritHandles:true - showWindow:showWindowBooleanOrNil. + primExec:aCommandPath + commandLine:argString + fileDescriptors:fdArray + fork:doFork + newPgrp:newPgrp + inPath:dirPath + createFlags:nil + inheritHandles:true + showWindow:showWindowBooleanOrNil. "/ 'created ' print. cmdLine print. ' -> ' print. rslt printCR. ^ rslt - "Modified: / 31.1.1998 / 10:54:24 / md" - "Modified: / 15.5.1999 / 18:07:51 / cg" + "Modified: / 31-01-1998 / 10:54:24 / md" + "Modified: / 15-05-1999 / 18:07:51 / cg" + "Modified (comment): / 18-10-2016 / 16:00:26 / cg" ! getStatusOfProcess:aProcessId @@ -3859,15 +3863,18 @@ ! primExec:commandPath commandLine:commandLine fileDescriptors:fdArray fork:doFork newPgrp:newPgrp - inPath:dirName createFlags:flagsOrNil inheritHandles:inheritHandles - showWindow:showWindowBooleanOrNil + inPath:dirName createFlags:flagsOrNil inheritHandles:inheritHandles + showWindow:showWindowBooleanOrNil "Internal lowLevel entry for combined fork & exec for WIN32 showWindowBooleanOrNil may be: - true - a window is shown on start of the command - false - the command window is hidden - nil - the nCmdShown parameter of the commans's winmain function determins, - if a window is shown." + true - a window is shown on start of the command + false - the command window is hidden + nil - the nCmdShown parameter of the commans's winmain function determins, + if a window is shown. + #default + - same as nil + " |handle commandPathUni16 commandLineUni16 dirNameUni16| @@ -3878,13 +3885,13 @@ dirNameUni16 := dirName. commandPathUni16 notNil ifTrue:[ - commandPathUni16 := commandPathUni16 asUnicode16String. + commandPathUni16 := commandPathUni16 asUnicode16String. ]. commandLineUni16 notNil ifTrue:[ - commandLineUni16 := commandLineUni16 asUnicode16String. + commandLineUni16 := commandLineUni16 asUnicode16String. ]. dirNameUni16 notNil ifTrue:[ - dirNameUni16 := dirNameUni16 asUnicode16String. + dirNameUni16 := dirNameUni16 asUnicode16String. ]. @@ -3922,280 +3929,280 @@ SECURITY_DESCRIPTOR securityDescriptor; if ((__isUnicode16String(commandPathUni16) || (commandPathUni16 == nil)) && __isUnicode16String(commandLineUni16)) { - HANDLE stdinHandle = NULL; - HANDLE stdoutHandle = NULL; - HANDLE stderrHandle = NULL; - int mustClose_stdinHandle = 0; - int mustClose_stdoutHandle = 0; - int mustClose_stderrHandle = 0; - - /* - * terminate the multi byte strings - */ - // #commandPathUni16 - if (commandPathUni16 != nil) { - l = __unicode16StringSize(commandPathUni16); - if (l >= 4096) { // >= need 1 space for terminator - #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "argument #commandPathUni16 is to long\n"); - #endif - RETURN(nil); - } - for (i = 0; i < l; i++) { - cmdPathW[i] = __unicode16StringVal(commandPathUni16)[i]; - } - cmdPathW[i] = 0; // set terminator - cmdPathWP = &cmdPathW[0]; - } - - // commandLineUni16 - l = __unicode16StringSize(commandLineUni16); - if (l >= 4096) { // >= need 1 space for terminator - #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "argument #commandLineUni16 is to long\n"); - #endif - RETURN(nil); - } - for (i = 0; i < l; i++) { - cmdLineW[i] = __unicode16StringVal(commandLineUni16)[i]; - } - cmdLineW[i] = 0; // set terminator - cmdLineWP = &cmdLineW[0]; - - // #dirNameUni16 - if (__isUnicode16String(dirNameUni16)) { - l = __unicode16StringSize(dirNameUni16); - if (l >= 4096) { // >= need 1 space for terminator - #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "argument #dirNameUni16 is to long\n"); - #endif - RETURN(nil); - } - for (i = 0; i < l; i++) { - dirNameW[i] = __unicode16StringVal(dirNameUni16)[i]; - } - dirNameW[i] = 0; // set terminator - dirNameWP = &dirNameW[0]; - } - - /* - * create descriptors as req'd - */ - memset(&securityAttributes, 0, sizeof(securityAttributes)); - securityAttributes.nLength = sizeof(securityAttributes); - securityAttributes.bInheritHandle = (inheritHandles == true) ? TRUE : FALSE; - - InitializeSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&securityDescriptor, -1, 0, 0); - - securityAttributes.lpSecurityDescriptor = &securityDescriptor; - memset(&lppiProcInfo, 0, sizeof (lppiProcInfo)); - - memset(&lpsiStartInfo, 0, sizeof(lpsiStartInfo)); - lpsiStartInfo.cb = sizeof(lpsiStartInfo); - lpsiStartInfo.lpReserved = NULL; - lpsiStartInfo.lpDesktop = NULL; - lpsiStartInfo.lpTitle = NULL; - lpsiStartInfo.dwX = 0; - lpsiStartInfo.dwY = 0; - lpsiStartInfo.dwXSize = 100; - lpsiStartInfo.dwYSize = 100; - lpsiStartInfo.dwXCountChars = 0; - lpsiStartInfo.dwYCountChars = 0; - lpsiStartInfo.dwFillAttribute = 0; - lpsiStartInfo.dwFlags = STARTF_USESTDHANDLES /*| STARTF_USEPOSITION*/; - if (showWindowBooleanOrNil != nil) { - lpsiStartInfo.dwFlags |= STARTF_USESHOWWINDOW; - lpsiStartInfo.wShowWindow = showWindowBooleanOrNil == true ? SW_SHOWNORMAL : SW_HIDE; - } - lpsiStartInfo.cbReserved2 = 0; - lpsiStartInfo.lpReserved2 = NULL; - lpsiStartInfo.hStdInput = NULL; - lpsiStartInfo.hStdOutput = NULL; - lpsiStartInfo.hStdError = NULL; - - /* - * set create process flags - * if the flags arg is nil, use common defaults; - * if non-nil, it must be a positive integer containing the fdwCreate bits. - */ - if (flagsOrNil != nil) { - fdwCreate = __longIntVal(flagsOrNil); - } else { - fdwCreate = CREATE_NEW_CONSOLE; //|IDLE_PRIORITY_CLASS; // DETACHED_PROCESS; // NORMAL_PRIORITY_CLASS ; - if (newPgrp == true) { - fdwCreate |= CREATE_NEW_PROCESS_GROUP; - } - fdwCreate |= CREATE_DEFAULT_ERROR_MODE; - } - - if (fdArray == nil) { - stdinHandle = (HANDLE) _get_osfhandle (0); - stdoutHandle = (HANDLE) _get_osfhandle (1); - stderrHandle = (HANDLE) _get_osfhandle (2); - } else if (__isArrayLike(fdArray) && (__arraySize(fdArray) >= 3)) { - if (__ArrayInstPtr(fdArray)->a_element[0] != nil) { - if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[0])) { - stdinHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[0]); - } else { - stdinHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[0])); - } - } - if (__ArrayInstPtr(fdArray)->a_element[1] != nil) { - if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[1])) { - stdoutHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[1]); - } else { - stdoutHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[1])); - } - } - if (__ArrayInstPtr(fdArray)->a_element[2] != nil) { - if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[2])) { - stderrHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[2]); - } else { - stderrHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[2])); - } - } - } else { - console_fprintf(stderr, "Win32OS [warning]: bad fd arg in createProcess\n"); - } + HANDLE stdinHandle = NULL; + HANDLE stdoutHandle = NULL; + HANDLE stderrHandle = NULL; + int mustClose_stdinHandle = 0; + int mustClose_stdoutHandle = 0; + int mustClose_stderrHandle = 0; + + /* + * terminate the multi byte strings + */ + // #commandPathUni16 + if (commandPathUni16 != nil) { + l = __unicode16StringSize(commandPathUni16); + if (l >= 4096) { // >= need 1 space for terminator + #ifdef PROCESSDEBUGWIN32 + console_fprintf(stderr, "argument #commandPathUni16 is to long\n"); + #endif + RETURN(nil); + } + for (i = 0; i < l; i++) { + cmdPathW[i] = __unicode16StringVal(commandPathUni16)[i]; + } + cmdPathW[i] = 0; // set terminator + cmdPathWP = &cmdPathW[0]; + } + + // commandLineUni16 + l = __unicode16StringSize(commandLineUni16); + if (l >= 4096) { // >= need 1 space for terminator + #ifdef PROCESSDEBUGWIN32 + console_fprintf(stderr, "argument #commandLineUni16 is to long\n"); + #endif + RETURN(nil); + } + for (i = 0; i < l; i++) { + cmdLineW[i] = __unicode16StringVal(commandLineUni16)[i]; + } + cmdLineW[i] = 0; // set terminator + cmdLineWP = &cmdLineW[0]; + + // #dirNameUni16 + if (__isUnicode16String(dirNameUni16)) { + l = __unicode16StringSize(dirNameUni16); + if (l >= 4096) { // >= need 1 space for terminator + #ifdef PROCESSDEBUGWIN32 + console_fprintf(stderr, "argument #dirNameUni16 is to long\n"); + #endif + RETURN(nil); + } + for (i = 0; i < l; i++) { + dirNameW[i] = __unicode16StringVal(dirNameUni16)[i]; + } + dirNameW[i] = 0; // set terminator + dirNameWP = &dirNameW[0]; + } + + /* + * create descriptors as req'd + */ + memset(&securityAttributes, 0, sizeof(securityAttributes)); + securityAttributes.nLength = sizeof(securityAttributes); + securityAttributes.bInheritHandle = (inheritHandles == true) ? TRUE : FALSE; + + InitializeSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&securityDescriptor, -1, 0, 0); + + securityAttributes.lpSecurityDescriptor = &securityDescriptor; + memset(&lppiProcInfo, 0, sizeof (lppiProcInfo)); + + memset(&lpsiStartInfo, 0, sizeof(lpsiStartInfo)); + lpsiStartInfo.cb = sizeof(lpsiStartInfo); + lpsiStartInfo.lpReserved = NULL; + lpsiStartInfo.lpDesktop = NULL; + lpsiStartInfo.lpTitle = NULL; + lpsiStartInfo.dwX = 0; + lpsiStartInfo.dwY = 0; + lpsiStartInfo.dwXSize = 100; + lpsiStartInfo.dwYSize = 100; + lpsiStartInfo.dwXCountChars = 0; + lpsiStartInfo.dwYCountChars = 0; + lpsiStartInfo.dwFillAttribute = 0; + lpsiStartInfo.dwFlags = STARTF_USESTDHANDLES /*| STARTF_USEPOSITION*/; + if ((showWindowBooleanOrNil != nil) && (showWindowBooleanOrNil != @symbol(default))) { + lpsiStartInfo.dwFlags |= STARTF_USESHOWWINDOW; + lpsiStartInfo.wShowWindow = showWindowBooleanOrNil == true ? SW_SHOWNORMAL : SW_HIDE; + } + lpsiStartInfo.cbReserved2 = 0; + lpsiStartInfo.lpReserved2 = NULL; + lpsiStartInfo.hStdInput = NULL; + lpsiStartInfo.hStdOutput = NULL; + lpsiStartInfo.hStdError = NULL; + + /* + * set create process flags + * if the flags arg is nil, use common defaults; + * if non-nil, it must be a positive integer containing the fdwCreate bits. + */ + if (flagsOrNil != nil) { + fdwCreate = __longIntVal(flagsOrNil); + } else { + fdwCreate = CREATE_NEW_CONSOLE; //|IDLE_PRIORITY_CLASS; // DETACHED_PROCESS; // NORMAL_PRIORITY_CLASS ; + if (newPgrp == true) { + fdwCreate |= CREATE_NEW_PROCESS_GROUP; + } + fdwCreate |= CREATE_DEFAULT_ERROR_MODE; + } + + if (fdArray == nil) { + stdinHandle = (HANDLE) _get_osfhandle (0); + stdoutHandle = (HANDLE) _get_osfhandle (1); + stderrHandle = (HANDLE) _get_osfhandle (2); + } else if (__isArrayLike(fdArray) && (__arraySize(fdArray) >= 3)) { + if (__ArrayInstPtr(fdArray)->a_element[0] != nil) { + if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[0])) { + stdinHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[0]); + } else { + stdinHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[0])); + } + } + if (__ArrayInstPtr(fdArray)->a_element[1] != nil) { + if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[1])) { + stdoutHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[1]); + } else { + stdoutHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[1])); + } + } + if (__ArrayInstPtr(fdArray)->a_element[2] != nil) { + if (__isExternalAddressLike(__ArrayInstPtr(fdArray)->a_element[2])) { + stderrHandle = _HANDLEVal(__ArrayInstPtr(fdArray)->a_element[2]); + } else { + stderrHandle = (HANDLE) _get_osfhandle (__intVal(__ArrayInstPtr(fdArray)->a_element[2])); + } + } + } else { + console_fprintf(stderr, "Win32OS [warning]: bad fd arg in createProcess\n"); + } #if defined(PROCESSDEBUGWIN32) - console_fprintf(stderr, "stdin %x\n", stdinHandle); - console_fprintf(stderr, "stdout %x\n", stdoutHandle); - console_fprintf(stderr, "stderr %x\n", stderrHandle); -#endif - - { - HANDLE childHandle; - int sameHandle = (stdoutHandle == stderrHandle); - - // these MUST be inheritable! - if (stdinHandle) { + console_fprintf(stderr, "stdin %x\n", stdinHandle); + console_fprintf(stderr, "stdout %x\n", stdoutHandle); + console_fprintf(stderr, "stderr %x\n", stderrHandle); +#endif + + { + HANDLE childHandle; + int sameHandle = (stdoutHandle == stderrHandle); + + // these MUST be inheritable! + if (stdinHandle) { #if 0 - if (SetHandleInformation(stdinHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - // good - } else { - console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); - } -#else - if (DuplicateHandle(GetCurrentProcess(), stdinHandle, GetCurrentProcess(), - &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - stdinHandle = childHandle; - mustClose_stdinHandle = 1; - } else { - console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); - } -#endif - } - if (stdoutHandle) { + if (SetHandleInformation(stdinHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + // good + } else { + console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); + } +#else + if (DuplicateHandle(GetCurrentProcess(), stdinHandle, GetCurrentProcess(), + &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + stdinHandle = childHandle; + mustClose_stdinHandle = 1; + } else { + console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); + } +#endif + } + if (stdoutHandle) { #if 0 - if (SetHandleInformation(stdoutHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - // good - } else { - console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); - } -#else - if (DuplicateHandle(GetCurrentProcess(), stdoutHandle, GetCurrentProcess(), - &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - stdoutHandle = childHandle; - mustClose_stdoutHandle = 1; - } else { - console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); - } -#endif - } - if (stderrHandle) { - if (sameHandle) { - stderrHandle = stdoutHandle; - } else { + if (SetHandleInformation(stdoutHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + // good + } else { + console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); + } +#else + if (DuplicateHandle(GetCurrentProcess(), stdoutHandle, GetCurrentProcess(), + &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + stdoutHandle = childHandle; + mustClose_stdoutHandle = 1; + } else { + console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); + } +#endif + } + if (stderrHandle) { + if (sameHandle) { + stderrHandle = stdoutHandle; + } else { #if 0 - if (SetHandleInformation(stderrHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - // good - } else { - console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); - } -#else - if (DuplicateHandle(GetCurrentProcess(), stderrHandle, GetCurrentProcess(), - &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - stderrHandle = childHandle; - mustClose_stderrHandle = 1; - } else { - console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); - } -#endif - } - } - } - lpsiStartInfo.hStdInput = stdinHandle; - lpsiStartInfo.hStdOutput = stdoutHandle; - lpsiStartInfo.hStdError = stderrHandle; - - if (doFork == true) { + if (SetHandleInformation(stderrHandle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + // good + } else { + console_fprintf(stderr, "Win32OS [warning]: SetHandleInformation failed in createProcess\n"); + } +#else + if (DuplicateHandle(GetCurrentProcess(), stderrHandle, GetCurrentProcess(), + &childHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + stderrHandle = childHandle; + mustClose_stderrHandle = 1; + } else { + console_fprintf(stderr, "Win32OS [warning]: duplicateHandle failed in createProcess\n"); + } +#endif + } + } + } + lpsiStartInfo.hStdInput = stdinHandle; + lpsiStartInfo.hStdOutput = stdoutHandle; + lpsiStartInfo.hStdError = stderrHandle; + + if (doFork == true) { #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "create process cmdPath:<%s> cmdLine:<%s> in <%s>\n", cmdPath, cmdLine, dir); -#endif - if (CreateProcessW( cmdPathWP, - cmdLineWP, - &securityAttributes, NULL /* &securityAttributes */, - securityAttributes.bInheritHandle, /* inherit handles */ - fdwCreate | CREATE_SUSPENDED, /* resume after setting affinity */ - NULL, /* env */ - dirNameWP, - &lpsiStartInfo, - &lppiProcInfo )) - { - DWORD_PTR processAffinityMask, systemAffinityMask; - - /* - * Process was created suspended, now set the affinity mask - * to any processor, and resume the processes main thread. - * (librun/process.s limited the affinity to a single processor). - */ - GetProcessAffinityMask(lppiProcInfo.hProcess, &processAffinityMask, &systemAffinityMask); - SetProcessAffinityMask(lppiProcInfo.hProcess, systemAffinityMask); - if ((fdwCreate & CREATE_SUSPENDED) == 0) { - ResumeThread(lppiProcInfo.hThread); - } - CloseHandle(lppiProcInfo.hThread); + console_fprintf(stderr, "create process cmdPath:<%s> cmdLine:<%s> in <%s>\n", cmdPath, cmdLine, dir); +#endif + if (CreateProcessW( cmdPathWP, + cmdLineWP, + &securityAttributes, NULL /* &securityAttributes */, + securityAttributes.bInheritHandle, /* inherit handles */ + fdwCreate | CREATE_SUSPENDED, /* resume after setting affinity */ + NULL, /* env */ + dirNameWP, + &lpsiStartInfo, + &lppiProcInfo )) + { + DWORD_PTR processAffinityMask, systemAffinityMask; + + /* + * Process was created suspended, now set the affinity mask + * to any processor, and resume the processes main thread. + * (librun/process.s limited the affinity to a single processor). + */ + GetProcessAffinityMask(lppiProcInfo.hProcess, &processAffinityMask, &systemAffinityMask); + SetProcessAffinityMask(lppiProcInfo.hProcess, systemAffinityMask); + if ((fdwCreate & CREATE_SUSPENDED) == 0) { + ResumeThread(lppiProcInfo.hThread); + } + CloseHandle(lppiProcInfo.hThread); #if 0 - // only works with real console handles - { - // change the child's stdIn (console) mode - DWORD mode = 0; - - if (! GetConsoleMode(stdinHandle, &mode)) { - console_fprintf(stderr, "Win32OS [warning]: GetConsoleMode failed in createProcess\n"); - } - if (! SetConsoleMode(stdinHandle, mode & (~ENABLE_ECHO_INPUT))){ - console_fprintf(stderr, "Win32OS [warning]: SetConsoleMode failed in createProcess\n"); - } - } -#endif - if (mustClose_stdinHandle) { - CloseHandle(stdinHandle); - } - if (mustClose_stdoutHandle) { - CloseHandle(stdoutHandle); - } - if (mustClose_stderrHandle) { - CloseHandle(stderrHandle); - } + // only works with real console handles + { + // change the child's stdIn (console) mode + DWORD mode = 0; + + if (! GetConsoleMode(stdinHandle, &mode)) { + console_fprintf(stderr, "Win32OS [warning]: GetConsoleMode failed in createProcess\n"); + } + if (! SetConsoleMode(stdinHandle, mode & (~ENABLE_ECHO_INPUT))){ + console_fprintf(stderr, "Win32OS [warning]: SetConsoleMode failed in createProcess\n"); + } + } +#endif + if (mustClose_stdinHandle) { + CloseHandle(stdinHandle); + } + if (mustClose_stdoutHandle) { + CloseHandle(stdoutHandle); + } + if (mustClose_stderrHandle) { + CloseHandle(stderrHandle); + } #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "created process hProcess=%x\n", lppiProcInfo.hProcess); -#endif - - __externalAddressVal(handle) = lppiProcInfo.hProcess; - ((struct __Win32OperatingSystem__Win32ProcessHandle_struct *)(handle))->pid = __mkSmallInteger(lppiProcInfo.dwProcessId); - RETURN (handle); - } + console_fprintf(stderr, "created process hProcess=%x\n", lppiProcInfo.hProcess); +#endif + + __externalAddressVal(handle) = lppiProcInfo.hProcess; + ((struct __Win32OperatingSystem__Win32ProcessHandle_struct *)(handle))->pid = __mkSmallInteger(lppiProcInfo.dwProcessId); + RETURN (handle); + } #ifdef PROCESSDEBUGWIN32 - console_fprintf(stderr, "created process error %d\n", GetLastError()); -#endif - RETURN (nil); - } else { - ; /* should never be called that way */ - } + console_fprintf(stderr, "created process error %d\n", GetLastError()); +#endif + RETURN (nil); + } else { + ; /* should never be called that way */ + } } %}. " @@ -4205,6 +4212,8 @@ or not supported by OS " ^ self primitiveFailed + + "Modified: / 18-10-2016 / 16:00:03 / cg" ! shellExecute:hwndArg lpOperation:lpOperationArg lpFile:lpFileArg lpParameters:lpParametersArg lpDirectory:lpDirectoryArg nShowCmd:nShowCmd