diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-05 01:11:54 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-05 01:11:54 +0000 |
commit | ffcbbbab99149ea7d8e800326458b70b54438076 (patch) | |
tree | e2a997b294961a00f5d259edefbef93b8501c089 /libchill/basicio.c | |
parent | ff8e09bdcb33f98c7094eec337fb5e93da360a0d (diff) | |
download | gcc-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.c | 467 |
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; +} |