diff options
Diffstat (limited to 'ufileIO2.c')
-rw-r--r-- | ufileIO2.c | 1634 |
1 files changed, 1634 insertions, 0 deletions
diff --git a/ufileIO2.c b/ufileIO2.c new file mode 100644 index 0000000..f08a567 --- /dev/null +++ b/ufileIO2.c @@ -0,0 +1,1634 @@ +/* + File: ufileIO2.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#ifdef applec +# define MPW3 +#endif + +#include <stdio.h> + +#ifdef MPW3 +# include <stdlib.h> +# include <string.h> +#endif + +#include "scon.h" + +extern void IO_error (char*); + +#ifdef GNU_C +# ifdef OS2 +# include <sys/types.h> +# endif +# include <sys/stat.h> +#else +# include <Traps.h> +# include <Files.h> +#endif + +#define MAX_N_FILES 20 + +#define MAX_FILE_NAME_LENGTH 128 + +#define FIRST_REAL_FILE 2 + +struct file { + FILE *file; + unsigned long position; + unsigned long file_length; + char *file_name; + long file_number; +#ifdef GNU_C + int device_number; +#else + int volume_number; +#endif + short mode; + short unique; + unsigned long position_2; +}; + +struct clean_string { + long length; +#if (defined (GNU_C) && !defined (SUN_C)) || defined (powerc) + char characters[0]; +#else + char characters[]; +#endif +}; + +static struct file file_table [MAX_N_FILES]; + +#ifdef LINUX +static void *buffers[MAX_N_FILES]; +#endif + +static int number_of_files=FIRST_REAL_FILE; + +extern void *malloc(); + +static char *clean_to_c_string (struct clean_string *cs) +{ + int l; + char *cp,*s,*sp; + + cp=cs->characters; + l=cs->length; + + s=malloc (l+1); + if (s==NULL) + IO_error ("out of memory while opening file"); + + for (sp=s; l!=0; --l) + *sp++=*cp++; + *sp='\0'; + + return s; +} + +#ifdef GNU_C + + static int get_file_number_and_device_number + (char *file_name,long *file_number_p,int *device_number_p) + { + struct stat stat_buffer; + + if (stat (file_name,&stat_buffer)) + return 0; + + if ((stat_buffer.st_mode & S_IFMT)!=S_IFREG) + return 0; + + *file_number_p=stat_buffer.st_ino; + *device_number_p=stat_buffer.st_dev; + return 1; + } + + static int file_exists (char *file_name,long *file_number_p,int *device_number_p) + { + int n; + + if (!get_file_number_and_device_number (file_name,file_number_p,device_number_p)) + return -1; + + for (n=FIRST_REAL_FILE; n<number_of_files; ++n) + if (file_table[n].file!=NULL && + file_table[n].file_number==*file_number_p && + file_table[n].device_number==*device_number_p) + { + return n; + } + + return -1; + } + +#else + +#ifdef THINK_C + extern OSErr PBGetFInfo (ParmBlkPtr paramBlock,Boolean async); +#endif + static int get_file_number (char *file_name,long *file_number_p) + { + FileParam fileParam; + char file_name_s[MAX_FILE_NAME_LENGTH+2]; + int length; + + length=strlen (file_name); + if (length>MAX_FILE_NAME_LENGTH) + return 0; + file_name_s[0]=length; + strcpy (&file_name_s[1],file_name); + + fileParam.ioCompletion=NULL; + fileParam.ioFDirIndex=0; + fileParam.ioNamePtr=file_name_s; + fileParam.ioFVersNum=0; + fileParam.ioVRefNum=0; + +#ifdef MPW3 + if (PBGetFInfo ((ParmBlkPtr)&fileParam,0)!=noErr) +#else + if (PBGetFInfo (&fileParam,0)!=noErr) +#endif + return 0; + *file_number_p=fileParam.ioFlNum; + return 1; + } + +#ifdef THINK_C + extern OSErr PBGetVInfo (ParmBlkPtr paramBlock,Boolean async); +#endif + + static int get_volume_number (char *file_name,int *volume_number_p) + { + VolumeParam volumeParam; + char file_name_s[MAX_FILE_NAME_LENGTH+2]; + int length; + + length=strlen (file_name); + if (length>MAX_FILE_NAME_LENGTH) + return 0; + file_name_s[0]=length; + strcpy (&file_name_s[1],file_name); + + volumeParam.ioCompletion=NULL; + volumeParam.ioVolIndex=-1; + volumeParam.ioNamePtr=file_name_s; + volumeParam.ioVRefNum=0; +#ifdef MPW3 + if (PBGetVInfo ((ParmBlkPtr)&volumeParam,0)!=noErr) +#else + if (PBGetVInfo (&volumeParam,0)!=noErr) +#endif + return 0; + *volume_number_p=volumeParam.ioVRefNum; + return 1; + } + + static int file_exists (char *file_name,long *file_number_p,int *volume_number_p) + { + int n; + + if (!get_file_number (file_name,file_number_p)) + return -1; + + if (!get_volume_number (file_name,volume_number_p)) + IO_error ("can't determine volume number while opening file"); + + for (n=FIRST_REAL_FILE; n<number_of_files; ++n) + if (file_table[n].file!=NULL && + file_table[n].file_number==*file_number_p && + file_table[n].volume_number==*volume_number_p) + { + return n; + } + + return -1; + } + +#endif + +#define FILE_IO_BUFFER_SIZE (4*1024) + +#define F_READ_TEXT 0 +#define F_WRITE_TEXT 1 +#define F_APPEND_TEXT 2 +#define F_READ_DATA 3 +#define F_WRITE_DATA 4 +#define F_APPEND_DATA 5 + +static char *file_mode_string[] ={ "r","w","r+","rb","wb","r+b" }; + +long open_file (struct clean_string *file_name,unsigned int file_mode) +{ + FILE *fd; + int fn,existing_fn; + char *file_name_s; + struct file *f; + unsigned long file_length; + long file_number; +#ifdef GNU_C + int device_number; +#else + int volume_number; +#endif + + if (file_mode>5) + IO_error ("FOpen: invalid file mode"); + + file_name_s=clean_to_c_string (file_name); + +#ifdef GNU_C + existing_fn=file_exists (file_name_s,&file_number,&device_number); +#else + existing_fn=file_exists (file_name_s,&file_number,&volume_number); +#endif + + if (existing_fn>=0) + IO_error ("FOpen: file already open"); + + fn=number_of_files; + if (fn>=MAX_N_FILES){ + for (fn=FIRST_REAL_FILE; fn<MAX_N_FILES; ++fn) + if (file_table[fn].file==NULL) + break; + if (fn>=MAX_N_FILES) + IO_error ("FOpen: too many files"); + } + f=&file_table[fn]; + + f->file_number=file_number; +#ifdef GNU_C + f->device_number=device_number; +#else + f->volume_number=volume_number; +#endif + + fd=fopen (file_name_s,file_mode_string[file_mode]); + if (fd==NULL){ + free (file_name_s); + return -1; + } + +#ifdef LINUX + { + char *buffer; + + buffer=malloc (FILE_IO_BUFFER_SIZE); + + buffers[fn]=buffer; + + if (buffer!=NULL) + setvbuf (fd,buffer,_IOFBF,FILE_IO_BUFFER_SIZE); + } +#else + setvbuf (fd,NULL,_IOFBF,FILE_IO_BUFFER_SIZE); +#endif + + switch (file_mode){ + case F_WRITE_TEXT: +#ifndef GNU_C + { + FileParam pb; + + pb.ioNamePtr=file_name->characters-1; + pb.ioVRefNum=0; + pb.ioFVersNum=0; + pb.ioFDirIndex=0; +# ifdef MPW3 + if (PBGetFInfo ((ParmBlkPtr)&pb,0)==noErr) { + pb.ioFlFndrInfo.fdType='TEXT'; + PBSetFInfo ((ParmBlkPtr)&pb,0); + } +# else + if (PBGetFInfo ((ParmBlkPtr)&pb,0)==noErr) { + pb.ioFlFndrInfo.fdType='TEXT'; + PBSetFInfo (&pb,0); + } +# endif + } +#endif + case F_WRITE_DATA: + file_length=0; + break; + case F_APPEND_TEXT: + case F_APPEND_DATA: + if (fseek (fd,0l,2)!=0){ + fclose (fd); + IO_error ("FOpen: seek to end of file failed"); + } + file_length=ftell (fd); + if (file_length==-1l){ + fclose (fd); + IO_error ("FOpen: can't get file position"); + } + break; + default: + if (fseek (fd,0l,2)!=0){ + fclose (fd); + IO_error ("FOpen: seek to end of file failed"); + } + file_length=ftell (fd); + if (file_length==-1l){ + fclose (fd); + IO_error ("FOpen: can't get file position"); + } + if (fseek (fd,0l,0)!=0){ + fclose (fd); + IO_error ("FOpen: seek to beginning of file failed"); + } + } + + f->file=fd; + f->mode=1<<file_mode; + f->unique=1; + f->file_name=file_name_s; + f->file_length=file_length; + f->position=-2; + f->position_2=-1; + + if (fn>=number_of_files) + number_of_files=fn+1; + + return fn; +} + +static int stdio_open=0; + +long open_stdio (void) +{ + if (stdio_open) + IO_error ("stdio: already open"); + + stdio_open=1; + return 1; +} + +long open_stderr (void) +{ + return 0; +} + +int close_file (long fn) +{ + if (fn<FIRST_REAL_FILE){ + if (fn==1){ + if (!stdio_open) + IO_error ("fclose: file not open (stdio)"); + stdio_open=0; + } + return -1; + } else { + struct file *f; + int result; + + f=&file_table[fn]; + + if (f->file==NULL) + IO_error ("FClose: File not open"); + + result=-1; + if (fclose (f->file)!=0) + result=0; + + free (f->file_name); + +#ifdef LINUX + if (buffers[fn]!=NULL) + free (buffers[fn]); +#endif + + f->file=NULL; + + return result; + } +} + +int re_open_file (long fn,unsigned int file_mode) +{ + if (file_mode>5) + IO_error ("FReOpen: Invalid file mode"); + + if (fn<FIRST_REAL_FILE){ + if (fn==0 && (file_mode==F_READ_TEXT || file_mode==F_READ_DATA)) + IO_error ("FReOpen: StdErr can't be opened for reading"); + return -1; + } else { + unsigned long file_length; + struct file *f; + FILE *fd; + int result; + + f=&file_table[fn]; + + result=-1; + if (fclose (f->file)!=0) + result=0; + + fd=fopen (f->file_name,file_mode_string[file_mode]); + if (fd==NULL) + IO_error ("FReOpen: can't open file"); + +#ifdef LINUX + if (buffers[fn]!=NULL) + setvbuf (fd,buffers[fn],_IOFBF,FILE_IO_BUFFER_SIZE); +#else + setvbuf (fd,NULL,_IOFBF,FILE_IO_BUFFER_SIZE); +#endif + + switch (file_mode){ + case F_WRITE_TEXT: + case F_WRITE_DATA: + file_length=0; + break; + case F_APPEND_TEXT: + case F_APPEND_DATA: + if (fseek (fd,0l,2)!=0){ + fclose (fd); + IO_error ("FOpen: seek to end of file failed"); + } + + file_length=ftell (fd); + if (file_length==-1l){ + fclose (fd); + IO_error ("FReOpen: can't get file position"); + } + break; + default: + if (fseek (fd,0l,2)!=0){ + fclose (fd); + IO_error ("FReOpen: seek to end of file failed"); + } + file_length=ftell (fd); + if (file_length==-1l){ + fclose (fd); + IO_error ("FReOpen: can't get file position"); + } + if (fseek (fd,0l,0)!=0){ + fclose (fd); + IO_error ("FReOpen: seek to beginning of file failed"); + } + } + + f->file=fd; + f->mode=1<<file_mode; + f->file_length=file_length; + f->position=-2; + f->position_2=-1; + + return result; + } +} + +int file_read_char (long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("FReadC: can't read from StdErr"); + case 1: + return w_get_char(); + default: + IO_error ("FReadC: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("FReadC: read from an output file"); + + return getc (f->file); + } +} + +int file_read_int (long fn,int *i_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("FReadI: can't read from StdErr"); + case 1: + return w_get_int (i_p); + default: + IO_error ("FReadI: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + *i_p=0; + + if (f->mode & (1<<F_READ_DATA)){ + int i; + FILE *fd; + + fd=f->file; + + if ((i=getc (fd))==EOF) + return 0; + ((char*)i_p)[0]=i; + if ((i=getc (fd))==EOF) + return 0; + ((char*)i_p)[1]=i; + if ((i=getc (fd))==EOF) + return 0; + ((char*)i_p)[2]=i; + if ((i=getc (fd))==EOF) + return 0; + ((char*)i_p)[3]=i; + } else if (f->mode & (1<<F_READ_TEXT)){ + if (fscanf (f->file,"%d",i_p)!=1) + return 0; + } else + IO_error ("FReadI: read from an output file"); + + return -1; + } +} + +int file_read_real (long fn,double *r_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("FReadR: can't read from StdErr"); + case 1: + return w_get_real (r_p); + default: + IO_error ("FReadR: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + *r_p=0.0; + + if (f->mode & (1<<F_READ_DATA)){ + int n; + FILE *fd; + + fd=f->file; + for (n=0; n<8; ++n){ + int i; + + if ((i=getc (fd))==EOF) + return 0; + ((char*)r_p)[n]=i; + } + } else if (f->mode & (1<<F_READ_TEXT)){ + if (fscanf (f->file,"%lg",r_p)!=1) + return 0; + } else + IO_error ("FReadR: read from an output file"); + + return -1; + } +} + +unsigned long file_read_string (long fn,unsigned long max_length,struct clean_string *s) +{ + unsigned long length; + + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("FReadS: can't read from StdErr"); + case 1: + { + char *string; + + length=0; + string=s->characters; + + while (length!=max_length){ + *string++=w_get_char(); + ++length; + } + + s->length=length; + return length; + } + default: + IO_error ("FReadS: can't open this file"); + } + } else { + struct file *f; + FILE *fd; + char *string; + int c; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("FReadS: read from an output file"); + + fd=f->file; + length=0; + string=s->characters; + + while (length!=max_length && (c=getc (fd),c!=EOF)){ + *string++=c; + ++length; + } + + s->length=length; + + return length; + } +} + +unsigned long file_read_line (long fn,unsigned long max_length,char *string) +{ + unsigned long length; + + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("FReadLine: can't read from StdErr"); + case 1: + { + length=0; + + while (length!=max_length){ + int c; + + c=w_get_char(); + *string++=c; + ++length; + if (c=='\n') + return length; + } + + return -1; + } + default: + IO_error ("FReadLine: can't open this file"); + } + } else { + struct file *f; + FILE *fd; + int c; + + f=&file_table[fn]; + + fd=f->file; + length=0; + + c=0; + if (f->mode & (1<<F_READ_TEXT)){ + while (length!=max_length && (c=getc (fd),c!=EOF)){ + *string++=c; + ++length; + if (c=='\n') + return length; + } + } else if (f->mode & (1<<F_READ_DATA)){ + while (length!=max_length && (c=getc (fd),c!=EOF)){ + *string++=c; + ++length; + if (c=='\xa') + return length; + else if (c=='\xd'){ + if (length!=max_length){ + if ((c=getc (fd),c!=EOF)){ + if (c=='\xa'){ + *string++=c; + ++length; + } else + ungetc (c,fd); + + return length; + } else + return length; + } else { + if ((c=getc (fd),c!=EOF)){ + if (c=='\xa'){ + ungetc (c,fd); + return -1; + } else + ungetc (c,fd); + + return length; + } else + return length; + } + } + } + } else + IO_error ("freadline: read from an output file"); + + if (c!=EOF) + return -1; + + return length; + } +} + +void file_write_char (int c,long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + ew_print_char (c); + break; + case 1: + w_print_char (c); + break; + default: + IO_error ("FWriteC: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)|(1<<F_APPEND_TEXT)|(1<<F_APPEND_DATA))) + IO_error ("FWriteC: write to an input file"); + putc (c,f->file); + } +} + +void file_write_int (int i,long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + ew_print_int (i); + break; + case 1: + w_print_int (i); + break; + default: + IO_error ("FWriteI: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)|(1<<F_APPEND_TEXT)|(1<<F_APPEND_DATA))) + IO_error ("FWriteI: write to an input file"); + + if (f->mode & ((1<<F_WRITE_DATA)|(1<<F_APPEND_DATA))){ +#ifdef powerc + /* work around bug in lucid compiler for power macintosh */ + FILE *fd=f->file; + + putc (i>>24,fd); + putc (i>>16,fd); + putc (i>>8,fd); + putc (i,fd); +#else + int v=i; + FILE *fd=f->file; + + putc (((char*)&v)[0],fd); + putc (((char*)&v)[1],fd); + putc (((char*)&v)[2],fd); + putc (((char*)&v)[3],fd); +#endif + } else + fprintf (f->file,"%d",i); + } +} + +void file_write_real (double r,long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + ew_print_real (r); + break; + case 1: + w_print_real (r); + break; + default: + IO_error ("FWriteR: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)|(1<<F_APPEND_TEXT)|(1<<F_APPEND_DATA))) + IO_error ("FWriteR: write to an input file"); + + if (f->mode & ((1<<F_WRITE_DATA)|(1<<F_APPEND_DATA))){ +#ifdef powerc + /* work around bug in lucid compiler for power macintosh */ + int i1,i2; + FILE *fd=f->file; + + i1=((int*)&r)[0]; + i2=((int*)&r)[1]; + + putc (i1>>24,fd); + putc (i1>>16,fd); + putc (i1>>8,fd); + putc (i1,fd); + putc (i2>>24,fd); + putc (i2>>16,fd); + putc (i2>>8,fd); + putc (i2,fd); +#else + double v=r; + FILE *fd=f->file; + putc (((char*)&v)[0],fd); + putc (((char*)&v)[1],fd); + putc (((char*)&v)[2],fd); + putc (((char*)&v)[3],fd); + putc (((char*)&v)[4],fd); + putc (((char*)&v)[5],fd); + putc (((char*)&v)[6],fd); + putc (((char*)&v)[7],fd); +#endif + } else + fprintf (f->file,"%.15g",r); + } +} + +void file_write_string (struct clean_string *s,long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + ew_print_text (s->characters,s->length); + break; + case 1: + w_print_text (s->characters,s->length); + break; + default: + IO_error ("FWriteS: can't open this file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->mode & ~((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)|(1<<F_APPEND_TEXT)|(1<<F_APPEND_DATA))) + IO_error ("FWriteS: write to an input file"); + + fwrite (s->characters,sizeof (char),s->length,f->file); + } +} + +int file_end (long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + IO_error ("FEnd: not allowed for StdIO and StdErr"); + default: + IO_error ("FEnd: can't open file"); + } + } else { + struct file *f; + int c; + FILE *file_p; + + f=&file_table[fn]; + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("FEnd: not allowed for output files"); + + file_p=f->file; + + /* not portable to all compilers: */ +#ifdef LINUX +/* + if (file_p->_gptr < file_p->_egptr) +*/ + if (file_p->_IO_read_ptr < file_p->_IO_read_end) +#else +# ifdef OS2 + if (file_p->rcount>0) +# else +# ifdef _WINDOWS_ + if (file_p->_r>0) +# else + if (file_p->_cnt>0) +# endif +# endif +#endif + return 0; + + c=getc (file_p); + if (c==EOF) + return -1; + + ungetc (c,file_p); + return 0; + } +} + +int file_error (long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + return 0; + default: + return -1; + } + } else + return ferror (file_table[fn].file) ? -1 : 0; +} + +unsigned long file_position (long fn) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + IO_error ("FPosition: not allowed for StdIO and StdErr"); + default: + IO_error ("FPosition: can't open file"); + } + } else { + unsigned long position; + + position=ftell (file_table[fn].file); + if (position==-1l) + IO_error ("FPosition: can't get file position"); + + return position; + } +} + +int file_seek (long fn,unsigned long position,unsigned long seek_mode) +{ + if (seek_mode>(unsigned)2) + IO_error ("FSeek: invalid mode"); + + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + IO_error ("FSeek: can't seek on StdIO and StdErr"); + default: + IO_error ("FSeek: can't open file"); + } + } else { + struct file *f; + int r; + + f=&file_table[fn]; + + r=fseek (f->file,position,(int)seek_mode); + if (r!=0) + return 0; + + return -1; + } +} + +long open_s_file (struct clean_string *file_name,unsigned int file_mode) +{ + FILE *fd; + int fn,existing_fn; + char *file_name_s; + struct file *f; + unsigned long file_length; + + long file_number; +#ifdef GNU_C + int device_number; +#else + int volume_number; +#endif + + if (file_mode!=F_READ_TEXT && file_mode!=F_READ_DATA) + IO_error ("SFOpen: invalid file mode"); + + file_name_s=clean_to_c_string (file_name); + +#ifdef GNU_C + existing_fn=file_exists (file_name_s,&file_number,&device_number); +#else + existing_fn=file_exists (file_name_s,&file_number,&volume_number); +#endif + + if (existing_fn>=0){ + if (file_table[existing_fn].unique) + IO_error ("SFOpen: file already opened by FOpen"); + if (file_table[existing_fn].mode!=(1<<file_mode)) + IO_error ("SFOpen: file already open in another file mode"); + + free (file_name_s); + + return existing_fn; + } + + fn=number_of_files; + if (fn>=MAX_N_FILES){ + for (fn=FIRST_REAL_FILE; fn<MAX_N_FILES; ++fn) + if (file_table[fn].file==NULL) + break; + if (fn>=MAX_N_FILES) + IO_error ("SFOpen: too many files"); + } + f=&file_table[fn]; + + f->file_number=file_number; +#ifdef GNU_C + f->device_number=device_number; +#else + f->volume_number=volume_number; +#endif + + fd=fopen (file_name_s,file_mode_string[file_mode]); + if (fd==NULL){ + free (file_name_s); + + return -1; + } + +#ifdef LINUX + { + char *buffer; + + buffer=malloc (FILE_IO_BUFFER_SIZE); + + buffers[fn]=buffer; + + if (buffer!=NULL) + setvbuf (fd,buffer,_IOFBF,FILE_IO_BUFFER_SIZE); + } +#else + setvbuf (fd,NULL,_IOFBF,FILE_IO_BUFFER_SIZE); +#endif + + if (fseek (fd,0l,2)!=0){ + fclose (fd); + IO_error ("SFOpen: seek to end of file failed"); + } + file_length=ftell (fd); + if (file_length==-1l){ + fclose (fd); + IO_error ("SFOpen: can't get file position"); + } + if (fseek (fd,0l,0)!=0){ + fclose (fd); + IO_error ("SFOpen: seek to beginning of file failed"); + } + + f->file=fd; + f->mode=1<<file_mode; + f->unique=0; + f->file_name=file_name_s; + f->file_length=file_length; + f->position=-2; + f->position_2=-1; + + if (fn>=number_of_files) + number_of_files=fn+1; + + return fn; +} + +void file_share (long fn) +{ + file_table[fn].unique=0; +} + +int file_read_s_char (long fn,unsigned long *position_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFReadC: can't read from StdErr"); + case 1: + IO_error ("SFReadC: can't read from StdIO, use FReadC"); + default: + IO_error ("SFReadC: can't open this file"); + } + } else { + struct file *f; + int c; + unsigned long position; + + f=&file_table[fn]; + + position=*position_p; + + if (f->unique) + IO_error ("SFReadC: can't read from a unique file"); + + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("SFReadC: read from an output file"); + + if (f->position!=position) + switch (position){ + case -1l: + if (position!=f->position_2) + position=f->position_2; + else { + position=ftell (f->file); + if (position==-1l) + IO_error ("SFReadC: can't get file position"); + f->position_2=position; + break; + } + default: + if (fseek (f->file,position,0)!=0) + IO_error ("SFReadC: seek failed"); + } + + c=getc (f->file); + if (c!=EOF) + ++position; + + f->position=position; + *position_p=position; + + return c; + } +} + +int file_read_s_int (long fn,int *i_p,unsigned long *position_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFReadI: can't read from StdErr"); + case 1: + IO_error ("SFReadI: can't read from StdIO, use FReadI"); + default: + IO_error ("SFReadI: can't open this file"); + } + } else { + struct file *f; + int result; + unsigned long position; + + f=&file_table[fn]; + position=*position_p; + + if (f->unique) + IO_error ("SFReadI: can't read from a unique file"); + + if (f->position!=position) + if (f->mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA))){ + switch (position){ + case -1l: + if (position!=f->position_2) + position=f->position_2; + else { + position=ftell (f->file); + if (position==-1l) + IO_error ("SFReadI: can't get file position"); + f->position_2=position; + break; + } + default: + if (fseek (f->file,position,0)!=0) + IO_error ("SFReadI: seek failed"); + } + } + + *i_p=0; + + if (f->mode & (1<<F_READ_DATA)){ + int i; + FILE *fd; + + fd=f->file; + + result=-1; + if ((i=getc (fd))==EOF) + result=0; + else { + ((char*)i_p)[0]=i; + if ((i=getc (fd))==EOF){ + ++position; + result=0; + } else { + ((char*)i_p)[1]=i; + if ((i=getc (fd))==EOF){ + position+=2; + result=0; + } else { + ((char*)i_p)[2]=i; + if ((i=getc (fd))==EOF){ + position+=3; + result=0; + } else { + ((char*)i_p)[3]=i; + position+=4; + } + } + } + } + } else if (f->mode & (1<<F_READ_TEXT)){ + if (fscanf (f->file,"%d",i_p)!=1) + result=0; + else + result=-1; + position=ftell (f->file); + if (position==-1l) + IO_error ("SFReadI: can't get file position"); + } else + IO_error ("SFReadI: read from an output file"); + + f->position=position; + *position_p=position; + + return result; + } +} + +int file_read_s_real (long fn,double *r_p,unsigned long *position_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFReadR: can't read from StdErr"); + case 1: + IO_error ("SFReadR: can't read from StdIO, use FReadR"); + default: + IO_error ("SFReadR: can't open this file"); + } + } else { + struct file *f; + int result; + unsigned long position; + + f=&file_table[fn]; + + if (f->unique) + IO_error ("SFReadR: can't read from a unique file"); + + position=*position_p; + if (f->position!=position) + if (f->mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA))){ + switch (position){ + case -1l: + if (position!=f->position_2) + position=f->position_2; + else { + position=ftell (f->file); + if (position==-1l) + IO_error ("SFReadR: can't get file position"); + f->position_2=position; + break; + } + default: + if (fseek (f->file,position,0)!=0) + IO_error ("SFReadR: seek failed"); + } + } + + *r_p=0.0; + + if (f->mode & (1<<F_READ_DATA)){ + int n; + FILE *fd; + + fd=f->file; + + result=-1; + for (n=0; n<8; ++n){ + int i; + + if ((i=getc (fd))==EOF){ + result=0; + break; + } + ((char*)r_p)[n]=i; + } + + position+=n; + } else if (f->mode & (1<<F_READ_TEXT)){ + if (fscanf (f->file,"%lg",r_p)!=1) + result=0; + else + result=-1; + position=ftell (f->file); + if (position==-1l) + IO_error ("SFReadR: can't get file position"); + } else + IO_error ("SFReadR: read from an output file"); + + f->position=position; + *position_p=position; + + return result; + } +} + +unsigned long file_read_s_string + (long fn,unsigned long max_length,struct clean_string *s,unsigned long *position_p) +{ + unsigned long length; + + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFReadS: can't read from StdErr"); + case 1: + IO_error ("SFReadS: can't read from StdIO, use FReadS"); + default: + IO_error ("SFReadS: can't open this file"); + } + } else { + struct file *f; + unsigned long position; + FILE *fd; + char *string; + int c; + + f=&file_table[fn]; + + if (f->unique) + IO_error ("SFReadS: can't read from a unique file"); + + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("SFReadS: read from an output file"); + + fd=f->file; + + position=*position_p; + if (f->position!=position) + switch (position){ + case -1l: + if (position!=f->position_2) + position=f->position_2; + else { + position=ftell (fd); + if (position==-1l) + IO_error ("SFReadS: can't get file position"); + f->position_2=position; + break; + } + default: + if (fseek (fd,position,0)!=0) + IO_error ("SFReadS: seek failed"); + } + + length=0; + string=s->characters; + + while (length!=max_length && (c=getc (fd),c!=EOF)){ + *string++=c; + ++length; + } + + s->length=length; + + position+=length; + + f->position=position; + *position_p=position; + + return length; + } +} + +unsigned long file_read_s_line + (long fn,unsigned long max_length,char *string,unsigned long *position_p) +{ + unsigned long length; + + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFReadLine: can't read from StdErr"); + case 1: + IO_error ("SFReadLine: can't read from StdIO, use FReadLine"); + default: + IO_error ("SFReadLine: can't open this file"); + } + } else { + struct file *f; + unsigned long position; + FILE *fd; + int c; + + f=&file_table[fn]; + + if (f->unique) + IO_error ("SFReadLine: can't read from a unique file"); + + if (f->mode & ~(1<<F_READ_TEXT)) + if (f->mode & (1<<F_READ_DATA)) + IO_error ("SFReadLine: read from a data file"); + else + IO_error ("SFReadLine: read from an output file"); + + fd=f->file; + + position=*position_p; + if (f->position!=position) + switch (position){ + case -1l: + if (position!=f->position_2) + position=f->position_2; + else { + position=ftell (fd); + if (position==-1l) + IO_error ("SFReadLine: can't get file position"); + f->position_2=position; + break; + } + default: + if (fseek (fd,position,0)!=0) + IO_error ("SFReadLine: seek failed"); + } + + length=0; + + c=0; + while (length!=max_length && (c=getc (fd),c!=EOF)){ + *string++=c; + ++length; + if (c=='\n') + break; + } + + position+=length; + + f->position=position; + *position_p=position; + + if (c!='\n' && c!=EOF) + return -1; + + return length; + } +} + +int file_s_end (long fn,unsigned long position) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + IO_error ("SFEnd: not allowed for StdIO and StdErr"); + default: + IO_error ("SFEnd: can't open file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + if (f->mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + IO_error ("SFEnd: not allowed for output files"); + + if (f->unique){ + int c; + FILE *file_p; + + file_p=f->file; + + /* not portable to all compilers: */ +#ifdef LINUX +/* + if (file_p->_gptr < file_p->_egptr) +*/ + if (file_p->_IO_read_ptr < file_p->_IO_read_end) +#else +# ifdef OS2 + if (file_p->rcount>0) +# else +# ifdef _WINDOWS_ + if (file_p->_r>0) +# else + if (file_p->_cnt>0) +# endif +# endif +#endif + return 0; + + c=getc (file_p); + if (c==EOF) + return -1; + + ungetc (c,file_p); + return 0; + } else { + if (position==-1l){ + if (f->position_2!=-1l) + position=f->position_2; + else { + position=ftell (f->file); + if (position==-1l) + IO_error ("SFEnd: can't get file position"); + f->position=position; + f->position_2=position; + } + } + + return (position==f->file_length) ? -1 : 0; + } + } +} + +unsigned long file_s_position (long fn,unsigned long position) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + case 1: + IO_error ("SFPosition: not allowed for StdIO and StdErr"); + default: + IO_error ("SFPosition: can't open file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->unique){ + unsigned long position; + + position=ftell (file_table[fn].file); + if (position==-1l) + IO_error ("SFPosition: can't get file position"); + + return position; + } else { + if (position==-1l){ + if (f->position_2!=-1l) + return f->position_2; + else { + position=ftell (f->file); + if (position==-1l) + IO_error ("SFPosition: can't get file position"); + f->position=position; + f->position_2=position; + } + } + + return position; + } + } +} + +#define F_SEEK_SET 0 +#define F_SEEK_CUR 1 +#define F_SEEK_END 2 + +int file_s_seek (long fn,unsigned long position,unsigned long seek_mode,unsigned long *position_p) +{ + if (fn<FIRST_REAL_FILE){ + switch (fn){ + case 0: + IO_error ("SFSeek: can't seek on StdIO"); + case 1: + IO_error ("SFSeek: can't seek on StdErr"); + default: + IO_error ("SFSeek: can't open file"); + } + } else { + struct file *f; + + f=&file_table[fn]; + + if (f->unique) + IO_error ("SFSeek: can't seek on a unique file"); + + if (*position_p==-1l){ + if (f->position_2!=-1l) + *position_p=f->position_2; + else { + unsigned long current_position; + + current_position=ftell (f->file); + if (current_position==-1l) + IO_error ("SFSeek: can't get file position"); + f->position_2=current_position; + *position_p=current_position; + } + } + + switch (seek_mode){ + case F_SEEK_SET: + break; + case F_SEEK_CUR: + position+=*position_p; + break; + case F_SEEK_END: + position=f->file_length+position; + seek_mode=F_SEEK_SET; + break; + default: + IO_error ("SFSeek: invalid mode"); + } + + if (fseek (f->file,position,(int)seek_mode)!=0) + return 0; + + *position_p=position; + f->position=position; + + return -1; + } +} |