Added input buffer in stdio_wrap.h to mimic command line behaviour. Added wait on output to avoid race condition with program termination.

This commit is contained in:
Xaver K 2020-04-03 13:48:32 +02:00
parent bddb7ca6b0
commit 3429b362ba
2 changed files with 71 additions and 10 deletions

View File

@ -72,8 +72,10 @@ class RealTimeSubprocess(subprocess.Popen):
if(len(contents) > 0):
self._write_to_stdout(contents)
readLine = self._read_from_stdin()
# need to add newline since it is not captured by frontend
readLine += "\n"
os.write(1, readLine.encode());
self.stdin.write(readLine.encode())
self.stdin.write(b"\n")
else:
self._write_to_stdout(contents)
@ -88,7 +90,7 @@ class CKernel(Kernel):
language = 'c'
language_version = 'C11'
language_info = {'name': 'text/x-csrc',
'mimetype': 'text/plain',
'mimetype': 'text/x-csrc',
'file_extension': '.c'}
banner = "C kernel.\n" \
"Uses gcc, compiles in C11, and creates source code files and executables in temporary folder.\n"
@ -188,10 +190,10 @@ class CKernel(Kernel):
# also add common magics like -lm
def _add_main(self, magics, code):
# remove comments
tmpCode = re.sub("//.*", "", code)
tmpCode = re.sub("/\*.*?\*/", "", tmpCode, flags=re.M|re.S)
tmpCode = re.sub(r"//.*", "", code)
tmpCode = re.sub(r"/\*.*?\*/", "", tmpCode, flags=re.M|re.S)
x = re.search("int\s+main\s*\(", tmpCode)
x = re.search(r"int\s+main\s*\(", tmpCode)
if not x:
code = self.main_head + code + self.main_foot
@ -234,6 +236,11 @@ class CKernel(Kernel):
p = self.create_jupyter_subprocess([self.master_path, binary_file.name] + magics['args'])
while p.poll() is None:
p.write_contents()
# wait for threads to finish, so output is always shown
p._stdout_thread.join()
p._stderr_thread.join()
p.write_contents()
# now remove the files we have just created

View File

@ -3,22 +3,76 @@
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
/* Need input buffer to know whether we need another input request */
char inputBuff[1<<10] = "";
/* read remaining input into buffer so it can be used in next call */
void readIntoBuffer() {
long length = strlen(inputBuff);
char nextChar = 0;
while((nextChar = getchar()) != '\n'){
inputBuff[length++] = nextChar;
}
inputBuff[length++] = '\n';
inputBuff[length] = '\0';
}
/* Define the functions to overload the old ones */
int scanf_wrap(const char *format, ...) {
printf("<inputRequest>");
fflush(stdout);
/* unget chars in buffer */
int doRequest = 1;
long index = strlen(inputBuff) - 1;
// printf("Start index: %ld\n", index);
for(; index >= 0; --index) {
ungetc(inputBuff[index], stdin);
/* if there already is a newline in buffer
we need no input request */
if(inputBuff[index] == '\n') {
doRequest = 0;
}
}
/* Buffer will always be empty after scanf call
since there is no way to enter more than one
newline in the frontend */
inputBuff[0] = '\0';
// printf("doRequest: %d\n", doRequest);
if(doRequest) {
printf("<inputRequest>");
fflush(stdout);
}
va_list arglist;
va_start( arglist, format );
int result = vscanf( format, arglist );
va_end( arglist );
return result;
}
int getchar_wrap(){
printf("<inputRequest>");
fflush(stdout);
return getchar();
/* check if there is still something in the input buffer*/
char input = 0;
long length = strlen(inputBuff);
if(length <= 0) {
printf("<inputRequest>");
fflush(stdout);
input = getchar();
readIntoBuffer();
} else {
input = inputBuff[0];
/* shift all chars one to the left */
int i = 1;
for(; i < 100; ++i){
inputBuff[i-1] = inputBuff[i];
if(inputBuff[i] == '\0') {
break;
}
}
}
return input;
}
/* Replace all the necessary input functions