diff options
Diffstat (limited to 'gcc/ch/runtime/readrecord.c')
-rw-r--r-- | gcc/ch/runtime/readrecord.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/gcc/ch/runtime/readrecord.c b/gcc/ch/runtime/readrecord.c new file mode 100644 index 0000000..03641f9 --- /dev/null +++ b/gcc/ch/runtime/readrecord.c @@ -0,0 +1,208 @@ +/* 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 <setjmp.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> + +#include "fileio.h" + +#ifdef EOF +#undef EOF +#endif +#define EOF -1 + +static +Boolean +doRead( Access_Mode* the_access, void* buf, size_t nbyte ) +{ + size_t nread; + + nread = read( the_access->association->handle, buf, nbyte ); + if( nread == nbyte ) + { + CLR_FLAG( the_access, IO_OUTOFFILE ); + return True; + } + if( nread == 0 ) + { + SET_FLAG( the_access, IO_OUTOFFILE ); + return False; + } + the_access->association->syserrno = errno; + RWEXCEPTION( READFAIL, OS_IO_ERROR ); + /* no return */ +} + +static +int bgetc( int handle, readbuf_t* rbptr ) +{ + if( rbptr->cur >= rbptr->len ) + { + rbptr->len = read( handle, rbptr->buf, READBUFLEN ); + if( rbptr->len == 0 ) + return EOF; + rbptr->cur = 0; + } + return rbptr->buf[rbptr->cur++]; +} + +static +void bungetc( readbuf_t* rbptr, int c ) +{ + rbptr->buf[--rbptr->cur] = c; +} + +void* +__readrecord( Access_Mode* the_access, + signed long the_index, + char* the_buf_addr, + char* file, + int line ) +{ + unsigned long info; + char* actaddr; + unsigned short actlen; + off_t filepos; + unsigned short reclen; + unsigned long readlen; + + if( !the_access ) + CHILLEXCEPTION( file, line, EMPTY, NULL_ACCESS ); + + if( !the_access->association ) + CHILLEXCEPTION( file, line, NOTCONNECTED, IS_NOT_CONNECTED ); + + /* Usage must not be WriteOnly */ + if( the_access->association->usage == WriteOnly ) + CHILLEXCEPTION( file, line, READFAIL, BAD_USAGE ); + + /* OUTOFFILE must not be True when connected for sequential read */ + if( !TEST_FLAG( the_access, IO_INDEXED ) + && TEST_FLAG( the_access, IO_OUTOFFILE ) ) + CHILLEXCEPTION( file, line, READFAIL, OUT_OF_FILE ); + + /* + * Positioning + */ + if( TEST_FLAG( the_access, IO_INDEXED ) ) + { + /* index expression must be within bounds of index mode */ + if( the_index < the_access->lowindex + || the_access->highindex < the_index ) + CHILLEXCEPTION( file, line, RANGEFAIL, BAD_INDEX ); + + filepos = the_access->base + + (the_index - the_access->lowindex) * the_access->reclength; + + if( lseek( the_access->association->handle, filepos, SEEK_SET ) == -1L ) + CHILLEXCEPTION( file, line, READFAIL, LSEEK_FAILS ); + } + + /* establish store loc */ + if( !(actaddr = the_buf_addr )) + { + /* if not yet allocated, do it now */ + if (!the_access->store_loc) + if( !(the_access->store_loc = (char*)malloc( the_access->reclength ) ) ) + CHILLEXCEPTION( file, line, SPACEFAIL, STORE_LOC_ALLOC ); + actaddr = the_access->store_loc; + } + actlen = the_access->reclength; + + if( (info = setjmp( __rw_exception )) ) + CHILLEXCEPTION( file, line, info>>16, info & 0xffff ); + + if( TEST_FLAG( the_access, IO_TEXTIO ) ) + { + readlen = actlen - 2; + if( TEST_FLAG( the_access, IO_INDEXED ) ) + { + if( ! doRead( the_access, &reclen, sizeof(reclen) ) ) + return NULL; + if( reclen > readlen ) + CHILLEXCEPTION( file, line, RANGEFAIL, RECORD_TOO_LONG ); + if( ! doRead( the_access, actaddr + 2, reclen ) ) + CHILLEXCEPTION( file, line, READFAIL, RECORD_TOO_SHORT ); + } + else + { + Association_Mode *assoc = the_access->association; + int handle = assoc->handle; + readbuf_t* rbuf = assoc->bufptr; + char* cptr = actaddr+2; + int curr; + + reclen = 0; + while( readlen-- ) + { + curr = bgetc( handle, rbuf ); + if( curr == '\n' ) + goto end_of_line; + if( curr == EOF ) + { + if( !reclen ) + SET_FLAG( the_access, IO_OUTOFFILE ); + goto end_of_line; + } + *cptr++ = curr; + reclen++; + } + if( (curr = bgetc( handle, rbuf )) != '\n' ) + { + bungetc( rbuf, curr ); + CHILLEXCEPTION( file, line, RANGEFAIL, RECORD_TOO_LONG ); + } +end_of_line: ; + } + MOV2(actaddr,&reclen); + } + else + { + switch( the_access->rectype ) + { + case Fixed: + if( ! doRead( the_access, actaddr, actlen ) ) + return NULL; + break; + case VaryingChars: + if( TEST_FLAG( the_access->association, IO_VARIABLE ) ) + { + if( ! doRead( the_access, &reclen, sizeof(reclen) ) ) + return NULL; + if( reclen > actlen - 2 ) + CHILLEXCEPTION( file, line, RANGEFAIL, RECORD_TOO_LONG ); + readlen = TEST_FLAG( the_access, IO_INDEXED ) ? actlen - 2 : reclen; + if( ! doRead( the_access, actaddr + 2, readlen ) ) + CHILLEXCEPTION( file, line, READFAIL, RECORD_TOO_SHORT ); + } + else + { + if( ! doRead( the_access, actaddr + 2, reclen = actlen - 2 ) ) + CHILLEXCEPTION( file, line, READFAIL, RECORD_TOO_SHORT ); + } + MOV2(actaddr,&reclen); + break; + } + } + + return actaddr; +} |