mirror of
https://github.com/XaverKlemenschits/jupyter-c-kernel.git
synced 2025-04-14 18:36:10 +00:00
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:
parent
f8e99ec24c
commit
8e97b754aa
@ -10,9 +10,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": 1,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stderr",
|
"name": "stderr",
|
||||||
@ -32,6 +30,7 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"int main() {\n",
|
"int main() {\n",
|
||||||
" printf(\"Hello world\\n\");\n",
|
" printf(\"Hello world\\n\");\n",
|
||||||
|
" return 0;\n",
|
||||||
"}"
|
"}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -52,9 +51,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stderr",
|
"name": "stderr",
|
||||||
@ -98,9 +95,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 3,
|
"execution_count": 3,
|
||||||
"metadata": {
|
"metadata": {},
|
||||||
"collapsed": false
|
|
||||||
},
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stderr",
|
"name": "stderr",
|
||||||
@ -142,14 +137,14 @@
|
|||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "C",
|
"display_name": "C",
|
||||||
"language": "c",
|
"language": "c",
|
||||||
"name": "c_kernel"
|
"name": "c"
|
||||||
},
|
},
|
||||||
"language_info": {
|
"language_info": {
|
||||||
"file_extension": "c",
|
"file_extension": ".c",
|
||||||
"mimetype": "text/plain",
|
"mimetype": "text/plain",
|
||||||
"name": "c"
|
"name": "text/x-c++src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
"nbformat_minor": 0
|
"nbformat_minor": 1
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,9 @@ class RealTimeSubprocess(subprocess.Popen):
|
|||||||
contents = contents.replace(self.__class__.inputRequest, '')
|
contents = contents.replace(self.__class__.inputRequest, '')
|
||||||
if(len(contents) > 0):
|
if(len(contents) > 0):
|
||||||
self._write_to_stdout(contents)
|
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
|
# need to add newline since it is not captured by frontend
|
||||||
readLine += "\n"
|
readLine += "\n"
|
||||||
self.stdin.write(readLine.encode())
|
self.stdin.write(readLine.encode())
|
||||||
@ -104,6 +106,7 @@ class CKernel(Kernel):
|
|||||||
super(CKernel, self).__init__(*args, **kwargs)
|
super(CKernel, self).__init__(*args, **kwargs)
|
||||||
self._allow_stdin = True
|
self._allow_stdin = True
|
||||||
self.readOnlyFileSystem = False
|
self.readOnlyFileSystem = False
|
||||||
|
self.linkMaths = True # always link math library
|
||||||
self.wAll = True # show all warnings by default
|
self.wAll = True # show all warnings by default
|
||||||
self.wError = False # but keep comipiling for warnings
|
self.wError = False # but keep comipiling for warnings
|
||||||
self.files = []
|
self.files = []
|
||||||
@ -148,7 +151,12 @@ class CKernel(Kernel):
|
|||||||
self._read_from_stdin)
|
self._read_from_stdin)
|
||||||
|
|
||||||
def compile_with_gcc(self, source_filename, binary_filename, cflags=None, ldflags=None):
|
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:
|
if self.wError:
|
||||||
cflags = cflags + ['-Werror']
|
cflags = cflags + ['-Werror']
|
||||||
if self.wAll:
|
if self.wAll:
|
||||||
|
@ -5,8 +5,20 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.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 */
|
/* 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 */
|
/* read remaining input into buffer so it can be used in next call */
|
||||||
void readIntoBuffer() {
|
void readIntoBuffer() {
|
||||||
@ -19,8 +31,8 @@ void readIntoBuffer() {
|
|||||||
inputBuff[length] = '\0';
|
inputBuff[length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define the functions to overload the old ones */
|
/* check whether input request is needed */
|
||||||
int scanf_wrap(const char *format, ...) {
|
char checkInputRequest() {
|
||||||
/* unget chars in buffer */
|
/* unget chars in buffer */
|
||||||
char doRequest = 1;
|
char doRequest = 1;
|
||||||
char leadingNewline = 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) {
|
if(doRequest) {
|
||||||
printf("<inputRequest>");
|
printf("<inputRequest>");
|
||||||
fflush(stdout);
|
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(){
|
int getchar_wrap(){
|
||||||
/* check if there is still something in the input buffer*/
|
/* check if there is still something in the input buffer*/
|
||||||
char input = 0;
|
char input = 0;
|
||||||
@ -64,9 +104,10 @@ int getchar_wrap(){
|
|||||||
input = getchar();
|
input = getchar();
|
||||||
readIntoBuffer();
|
readIntoBuffer();
|
||||||
} else {
|
} else {
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
input = inputBuff[0];
|
input = inputBuff[0];
|
||||||
/* shift all chars one to the left */
|
/* shift all chars one to the left */
|
||||||
int i = 1;
|
|
||||||
for(; i < 100; ++i){
|
for(; i < 100; ++i){
|
||||||
inputBuff[i-1] = inputBuff[i];
|
inputBuff[i-1] = inputBuff[i];
|
||||||
if(inputBuff[i] == '\0') {
|
if(inputBuff[i] == '\0') {
|
||||||
@ -79,8 +120,15 @@ int getchar_wrap(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Replace all the necessary input functions
|
/* 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__)
|
#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()
|
#define getchar() getchar_wrap()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user