/* File: ufileIO2.c Author: John van Groningen At: University of Nijmegen */ #ifdef applec # define MPW3 #endif #include #include #ifdef MPW3 # include #endif #if defined (__x86_64__) || defined (__aarch64__) # define A64 #endif #include "scon.h" extern void IO_error (char*); #ifdef GNU_C # ifdef OS2 # include # endif # include #else # include # include #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 }; #ifdef I486 # define CLEAN_TRUE 1 #else # define CLEAN_TRUE (-1) #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 -2; for (n=FIRST_REAL_FILE; nMAX_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 -2; if (!get_volume_number (file_name,volume_number_p)) IO_error ("can't determine volume number while opening file"); for (n=FIRST_REAL_FILE; n5) 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) IO_error ("FOpen: too many files"); } f=&file_table[fn]; fd=fopen (file_name_s,file_mode_string[file_mode]); if (fd==NULL){ free (file_name_s); return -1; } if (existing_fn==-2) #ifdef GNU_C get_file_number_and_device_number (file_name_s,&file_number,&device_number); #else get_file_number_and_device_number (file_name_s,&file_number,&volume_number); #endif f->file_number=file_number; #ifdef GNU_C f->device_number=device_number; #else f->volume_number=volume_number; #endif #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<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; } long close_file (long fn) { if (fnfile==NULL) IO_error ("FClose: File not open"); result=CLEAN_TRUE; if (fclose (f->file)!=0) result=0; free (f->file_name); #ifdef LINUX if (buffers[fn]!=NULL) free (buffers[fn]); #endif f->file=NULL; if (fn==number_of_files-1) --number_of_files; return result; } } long flush_file_buffer (long fn) { if (fn5) IO_error ("FReOpen: Invalid file mode"); if (fnfile)!=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_length=file_length; f->position=-2; f->position_2=-1; return result; } } int file_read_char (long fn) { if (fnmode & ~((1<file); } } int file_read_int (long fn,long *i_p) { if (fnmode & (1<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; #ifdef A64 *i_p=(long)*(int*)i_p; #endif } else if (f->mode & (1<file,"%ld",i_p)!=1) #else if (fscanf (f->file,"%d",i_p)!=1) #endif return 0; } else IO_error ("FReadI: read from an output file"); return -1; } } int file_read_real (long fn,double *r_p) { if (fnmode & (1<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<file,"%lg",r_p)!=1) return 0; } else IO_error ("FReadR: read from an output file"); return -1; } } #ifndef LINUX # define OLD_READ_STRING 1 # define OLD_WRITE_STRING 1 #endif #if OLD_READ_STRING unsigned long file_read_string (long fn,unsigned long max_length,struct clean_string *s) { #else unsigned long file_read_characters (long fn,unsigned long *length_p,char *s) { unsigned long max_length; max_length=*length_p; #endif unsigned long length; if (fncharacters,1,max_length,stdin); s->length=length; #else length = fread (s,1,max_length,stdin); *length_p=length; #endif return length; default: IO_error ("FReadS: can't open this file"); } } else { struct file *f; FILE *fd; f=&file_table[fn]; if (f->mode & ~((1<file; #if OLD_READ_STRING length = fread (s->characters,1,max_length,fd); s->length=length; #else length = fread (s,1,max_length,fd); *length_p=length; #endif return length; } } unsigned long file_read_line (long fn,unsigned long max_length,char *string) { unsigned long length; if (fnfile; length=0; c=0; if (f->mode & (1<mode & (1<mode & ~((1<file); } } #ifdef A64 void file_write_int (long i,long fn) #else void file_write_int (int i,long fn) #endif { if (fnmode & ~((1<mode & ((1<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 #ifdef A64 fprintf (f->file,"%ld",i); #else fprintf (f->file,"%d",i); #endif } } void file_write_real (double r,long fn) { if (fnmode & ~((1<mode & ((1<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); } } #if OLD_WRITE_STRING void file_write_string (struct clean_string *s,long fn) #else void file_write_characters (unsigned char *p,int length,long fn) #endif { if (fncharacters,s->length); #else ew_print_text (p,length); #endif break; case 1: #if OLD_WRITE_STRING w_print_text (s->characters,s->length); #else w_print_text (p,length); #endif break; default: IO_error ("FWriteS: can't open this file"); } } else { struct file *f; f=&file_table[fn]; if (f->mode & ~((1<characters,sizeof (char),s->length,f->file); #else fwrite (p,sizeof (char),length,f->file); #endif } } int file_end (long fn) { if (fnmode & ~((1<file; /* not portable to all compilers: */ #ifdef LINUX # if defined (MACH_O64) || defined (ANDROID) if (file_p->_r>0) # else /* if (file_p->_gptr < file_p->_egptr) */ if (file_p->_IO_read_ptr < file_p->_IO_read_end) # endif #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(unsigned)2) IO_error ("FSeek: invalid mode"); if (fnfile,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<=MAX_N_FILES){ for (fn=FIRST_REAL_FILE; fn=MAX_N_FILES) IO_error ("SFOpen: too many files"); } f=&file_table[fn]; fd=fopen (file_name_s,file_mode_string[file_mode]); if (fd==NULL){ free (file_name_s); return -1; } if (existing_fn==-2) #ifdef GNU_C get_file_number_and_device_number (file_name_s,&file_number,&device_number); #else get_file_number_and_device_number (file_name_s,&file_number,&volume_number); #endif f->file_number=file_number; #ifdef GNU_C f->device_number=device_number; #else f->volume_number=volume_number; #endif #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<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 (fnunique) IO_error ("SFReadC: can't read from a unique file"); if (f->mode & ~((1<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,long *i_p,unsigned long *position_p) { if (fnunique) IO_error ("SFReadI: can't read from a unique file"); if (f->position!=position) if (f->mode & ((1<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<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; #ifdef A64 *i_p=(long)*(int*)i_p; #endif } } } } } else if (f->mode & (1<file,"%ld",i_p)!=1) #else if (fscanf (f->file,"%d",i_p)!=1) #endif 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 (fnunique) IO_error ("SFReadR: can't read from a unique file"); position=*position_p; if (f->position!=position) if (f->mode & ((1<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<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<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 (fnunique) IO_error ("SFReadS: can't read from a unique file"); if (f->mode & ~((1<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 (fnunique) IO_error ("SFReadLine: can't read from a unique file"); if (f->mode & ~(1<mode & (1<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 (fnmode & ~((1<unique){ int c; FILE *file_p; file_p=f->file; /* not portable to all compilers: */ #ifdef LINUX # if defined (MACH_O64) || defined (ANDROID) if (file_p->_r>0) # else /* if (file_p->_gptr < file_p->_egptr) */ if (file_p->_IO_read_ptr < file_p->_IO_read_end) # endif #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 (fnunique){ 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 (fnunique) 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; } }