summaryrefslogtreecommitdiff
path: root/libchill/basicio.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-09-05 01:11:54 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1998-09-05 01:11:54 +0000
commitffcbbbab99149ea7d8e800326458b70b54438076 (patch)
treee2a997b294961a00f5d259edefbef93b8501c089 /libchill/basicio.c
parentff8e09bdcb33f98c7094eec337fb5e93da360a0d (diff)
downloadgcc-ffcbbbab99149ea7d8e800326458b70b54438076.tar.gz
* Chill runtime moved into toplevel libchill.
* Makefile.in Revamped due to move. Add multilib support. * configure.in: Similarly. Use autoconf. * powerset.h: Do not depend on BITS_PER_UNIT. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22238 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libchill/basicio.c')
-rw-r--r--libchill/basicio.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/libchill/basicio.c b/libchill/basicio.c
new file mode 100644
index 00000000000..b13b0b8debf
--- /dev/null
+++ b/libchill/basicio.c
@@ -0,0 +1,467 @@
+/* Implement Input/Output runtime actions for CHILL.
+ Copyright (C) 1992,1993 Free Software Foundation, Inc.
+ Author: Wilfried Moser, et al
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "fileio.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+static
+void
+GetSetAttributes( Association_Mode* the_assoc )
+{
+ struct stat statbuf;
+ int retco;
+
+ if( (retco = stat( the_assoc->pathname, &statbuf )) )
+ return;
+
+ if( S_ISREG(statbuf.st_mode) )
+ {
+ SET_FLAG( the_assoc, IO_EXISTING );
+ if( !TEST_FLAG( the_assoc, IO_VARIABLE ) )
+ SET_FLAG( the_assoc, IO_INDEXABLE );
+ }
+ else
+ if( S_ISCHR(statbuf.st_mode) || S_ISFIFO(statbuf.st_mode) )
+ {
+ SET_FLAG( the_assoc, IO_EXISTING );
+ CLR_FLAG( the_assoc, IO_INDEXABLE );
+ }
+ SET_FLAG( the_assoc, IO_SEQUENCIBLE );
+
+ /* FIXME: File size and computation of number of records for outoffile ? */
+
+ if( !access( the_assoc->pathname, R_OK ) )
+ SET_FLAG( the_assoc, IO_READABLE );
+ if( !access( the_assoc->pathname, W_OK ) )
+ SET_FLAG( the_assoc, IO_WRITEABLE );
+}
+
+static
+void
+makeName( Association_Mode* the_assoc, char* the_path, int the_path_len,
+ char* file, int line)
+{
+ int namlen;
+ if( ! the_assoc->pathname &&
+ ! (the_assoc->pathname = (char*)malloc( PATH_MAX )) )
+ CHILLEXCEPTION( file, line, SPACEFAIL, PATHNAME_ALLOC );
+
+ if( the_path[0] != DIRSEP )
+ {
+ if( !getcwd( the_assoc->pathname, PATH_MAX ) )
+ {
+ the_assoc->syserrno = errno;
+ CHILLEXCEPTION( file, line, ASSOCIATEFAIL, GETCWD_FAILS );
+ }
+ namlen = strlen( the_assoc->pathname );
+ the_assoc->pathname[namlen++] = DIRSEP;
+ }
+ else
+ namlen = 0;
+
+ strncpy( the_assoc->pathname + namlen, the_path, the_path_len );
+ the_assoc->pathname[namlen+the_path_len] = '\0';
+}
+
+/*
+ * ASSOCIATE
+ */
+/* Caution: returns an Association mode location (!) */
+Association_Mode*
+__associate( Association_Mode* the_assoc,
+ char* the_path,
+ int the_path_len,
+ char* the_mode,
+ int the_mode_len,
+ char* file,
+ int line )
+{
+ if( !the_assoc )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
+
+ if( TEST_FLAG(the_assoc, IO_ISASSOCIATED) )
+ CHILLEXCEPTION( file, line, ASSOCIATEFAIL, IS_ASSOCIATED );
+
+ /* clear all flags */
+ the_assoc->flags = 0;
+
+ if( ! the_path_len )
+ CHILLEXCEPTION( file, line, ASSOCIATEFAIL, NO_PATH_NAME );
+
+ makeName( the_assoc, the_path, the_path_len, file, line );
+ GetSetAttributes( the_assoc );
+
+ CLR_FLAG( the_assoc, IO_VARIABLE );
+ if ( the_mode )
+ {
+ if( !strncmp( the_mode, "VARIABLE", 8 ) )
+ {
+ SET_FLAG( the_assoc, IO_VARIABLE );
+ CLR_FLAG( the_assoc, IO_INDEXABLE );
+ }
+ else
+ if( strlen( the_mode ) )
+ CHILLEXCEPTION( file, line, ASSOCIATEFAIL, INVALID_ASSOCIATION_MODE );
+ }
+
+ SET_FLAG( the_assoc, IO_ISASSOCIATED );
+ return the_assoc;
+}
+
+/*
+ * DISSOCIATE
+ */
+void
+__dissociate( Association_Mode* the_assoc, char* file, int line )
+{
+ if( !the_assoc )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
+
+ if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
+ CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
+
+ if( the_assoc->access )
+ __disconnect( the_assoc->access, file, line );
+
+ the_assoc->access = NULL;
+ CLR_FLAG( the_assoc, IO_ISASSOCIATED );
+
+ /* free allocated memory */
+ if (the_assoc->pathname)
+ {
+ free (the_assoc->pathname);
+ the_assoc->pathname = 0;
+ }
+ if (the_assoc->bufptr)
+ {
+ free (the_assoc->bufptr);
+ the_assoc->bufptr = 0;
+ }
+}
+
+/*
+ * CREATE
+ */
+void __create( Association_Mode* the_assoc, char* file, int line )
+{
+ if( !the_assoc )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
+
+ if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
+ CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
+
+ if( TEST_FLAG( the_assoc, IO_EXISTING ) )
+ CHILLEXCEPTION( file, line, CREATEFAIL, FILE_EXISTING );
+
+ if( (the_assoc->handle = open( the_assoc->pathname, O_CREAT+O_TRUNC+O_WRONLY, 0666 ))
+ == -1 )
+ CHILLEXCEPTION( file, line, CREATEFAIL, CREATE_FAILS );
+
+ the_assoc->usage = ReadWrite;
+ GetSetAttributes( the_assoc );
+
+ close( the_assoc->handle );
+}
+
+/*
+ * MODIFY
+ */
+void
+__modify( Association_Mode* the_assoc,
+ char* the_path,
+ int the_path_len,
+ char* the_mode,
+ int the_mode_len,
+ char* file,
+ int line )
+{
+ if( !the_assoc )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
+
+ if( !TEST_FLAG( the_assoc, IO_ISASSOCIATED ) )
+ CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
+
+ if( the_path_len )
+ {
+ char* oldname;
+
+ if( ! (oldname = (char*)malloc( PATH_MAX )) )
+ CHILLEXCEPTION( file, line, SPACEFAIL, PATHNAME_ALLOC );
+ strcpy( oldname, the_assoc->pathname );
+
+ makeName( the_assoc, the_path, the_path_len, file, line );
+
+ if( rename( oldname, the_assoc->pathname ) )
+ {
+ free( oldname );
+ CHILLEXCEPTION( file, line, MODIFYFAIL, RENAME_FAILS );
+ }
+ free( oldname );
+ }
+ else
+ {
+ /* FIXME: other options? */
+ }
+}
+
+static
+/*** char* DirMode[] = { "rb", "r+b", "r+b" }; ***/
+int DirMode[] = { O_RDONLY, O_RDWR, O_RDWR };
+
+static
+/*** char* SeqMode [] = { "rb", "r+b", "r+b" }; ***/
+int SeqMode[] = { O_RDONLY, O_RDWR, O_RDWR };
+
+/*
+ * CONNECT
+ */
+void
+__connect( void* the_transfer,
+ Association_Mode* the_assoc,
+ Usage_Mode the_usage,
+ Where_Mode the_where,
+ Boolean with_index,
+ signed long the_index,
+ char* file,
+ int line )
+{
+ Access_Mode* the_access;
+ off_t filepos;
+ off_t savepos;
+ char dummy;
+ unsigned long nbytes;
+ int oflag;
+
+ if( !the_transfer )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ACCESS );
+ if( !the_assoc )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ASSOCIATION );
+
+ if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ))
+ {
+ if( ! ((Text_Mode*)the_transfer)->access_sub )
+ CHILLEXCEPTION( file, line, EMPTY, NO_ACCESS_SUBLOCATION );
+ the_access = ((Text_Mode*)the_transfer)->access_sub;
+ SET_FLAG( the_access, IO_TEXTIO );
+ }
+ else
+ {
+ the_access = (Access_Mode*)the_transfer;
+ CLR_FLAG( the_access, IO_TEXTIO );
+ }
+
+ /* FIXME: This should be an (implementation-dependent) static check
+ if( with_index && the_access->rectype > Fixed )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, IMPL_RESTRICTION );
+ */
+
+ if( ! TEST_FLAG(the_assoc, IO_ISASSOCIATED) )
+ CHILLEXCEPTION( file, line, NOTASSOCIATED, IS_NOT_ASSOCIATED );
+
+ if( ! TEST_FLAG( the_assoc, IO_EXISTING ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_EXISTING );
+
+ if( ! TEST_FLAG( the_assoc, IO_READABLE ) &&
+ ( the_usage = ReadOnly || the_usage == ReadWrite ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_READABLE );
+
+ if( ! TEST_FLAG( the_assoc, IO_WRITEABLE ) &&
+ ( the_usage = WriteOnly || the_usage == ReadWrite ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_WRITEABLE );
+
+ if( ! TEST_FLAG( the_assoc, IO_INDEXABLE )
+ && TEST_FLAG( the_access, IO_INDEXED ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_INDEXABLE );
+
+ if( ! TEST_FLAG( the_assoc, IO_SEQUENCIBLE )
+ && ! TEST_FLAG( the_access, IO_INDEXED ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_SEQUENCIBLE );
+
+ if( the_where == Same && the_assoc->access == NULL )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NO_CURRENT_POS );
+
+ /* This dynamic condition is not checked for text connections. */
+ if( ! TEST_FLAG( the_access, IO_TEXTIO ) )
+ if( ! TEST_FLAG( the_assoc, IO_VARIABLE )
+ && the_access->rectype > Fixed
+ && ( the_usage == WriteOnly || the_usage == ReadWrite ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_VARIABLE );
+
+ if( TEST_FLAG( the_assoc, IO_VARIABLE )
+ && the_access->rectype == Fixed
+ && ( the_usage == ReadOnly || the_usage == ReadWrite ) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_FIXED );
+
+ if( ! TEST_FLAG( the_access, IO_INDEXED ) && the_usage == ReadWrite )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, NOT_INDEXED );
+
+ /* Access location may be connected to a different association. */
+ if( the_access->association && the_access->association != the_assoc )
+ __disconnect( the_access, file, line );
+
+ /* Is the association location already connected? */
+ if( the_assoc->access )
+ {
+ /* save position just in case we need it for the_where == Same */
+ if( (savepos = lseek( the_assoc->handle, 0L, SEEK_CUR )) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
+
+ /* text: read correction, flush buffer */
+ if( the_assoc->bufptr ){
+ savepos -= the_assoc->bufptr->len - the_assoc->bufptr->cur;
+ the_assoc->bufptr->len = the_assoc->bufptr->cur = 0;
+ }
+
+ /* implicit disconnect */
+ __disconnect( the_assoc->access, file, line );
+ }
+
+ the_assoc->usage = the_usage;
+ CLR_FLAG( the_access, IO_OUTOFFILE );
+
+ if( TEST_FLAG( the_access, IO_INDEXED ) )
+ {
+ if( (the_assoc->handle = open( the_assoc->pathname, DirMode[the_usage] )) == -1 )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
+
+ /* Set base index. */
+ switch( the_where )
+ {
+ case First:
+ filepos = 0;
+ break;
+ case Same:
+ filepos = savepos;
+ break;
+ case Last:
+ if( lseek( the_assoc->handle, 0L, SEEK_END ) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
+ filepos = lseek( the_assoc->handle, 0L, SEEK_CUR );
+ break;
+ }
+
+ /* Set current index */
+ if( with_index )
+ {
+ if( the_index < the_access->lowindex
+ || the_access->highindex < the_index )
+ CHILLEXCEPTION( file, line, RANGEFAIL, BAD_INDEX );
+ filepos += (the_index - the_access->lowindex) * the_access->reclength;
+ }
+ if( lseek( the_assoc->handle, filepos, SEEK_SET ) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
+ the_access->base = filepos;
+ }
+ else
+ {
+ /* for association to text for reading: allocate buffer */
+ if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ) &&
+ the_usage == ReadOnly &&
+ !the_assoc->bufptr )
+ {
+ if( ! (the_assoc->bufptr = (readbuf_t*)malloc( sizeof(readbuf_t) )) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, BUFFER_ALLOC );
+ memset (the_assoc->bufptr, 0, sizeof (readbuf_t));
+ }
+ if( (the_assoc->handle = open( the_assoc->pathname, SeqMode[the_usage] )) == -1 )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
+
+ /* Set base index. */
+ switch( the_where )
+ {
+ case First:
+ filepos = 0;
+ break;
+ case Same:
+ filepos = savepos;
+ break;
+ case Last:
+ if( lseek( the_assoc->handle, 0L, SEEK_END ) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
+ filepos = lseek( the_assoc->handle, 0L, SEEK_CUR );
+ break;
+ }
+
+ /* file truncation for sequential, Write Only */
+ /***************************** FIXME: cannot truncate at Same
+ if( the_usage == WriteOnly )
+ {
+ if( fseek( the_assoc->file_ptr, filepos, SEEK_SET ) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, FSEEK_FAILS );
+ fclose( the_assoc->file_ptr );
+ if( !(the_assoc->file_ptr = fopen( the_assoc->pathname, "ab" )) )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, OPEN_FAILS );
+ }
+ else
+ ***************************/
+ if( (filepos = lseek( the_assoc->handle, filepos, SEEK_SET )) == -1L )
+ CHILLEXCEPTION( file, line, CONNECTFAIL, LSEEK_FAILS );
+ }
+
+ the_access->association = the_assoc;
+ the_assoc->access = the_access;
+ /* for text: set carriage control default */
+ if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ) ){
+ the_assoc->ctl_pre = '\0';
+ the_assoc->ctl_post = '\n';
+ }
+}
+
+void
+__disconnect( void* the_transfer, char* file, int line )
+{
+ Access_Mode* the_access;
+
+ if( !the_transfer )
+ CHILLEXCEPTION( file, line, EMPTY, NULL_ACCESS );
+
+ if( TEST_FLAG((Text_Mode*)the_transfer, IO_TEXTLOCATION ))
+ {
+ the_access = ((Text_Mode*)the_transfer)->access_sub;
+ CLR_FLAG( the_access, IO_TEXTIO );
+ }
+ else
+ the_access = (Access_Mode*)the_transfer;
+
+ if( !the_access->association )
+ CHILLEXCEPTION( file, line, NOTCONNECTED, IS_NOT_CONNECTED );
+
+ close( the_access->association->handle );
+ /* FIXME: check result */
+
+ if( the_access->store_loc )
+ free( the_access->store_loc );
+ the_access->store_loc = NULL;
+ the_access->association->access = NULL;
+ the_access->association = NULL;
+}