From 31bbb6f6e10b5d584f5dc3fc6e0b9ee4bb8469a0 Mon Sep 17 00:00:00 2001 From: Quinten Date: Thu, 22 Jan 2026 16:55:33 +0100 Subject: [PATCH 1/8] Remove refcounting from the File module and move all the implementations into one file. --- CMakeLists.txt | 9 ++ src/CMakeLists.txt | 25 ++---- src/stdio/File.sac | 90 ++++++++++++-------- src/stdio/src/File/File.c | 169 ++++++++++++++++++++++++++++++++++++++ src/stdio/src/File/File.h | 29 +++++-- src/structures/String.sac | 1 + 6 files changed, 262 insertions(+), 61 deletions(-) create mode 100644 src/stdio/src/File/File.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fb06ae6..9742625c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,3 +69,12 @@ SET (PROJECT_MINOR_VERSION) SET (PROJECT_PATCH_VERSION) GET_PROJECT_VERSION (PROJECT_SHORT_VERSION PROJECT_MAJOR_VERSION PROJECT_MINOR_VERSION PROJECT_PATCH_VERSION) INCLUDE ("${PROJECT_SOURCE_DIR}/cmake/cpack.cmake") + +add_library(QUINTEN1 STATIC + src/stdio/src/File/File.c + src/stdio/src/File/File.h # List for CLion visibility +) + +target_include_directories(QUINTEN1 PRIVATE + /home/qc/Projecten/sac2c/include +) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5b895ec9..623d7eb5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -270,23 +270,7 @@ SET (C_DEPS_SRC stdio/src/TermFile/fscanl.c stdio/src/TermFile/fprintf.c stdio/src/File/rm.c - stdio/src/File/mkstemp.c - stdio/src/File/fscans.c - stdio/src/File/fscanl.c - stdio/src/File/fscanf.c - stdio/src/File/fprintf.c - stdio/src/File/fopen.c - stdio/src/File/fputc.c - stdio/src/File/fgetc.c - stdio/src/File/fputs.c - stdio/src/File/fgets.c - stdio/src/File/ungetc.c - stdio/src/File/fflush.c - stdio/src/File/feof.c - stdio/src/File/rewind.c - stdio/src/File/fseek.c - stdio/src/File/ftell.c - stdio/src/File/fclose.c + stdio/src/File/File.c stdio/src/FibreIO/ScanStringArr.c stdio/src/FibreIO/ScanString.c stdio/src/FibreIO/ScanOthersArr.c @@ -346,8 +330,8 @@ MESSAGE (DEBUG "Compiled together all source paths: ${ALL_SAC_SRC}") # core modules or core + extended modules are built. ADD_CUSTOM_TARGET (${TARGET}-all-modules ALL) -# TODO(artem) We may want to introduce a mechanism of generating depenencies -# on a given sac2c versoin. That is, recompiler all modules if +# TODO(artem) We may want to introduce a mechanism of generating dependencies +# on a given sac2c version. That is, recompiler all modules if # sac2c version changes. @@ -439,6 +423,7 @@ FOREACH (name ${SAC_SRC}) # of the call to sac2c. GET_FILENAME_COMPONENT (dir "${CMAKE_CURRENT_BINARY_DIR}/${name}" DIRECTORY) GET_FILENAME_COMPONENT (dst ${name} NAME_WE) + GET_FILENAME_COMPONENT (src_dir "${src}" DIRECTORY) SET (mod "${DLL_BUILD_DIR}/${TARGET_ENV}/${SBI}/lib${dst}Mod${VARIANT}${MODEXT}") SET (tree @@ -477,7 +462,7 @@ FOREACH (name ${SAC_SRC}) ADD_CUSTOM_COMMAND ( OUTPUT "${mod}" "${tree}" COMMAND - ${SAC2C} -v0 -maxoptcyc 2 -linksetsize ${LINKSETSIZE} ${NOTREE_FLAG} ${SAC2C_CC_FLAGS} -o ${DLL_BUILD_DIR} "${src}" + ${SAC2C} -v0 -maxoptcyc 2 -linksetsize ${LINKSETSIZE} ${NOTREE_FLAG} ${SAC2C_CC_FLAGS} -Xc -I"${src_dir}" -o ${DLL_BUILD_DIR} "${src}" WORKING_DIRECTORY "${dir}" MAIN_DEPENDENCY "${src}" diff --git a/src/stdio/File.sac b/src/stdio/File.sac index c453a934..e197fdf6 100644 --- a/src/stdio/File.sac +++ b/src/stdio/File.sac @@ -2,6 +2,7 @@ class File; external classtype; + #pragma ctype "FILE*" use Array: all; use String: { string, strsel, strlen, strtake, strcat }; @@ -18,7 +19,8 @@ export all; external syserr, File fopen(string NAME, string MODE); #pragma effect TheFileSystem - #pragma linkobj "src/File/fopen.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfopen" #pragma linksign [0,1,2,3] /* @@ -28,12 +30,22 @@ external syserr, File fopen(string NAME, string MODE); * using the file handle. */ +external syserr fclose(File STREAM); + #pragma effect TheFileSystem + #pragma linkobj "src/File/File.o" + #pragma linkname "SACfclose" + #pragma header "src/File/File.h" + /* + * Close the stream given by the file handle STREAM. + */ + + external syserr, File, string mkstemp(string template); #pragma effect TheFileSystem - #pragma linkobj "src/File/mkstemp.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACmkstemp" - #pragma linksign [0,1,2,3] - #pragma refcounting [2] + #pragma linksign [0,1,2,2] /* * Create a temporary file using a name generated by the function * mkstemp, and returns the corresponding file handle. The file is @@ -60,17 +72,10 @@ syserr, File, string tmpfile() * using the file handle. */ -external void fclose(File STREAM); +external syserr fremove(string fname); #pragma effect TheFileSystem - #pragma linkobj "src/File/fclose.o" - #pragma linkname "SACfclose" - /* - * Close the stream given by the file handle STREAM. - */ - -external void fremove(string fname); - #pragma effect TheFileSystem - #pragma linkobj "src/File/rm.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" /* * Remove file or directory. */ @@ -81,23 +86,25 @@ external void fremove(string fname); * ******************************************************************************/ -external void fputc(char C, File &STREAM); - #pragma linkobj "src/File/fputc.o" +external syserr fputc(char C, File &STREAM); + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfputc" /* * Write the character C to the output stream STREAM. */ external char fgetc(File &STREAM); - #pragma linkobj "src/File/fgetc.o" - #pragma linkname "SACfgetc" #pragma linksign [0,1] + #pragma header "src/File/File.h" + #pragma linkname "SACfgetc" /* * Get the next character from the input stream STREAM. */ -external void ungetc(char C, File &STREAM); - #pragma linkobj "src/File/ungetc.o" +external syserr ungetc(char C, File &STREAM); + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACungetc" /* * Put the character C back to the input stream STREAM for further @@ -106,17 +113,20 @@ external void ungetc(char C, File &STREAM); * is overwritten. */ -external void fputs(string S, File &STREAM); - #pragma linkobj "src/File/fputs.o" +external syserr fputs(string S, File &STREAM); + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfputs" /* * Write string S to stream. */ external syserr, string fgets (int size, File &STREAM); - #pragma linkname "SACfgets_F" - #pragma linkobj "src/File/fgets.o" + #pragma linkname "SACfgets" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linksign [0,1,2,3] + #pragma sacarg [1] /* * Read a string of max. length size from the provided TermFile. */ @@ -142,7 +152,8 @@ syserr, string fgetl (File &stream) ******************************************************************************/ external void fprintf(File &STREAM, string FORMAT, ...); - #pragma linkobj "src/File/fprintf.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfprintf" /* * Print formatted output to STREAM which must be open for writing. @@ -152,7 +163,8 @@ external void fprintf(File &STREAM, string FORMAT, ...); */ external int, ... fscanf(File &STREAM, string FORMAT); - #pragma linkobj "src/File/fscanf.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfscanf" #pragma linksign [0,1,2] /* @@ -167,7 +179,8 @@ external int, ... fscanf(File &STREAM, string FORMAT); */ external string fscans(File &STREAM, int MAX); - #pragma linkobj "src/File/fscans.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linksign [0,1,2] /* * Read the next character string from the input stream STREAM. Strings @@ -177,7 +190,8 @@ external string fscans(File &STREAM, int MAX); */ external string fscanl(File &STREAM, int MAX); - #pragma linkobj "src/File/fscanl.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linksign [0,1,2] /* * Read the next line from the input stream STREAM. Lines are character @@ -193,23 +207,27 @@ external string fscanl(File &STREAM, int MAX); ******************************************************************************/ external bool feof(File &STREAM); - #pragma linkobj "src/File/feof.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfeof" #pragma linksign [0,1] /* * Test the stream STREAM for having reached the end of the respective file. */ -external void fflush(File &STREAM); - #pragma linkobj "src/File/fflush.o" +external int fflush(File &STREAM); + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfflush" + #pragma linksign [0,1] /* * Write the buffer of a buffered output stream STREAM * to the respective file. */ -external void fseek(File &STREAM, int OFFSET, int BASE); - #pragma linkobj "src/File/fseek.o" +external int fseek(File &STREAM, int OFFSET, int BASE); + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACfseek" /* * Reposition the stream STREAM. The new position is given as an offset @@ -218,7 +236,8 @@ external void fseek(File &STREAM, int OFFSET, int BASE); */ external int ftell(File &STREAM); - #pragma linkobj "src/File/ftell.o" + #pragma linkobj "src/File/File.o" + #pragma header "src/File/File.h" #pragma linkname "SACftell" #pragma linksign [0,1] /* @@ -227,8 +246,7 @@ external int ftell(File &STREAM); */ external void rewind(File &STREAM); - #pragma linkobj "src/File/rewind.o" - #pragma linkname "SACrewind" + #pragma header "" /* * Reposition the stream STREAM to the beginning of the file associated * with it (identical to fseek(, 0, 0)). diff --git a/src/stdio/src/File/File.c b/src/stdio/src/File/File.c new file mode 100644 index 00000000..fd37122b --- /dev/null +++ b/src/stdio/src/File/File.c @@ -0,0 +1,169 @@ +#include "File.h" +#include +#include +#include +#include +#include +#include + +#include "sacinterface.h" + + +sac_int SACfopen(File *f, string name, string mode) +{ + *f = fopen(name, mode); + + bool is_error = *f==NULL; + int error = is_error ? errno : -1; + + return error; +} + +sac_int SACfclose(File f) +{ + return fclose(f); +} + +sac_int SACmkstemp(File* f_out, string template) +{ + int filedesc = mkstemp (template); + + bool is_error = filedesc == -1; + if (is_error) { + return EIO; + } + + // Actually open the file for reading + *f_out = fdopen(filedesc, "w+"); + + is_error = *f_out == NULL; + if (is_error) { + return errno; + } + + return EXIT_SUCCESS; +} + +sac_int SACremove(string name) +{ + int code = remove(name); + + bool is_error = code == -1; + if (is_error) + return errno; + else + return code; +} + + +sac_int SACfputc(unsigned char c, File f) +{ + return fputc(c, f); +} + +unsigned char SACfgetc(File stream) +{ + return fgetc(stream); +} + +sac_int SACungetc(unsigned char c, File f) +{ + return ungetc(c, f); +} + +sac_int SACfputs(char *s, FILE *f) +{ + return fputs( s, f); +} + +SAC_C_EXTERN SACtypes *SACTYPE_String__string; + +sac_int SACfgets(SACarg **str, sac_int size, File f) +{ + string buf = malloc (sizeof(char) * size); + + bool malloc_fail = buf == NULL; + if (malloc_fail) { + free (buf); + return ENOMEM; + } + + char* result = fgets (buf, size, f); + bool fgets_fail = result == NULL; + if (fgets_fail) { + free (buf); + return errno; + } + + size_t written = strlen (buf) + sizeof ('\0'); + *str = SACARGcreateFromPointer (SACTYPE_String__string, buf, 1, written); + + return -1; +} + +void SACfprintf(File f, string format, ...) { + va_list args; + + va_start(args, format); + vfprintf( f, format, args); + va_end(args); +} + +sac_int SACfscanf(File f, char *format, ...) +{ + va_list args; + va_start(args, format); + const sac_int ret = vfscanf(f, format, args); + va_end(args); + + return ret; +} + +string SACfscans(File stream, sac_int length) +{ + char format[32]; + + string input = malloc(length + 1); + snprintf(format, sizeof format, " %%%"PRIisac"s", length); + + int success = fscanf(stream, format, input); + if (success != 1) { + input[0] = 0; + } + + return input; +} + +string fscanl(File stream, const sac_int max) +{ + char *input, *success; + + input = malloc(max+3); + success = fgets(input, max+1, stream); + + if (success == NULL) { + input[0]=0; + } + + return input; +} + +bool SACfeof(const File f) +{ + return feof( f); +} + +sac_int SACflush(const File f) +{ + return feof( f); +} + +sac_int SACfseek(File f, const sac_int offset, const sac_int base) +{ + return fseek(f, offset, base); +} + +sac_int SACftell(const File f) +{ + return ftell(f); +} diff --git a/src/stdio/src/File/File.h b/src/stdio/src/File/File.h index ca339466..47492257 100644 --- a/src/stdio/src/File/File.h +++ b/src/stdio/src/File/File.h @@ -5,12 +5,31 @@ */ +#include #include -#include -#include -#include -#include -#include "sac.h" +#include "sacinterface.h" + +typedef char* string; +typedef FILE* File; + +sac_int SACfopen(File* f, string name, string mode); +sac_int SACfclose(File f); +sac_int SACmkstemp(File* f_out, string template); +sac_int SACremove(string name); +sac_int SACfputc(unsigned char C, File f); +unsigned char SACfgetc(File f); +sac_int SACungetc(unsigned char c, File f); +sac_int SACfputs(string s, File f); +sac_int SACfgets(SACarg **str, sac_int size, File f); +void SACfprintf(File f, string format, ...); +sac_int SACfscanf(File f, string format, ...); +string SACfscans(File f, sac_int max); +string fscanl(File f, sac_int max); +bool SACfeof(File f); +sac_int SACflush(File f); +sac_int SACfseek(File f, sac_int offset, sac_int base); +sac_int SACftell(File f); +sac_int SACrewind(File f); #endif /* _STDLIB_FILE_H_ */ diff --git a/src/structures/String.sac b/src/structures/String.sac index 7167ebfe..ad79c9d8 100644 --- a/src/structures/String.sac +++ b/src/structures/String.sac @@ -15,6 +15,7 @@ external typedef string; #pragma linkobj "src/String/freestr.o" #pragma copyfun "copy_string" #pragma linkobj "src/String/copystr.o" + #pragma ctype "char*" external string to_string(char[.] A, int LENGTH); #pragma linksign [1,2,3] From 6f30bd0bd2c78a8804a8d5a7c24684d094e55f52 Mon Sep 17 00:00:00 2001 From: Quinten Date: Thu, 22 Jan 2026 17:31:18 +0100 Subject: [PATCH 2/8] Remove refcounting from the File module and move all the implementations into one file. --- CMakeLists.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9742625c..3fb06ae6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,12 +69,3 @@ SET (PROJECT_MINOR_VERSION) SET (PROJECT_PATCH_VERSION) GET_PROJECT_VERSION (PROJECT_SHORT_VERSION PROJECT_MAJOR_VERSION PROJECT_MINOR_VERSION PROJECT_PATCH_VERSION) INCLUDE ("${PROJECT_SOURCE_DIR}/cmake/cpack.cmake") - -add_library(QUINTEN1 STATIC - src/stdio/src/File/File.c - src/stdio/src/File/File.h # List for CLion visibility -) - -target_include_directories(QUINTEN1 PRIVATE - /home/qc/Projecten/sac2c/include -) \ No newline at end of file From a4922f5f604a0d460bb7e00c330a0cc1e57caaec Mon Sep 17 00:00:00 2001 From: Quinten Date: Thu, 22 Jan 2026 17:35:38 +0100 Subject: [PATCH 3/8] Remove unneeded linksign pragma --- src/stdio/File.sac | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/stdio/File.sac b/src/stdio/File.sac index e197fdf6..3ab7dfc4 100644 --- a/src/stdio/File.sac +++ b/src/stdio/File.sac @@ -181,7 +181,6 @@ external int, ... fscanf(File &STREAM, string FORMAT); external string fscans(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" #pragma header "src/File/File.h" - #pragma linksign [0,1,2] /* * Read the next character string from the input stream STREAM. Strings * are delimited by any whitespace character including the @@ -192,7 +191,6 @@ external string fscans(File &STREAM, int MAX); external string fscanl(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" #pragma header "src/File/File.h" - #pragma linksign [0,1,2] /* * Read the next line from the input stream STREAM. Lines are character * strings delimited by any new-line or end-of-file symbol. @@ -210,7 +208,6 @@ external bool feof(File &STREAM); #pragma linkobj "src/File/File.o" #pragma header "src/File/File.h" #pragma linkname "SACfeof" - #pragma linksign [0,1] /* * Test the stream STREAM for having reached the end of the respective file. */ @@ -219,7 +216,6 @@ external int fflush(File &STREAM); #pragma linkobj "src/File/File.o" #pragma header "src/File/File.h" #pragma linkname "SACfflush" - #pragma linksign [0,1] /* * Write the buffer of a buffered output stream STREAM * to the respective file. @@ -239,7 +235,6 @@ external int ftell(File &STREAM); #pragma linkobj "src/File/File.o" #pragma header "src/File/File.h" #pragma linkname "SACftell" - #pragma linksign [0,1] /* * Return the offset of the current byte relative to * the beginning of the file associated with STREAM. From aa24e7bd27bd5e0f48a49a472c72c93adfe0fad8 Mon Sep 17 00:00:00 2001 From: Quinten Date: Thu, 22 Jan 2026 22:50:06 +0100 Subject: [PATCH 4/8] Remove the fix for the header pragma to unfix it because we have to fix it better later --- src/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 623d7eb5..c7b7478b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -423,7 +423,6 @@ FOREACH (name ${SAC_SRC}) # of the call to sac2c. GET_FILENAME_COMPONENT (dir "${CMAKE_CURRENT_BINARY_DIR}/${name}" DIRECTORY) GET_FILENAME_COMPONENT (dst ${name} NAME_WE) - GET_FILENAME_COMPONENT (src_dir "${src}" DIRECTORY) SET (mod "${DLL_BUILD_DIR}/${TARGET_ENV}/${SBI}/lib${dst}Mod${VARIANT}${MODEXT}") SET (tree @@ -462,7 +461,7 @@ FOREACH (name ${SAC_SRC}) ADD_CUSTOM_COMMAND ( OUTPUT "${mod}" "${tree}" COMMAND - ${SAC2C} -v0 -maxoptcyc 2 -linksetsize ${LINKSETSIZE} ${NOTREE_FLAG} ${SAC2C_CC_FLAGS} -Xc -I"${src_dir}" -o ${DLL_BUILD_DIR} "${src}" + ${SAC2C} -v0 -maxoptcyc 2 -linksetsize ${LINKSETSIZE} ${NOTREE_FLAG} ${SAC2C_CC_FLAGS} -o ${DLL_BUILD_DIR} "${src}" WORKING_DIRECTORY "${dir}" MAIN_DEPENDENCY "${src}" From 2bd8d40a173d472e826d5d4bcb737b6c4a93291c Mon Sep 17 00:00:00 2001 From: Quinten Date: Thu, 22 Jan 2026 22:51:19 +0100 Subject: [PATCH 5/8] Comment out #pragma header in File.sac --- src/stdio/File.sac | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/stdio/File.sac b/src/stdio/File.sac index 3ab7dfc4..7c57719d 100644 --- a/src/stdio/File.sac +++ b/src/stdio/File.sac @@ -20,7 +20,7 @@ export all; external syserr, File fopen(string NAME, string MODE); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfopen" #pragma linksign [0,1,2,3] /* @@ -34,7 +34,7 @@ external syserr fclose(File STREAM); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" #pragma linkname "SACfclose" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" /* * Close the stream given by the file handle STREAM. */ @@ -43,7 +43,7 @@ external syserr fclose(File STREAM); external syserr, File, string mkstemp(string template); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACmkstemp" #pragma linksign [0,1,2,2] /* @@ -75,7 +75,7 @@ syserr, File, string tmpfile() external syserr fremove(string fname); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" /* * Remove file or directory. */ @@ -88,7 +88,7 @@ external syserr fremove(string fname); external syserr fputc(char C, File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfputc" /* * Write the character C to the output stream STREAM. @@ -96,7 +96,7 @@ external syserr fputc(char C, File &STREAM); external char fgetc(File &STREAM); #pragma linksign [0,1] - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfgetc" /* * Get the next character from the input stream STREAM. @@ -104,7 +104,7 @@ external char fgetc(File &STREAM); external syserr ungetc(char C, File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACungetc" /* * Put the character C back to the input stream STREAM for further @@ -115,7 +115,7 @@ external syserr ungetc(char C, File &STREAM); external syserr fputs(string S, File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfputs" /* * Write string S to stream. @@ -124,7 +124,7 @@ external syserr fputs(string S, File &STREAM); external syserr, string fgets (int size, File &STREAM); #pragma linkname "SACfgets" #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linksign [0,1,2,3] #pragma sacarg [1] /* @@ -153,7 +153,7 @@ syserr, string fgetl (File &stream) external void fprintf(File &STREAM, string FORMAT, ...); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfprintf" /* * Print formatted output to STREAM which must be open for writing. @@ -164,7 +164,7 @@ external void fprintf(File &STREAM, string FORMAT, ...); external int, ... fscanf(File &STREAM, string FORMAT); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfscanf" #pragma linksign [0,1,2] /* @@ -180,7 +180,7 @@ external int, ... fscanf(File &STREAM, string FORMAT); external string fscans(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" /* * Read the next character string from the input stream STREAM. Strings * are delimited by any whitespace character including the @@ -190,7 +190,7 @@ external string fscans(File &STREAM, int MAX); external string fscanl(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" /* * Read the next line from the input stream STREAM. Lines are character * strings delimited by any new-line or end-of-file symbol. @@ -206,7 +206,7 @@ external string fscanl(File &STREAM, int MAX); external bool feof(File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfeof" /* * Test the stream STREAM for having reached the end of the respective file. @@ -214,7 +214,7 @@ external bool feof(File &STREAM); external int fflush(File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfflush" /* * Write the buffer of a buffered output stream STREAM @@ -223,7 +223,7 @@ external int fflush(File &STREAM); external int fseek(File &STREAM, int OFFSET, int BASE); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACfseek" /* * Reposition the stream STREAM. The new position is given as an offset @@ -233,7 +233,7 @@ external int fseek(File &STREAM, int OFFSET, int BASE); external int ftell(File &STREAM); #pragma linkobj "src/File/File.o" - #pragma header "src/File/File.h" + // #pragma header "src/File/File.h" #pragma linkname "SACftell" /* * Return the offset of the current byte relative to From 595b47005392235d9f5431a48b20fc3d856f890c Mon Sep 17 00:00:00 2001 From: Jordy Aaldering <33897257+JordyAaldering@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:33:58 +0100 Subject: [PATCH 6/8] FFI was updated, not expects an array instead of varargs I did this through the web interface, I hope this works lol --- src/stdio/src/File/File.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stdio/src/File/File.c b/src/stdio/src/File/File.c index fd37122b..0323e18e 100644 --- a/src/stdio/src/File/File.c +++ b/src/stdio/src/File/File.c @@ -96,7 +96,8 @@ sac_int SACfgets(SACarg **str, sac_int size, File f) } size_t written = strlen (buf) + sizeof ('\0'); - *str = SACARGcreateFromPointer (SACTYPE_String__string, buf, 1, written); + sac_int shp[] = { (sac_int)written }; + *str = SACARGcreateFromPointer (SACTYPE_String__string, buf, 1, shp); return -1; } From 9bbded16c3c583d4d8ccaee22a190b0612833453 Mon Sep 17 00:00:00 2001 From: Quinten Cabo Date: Sat, 24 Jan 2026 08:23:37 +0100 Subject: [PATCH 7/8] Add overloaded versions of functions that used to return void. This way we stay backwards compatible, and we have the best of both words. Programmers can get the status code of operations if they want too, but they are not forced to assign the result of the operations because a void version does exist. --- src/stdio/File.sac | 218 ++++++++++++++++++++++++++------------------- 1 file changed, 125 insertions(+), 93 deletions(-) diff --git a/src/stdio/File.sac b/src/stdio/File.sac index 7c57719d..4c5edd26 100644 --- a/src/stdio/File.sac +++ b/src/stdio/File.sac @@ -16,83 +16,97 @@ export all; * Functions to open and close files. * ******************************************************************************/ - +/* + * Open the file NAME in mode MODE. The modes supported are identical + * to the C version of this function. An error condition and a file + * handle are returned. You should inspect the error condition before + * using the file handle. + */ external syserr, File fopen(string NAME, string MODE); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfopen" #pragma linksign [0,1,2,3] - /* - * Open the file NAME in mode MODE. The modes supported are identical - * to the C version of this function. An error condition and a file - * handle are returned. You should inspect the error condition before - * using the file handle. - */ +/* + * Close the stream given by the file handle STREAM. + */ external syserr fclose(File STREAM); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" #pragma linkname "SACfclose" // #pragma header "src/File/File.h" - /* - * Close the stream given by the file handle STREAM. - */ +/* Overloaded version that ignores the return code */ +void fclose(File STREAM) { + ignore = fclose(STREAM); +} +/* + * Create a temporary file using a name generated by the function + * mkstemp, and returns the corresponding file handle. The file is + * opened for update ("w+"). An error condition is + * returned as well. You should inspect the error condition before + * using the file handle. + * The name of the resulting file is derived from the template + * argument. It should look like a file name with six trailing 'X's. + * Each X is then replaced by a character from the portable file + * name character set. The characters are chosen such that the + * resulting name does not duplicate the name of an existing file. + */ external syserr, File, string mkstemp(string template); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACmkstemp" #pragma linksign [0,1,2,2] - /* - * Create a temporary file using a name generated by the function - * mkstemp, and returns the corresponding file handle. The file is - * opened for update ("w+"). An error condition is - * returned as well. You should inspect the error condition before - * using the file handle. - * The name of the resulting file is derived from the template - * argument. It should look like a file name with six trailing 'X's. - * Each X is then replaced by a character from the portable file - * name character set. The characters are chosen such that the - * resulting name does not duplicate the name of an existing file. - */ + +/* + * Create a temporary file using a name generated by the function + * mkstemp, and returns the corresponding file handle. The file is + * opened for update ("w+"). An error condition is + * returned as well. You should inspect the error condition before + * using the file handle. + */ syserr, File, string tmpfile() { err, file, name = mkstemp("TMP_XXXXXX"); return(err, file, name); } - /* - * Create a temporary file using a name generated by the function - * mkstemp, and returns the corresponding file handle. The file is - * opened for update ("w+"). An error condition is - * returned as well. You should inspect the error condition before - * using the file handle. - */ +/* + * Remove file or directory. + */ external syserr fremove(string fname); #pragma effect TheFileSystem #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" - /* - * Remove file or directory. - */ -/****************************************************************************** +void fremove(string fname) { + unused = fremove(fname); +} + + + + /****************************************************************************** * * Functions for low-level input / output operations. * ******************************************************************************/ +/* + * Write the character C to the output stream STREAM. + */ external syserr fputc(char C, File &STREAM); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfputc" - /* - * Write the character C to the output stream STREAM. - */ + +void fputc(char C, File &STREAM) { + unused = fputc(C, STREAM); +}; external char fgetc(File &STREAM); #pragma linksign [0,1] @@ -102,34 +116,42 @@ external char fgetc(File &STREAM); * Get the next character from the input stream STREAM. */ +/* + * Put the character C back to the input stream STREAM for further + * read operations. Only one character may be put back between two + * consecutive read operations, otherwise the character put back first + * is overwritten. + */ external syserr ungetc(char C, File &STREAM); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACungetc" - /* - * Put the character C back to the input stream STREAM for further - * read operations. Only one character may be put back between two - * consecutive read operations, otherwise the character put back first - * is overwritten. - */ +void ungetc(char C, File &STREAM) { + unused = ungetc(C, STREAM); +} + +/* + * Write string S to stream. + */ external syserr fputs(string S, File &STREAM); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfputs" - /* - * Write string S to stream. - */ +void fputs(string S, File &STREAM) { + unused = fputs(S, STREAM); +} + +/* + * Read a string of max. length size from the provided TermFile. + */ external syserr, string fgets (int size, File &STREAM); #pragma linkname "SACfgets" #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linksign [0,1,2,3] #pragma sacarg [1] - /* - * Read a string of max. length size from the provided TermFile. - */ syserr, string fgetl (File &stream) { @@ -151,52 +173,53 @@ syserr, string fgetl (File &stream) * ******************************************************************************/ +/* + * Print formatted output to STREAM which must be open for writing. + * The syntax of format strings is identical to that known from C. + * This function may be used to print values of types + * char, string, int, float, and double. + */ external void fprintf(File &STREAM, string FORMAT, ...); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfprintf" - /* - * Print formatted output to STREAM which must be open for writing. - * The syntax of format strings is identical to that known from C. - * This function may be used to print values of types - * char, string, int, float, and double. - */ +/* + * Scan the given stream STREAM concerning the format string FORMAT. + * The syntax of format strings is identical to C except that the + * string conversion specifier %s is not supported. + * This function may be used to scan values of types + * char, int, float, and double. To scan strings use either fscans + * or fscanl, respectively. + * The int result gives the number of successfully performed + * conversions. + */ external int, ... fscanf(File &STREAM, string FORMAT); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfscanf" #pragma linksign [0,1,2] - /* - * Scan the given stream STREAM concerning the format string FORMAT. - * The syntax of format strings is identical to C except that the - * string conversion specifier %s is not supported. - * This function may be used to scan values of types - * char, int, float, and double. To scan strings use either fscans - * or fscanl, respectively. - * The int result gives the number of successfully performed - * conversions. - */ +/* + * Read the next character string from the input stream STREAM. Strings + * are delimited by any whitespace character including the + * end-of-file symbol. Always read at most MAX characters. + * Upon failure an empty string is returned. + */ external string fscans(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" - /* - * Read the next character string from the input stream STREAM. Strings - * are delimited by any whitespace character including the - * end-of-file symbol. Always read at most MAX characters. - * Upon failure an empty string is returned. - */ + /* + * Read the next line from the input stream STREAM. Lines are character + * strings delimited by any new-line or end-of-file symbol. + * Always read at most MAX characters. + * Upon failure an empty string is returned. + */ external string fscanl(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" - /* - * Read the next line from the input stream STREAM. Lines are character - * strings delimited by any new-line or end-of-file symbol. - * Always read at most MAX characters. - * Upon failure an empty string is returned. - */ + /****************************************************************************** * @@ -212,37 +235,46 @@ external bool feof(File &STREAM); * Test the stream STREAM for having reached the end of the respective file. */ +/* + * Write the buffer of a buffered output stream STREAM + * to the respective file + */ external int fflush(File &STREAM); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfflush" - /* - * Write the buffer of a buffered output stream STREAM - * to the respective file. - */ +void fflush(File &STREAM) { + unused = fflush(STREAM); +} + +/* + * Reposition the stream STREAM. The new position is given as an offset + * in bytes relative to BASE which may be 0 (beginning of file), + * 1 (current position), or 2 (end of file). + */ external int fseek(File &STREAM, int OFFSET, int BASE); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACfseek" - /* - * Reposition the stream STREAM. The new position is given as an offset - * in bytes relative to BASE which may be 0 (beginning of file), - * 1 (current position), or 2 (end of file). - */ +void fseek(File &STREAM, int OFFSET, int BASE) { + unused = fseek(STREAM, OFFSET, BASE); +} + +/* + * Return the offset of the current byte relative to + * the beginning of the file associated with STREAM. + */ external int ftell(File &STREAM); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" #pragma linkname "SACftell" - /* - * Return the offset of the current byte relative to - * the beginning of the file associated with STREAM. - */ + +/* + * Reposition the stream STREAM to the beginning of the file associated + * with it (identical to fseek(, 0, 0)). + */ external void rewind(File &STREAM); #pragma header "" - /* - * Reposition the stream STREAM to the beginning of the file associated - * with it (identical to fseek(, 0, 0)). - */ From 416717ac265e0898fbc035e1790157bb8ace99a0 Mon Sep 17 00:00:00 2001 From: Jordy Aaldering <33897257+JordyAaldering@users.noreply.github.com> Date: Sat, 24 Jan 2026 13:09:44 +0100 Subject: [PATCH 8/8] Oops, one semicolon too many --- src/stdio/File.sac | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/stdio/File.sac b/src/stdio/File.sac index 4c5edd26..874dc11b 100644 --- a/src/stdio/File.sac +++ b/src/stdio/File.sac @@ -16,6 +16,7 @@ export all; * Functions to open and close files. * ******************************************************************************/ + /* * Open the file NAME in mode MODE. The modes supported are identical * to the C version of this function. An error condition and a file @@ -62,7 +63,6 @@ external syserr, File, string mkstemp(string template); #pragma linkname "SACmkstemp" #pragma linksign [0,1,2,2] - /* * Create a temporary file using a name generated by the function * mkstemp, and returns the corresponding file handle. The file is @@ -88,8 +88,6 @@ void fremove(string fname) { unused = fremove(fname); } - - /****************************************************************************** * * Functions for low-level input / output operations. @@ -106,7 +104,7 @@ external syserr fputc(char C, File &STREAM); void fputc(char C, File &STREAM) { unused = fputc(C, STREAM); -}; +} external char fgetc(File &STREAM); #pragma linksign [0,1] @@ -220,7 +218,6 @@ external string fscanl(File &STREAM, int MAX); #pragma linkobj "src/File/File.o" // #pragma header "src/File/File.h" - /****************************************************************************** * * Functions for managing file-bound I/O-streams. @@ -271,7 +268,6 @@ external int ftell(File &STREAM); // #pragma header "src/File/File.h" #pragma linkname "SACftell" - /* * Reposition the stream STREAM to the beginning of the file associated * with it (identical to fseek(, 0, 0)).