diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36e9e284..a12ef26f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,23 +216,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 @@ -288,8 +272,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. diff --git a/src/stdio/File.sac b/src/stdio/File.sac index c453a934..874dc11b 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 }; @@ -16,110 +17,139 @@ export all; * ******************************************************************************/ +/* + * 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/fopen.o" + #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" + +/* 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/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] - /* - * 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. - */ + #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. + */ 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. - */ -external void fclose(File STREAM); +/* + * Remove file or directory. + */ +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. - */ + #pragma linkobj "src/File/File.o" + // #pragma header "src/File/File.h" -external void fremove(string fname); - #pragma effect TheFileSystem - #pragma linkobj "src/File/rm.o" - /* - * Remove file or directory. - */ +void fremove(string fname) { + unused = fremove(fname); +} -/****************************************************************************** + /****************************************************************************** * * Functions for low-level input / output operations. * ******************************************************************************/ -external void fputc(char C, File &STREAM); - #pragma linkobj "src/File/fputc.o" +/* + * 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 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" +/* + * 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. - */ -external void fputs(string S, File &STREAM); - #pragma linkobj "src/File/fputs.o" +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_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] - /* - * Read a string of max. length size from the provided TermFile. - */ + #pragma sacarg [1] syserr, string fgetl (File &stream) { @@ -141,50 +171,52 @@ 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/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. - * 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/fscanf.o" + #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/fscans.o" - #pragma linksign [0,1,2] - /* - * 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. - */ + #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. + */ external string fscanl(File &STREAM, int MAX); - #pragma linkobj "src/File/fscanl.o" - #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. - * Always read at most MAX characters. - * Upon failure an empty string is returned. - */ + #pragma linkobj "src/File/File.o" + // #pragma header "src/File/File.h" /****************************************************************************** * @@ -193,43 +225,52 @@ 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" +/* + * 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. - */ -external void fseek(File &STREAM, int OFFSET, int BASE); - #pragma linkobj "src/File/fseek.o" +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/ftell.o" + #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. - */ +/* + * Reposition the stream STREAM to the beginning of the file associated + * with it (identical to fseek(, 0, 0)). + */ external void rewind(File &STREAM); - #pragma linkobj "src/File/rewind.o" - #pragma linkname "SACrewind" - /* - * Reposition the stream STREAM to the beginning of the file associated - * with it (identical to fseek(, 0, 0)). - */ + #pragma header "" diff --git a/src/stdio/src/File/File.c b/src/stdio/src/File/File.c new file mode 100644 index 00000000..0323e18e --- /dev/null +++ b/src/stdio/src/File/File.c @@ -0,0 +1,170 @@ +#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'); + sac_int shp[] = { (sac_int)written }; + *str = SACARGcreateFromPointer (SACTYPE_String__string, buf, 1, shp); + + 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_ */