Add forgotten files 1.4.70b
[polyglot.git] / pipe.cpp
index 163e591..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,21 +73,35 @@ 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);
     hEvent=CreateEvent(NULL,           // default security
                        FALSE,          // auto reset
                        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();
 }
 
@@ -103,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;
@@ -111,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);
@@ -131,106 +151,70 @@ void PipeStruct::set_Active(void){
     LeaveCriticalSection(&CriticalSection);
 }
 
-
-
-int PipeStruct::ReadLine(void){
+int PipeStruct::ReadData(void){
     DWORD dwBytes;
-    int ret;
-    int start=0;
-    int start1;    
-    
-    if(!bPipe){
-        fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,stdin);
-        start=strlen(lpReadBuffer);
-        if(!start){
-            set_EOF_();
-            lpReadBuffer[0]='\0';
-        }
-        return start;
-    }else{
-        while(TRUE){
-                // 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+start,
-                         LINE_INPUT_MAX_CHAR-start,
-                         &dwBytes,
-                         NULL);
-            if(!ret){
-                set_EOF_();
-                lpReadBuffer[0]='\0';
-                return 0;
-            }else{
-                start1=start;
-                start+=dwBytes;
-                if (memchr(lpReadBuffer+start1, '\n', dwBytes)){
-                    lpReadBuffer[start]='\0';
-                    return start;
-                }
-            }
-        }
+    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;
 }
 
 void PipeStruct::ReadInput(void) {
   DWORD dwBytes;
   int ret;
-  ret=ReadLine();
+  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);
-  SetEvent(hEvent);
+  if(EOF_input() || bSetEvent){
+      SetEvent(hEvent);
+  }
 }
 
-void PipeStruct::LineOutput(const char *szLineStr) const {
-  DWORD dwBytes;
-  int nStrLen;
-  char szWriteBuffer[LINE_INPUT_MAX_CHAR];
-  if(bPipe){
-      nStrLen = strlen(szLineStr);
-      memcpy(szWriteBuffer, szLineStr, nStrLen);
-      szWriteBuffer[nStrLen] = '\r';
-      szWriteBuffer[nStrLen + 1] = '\n';
-      WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+bool PipeStruct::EOF_(void){
+  int ret;
+  EnterCriticalSection(&CriticalSection);
+  if(lpFeedEnd != NULL){
+    ret=FALSE;
+  }else if(EOF_input()){
+    ret=TRUE;
   }else{
-      printf("%s\n",szLineStr);
-      fflush(stdout);
+    ret=FALSE;
   }
+  LeaveCriticalSection(&CriticalSection);
+  return ret;
 }
 
 bool PipeStruct::GetBuffer(char *szLineStr) {
-  char *lpFeedEnd;
   int nFeedEnd;
   int ret;
   EnterCriticalSection(&CriticalSection);
-  lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
   if (lpFeedEnd == NULL) {
     ret=FALSE;
   } else {
@@ -244,14 +228,17 @@ bool PipeStruct::GetBuffer(char *szLineStr) {
     nFeedEnd ++;
     nReadEnd -= nFeedEnd;
     memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
+    lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
     ret=TRUE;
   }
   LeaveCriticalSection(&CriticalSection);
   return ret;
 }
 
+
+
 void PipeStruct::LineInput(char *szLineStr) {
-    while(!EOF_()){
+  while(!EOF_()){
         if (GetBuffer(szLineStr)) {
             break;
         }else{
@@ -259,4 +246,20 @@ void PipeStruct::LineInput(char *szLineStr) {
         }
     }
 }
+
+void PipeStruct::LineOutput(const char *szLineStr) const {
+  DWORD dwBytes;
+  int nStrLen;
+  char szWriteBuffer[LINE_INPUT_MAX_CHAR];
+  if(bPipe){
+      nStrLen = strlen(szLineStr);
+      memcpy(szWriteBuffer, szLineStr, nStrLen);
+      szWriteBuffer[nStrLen] = '\r';
+      szWriteBuffer[nStrLen + 1] = '\n';
+      WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+  }else{
+      printf("%s\n",szLineStr);
+      fflush(stdout);
+  }
+}
 #endif