Add forgotten files 1.4.70b
[polyglot.git] / pipe.cpp
index 7f868bd..170da4a 100644 (file)
--- a/pipe.cpp
+++ b/pipe.cpp
@@ -4,10 +4,15 @@
 
 // functions
 
-DWORD WINAPI ThreadProc(LPVOID lpParam){
+DWORD WINAPI ThreadProc(LPVOID lpParam){ 
     PipeStruct *p=(PipeStruct *) lpParam;
-    while(!p->EOF_()){
-        p->ReadInput();
+    while(!p->EOF_input()){
+        if(p->nReadEnd<LINE_INPUT_MAX_CHAR-1){
+            p->ReadInput();
+        }else{
+                // wait until there is room in buffer
+            Sleep(10);
+        }
     }
     return 0;
 }
@@ -15,11 +20,12 @@ DWORD WINAPI ThreadProc(LPVOID lpParam){
 
 
 void PipeStruct::Open(const char *szProcFile) {
-    DWORD dwMode;
+    DWORD dwMode, dwThreadId;
     HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
     SECURITY_ATTRIBUTES sa;
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
+    int fdInput;
     state=0;
     if (szProcFile == NULL) {
         hInput = GetStdHandle(STD_INPUT_HANDLE);
@@ -67,6 +73,14 @@ void PipeStruct::Open(const char *szProcFile) {
                        dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
         FlushConsoleInputBuffer(hInput);
     } 
+    fdInput=_open_osfhandle((long) hInput,_O_RDONLY);
+    if(fdInput==-1){
+        my_fatal("PipeStruct::Open(): %s",my_error());
+    }
+    fpInput=fdopen(fdInput,"r");
+    if(fpInput==NULL){
+        my_fatal("PipeStruct::Open(): %s",my_error());
+    }
     nReadEnd = 0;
     lpFeedEnd = NULL;
     InitializeCriticalSection(&CriticalSection);
@@ -75,14 +89,19 @@ void PipeStruct::Open(const char *szProcFile) {
                        FALSE,          // not signaled
                        NULL            // nameless
                        );
+    if(!hEvent){
+        my_fatal("PipeStruct::Open(): %s",my_error());
+    }
     hThread=CreateThread(NULL,         // default security
                          0,            // default stacksize
                          ThreadProc,   // worker function
                          this,         // tell worker about ourselves
                          0,            // run immediately
-                         NULL          // nameless
+                         &dwThreadId   // dropped, but needed for the call to work in Win9x
                          );          
-    
+    if(!hThread){
+        my_fatal("PipeStruct::Open(): %s",my_error());
+    }
     set_Active();
 }
 
@@ -104,7 +123,7 @@ void PipeStruct::Kill(void) const {
        CloseHandle(hProcess);
 }
 
-bool PipeStruct::EOF_(void){   // EOF is defined
+bool PipeStruct::EOF_input(void){   // EOF is defined
     int ret;
     EnterCriticalSection(&CriticalSection);
     ret=state&PIPE_EOF;
@@ -112,7 +131,7 @@ bool PipeStruct::EOF_(void){   // EOF is defined
     return ret;
 }
 
-void PipeStruct::set_EOF_(void){
+void PipeStruct::set_EOF_input(void){
     EnterCriticalSection(&CriticalSection);
     state|=PIPE_EOF;
     LeaveCriticalSection(&CriticalSection);
@@ -134,51 +153,17 @@ void PipeStruct::set_Active(void){
 
 int PipeStruct::ReadData(void){
     DWORD dwBytes;
-    int ret;
-    
-    if(!bPipe){
-        fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,stdin);
-        dwBytes=strlen(lpReadBuffer);
-        if(!dwBytes){
-            set_EOF_();
-            lpReadBuffer[0]='\0';
-            return 0;
-        }
-    }else{
-            // Unfortunately we need to use polling here.
-            // Otherwise Windows returns single bytes if
-            // the engine runs at low priority.
-            // This kills performance.
-        while(TRUE){
-            ret=PeekNamedPipe(hInput,
-                              NULL,    // don't read anything yet
-                              0,       // no buffer
-                              NULL,    // no we don't read anything!
-                              &dwBytes,// now we're talking
-                              NULL);   // nono we don't read anything
-            if(!ret){
-                set_EOF_();
-                lpReadBuffer[0]='\0';
-                return 0;
-            }
-            if(dwBytes>0){
-                break;
-            }else{
-                Idle();
-            }
-            
-        }
-        ret=ReadFile(hInput,
-                     lpReadBuffer,
-                     LINE_INPUT_MAX_CHAR,
-                     &dwBytes,
-                     NULL);
-        if(!ret){
-            set_EOF_();
-            lpReadBuffer[0]='\0';
-            return 0;
-        }
+    char * ret;
+        // No protection. Access to nReadEnd is atomic.
+        // It is not a problem that nReadEnd becomes smaller after the call.
+        // This just means we have read less than we could have. 
+    ret=fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR-nReadEnd,fpInput);
+    if(!ret){
+        set_EOF_input();
+        lpReadBuffer[0]='\0';
+        return 0;
     }
+    dwBytes=strlen(lpReadBuffer);
     lpReadBuffer[dwBytes]='\0';
     return dwBytes;
 }
@@ -187,27 +172,45 @@ void PipeStruct::ReadInput(void) {
   DWORD dwBytes;
   int ret;
   BOOL bSetEvent=FALSE;
+      // ReadData is outside the critical section otherwise everything
+      // would block during the blocking read
   ret=ReadData();
   EnterCriticalSection(&CriticalSection);
-  if(!EOF_()){
+  if(!EOF_input()){
       if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
-          my_fatal("PipeStruct::ReadInput(): buffer overflow\n");
+          my_fatal("PipeStruct::ReadInput(): Internal error: buffer overflow\n");
       }
-      memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret);
+      memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret+1);
       nReadEnd += ret;
       if(!lpFeedEnd){
           lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
       }
       if(lpFeedEnd){
           bSetEvent=TRUE;
+      }else if(nReadEnd>=LINE_INPUT_MAX_CHAR-1){
+          my_fatal("PipeStruct::ReadInput(): LINE_INPUT_MAX_CHAR is equal to %d which is too small to contain a full line of engine output or GUI input.\n",LINE_INPUT_MAX_CHAR);
       }
   }
   LeaveCriticalSection(&CriticalSection);
-  if(EOF_() || bSetEvent){
+  if(EOF_input() || bSetEvent){
       SetEvent(hEvent);
   }
 }
 
+bool PipeStruct::EOF_(void){
+  int ret;
+  EnterCriticalSection(&CriticalSection);
+  if(lpFeedEnd != NULL){
+    ret=FALSE;
+  }else if(EOF_input()){
+    ret=TRUE;
+  }else{
+    ret=FALSE;
+  }
+  LeaveCriticalSection(&CriticalSection);
+  return ret;
+}
+
 bool PipeStruct::GetBuffer(char *szLineStr) {
   int nFeedEnd;
   int ret;
@@ -232,8 +235,10 @@ bool PipeStruct::GetBuffer(char *szLineStr) {
   return ret;
 }
 
+
+
 void PipeStruct::LineInput(char *szLineStr) {
-    while(!EOF_()){
+  while(!EOF_()){
         if (GetBuffer(szLineStr)) {
             break;
         }else{