diff options
Diffstat (limited to 'mfileIO3.c')
-rw-r--r-- | mfileIO3.c | 2718 |
1 files changed, 2718 insertions, 0 deletions
diff --git a/mfileIO3.c b/mfileIO3.c new file mode 100644 index 0000000..413469e --- /dev/null +++ b/mfileIO3.c @@ -0,0 +1,2718 @@ +/* + File: mfileIO3.c + Written by: John van Groningen + At: University of Nijmegen +*/ + +#define MAC + +#if defined(powerc) || defined (MACHO) +# define USE_CLIB 1 +#else +# define USE_CLIB 0 +#endif + +#define NEWLINE_CHAR '\015' + +#include "mcon.h" + +extern void IO_error (char*); + +#ifndef MACHO +# include <Traps.h> +#endif +#include <Memory.h> +#include <Files.h> +#include <Errors.h> +#include <Script.h> + +#define EOF (-1) + +#define MAX_N_FILES 20 + +#define MAX_FILE_NAME_LENGTH 255 + +#define FIRST_REAL_FILE 4 + +#define F_SEEK_SET 0 +#define F_SEEK_CUR 1 +#define F_SEEK_END 2 + +#define pb_RefNum (((HIOParam*)&pb)->ioRefNum) +#define pb_Permssn (((HIOParam*)&pb)->ioPermssn) +#define pb_Misc (((HIOParam*)&pb)->ioMisc) +#define pb_PosMode (((HIOParam*)&pb)->ioPosMode) +#define pb_PosOffset (((HIOParam*)&pb)->ioPosOffset) +#define pb_Buffer (((HIOParam*)&pb)->ioBuffer) +#define pb_NamePtr (((HIOParam*)&pb)->ioNamePtr) +#define pb_VRefNum (((HIOParam*)&pb)->ioVRefNum) +#define pb_DirID (((HFileParam*)&pb)->ioDirID) +#define pb_FDirIndex (((HFileParam*)&pb)->ioFDirIndex) +#define pb_FlFndrInfo (((HFileParam*)&pb)->ioFlFndrInfo) +#define pb_ReqCount (((HIOParam*)&pb)->ioReqCount) +#define pb_ActCount (((HIOParam*)&pb)->ioActCount) + +struct file { /* 48 bytes */ + unsigned char * file_read_p; /* offset 0 */ + unsigned char * file_write_p; /* offset 4 */ + unsigned char * file_end_buffer_p; /* offset 8 */ + unsigned short file_mode; /* offset 12 */ + char file_unique; /* offset 14 */ + char file_error; /* offset 15 */ + + unsigned char * file_buffer_p; + + unsigned long file_offset; + unsigned long file_length; + + char * file_name; + long file_number; + unsigned long file_position; + unsigned long file_position_2; + + short file_refnum; + short file_volume_number; +}; + +struct clean_string { + long length; +#if (defined (powerc) && !defined (__MRC__)) || defined (MACHO) + char characters[0]; +#else + char characters[]; +#endif +}; + +#ifdef MAC +#define allocate_memory NewPtr +#define free_memory DisposePtr +#else +#define allocate_memory malloc +#define free_memory free +#endif + +static struct file file_table[MAX_N_FILES]; + +static int number_of_files=FIRST_REAL_FILE; + +#define is_special_file(f) ((long)(f)<(long)(&file_table[3])) + +static char *clean_to_c_string (struct clean_string *cs) +{ + int l; + char *cp,*s; + + cp=cs->characters; + l=cs->length; + + s=allocate_memory (l+1); + + if (s!=NULL){ + register char *sp; + + for (sp=s; l!=0; --l) + *sp++=*cp++; + *sp='\0'; + } + + return s; +} + +static void copy_c_to_p_string (unsigned char *ps,char *cs,int max_length) +{ + unsigned char *p,*max_p; + char c; + + p=ps+1; + + max_p=p+max_length; + + while ((c=*cs++)!=0){ + if (p>=max_p){ + *ps=0; + return; + } + *p++ = c; + } + + *ps=p-(ps+1); +} + +static int get_file_number (char *file_name,long *file_number_p) +{ + unsigned char file_name_s[MAX_FILE_NAME_LENGTH+1]; + HFileParam fileParam; + + copy_c_to_p_string (file_name_s,file_name,MAX_FILE_NAME_LENGTH); + if (file_name_s[0]==0) + return 0; + + fileParam.ioFDirIndex=0; + fileParam.ioNamePtr=file_name_s; + fileParam.ioVRefNum=0; + fileParam.ioFDirIndex=-1; + fileParam.ioDirID=0; + + if (PBHGetFInfoSync ((HParmBlkPtr)&fileParam)!=noErr) + return 0; + + *file_number_p= fileParam.ioDirID; + return 1; +} + +static int get_volume_number (char *file_name,short *volume_number_p) +{ + HVolumeParam volumeParam; + unsigned char file_name_s[MAX_FILE_NAME_LENGTH+1]; + + copy_c_to_p_string (file_name_s,file_name,MAX_FILE_NAME_LENGTH); + if (*file_name_s==0) + return 0; + + volumeParam.ioVolIndex=-1; + volumeParam.ioNamePtr=file_name_s; + volumeParam.ioVRefNum=0; + + if (PBHGetVInfoSync ((HParmBlkPtr)&volumeParam)!=noErr) + return 0; + + *volume_number_p=volumeParam.ioVRefNum; + return 1; +} + +static int file_exists (char *file_name,long *file_number_p,short *volume_number_p) +{ + int n; + + *volume_number_p=0; + + 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; n<number_of_files; ++n) + if (file_table[n].file_mode!=0 && + file_table[n].file_number==*file_number_p && + file_table[n].file_volume_number==*volume_number_p) + { + return n; + } + + return -1; +} + +#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 + +#define ERROR_FILE ((struct file*)-(long)&file_table[2]) + +static char file_permission[] ={ fsRdPerm,fsWrPerm,fsWrPerm,fsRdPerm,fsWrPerm,fsWrPerm }; + +OSType new_file_creator='3PRM'; + +struct file *open_file (struct clean_string *file_name,unsigned int file_mode) +{ + unsigned char p_file_name[MAX_FILE_NAME_LENGTH+1]; + char *file_name_s; + int fn,existing_fn; + struct file *f; + long file_length; + long file_number; + unsigned char *buffer; + short file_refnum,volume_number; + OSErr error; + HParamBlockRec pb; + unsigned int buffer_mask; + + buffer_mask = file_mode & ~255; + if (buffer_mask<8192) + buffer_mask=4095; + else if (buffer_mask>65535) + buffer_mask=65535; + else { + buffer_mask |= buffer_mask>>8; + buffer_mask |= buffer_mask>>4; + buffer_mask |= buffer_mask>>2; + buffer_mask |= buffer_mask>>1; + buffer_mask = (buffer_mask>>1) | 4095; + } + + file_mode &= 255; + + if (file_mode>5) + IO_error ("fopen: invalid file mode"); + + file_name_s=clean_to_c_string (file_name); + if (file_name_s==NULL){ + IO_error ("fopen: out of memory"); + return ERROR_FILE; + } + + existing_fn=file_exists (file_name_s,&file_number,&volume_number); + + if (existing_fn>=0){ + free_memory (file_name_s); + return ERROR_FILE; +/* 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_mode==0) + break; + + if (fn>=MAX_N_FILES){ + free_memory (file_name_s); + IO_error ("fopen: too many files"); + } + } + + f=&file_table[fn]; + + f->file_number=file_number; + f->file_volume_number=volume_number; + + copy_c_to_p_string (p_file_name,file_name_s,MAX_FILE_NAME_LENGTH); + + if (existing_fn==-2 && ((1<<file_mode) & ((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)))){ + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + + /* may be use HCreate, which also sets creator and filetype ? */ + + error=PBHCreateSync ((void*)&pb); + if (error!=noErr){ + free_memory (file_name_s); + return ERROR_FILE; + } + + pb_VRefNum=0; + pb_DirID=0; + pb_FDirIndex=0; + + if (PBHGetFInfoSync ((void*)&pb)==noErr){ + pb_VRefNum=0; + pb_DirID=0; + pb_FlFndrInfo.fdCreator=new_file_creator; + if ((1<<file_mode) & (1<<F_WRITE_TEXT)) + pb_FlFndrInfo.fdType='TEXT'; + PBHSetFInfoSync ((void*)&pb); + } + } + + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + pb_Misc=(Ptr)0; + pb_Permssn=file_permission[file_mode]; + + error=PBHOpenSync ((void*)&pb); + if (error!=noErr){ + free_memory (file_name_s); + return ERROR_FILE; + } + + file_refnum=pb_RefNum; + + buffer=allocate_memory (buffer_mask+1); + if (buffer==NULL){ + free_memory (file_name_s); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: out of memory"); + } + + f->file_buffer_p=buffer; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + f->file_offset=0; + + switch (file_mode){ + case F_WRITE_TEXT: + case F_WRITE_DATA: + pb_RefNum=file_refnum; + pb_Misc=(Ptr)0; + + error=PBSetEOFSync ((ParmBlkPtr)&pb); + + if (error!=noErr){ + free_memory (file_name_s); + free_memory (buffer); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: can't set eof"); + } + + file_length=0; + break; + case F_APPEND_TEXT: + case F_APPEND_DATA: + pb_RefNum=file_refnum; + pb_PosMode=fsFromLEOF; + pb_PosOffset=0; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + if (error!=noErr){ + free_memory (file_name_s); + free_memory (buffer); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: can't seek to eof"); + } + + file_length=pb_PosOffset; + f->file_offset=file_length; + + break; + default: + pb_RefNum=file_refnum; + + error=PBGetEOFSync ((ParmBlkPtr)&pb); + + file_length=(long)pb_Misc; + + if (error!=noErr){ + free_memory (file_name_s); + free_memory (buffer); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: can't get eof"); + } + } + + f->file_mode=(1<<file_mode) | (buffer_mask & ~255); + f->file_unique=1; + f->file_error=0; + + f->file_name=file_name_s; + f->file_length=file_length; + f->file_position=-2; + f->file_position_2=-1; + f->file_refnum=file_refnum; + + if (fn>=number_of_files) + number_of_files=fn+1; + + return f; +} + +static int stdio_open=0; + +struct file *open_stdio (void) +{ + if (stdio_open) + IO_error ("stdio: already open"); + + stdio_open=1; + return &file_table[1]; +} + +static int open_stderr_file_failed=0; + +static int open_stderr_file (void) +{ + unsigned char p_file_name[MAX_FILE_NAME_LENGTH+1]; + char *file_name_s; + int existing_fn; + struct file *f; + long file_length; + long file_number; + unsigned char *buffer; + short file_refnum,volume_number; + OSErr error; + unsigned int file_mode; + HParamBlockRec pb; + + file_name_s="Messages"; + + file_mode=F_WRITE_TEXT; + + if (!get_file_number (file_name_s,&file_number)) + existing_fn=-2; + else { + if (!get_volume_number (file_name_s,&volume_number)) + IO_error ("can't determine volume number while opening file"); + + existing_fn=-1; + } + + f=&file_table[3]; + f->file_number=file_number; + f->file_volume_number=volume_number; + + copy_c_to_p_string (p_file_name,file_name_s,MAX_FILE_NAME_LENGTH); + + if (existing_fn==-2){ + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + + error=PBHCreateSync ((void*)&pb); + if (error!=noErr){ + open_stderr_file_failed=1; + return 0; + } + + pb_VRefNum=0; + pb_DirID=0; + pb_FDirIndex=0; + + if (PBHGetFInfoSync ((void*)&pb)==noErr){ + pb_VRefNum=0; + pb_DirID=0; + pb_FlFndrInfo.fdCreator=new_file_creator; + pb_FlFndrInfo.fdType='TEXT'; + PBHSetFInfoSync ((void*)&pb); + } + } + + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + pb_Misc=(Ptr)0; + pb_Permssn=file_permission[file_mode]; + + error=PBHOpenSync ((void*)&pb); + if (error!=noErr){ + open_stderr_file_failed=1; + return 0; + } + + file_refnum=pb_RefNum; + + buffer=allocate_memory (4096); + if (buffer==NULL){ + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: out of memory"); + } + + f->file_buffer_p=buffer; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + f->file_offset=0; + + pb_RefNum=file_refnum; + pb_Misc=(Ptr)0; + + error=PBSetEOFSync ((ParmBlkPtr)&pb); + + if (error!=noErr){ + free_memory (buffer); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("fopen: can't set eof"); + } + + file_length=0; + + f->file_mode=(1<<file_mode); + f->file_unique=1; + f->file_error=0; + + f->file_name=file_name_s; + f->file_length=file_length; + f->file_position=-2; + f->file_position_2=-1; + f->file_refnum=file_refnum; + + return 1; +} + +extern long flags; + +struct file *open_stderr (void) +{ + if ((flags & 128) && file_table[3].file_mode==0 && !open_stderr_file_failed) + open_stderr_file(); + + return file_table; +} + +static int flush_write_buffer (struct file *f) +{ + if (f->file_mode & ((1<<F_WRITE_TEXT)|(1<<F_WRITE_DATA)|(1<<F_APPEND_TEXT)|(1<<F_APPEND_DATA))){ + unsigned char *buffer; + + buffer=f->file_buffer_p; + if (buffer!=f->file_end_buffer_p){ + OSErr error; + long count; + + count=f->file_write_p-buffer; + + if (count==0) + error=0; + else { + HParamBlockRec pb; + + pb_RefNum=f->file_refnum; + pb_Buffer=buffer; + pb_ReqCount=count; + + pb_PosMode=fsAtMark; + pb_PosOffset=0; + + error=PBWriteSync ((ParmBlkPtr)&pb); + + count=pb_ActCount; + + f->file_offset = pb_PosOffset; + } + + if (f->file_offset > f->file_length) + f->file_length=f->file_offset; + + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + + if (error!=noErr || count!=f->file_write_p-buffer){ + f->file_write_p=buffer; + f->file_error=-1; + return 0; + } + + f->file_write_p=buffer; + } + } + + return 1; +} + +int close_file (struct file *f) +{ + if (is_special_file (f)){ + if (f==&file_table[1]){ + if (!stdio_open) + IO_error ("fclose: file not open (stdio)"); + stdio_open=0; + } + return -1; + } else { + HParamBlockRec pb; + int result; + + if (f->file_mode==0) + IO_error ("fclose: file not open"); + + result=-1; + + if (f->file_error) + result=0; + + if (! flush_write_buffer (f)) + result=0; + + pb_RefNum=f->file_refnum; + if (PBCloseSync ((ParmBlkPtr)&pb)!=0) + result=0; + + free_memory (f->file_name); + free_memory (f->file_buffer_p); + + f->file_mode=0; + + return result; + } +} + +void close_stderr_file (void) +{ + if ((flags & 128) && file_table[3].file_mode!=0){ + HParamBlockRec pb; + struct file *f; + + f=&file_table[3]; + + flush_write_buffer (f); + + pb_RefNum=f->file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + + free_memory (f->file_buffer_p); + + f->file_mode=0; + } +} + +int re_open_file (struct file *f,unsigned int file_mode) +{ + HParamBlockRec pb; + unsigned int buffer_mask; + + buffer_mask = file_mode & ~255; + if (buffer_mask<8192) + buffer_mask=4095; + else if (buffer_mask>65535) + buffer_mask=65535; + else { + buffer_mask |= buffer_mask>>8; + buffer_mask |= buffer_mask>>4; + buffer_mask |= buffer_mask>>2; + buffer_mask |= buffer_mask>>1; + buffer_mask = (buffer_mask>>1) | 4095; + } + + file_mode &= 255; + + if (file_mode>5) + IO_error ("freopen: invalid file mode"); + + if (is_special_file (f)){ + if (f==file_table && (file_mode==F_READ_TEXT || file_mode==F_READ_DATA)) + IO_error ("freopen: stderr can't be opened for reading"); + if (f==&file_table[2]) + IO_error ("freopen: file not open"); + return -1; + } else { + long file_length; + unsigned char p_file_name[MAX_FILE_NAME_LENGTH+1]; + int result; + unsigned char *buffer; + short file_refnum; + OSErr error; + + result=-1; + + if (f->file_mode!=0){ + flush_write_buffer (f); + + pb_RefNum=f->file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + + if ((f->file_mode | 255)!=buffer_mask){ + free_memory (f->file_buffer_p); + + buffer=allocate_memory (buffer_mask+1); + if (buffer==NULL) + IO_error ("freopen: out of memory"); + f->file_buffer_p=buffer; + } + } else { + buffer=allocate_memory (buffer_mask+1); + if (buffer==NULL) + IO_error ("freopen: out of memory"); + f->file_buffer_p=buffer; + } + + f->file_mode=0; + + copy_c_to_p_string (p_file_name,f->file_name,MAX_FILE_NAME_LENGTH); + + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + pb_Misc=(Ptr)0; + pb_Permssn=file_permission[file_mode]; + + error=PBHOpenSync ((void*)&pb); + if (error!=noErr){ + free_memory (f->file_name); + free_memory (f->file_buffer_p); + return 0; + } + + file_refnum=pb_RefNum; + + f->file_offset=0; + + switch (file_mode){ + case F_WRITE_TEXT: + case F_WRITE_DATA: + pb_RefNum=file_refnum; + pb_Misc=(Ptr)0; + + error=PBSetEOFSync ((ParmBlkPtr)&pb); + + if (error!=noErr){ + free_memory (f->file_name); + free_memory (f->file_buffer_p); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("freopen: can't set eof"); + } + + file_length=0; + break; + case F_APPEND_TEXT: + case F_APPEND_DATA: + pb_RefNum=file_refnum; + pb_PosMode=fsFromLEOF; + pb_PosOffset=0; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + if (error!=noErr){ + free_memory (f->file_name); + free_memory (f->file_buffer_p); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("freopen: can't seek to eof"); + } + + file_length=pb_PosOffset; + f->file_offset=file_length; + break; + default: + pb_RefNum=file_refnum; + + error=PBGetEOFSync ((ParmBlkPtr)&pb); + + file_length=(long)pb_Misc; + + if (error!=noErr){ + free_memory (f->file_name); + free_memory (f->file_buffer_p); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("freopen: can't get eof"); + } + } + + f->file_refnum=file_refnum; + f->file_mode= (1<<file_mode) | (buffer_mask & ~255); + f->file_length=file_length; + f->file_position=-2; + f->file_position_2=-1; + f->file_error=0; + + buffer=f->file_buffer_p; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + return result; + } +} + +static void char_to_new_buffer (int c,struct file *f) +{ + long count; + unsigned char *buffer; + + flush_write_buffer (f); + + count=((f->file_mode | 255)+1) - (f->file_offset & (f->file_mode | 255)); + buffer=f->file_buffer_p; + + *buffer=c; + f->file_write_p=buffer+1; + buffer+=count; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; +} + +#if defined (__MWERKS__) || defined (powerc) +#define write_char(c,f) if ((f)->file_write_p<(f)->file_end_buffer_p) \ + *((f)->file_write_p)++=(c); \ + else \ + char_to_new_buffer((c),(f)) +#else +#define write_char(c,f) ((f)->file_write_p<(f)->file_end_buffer_p ? (*((f)->file_write_p)++=(c)) : char_to_new_buffer((c),(f))) +#endif + +static int char_from_new_buffer (struct file *f) +{ + OSErr error; + long count; + unsigned char *buffer; + HParamBlockRec pb; + int c; + + count=((f->file_mode | 255)+1) - (f->file_offset & (f->file_mode | 255)); + buffer=f->file_buffer_p; + + pb_RefNum=f->file_refnum; + pb_Buffer=buffer; + pb_ReqCount=count; + + pb_PosMode=fsAtMark; + pb_PosOffset=0; + + error=PBReadSync ((ParmBlkPtr)&pb); + if (error==eofErr) + error=noErr; + + count=pb_ActCount; + + f->file_offset = pb_PosOffset; + + if (error!=noErr) + f->file_error=-1; + + if (error!=noErr || count==0){ + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + return EOF; + } + + c=*buffer; + f->file_read_p=buffer+1; + buffer+=count; + f->file_end_buffer_p=buffer; + f->file_write_p=buffer; + + return c; +} + +#define read_char(f) ((f)->file_read_p<(f)->file_end_buffer_p ? *((f)->file_read_p)++ : char_from_new_buffer(f)) + +int file_read_char (struct file *f) +{ + if (f->file_read_p < f->file_end_buffer_p) + return *(f->file_read_p)++; + else { + if (is_special_file (f)){ + if (f==file_table) + IO_error ("freadc: can't read from stderr"); + else if (f==&file_table[1]) + return w_get_char(); + else + IO_error ("freadc: can't open this file"); + } else { + if (! (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA)))) + IO_error ("freadc: read from an output file"); + + return char_from_new_buffer (f); + } + } +} + +#define is_digit(n) ((unsigned)((n)-'0')<(unsigned)10) + +int file_read_int (struct file *f,int *i_p) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("freadi: can't read from stderr"); + else if (f==&file_table[1]) + return w_get_int (i_p); + else + IO_error ("freadi: can't open this file"); + } else { + *i_p=0; + + if (f->file_mode & (1<<F_READ_DATA)){ + int i; + + if ((i=read_char (f))==EOF){ + f->file_error=-1; + return 0; + } + ((char*)i_p)[0]=i; + if ((i=read_char (f))==EOF){ + f->file_error=-1; + return 0; + } + ((char*)i_p)[1]=i; + if ((i=read_char (f))==EOF){ + f->file_error=-1; + return 0; + } + ((char*)i_p)[2]=i; + if ((i=read_char (f))==EOF){ + f->file_error=-1; + return 0; + } + ((char*)i_p)[3]=i; + } else if (f->file_mode & (1<<F_READ_TEXT)){ + int c,negative,result; + + result=-1; + + while ((c=read_char (f))==' ' || c=='\t' || c=='\n' || c=='\r') + ; + + negative=0; + if (c=='+') + c=read_char (f); + else + if (c=='-'){ + c=read_char (f); + negative=1; + } + + if (!is_digit (c)){ + result=0; + f->file_error=-1; + } else { + unsigned int i; + + i=c-'0'; + + while (is_digit (c=read_char (f))){ + i+=i<<2; + i+=i; + i+=c-'0'; + }; + + if (negative) + i=-i; + + *i_p=i; + } + + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + + return result; + } else + IO_error ("freadi: read from an output file"); + + return -1; + } +} + +int file_read_real (struct file *f,double *r_p) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("freadr: can't read from stderr"); + else if (f==&file_table[1]) + return w_get_real (r_p); + else + IO_error ("freadr: can't open this file"); + } else { + *r_p=0.0; + + if (f->file_mode & (1<<F_READ_DATA)){ + int n; + + for (n=0; n<8; ++n){ + int i; + + if ((i=read_char (f))==EOF){ + f->file_error=-1; + return 0; + } + ((char*)r_p)[n]=i; + } + } else if (f->file_mode & (1<<F_READ_TEXT)){ + int c,dot,digits,result,n; + char s[256+1]; + + n=0; + + while ((c=read_char (f))==' ' || c=='\t' || c=='\n' || c=='\r') + ; + + if (c=='+') + c=read_char (f); + else + if (c=='-'){ + s[n++]=c; + c=read_char (f); + } + + dot=0; + digits=0; + + while (is_digit (c) || c=='.'){ + if (c=='.'){ + if (dot){ + dot=2; + break; + } + dot=1; + } else + digits=-1; + if (n<256) + s[n++]=c; + c=read_char (f); + } + + result=0; + if (digits) + if (dot==2 || ! (c=='e' || c=='E')) + result=-1; + else { + if (n<256) + s[n++]=c; + c=read_char (f); + + if (c=='+') + c=read_char (f); + else + if (c=='-'){ + if (n<256) + s[n++]=c; + c=read_char (f); + } + + if (is_digit (c)){ + do { + if (n<256) + s[n++]=c; + c=read_char (f); + } while (is_digit (c)); + + result=-1; + } + } + + if (n>=256) + result=0; + + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + + *r_p=0.0; + + if (result){ + s[n]='\0'; +#if USE_CLIB + if (sscanf (s,"%lg",r_p)!=1) + result=0; + else + result=-1; +#else + result=convert_string_to_real (s,r_p); +#endif + } + + if (!result) + f->file_error=-1; + + return result; + } else + IO_error ("freadr: read from an output file"); + + return -1; + } +} + +#define OLD_READ_STRING 0 +#define OLD_WRITE_STRING 0 + +#if OLD_READ_STRING +unsigned long file_read_string (struct file *f,unsigned long max_length,struct clean_string *s) +{ +#else +unsigned long file_read_characters (struct file *f,unsigned long *length_p,char *s) +{ + unsigned long max_length; + + max_length=*length_p; +#endif + if (is_special_file (f)){ + if (f==file_table) + IO_error ("freads: can't read from stderr"); + else if (f==&file_table[1]){ + char *string; + unsigned long length; + + length=0; + +#if OLD_READ_STRING + string=s->characters; +#else + string=s; +#endif + while (length!=max_length){ + *string++=w_get_char(); + ++length; + } + +#if OLD_READ_STRING + s->length=length; +#else + *length_p=length; +#endif + return length; + } else + IO_error ("freads: can't open this file"); + } else { + unsigned char *string,*end_string,*begin_string; + + if (! (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA)))) + IO_error ("freads: read from an output file"); + +#if OLD_READ_STRING + string=s->characters; +#else + string=s; +#endif + begin_string=string; + end_string=string+max_length; + + while (string<end_string){ + if (f->file_read_p < f->file_end_buffer_p){ + unsigned char *read_p; + long n; + + read_p=f->file_read_p; + + n=f->file_end_buffer_p-read_p; + if (n > end_string-string) + n=end_string-string; + + do { + *string++ = *read_p++; + } while (--n); + + f->file_read_p=read_p; + } else { + unsigned long align_buffer_mask; + + /* (unsigned long) cast added to prevent apple mpw c compiler from generating incorrect code */ + align_buffer_mask=~((unsigned long)f->file_mode | 255); + + if ((f->file_offset+(end_string-string) & align_buffer_mask) != (f->file_offset & align_buffer_mask)){ +/* if (end_string-string>=FILE_IO_BUFFER_SIZE && (f->file_offset & (FILE_IO_BUFFER_SIZE-1))==0){ */ + OSErr error; + long count; + unsigned char *buffer; + HParamBlockRec pb; + + count=end_string-string; + + if (f->file_offset+count < f->file_length) + count = (f->file_offset+count & align_buffer_mask) - f->file_offset; +/* count &= ~(FILE_IO_BUFFER_SIZE-1); */ + + pb_RefNum=f->file_refnum; + pb_Buffer=string; + pb_ReqCount=count; + + pb_PosMode=fsAtMark; + pb_PosOffset=0; + + error=PBReadSync ((ParmBlkPtr)&pb); + if (error==eofErr) + error=noErr; + + count=pb_ActCount; + + f->file_offset = pb_PosOffset; + + if (error!=noErr) + f->file_error=-1; + + buffer=f->file_buffer_p; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + string+=count; + + if (error!=noErr || count==0) +#if OLD_READ_STRING + return (s->length=string-begin_string); +#else + return (*length_p=string-begin_string); +#endif + } else { + int c; + + c=char_from_new_buffer (f); + if (c==EOF) + break; + *string++=c; + } + } + } + +#if OLD_READ_STRING + return (s->length=string-begin_string); +#else + return (*length_p=string-begin_string); +#endif + } +} + +unsigned long file_read_line (struct file *f,unsigned long max_length,char *string) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("freadline: can't read from stderr"); + else if (f==&file_table[1]){ + unsigned long length; + + length=0; + + while (length!=max_length){ + int c; + + c=w_get_char(); + *string++=c; + ++length; + if (c==NEWLINE_CHAR) + return length; + } + + return -1; + } else + IO_error ("freadline: can't open this file"); + } else { + unsigned char *end_string,*begin_string; + int c; + + begin_string=string; + end_string=string+max_length; + + c=0; + + if (f->file_mode & (1<<F_READ_TEXT)){ + while (string<end_string){ + if (f->file_read_p < f->file_end_buffer_p){ + unsigned char *read_p; + long n; + + read_p=f->file_read_p; + + n=f->file_end_buffer_p-read_p; + if (n > end_string-(unsigned char*)string) + n=end_string-(unsigned char*)string; + + do { + char ch; + + ch=*read_p++; + *string++=ch; + if (ch==NEWLINE_CHAR){ + f->file_read_p=read_p; + return (unsigned char*)string-begin_string; + } + } while (--n); + + c=0; + f->file_read_p=read_p; + } else { + c=char_from_new_buffer(f); + if (c==EOF) + break; + + *string++=c; + if (c==NEWLINE_CHAR) + return (unsigned char*)string-begin_string; + } + } + } else if (f->file_mode & (1<<F_READ_DATA)){ + while (string<end_string){ + if (f->file_read_p < f->file_end_buffer_p){ + unsigned char *read_p; + long n; + + read_p=f->file_read_p; + + n=f->file_end_buffer_p-read_p; + if (n > end_string-(unsigned char*)string) + n=end_string-(unsigned char*)string; + do { + char ch; + + ch=*read_p++; + + *string++=ch; + if (ch=='\xd'){ + if (n>1){ + if (*read_p=='\xa'){ + *string++='\xa'; + ++read_p; + } + f->file_read_p=read_p; + return (unsigned char*)string-begin_string; + } else if (read_p < f->file_end_buffer_p){ + f->file_read_p=read_p; + if (*read_p!='\xa'){ + return (unsigned char*)string-begin_string; + } else { + return -1; /* return \xd, read \xa next time */ + } + } else { + int c; + + f->file_read_p=read_p; + c=char_from_new_buffer(f); + read_p=f->file_read_p; + + if (c!='\xa'){ + if (read_p > f->file_buffer_p) + --read_p; + + f->file_read_p=read_p; + return (unsigned char*)string-begin_string; + } else { + if (string<end_string){ + *string++='\xa'; + f->file_read_p=read_p; + return (unsigned char*)string-begin_string; + } else { + if (read_p > f->file_buffer_p) + --read_p; + + f->file_read_p=read_p; + return -1; /* return \xd, read \xa next time */ + } + } + } + } else if (ch=='\xa'){ + f->file_read_p=read_p; + return (unsigned char*)string-begin_string; + } + } while (--n); + + c=0; + f->file_read_p=read_p; + } else { + c=char_from_new_buffer(f); + if (c==EOF) + break; + + *string++=c; + + if (c=='\xd'){ + c = read_char (f); + if (string<end_string){ + if (c=='\xa') + *string++=c; + else + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + } else { + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + + if (c=='\xa') + return -1; + } + + return (unsigned char*)string-begin_string; + } else if (c=='\xa') + return (unsigned char*)string-begin_string; + } + } + } else + IO_error ("freadline: read from an output file"); + + if (c!=EOF) + return -1; + + return (unsigned char*)string-begin_string; + } +} + +void file_write_char (int c,struct file *f) +{ + if (f->file_write_p < f->file_end_buffer_p) + *(f->file_write_p)++=c; + else { + if (is_special_file (f)){ + if (f==file_table){ + ew_print_char (c); + + if (!(flags & 128)) + return; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + + if (f->file_write_p < f->file_end_buffer_p) + *(f->file_write_p)++=c; + else + char_to_new_buffer (c,f); + + return; + } else if (f==&file_table[1]){ + w_print_char (c); + return; + } else { + IO_error ("fwritec: can't open this file"); + return; + } + } + + if (! (f->file_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"); + + char_to_new_buffer (c,f); + } +} + +#if !USE_CLIB +extern char *convert_int_to_string (char *string,int i); +extern char *convert_real_to_string (char *string,double *r_p); +#endif + +void file_write_int (int i,struct file *f) +{ + if (is_special_file (f)){ + if (f==file_table){ + ew_print_int (i); + + if (!(flags & 128)) + return; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + } else if (f==&file_table[1]){ + w_print_int (i); + return; + } else { + IO_error ("fwritei: can't open this file"); + return; + } + } + + if (! (f->file_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->file_mode & ((1<<F_WRITE_DATA)|(1<<F_APPEND_DATA))){ +#if defined (powerc) + /* work around bug in apple compiler for power macintosh */ + write_char (i>>24,f); + write_char (i>>16,f); + write_char (i>>8,f); + write_char (i,f); +#else + int v=i; + + write_char (((char*)&v)[0],f); + write_char (((char*)&v)[1],f); + write_char (((char*)&v)[2],f); + write_char (((char*)&v)[3],f); +#endif + } else { + unsigned char string[24],*end_p,*s; + int length; + +#if USE_CLIB + sprintf (string,"%d",i); + { + char *p; + + length=0; + for (p=string; *p; ++p) + ++length; + } +#else + end_p=convert_int_to_string (string,i); + length=end_p-string; +#endif + + s=string; + do { + write_char (*s++,f); + } while (--length); + } +} + +void file_write_real (double r,struct file *f) +{ + if (is_special_file (f)){ + if (f==file_table){ + ew_print_real (r); + + if (!(flags & 128)) + return; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + } else if (f==&file_table[1]){ + w_print_real (r); + return; + } else { + IO_error ("fwriter: can't open this file"); + return; + } + } + + if (! (f->file_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->file_mode & ((1<<F_WRITE_DATA)|(1<<F_APPEND_DATA))){ +#ifdef powerc + /* work around bug in apple compiler for power macintosh */ + int i1,i2; + + i1=((int*)&r)[0]; + i2=((int*)&r)[1]; + + write_char (i1>>24,f); + write_char (i1>>16,f); + write_char (i1>>8,f); + write_char (i1,f); + write_char (i2>>24,f); + write_char (i2>>16,f); + write_char (i2>>8,f); + write_char (i2,f); +#else + double v=r; + + write_char (((char*)&v)[0],f); + write_char (((char*)&v)[1],f); + write_char (((char*)&v)[2],f); + write_char (((char*)&v)[3],f); + write_char (((char*)&v)[4],f); + write_char (((char*)&v)[5],f); + write_char (((char*)&v)[6],f); + write_char (((char*)&v)[7],f); +#endif + } else { + unsigned char string[32],*end_p,*s; + int length; + +#if USE_CLIB + sprintf (string,"%.15g",r); + { + char *p; + + length=0; + for (p=string; *p; ++p) + ++length; + } +#else + end_p=convert_real_to_string (string,&r); + length=end_p-string; +#endif + s=string; + do { + write_char (*s++,f); + } while (--length); + } +} + +#if OLD_WRITE_STRING +void file_write_string (struct clean_string *s,struct file *f) +#else +void file_write_characters (unsigned char *p,int length,struct file *f) +#endif +{ + if (is_special_file (f)){ + if (f==file_table){ +#if OLD_WRITE_STRING + ew_print_text (s->characters,s->length); +#else + ew_print_text (p,length); +#endif + if (!(flags & 128)) + return; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + } else if (f==&file_table[1]){ +#if OLD_WRITE_STRING + w_print_text (s->characters,s->length); +#else + w_print_text (p,length); +#endif + return; + } else { + IO_error ("fwrites: can't open this file"); + return; + } + } + + { +#if OLD_WRITE_STRING + unsigned char *p,*end_p; +#else + unsigned char *end_p; +#endif + if (! (f->file_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"); + +#if OLD_WRITE_STRING + p=s->characters; + end_p=p+s->length; +#else + end_p=p+length; +#endif + + while (p<end_p){ + if (f->file_write_p < f->file_end_buffer_p){ + unsigned char *write_p; + long n; + + write_p=f->file_write_p; + + n=f->file_end_buffer_p-write_p; + if (n>end_p-p) + n=end_p-p; + + do { + *write_p++ = *p++; + } while (--n); + + f->file_write_p=write_p; + } else + char_to_new_buffer (*p++,f); + } + } +} + +int file_end (struct file *f) +{ + if (f->file_read_p < f->file_end_buffer_p) + return 0; + + if (is_special_file (f)){ + if (f==file_table || f==&file_table[1]) + IO_error ("fend: not allowed for stdio and stderr"); + else + IO_error ("fend: can't open file"); + } else { + if (! (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA)))) + IO_error ("fend: not allowed for output files"); + + if (f->file_offset < f->file_length) + return 0; + + return -1; + } +} + +int file_error (struct file *f) +{ + if (is_special_file (f)){ + if (f==file_table || f==&file_table[1]) + return 0; + else + return -1; + } else + return f->file_error; +} + +unsigned long file_position (struct file *f) +{ + if (is_special_file (f)){ + if (f==file_table || f==&file_table[1]) + IO_error ("fposition: not allowed for stdio and stderr"); + else + IO_error ("fposition: can't open file"); + } else { + unsigned long position; + + if (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + position=f->file_offset - (f->file_end_buffer_p - f->file_read_p); + else + position=f->file_offset + (f->file_write_p - f->file_buffer_p); + + return position; + } +} + +int file_seek (struct file *f,unsigned long position,unsigned long seek_mode) +{ + HParamBlockRec pb; + + if (is_special_file (f)){ + if (seek_mode>(unsigned)2) + IO_error ("fseek: invalid mode"); + + if (f==file_table || f==&file_table[1]) + IO_error ("fseek: can't seek on stdio and stderr"); + else + IO_error ("fseek: can't open file"); + } else { + long current_position; + unsigned long buffer_size; + + if (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA))){ + current_position=f->file_offset - (f->file_end_buffer_p - f->file_read_p); + + switch (seek_mode){ + case F_SEEK_SET: + break; + case F_SEEK_CUR: + position+=current_position; + break; + case F_SEEK_END: + position=f->file_length-position; + break; + default: + IO_error ("fseek: invalid mode"); + } + + buffer_size=f->file_end_buffer_p - f->file_buffer_p; + if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){ + f->file_read_p = f->file_buffer_p + (position - (f->file_offset-buffer_size)); + + return -1; + } else { + unsigned char *buffer; + OSErr error; + + if (position<0 || position>f->file_length){ + f->file_error=-1; + return 0; + } + + buffer=f->file_buffer_p; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + pb_RefNum=f->file_refnum; + pb_PosMode=fsFromStart; + pb_PosOffset=position; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + f->file_offset=pb_PosOffset; + + if (error!=noErr){ + f->file_error=-1; + return 0; + } + + return -1; + } + } else { + OSErr error; + int result; + + result=-1; + + current_position=f->file_offset + (f->file_write_p - f->file_buffer_p); + + if (current_position > f->file_length) + f->file_length=current_position; + + switch (seek_mode){ + case F_SEEK_SET: + break; + case F_SEEK_CUR: + position+=current_position; + break; + case F_SEEK_END: + position=f->file_length-position; + break; + default: + IO_error ("fseek: invalid mode"); + } + + if (position==current_position) + return -1; + + if (! flush_write_buffer (f)){ + f->file_error=-1; + result=0; + } + + if (position<0 || position>f->file_length){ + f->file_error=-1; + return 0; + } + + pb_RefNum=f->file_refnum; + pb_PosMode=fsFromStart; + pb_PosOffset=position; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + f->file_offset=pb_PosOffset; + + if (error!=noErr){ + f->file_error=-1; + result=0; + } + + return result; + } + } +} + +struct file *open_s_file (struct clean_string *file_name,unsigned int file_mode) +{ + unsigned char p_file_name[MAX_FILE_NAME_LENGTH+1]; + int fn,existing_fn; + char *file_name_s; + struct file *f; + long file_length; + long file_number; + short volume_number,file_refnum; + unsigned char *buffer; + OSErr error; + HParamBlockRec pb; + unsigned int buffer_mask; + + buffer_mask = file_mode & ~255; + if (buffer_mask<8192) + buffer_mask=4095; + else if (buffer_mask>65535) + buffer_mask=65535; + else { + buffer_mask |= buffer_mask>>8; + buffer_mask |= buffer_mask>>4; + buffer_mask |= buffer_mask>>2; + buffer_mask |= buffer_mask>>1; + buffer_mask = (buffer_mask>>1) | 4095; + } + + file_mode &= 255; + + 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); + if (file_name_s==NULL){ + IO_error ("sfopen: out of memory"); + return ERROR_FILE; + } + + existing_fn=file_exists (file_name_s,&file_number,&volume_number); + + if (existing_fn>=0){ + if (file_table[existing_fn].file_unique) + IO_error ("sfopen: file already opened by fopen"); + + if ((file_table[existing_fn].file_mode & 255)!=(1<<file_mode)) + IO_error ("sfopen: file already open in another file mode"); + + free_memory (file_name_s); + + return &file_table[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_mode==0) + break; + + if (fn>=MAX_N_FILES) + IO_error ("sfopen: too many files"); + } + f=&file_table[fn]; + + f->file_number=file_number; + f->file_volume_number=volume_number; + + copy_c_to_p_string (p_file_name,file_name_s,MAX_FILE_NAME_LENGTH); + + pb_NamePtr=p_file_name; + pb_VRefNum=0; + pb_DirID=0; + pb_Misc=(Ptr)0; + pb_Permssn=file_permission[file_mode]; + + error=PBHOpenSync ((void*)&pb); + if (error!=noErr){ + free_memory (file_name_s); + return ERROR_FILE; + } + + file_refnum=pb_RefNum; + + buffer=allocate_memory (buffer_mask+1); + if (buffer==NULL){ + free_memory (file_name_s); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("sfopen: out of memory"); + } + + f->file_buffer_p=buffer; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + f->file_offset=0; + + pb_RefNum=file_refnum; + + error=PBGetEOFSync ((ParmBlkPtr)&pb); + + file_length=(long)pb_Misc; + + if (error!=noErr){ + free_memory (file_name_s); + free_memory ((char*)buffer); + pb_RefNum=file_refnum; + PBCloseSync ((ParmBlkPtr)&pb); + IO_error ("sfopen: can't get eof"); + } + + f->file_refnum=file_refnum; + f->file_mode= (1<<file_mode) | (buffer_mask & ~255); + f->file_unique=0; + f->file_error=0; + + f->file_name=file_name_s; + f->file_length=file_length; + f->file_position=-2; + f->file_position_2=-1; + + if (fn>=number_of_files) + number_of_files=fn+1; + + return f; +} + +void file_share (struct file *f) +{ + f->file_unique=0; +} + +static int simple_seek (struct file *f,long position) +{ + int result; + long buffer_size; + HParamBlockRec pb; + + result=1; + + buffer_size=f->file_end_buffer_p - f->file_buffer_p; + if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){ + f->file_read_p = f->file_buffer_p + (position - (f->file_offset-buffer_size)); + f->file_position=position; + } else { + unsigned char *buffer; + OSErr error; + + if (position<0 || position>f->file_length){ + f->file_error=-1; + result=0; + } else { + buffer=f->file_buffer_p; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + pb_RefNum=f->file_refnum; + pb_PosMode=fsFromStart; + pb_PosOffset=position; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + f->file_offset=pb_PosOffset; + + if (error!=noErr){ + f->file_error=-1; + result=0; + } + f->file_position=position; + } + } + + return result; +} + +int file_read_s_char (struct file *f,unsigned long *position_p) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("sfreadc: can't read from stderr"); + else if (f==&file_table[1]) + IO_error ("sfreadc: can't read from stdio, use freadc"); + else + IO_error ("sfreadc: can't open this file"); + } else { + int c; + unsigned long position; + + position=*position_p; + + if (f->file_position!=position){ + if (f->file_unique) + IO_error ("sfreadc: can't read from a unique file"); + + switch (position){ + case -1l: + if (position!=f->file_position_2) + position=f->file_position_2; + else { + position=f->file_offset + (f->file_write_p - f->file_buffer_p); + f->file_position_2=position; + break; + } + default: + if (!simple_seek (f,position)) + IO_error ("sfreadc: seek failed"); + } + } + + if (f->file_read_p < f->file_end_buffer_p){ + c=*f->file_read_p++; + ++position; + } else { + c=char_from_new_buffer(f); + if (c!=EOF) + ++position; + } + + f->file_position=position; + *position_p=position; + + return c; + } +} + +int file_read_s_int (struct file *f,int *i_p,unsigned long *position_p) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("sfreadi: can't read from stderr"); + else if (f==&file_table[1]) + IO_error ("sfreadi: can't read from stdio, use freadi"); + else + IO_error ("sfreadi: can't open this file"); + } else { + int result; + unsigned long position; + + position=*position_p; + + if (f->file_position!=position){ + if (f->file_unique) + IO_error ("sfreadi: can't read from a unique file"); + + switch (position){ + case -1l: + if (position!=f->file_position_2) + position=f->file_position_2; + else { + position=position=f->file_offset + (f->file_write_p - f->file_buffer_p); + f->file_position_2=position; + break; + } + default: + if (!simple_seek (f,position)) + IO_error ("sfreadi: seek failed"); + } + } + + *i_p=0; + + result=-1; + if (f->file_mode & (1<<F_READ_DATA)){ + int i; + + if ((i=read_char (f))==EOF){ + f->file_error=-1; + result=0; + } else { + ((char*)i_p)[0]=i; + if ((i=read_char (f))==EOF){ + ++position; + f->file_error=-1; + result=0; + } else { + ((char*)i_p)[1]=i; + if ((i=read_char (f))==EOF){ + position+=2; + f->file_error=-1; + result=0; + } else { + ((char*)i_p)[2]=i; + if ((i=read_char (f))==EOF){ + position+=3; + f->file_error=-1; + result=0; + } else { + ((char*)i_p)[3]=i; + position+=4; + } + } + } + } + } else if (f->file_mode & (1<<F_READ_TEXT)){ + int c,negative,n_characters; + + n_characters=-1; + ++n_characters; + while ((c=read_char (f))==' ' || c=='\t' || c=='\n' || c=='\r') + ++n_characters; + + negative=0; + if (c=='+'){ + c=read_char (f); + ++n_characters; + } else + if (c=='-'){ + c=read_char (f); + ++n_characters; + negative=1; + } + + if (!is_digit (c)){ + f->file_error=-1; + result=0; + } else { + unsigned int i; + + i=c-'0'; + + ++n_characters; + while (is_digit (c=read_char (f))){ + i+=i<<2; + i+=i; + i+=c-'0'; + ++n_characters; + }; + + if (negative) + i=-i; + + *i_p=i; + } + + position+=n_characters; + + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + } + + f->file_position=position; + *position_p=position; + + return result; + } +} + +int file_read_s_real (struct file *f,double *r_p,unsigned long *position_p) +{ + if (is_special_file (f)){ + if (f==file_table) + IO_error ("sfreadr: can't read from stderr"); + else if (f==&file_table[1]) + IO_error ("sfreadr: can't read from stdio, use freadr"); + else + IO_error ("sfreadr: can't open this file"); + } else { + int result; + unsigned long position; + + position=*position_p; + if (f->file_position!=position){ + if (f->file_unique) + IO_error ("sfreadr: can't read from a unique file"); + + switch (position){ + case -1l: + if (position!=f->file_position_2) + position=f->file_position_2; + else { + position=position=f->file_offset + (f->file_write_p - f->file_buffer_p); + f->file_position_2=position; + break; + } + default: + if (!simple_seek (f,position)) + IO_error ("sfreadr: seek failed"); + } + } + + *r_p=0.0; + + if (f->file_mode & (1<<F_READ_DATA)){ + int n; + + result=-1; + for (n=0; n<8; ++n){ + int i; + + if ((i=read_char (f))==EOF){ + f->file_error=-1; + result=0; + break; + } + ((char*)r_p)[n]=i; + } + + position+=n; + } else if (f->file_mode & (1<<F_READ_TEXT)){ + int c,dot,digits,result,n,n_characters; + char s[256+1]; + + n_characters=-1; + + n=0; + + ++n_characters; + while ((c=read_char (f))==' ' || c=='\t' || c=='\n' || c=='\r') + ++n_characters; + + if (c=='+'){ + c=read_char (f); + ++n_characters; + } else + if (c=='-'){ + s[n++]=c; + c=read_char (f); + ++n_characters; + } + + dot=0; + digits=0; + + while (is_digit (c) || c=='.'){ + if (c=='.'){ + if (dot){ + dot=2; + break; + } + dot=1; + } else + digits=-1; + if (n<256) + s[n++]=c; + c=read_char (f); + ++n_characters; + } + + result=0; + if (digits) + if (dot==2 || ! (c=='e' || c=='E')) + result=-1; + else { + if (n<256) + s[n++]=c; + c=read_char (f); + ++n_characters; + + if (c=='+'){ + c=read_char (f); + ++n_characters; + } else + if (c=='-'){ + if (n<256) + s[n++]=c; + c=read_char (f); + ++n_characters; + } + + if (is_digit (c)){ + do { + if (n<256) + s[n++]=c; + c=read_char (f); + ++n_characters; + } while (is_digit (c)); + + result=-1; + } + } + + if (n>=256) + result=0; + + position+=n_characters; + + if (f->file_read_p > f->file_buffer_p) + --f->file_read_p; + + *r_p=0.0; + + if (result){ + s[n]='\0'; +#if USE_CLIB + if (sscanf (s,"%lg",r_p)!=1) + result=0; + else + result=-1; +#else + result=convert_string_to_real (s,r_p); +#endif + } + + if (!result) + f->file_error=-1; + } + + f->file_position=position; + *position_p=position; + + return result; + } +} + +unsigned long file_read_s_string + (struct file *f,unsigned long max_length,struct clean_string *s,unsigned long *position_p) +{ + unsigned long length; + + if (is_special_file (f)){ + if (f==file_table) + IO_error ("sfreads: can't read from stderr"); + else if (f==&file_table[1]) + IO_error ("sfreads: can't read from stdio, use freads"); + else + IO_error ("sfreads: can't open this file"); + } else { + unsigned long position; + char *string; + int c; + + position=*position_p; + if (f->file_position!=position){ + if (f->file_unique) + IO_error ("sfreads: can't read from a unique file"); + + switch (position){ + case -1l: + if (position!=f->file_position_2) + position=f->file_position_2; + else { + position=f->file_offset + (f->file_write_p - f->file_buffer_p); + f->file_position_2=position; + break; + } + default: + if (!simple_seek (f,position)) + IO_error ("sfreads: seek failed"); + } + } + + length=0; + string=s->characters; + + while (length!=max_length && ((c=read_char (f))!=EOF)){ + *string++=c; + ++length; + } + + s->length=length; + + position+=length; + + f->file_position=position; + *position_p=position; + + return length; + } +} + +unsigned long file_read_s_line + (struct file *f,unsigned long max_length,char *string,unsigned long *position_p) +{ + unsigned long length; + + if (is_special_file (f)){ + if (f==file_table) + IO_error ("sfreadline: can't read from stderr"); + else if (f==&file_table[1]) + IO_error ("sfreadline: can't read from stdio, use freadline"); + else + IO_error ("sfreadline: can't open this file"); + } else { + unsigned long position; + int c; + + position=*position_p; + if (f->file_position!=position){ + if (f->file_unique) + IO_error ("sfreadline: can't read from a unique file"); + + if (! (f->file_mode & (1<<F_READ_TEXT))) + IO_error ("sfreadline: read from a data file"); + + switch (position){ + case -1l: + if (position!=f->file_position_2) + position=f->file_position_2; + else { + position=f->file_offset + (f->file_write_p - f->file_buffer_p); + f->file_position_2=position; + break; + } + default: + if (!simple_seek (f,position)) + IO_error ("sfreadline: seek failed"); + } + } + + length=0; + + c=0; + while (length!=max_length && ((c=read_char (f))!=EOF)){ + *string++=c; + ++length; + if (c==NEWLINE_CHAR) + break; + } + + position+=length; + + f->file_position=position; + *position_p=position; + + if (c!=NEWLINE_CHAR && c!=EOF) + return -1; + + return length; + } +} + +int file_s_end (struct file *f,unsigned long position) +{ + if (is_special_file (f)){ + if (f==file_table || f==&file_table[1]) + IO_error ("sfend: not allowed for stdio and stderr"); + else + IO_error ("sfend: can't open file"); + } else { + if (f->file_unique){ + if (! (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA)))) + IO_error ("sfend: not allowed for output files"); + + if (f->file_read_p < f->file_end_buffer_p) + return 0; + + if (f->file_offset < f->file_length) + return 0; + + return -1; + } else { + if (position==-1l){ + if (f->file_position_2!=-1l) + position=f->file_position_2; + else { + position=f->file_offset + (f->file_end_buffer_p - f->file_read_p); + f->file_position=position; + f->file_position_2=position; + } + } + + return (position==f->file_length) ? -1 : 0; + } + } +} + +unsigned long file_s_position (struct file *f,unsigned long position) +{ + if (is_special_file (f)){ + if (f==file_table || f==&file_table[1]) + IO_error ("sfposition: not allowed for stdio and stderr"); + else + IO_error ("sfposition: can't open file"); + } else { + if (f->file_unique){ + if (f->file_mode & ((1<<F_READ_TEXT) | (1<<F_READ_DATA))) + position=f->file_offset - (f->file_end_buffer_p - f->file_read_p); + else + position=f->file_offset + (f->file_write_p - f->file_buffer_p); + + return position; + } else { + if (position==-1l){ + if (f->file_position_2!=-1l) + return f->file_position_2; + else { + position=f->file_offset - (f->file_end_buffer_p - f->file_read_p); + + f->file_position=position; + f->file_position_2=position; + } + } + + return position; + } + } +} + +#define F_SEEK_SET 0 +#define F_SEEK_CUR 1 +#define F_SEEK_END 2 + +int file_s_seek (struct file *f,unsigned long position,unsigned long seek_mode,unsigned long *position_p) +{ + HParamBlockRec pb; + + if (is_special_file (f)){ + if (seek_mode>(unsigned)2) + IO_error ("sfseek: invalid mode"); + + if (f==file_table) + IO_error ("sfseek: can't seek on stdio"); + else if (f==&file_table[1]) + IO_error ("sfseek: can't seek on stderr"); + else + IO_error ("sfseek: can't open file"); + } else { + long current_position,buffer_size; + int result; + + result=-1; + + if (f->file_unique) + IO_error ("sfseek: can't seek on a unique file"); + + current_position=f->file_offset - (f->file_end_buffer_p - f->file_read_p); + + if (*position_p==-1l){ + if (f->file_position_2!=-1l) + *position_p=f->file_position_2; + else { + f->file_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; + break; + default: + IO_error ("sfseek: invalid mode"); + } + + buffer_size=f->file_end_buffer_p - f->file_buffer_p; + if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){ + f->file_read_p = f->file_buffer_p + (position - (f->file_offset-buffer_size)); + f->file_position=position; + } else { + unsigned char *buffer; + OSErr error; + + if (position<0 || position>f->file_length){ + f->file_error=-1; + result=0; + f->file_position=current_position; + } else { + buffer=f->file_buffer_p; + f->file_end_buffer_p=buffer; + f->file_read_p=buffer; + f->file_write_p=buffer; + + pb_RefNum=f->file_refnum; + pb_PosMode=fsFromStart; + pb_PosOffset=position; + + error=PBSetFPosSync ((ParmBlkPtr)&pb); + + f->file_offset=pb_PosOffset; + + if (error!=noErr){ + f->file_error=-1; + result=0; + } + + f->file_position=position; + } + } + + *position_p=position; + + return result; + } +} + +void er_print_char (char c) +{ + ew_print_char (c); + + if (flags & 128){ + struct file *f; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + + if (f->file_write_p < f->file_end_buffer_p) + *(f->file_write_p)++=c; + else + char_to_new_buffer (c,f); + } +} + +void er_print_int (int i) +{ + ew_print_int (i); + + if (flags & 128){ + if (file_table[3].file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + + file_write_int (i,&file_table[3]); + } +} + +static void write_chars (unsigned char *p,unsigned char *end_p,struct file *f) +{ + while (p<end_p){ + if (f->file_write_p < f->file_end_buffer_p){ + unsigned char *write_p; + long n; + + write_p=f->file_write_p; + + n=f->file_end_buffer_p-write_p; + if (n>end_p-p) + n=end_p-p; + + do { + *write_p++ = *p++; + } while (--n); + + f->file_write_p=write_p; + } else + char_to_new_buffer (*p++,f); + } +} + +void er_print_text (char *s,unsigned long length) +{ + ew_print_text (s,length); + + if (flags & 128){ + struct file *f; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + + write_chars (s,s+length,f); + } +} + +void er_print_string (char *s) +{ + ew_print_string (s); + + if (flags & 128){ + unsigned char *end_p; + struct file *f; + + f=&file_table[3]; + if (f->file_mode==0){ + if (open_stderr_file_failed || !open_stderr_file()) + return; + } + + end_p=s; + while (*end_p) + ++end_p; + + write_chars (s,end_p,f); + } +} |