aboutsummaryrefslogtreecommitdiffstats
path: root/src/pdclib/functions/stdio/fopen.c
diff options
context:
space:
mode:
authortcsullivan <tullivan99@gmail.com>2018-11-17 13:02:57 -0500
committertcsullivan <tullivan99@gmail.com>2018-11-17 13:02:57 -0500
commitc6ef89664b8c0d7aa85bddd5c7014aa6df82cbe7 (patch)
treed1f9d09412a46bdf4344fe30392455070a72993d /src/pdclib/functions/stdio/fopen.c
parentdb38c4b9dac461de0ed75bf6d079dacba1b31bc9 (diff)
added pdclib, removed sash
Diffstat (limited to 'src/pdclib/functions/stdio/fopen.c')
-rw-r--r--src/pdclib/functions/stdio/fopen.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/pdclib/functions/stdio/fopen.c b/src/pdclib/functions/stdio/fopen.c
new file mode 100644
index 0000000..d5241a7
--- /dev/null
+++ b/src/pdclib/functions/stdio/fopen.c
@@ -0,0 +1,102 @@
+/* fopen( const char *, const char * )
+
+ This file is part of the Public Domain C Library (PDCLib).
+ Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef REGTEST
+
+#include "pdclib/_PDCLIB_glue.h"
+
+#include <string.h>
+
+extern struct _PDCLIB_file_t * _PDCLIB_filelist;
+
+struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
+{
+ struct _PDCLIB_file_t * rc;
+ size_t filename_len;
+ if ( mode == NULL || filename == NULL || filename[0] == '\0' )
+ {
+ /* Mode or filename invalid */
+ return NULL;
+ }
+ /* To reduce the number of malloc calls, all data fields are concatenated:
+ * the FILE structure itself,
+ * ungetc buffer,
+ * filename buffer,
+ * data buffer.
+ Data buffer comes last because it might change in size ( setvbuf() ).
+ */
+ filename_len = strlen( filename ) + 1;
+ if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + filename_len + BUFSIZ ) ) == NULL )
+ {
+ /* no memory */
+ return NULL;
+ }
+ if ( ( rc->status = _PDCLIB_filemode( mode ) ) == 0 )
+ {
+ /* invalid mode */
+ free( rc );
+ return NULL;
+ }
+ rc->handle = _PDCLIB_open( filename, rc->status );
+ if ( rc->handle == _PDCLIB_NOHANDLE )
+ {
+ /* OS open() failed */
+ free( rc );
+ return NULL;
+ }
+ /* Setting pointers into the memory block allocated above */
+ rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
+ rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
+ rc->buffer = rc->filename + filename_len;
+ /* Copying filename to FILE structure */
+ strcpy( rc->filename, filename );
+ /* Initializing the rest of the structure */
+ rc->bufsize = BUFSIZ;
+ rc->bufidx = 0;
+ rc->ungetidx = 0;
+ /* Setting buffer to _IOLBF because "when opened, a stream is fully
+ buffered if and only if it can be determined not to refer to an
+ interactive device."
+ */
+ rc->status |= _IOLBF;
+ /* TODO: Setting mbstate */
+ /* Adding to list of open files */
+ rc->next = _PDCLIB_filelist;
+ _PDCLIB_filelist = rc;
+ return rc;
+}
+
+#endif
+
+#ifdef TEST
+
+#include "_PDCLIB_test.h"
+
+int main( void )
+{
+ /* Some of the tests are not executed for regression tests, as the libc on
+ my system is at once less forgiving (segfaults on mode NULL) and more
+ forgiving (accepts undefined modes).
+ */
+ FILE * fh;
+ remove( testfile );
+ TESTCASE_NOREG( fopen( NULL, NULL ) == NULL );
+ TESTCASE( fopen( NULL, "w" ) == NULL );
+ TESTCASE_NOREG( fopen( "", NULL ) == NULL );
+ TESTCASE( fopen( "", "w" ) == NULL );
+ TESTCASE( fopen( "foo", "" ) == NULL );
+ TESTCASE_NOREG( fopen( testfile, "wq" ) == NULL ); /* Undefined mode */
+ TESTCASE_NOREG( fopen( testfile, "wr" ) == NULL ); /* Undefined mode */
+ TESTCASE( ( fh = fopen( testfile, "w" ) ) != NULL );
+ TESTCASE( fclose( fh ) == 0 );
+ TESTCASE( remove( testfile ) == 0 );
+ return TEST_RESULTS;
+}
+
+#endif