Support for other standards than c11 (#3)

* Finished C89/C90/C95/C99 support. Version can only be switched in kernel or with magics. Might be worth having separate kernels for each standard.

* Added option to link maths library. On by default.

* Fixed empty input error. Now input loops until there is input with length > 0.
This commit is contained in:
Xaver K 2020-04-17 19:27:16 +02:00 committed by GitHub
parent f8e99ec24c
commit 8e97b754aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 27 deletions

View File

@ -10,9 +10,7 @@
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"metadata": {},
"outputs": [
{
"name": "stderr",
@ -32,6 +30,7 @@
"\n",
"int main() {\n",
" printf(\"Hello world\\n\");\n",
" return 0;\n",
"}"
]
},
@ -52,9 +51,7 @@
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"metadata": {},
"outputs": [
{
"name": "stderr",
@ -98,9 +95,7 @@
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"metadata": {},
"outputs": [
{
"name": "stderr",
@ -142,14 +137,14 @@
"kernelspec": {
"display_name": "C",
"language": "c",
"name": "c_kernel"
"name": "c"
},
"language_info": {
"file_extension": "c",
"file_extension": ".c",
"mimetype": "text/plain",
"name": "c"
"name": "text/x-c++src"
}
},
"nbformat": 4,
"nbformat_minor": 0
"nbformat_minor": 1
}

View File

@ -71,7 +71,9 @@ class RealTimeSubprocess(subprocess.Popen):
contents = contents.replace(self.__class__.inputRequest, '')
if(len(contents) > 0):
self._write_to_stdout(contents)
readLine = self._read_from_stdin()
readLine = ""
while(len(readLine) == 0):
readLine = self._read_from_stdin()
# need to add newline since it is not captured by frontend
readLine += "\n"
self.stdin.write(readLine.encode())
@ -104,6 +106,7 @@ class CKernel(Kernel):
super(CKernel, self).__init__(*args, **kwargs)
self._allow_stdin = True
self.readOnlyFileSystem = False
self.linkMaths = True # always link math library
self.wAll = True # show all warnings by default
self.wError = False # but keep comipiling for warnings
self.files = []
@ -148,7 +151,12 @@ class CKernel(Kernel):
self._read_from_stdin)
def compile_with_gcc(self, source_filename, binary_filename, cflags=None, ldflags=None):
cflags = ['-std=c11', '-fPIC', '-shared', '-rdynamic'] + cflags
# cflags = ['-std=c89', '-pedantic', '-fPIC', '-shared', '-rdynamic'] + cflags
# cflags = ['-std=iso9899:199409', '-pedantic', '-fPIC', '-shared', '-rdynamic'] + cflags
# cflags = ['-std=c99', '-pedantic', '-fPIC', '-shared', '-rdynamic'] + cflags
cflags = ['-std=c11', '-pedantic', '-fPIC', '-shared', '-rdynamic'] + cflags
if self.linkMaths:
cflags = cflags + ['-lm']
if self.wError:
cflags = cflags + ['-Werror']
if self.wAll:

View File

@ -5,8 +5,20 @@
#include <stdarg.h>
#include <string.h>
/* Figure out used C standard.
__STDC_VERSION__ is not always defined until C99.
If it is not defined, set standard to C89.
It is safest to set it by hand, to make sure */
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ <= 199409L
#define C89_SUPPORT
#endif /* __STDC_VERSION__ <= 199409L */
#else /* __STDC_VERSION__ */
#define C89_SUPPORT
#endif /* __STDC_VERSION__ */
/* Need input buffer to know whether we need another input request */
char inputBuff[1<<10] = "";
static char inputBuff[1<<10] = "";
/* read remaining input into buffer so it can be used in next call */
void readIntoBuffer() {
@ -19,8 +31,8 @@ void readIntoBuffer() {
inputBuff[length] = '\0';
}
/* Define the functions to overload the old ones */
int scanf_wrap(const char *format, ...) {
/* check whether input request is needed */
char checkInputRequest() {
/* unget chars in buffer */
char doRequest = 1;
char leadingNewline = 1;
@ -38,21 +50,49 @@ int scanf_wrap(const char *format, ...) {
}
}
return doRequest;
}
/* Define the functions to overload the old ones */
/* Wrapping of scanf depends on standard */
#ifdef C89_SUPPORT
/* Need to define vscanf for c89.
TODO: This is a bit risky, since the underlying glibc does not
have to include this if it is old. If it does not, linking will fail.
The only safe way is reimplementing the whole function. */
/* Read formatted input from stdin into argument list ARG.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int vscanf (const char *__restrict __format, _G_va_list __arg)
__attribute__ ((__format__ (__scanf__, 1, 0))) __wur;
#endif /* C89_SUPPORT */
int scanf_wrap(const char *format, ...) {
char doRequest = checkInputRequest();
if(doRequest) {
printf("<inputRequest>");
fflush(stdout);
}
va_list arglist;
va_start( arglist, format );
int result = vscanf( format, arglist );
va_end( arglist );
/* Put the remaining input into the input buffer */
readIntoBuffer();
{
va_list arglist;
int result;
va_start( arglist, format );
result = vscanf( format, arglist );
va_end( arglist );
return result;
/* Put the remaining input into the input buffer */
readIntoBuffer();
return result;
}
}
int getchar_wrap(){
/* check if there is still something in the input buffer*/
char input = 0;
@ -64,9 +104,10 @@ int getchar_wrap(){
input = getchar();
readIntoBuffer();
} else {
int i = 1;
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') {
@ -79,8 +120,15 @@ int getchar_wrap(){
}
/* Replace all the necessary input functions
Need double hashes in case there are no __VA_ARGS__*/
depending on the language version used */
#ifndef C89_SUPPORT
/* Need double hashes in case there are no __VA_ARGS__*/
#define scanf(format, ...) scanf_wrap(format, ##__VA_ARGS__)
#else /* C89_SUPPORT */
/* Since there are no variadic macros in C89, this is the only way
although it is horrible */
#define scanf scanf_wrap
#endif /* C89_SUPPORT */
#define getchar() getchar_wrap()