summaryrefslogtreecommitdiff
path: root/wfileIO3.c
diff options
context:
space:
mode:
Diffstat (limited to 'wfileIO3.c')
-rw-r--r--wfileIO3.c2468
1 files changed, 2468 insertions, 0 deletions
diff --git a/wfileIO3.c b/wfileIO3.c
new file mode 100644
index 0000000..05e5bc0
--- /dev/null
+++ b/wfileIO3.c
@@ -0,0 +1,2468 @@
+/*
+ File: wfileIO3.c
+ Written by: John van Groningen
+ At: University of Nijmegen
+*/
+
+#include "wcon.h"
+
+#ifdef WINDOWS
+# include <windows.h>
+# define HFILE HANDLE
+# define ULONG unsigned long
+# define OS(w,o) w
+
+# ifndef FILE_END
+# define FILE_END 2
+# endif
+# ifndef FILE_BEGIN
+# define FILE_BEGIN 0
+# endif
+ extern DWORD __attribute__ ((stdcall)) GetFileSize (HANDLE,LPDWORD);
+#else
+# define INCL_DOSFILEMGR
+# include "os2.h"
+# define OS(w,o) o
+#endif
+
+extern void IO_error (char*);
+extern void *allocate_memory (int);
+extern void free_memory (void*);
+
+#define EOF (-1)
+
+#define CLEAN_TRUE 1
+#define CLEAN_BOOL int
+
+#define MAX_N_FILES 20
+
+#define MAX_FILE_NAME_LENGTH 255
+
+#define FIRST_REAL_FILE 3
+
+#define F_SEEK_SET 0
+#define F_SEEK_CUR 1
+#define F_SEEK_END 2
+
+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 */
+ 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;
+
+ HFILE file_refnum;
+};
+
+struct clean_string {
+ long length;
+ char characters[0];
+};
+
+#ifndef WINDOWS
+static
+#endif
+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[FIRST_REAL_FILE]))
+
+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;
+}
+
+#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 OS(DWORD,ULONG) file_permission[]={
+#ifdef WINDOWS
+ GENERIC_READ,
+ GENERIC_WRITE,
+ GENERIC_READ | GENERIC_WRITE,
+ GENERIC_READ,
+ GENERIC_WRITE,
+ GENERIC_READ | GENERIC_WRITE
+#else
+ OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
+ OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE,
+ OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE,
+ OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE,
+ OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE,
+ OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE
+#endif
+};
+
+static OS(DWORD,ULONG) file_action[]={
+#ifdef WINDOWS
+ OPEN_EXISTING,
+ CREATE_ALWAYS,
+ OPEN_ALWAYS,
+ OPEN_EXISTING,
+ CREATE_ALWAYS,
+ OPEN_ALWAYS
+#else
+ FILE_OPEN,
+ FILE_TRUNCATE | FILE_CREATE,
+ FILE_OPEN | FILE_CREATE,
+ FILE_OPEN,
+ FILE_TRUNCATE | FILE_CREATE,
+ FILE_OPEN | FILE_CREATE
+#endif
+};
+
+struct file *open_file (struct clean_string *file_name,unsigned int file_mode)
+{
+ char *file_name_s;
+ int fn;
+ struct file *f;
+ long file_length;
+ unsigned char *buffer;
+ HFILE file_handle;
+ ULONG action;
+ OS(DWORD,APIRET) error;
+
+ 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;
+ }
+
+ 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];
+
+#ifdef WINDOWS
+ file_handle=CreateFileA (file_name_s,file_permission[file_mode],file_permission[file_mode]==GENERIC_READ ? FILE_SHARE_READ : 0,NULL,
+ file_action[file_mode],FILE_ATTRIBUTE_NORMAL,NULL);
+ if (file_handle==INVALID_HANDLE_VALUE){
+ free_memory (file_name_s);
+ return ERROR_FILE;
+ }
+#else
+ error=DosOpen (file_name_s,&file_handle,&action,0,FILE_NORMAL,
+ file_action[file_mode],file_permission[file_mode],NULL);
+ if (error!=0){
+ free_memory (file_name_s);
+ return ERROR_FILE;
+ }
+#endif
+
+ buffer=allocate_memory (FILE_IO_BUFFER_SIZE);
+ if (buffer==NULL){
+ free_memory (file_name_s);
+ OS(CloseHandle,DosClose) (file_handle);
+ 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:
+ file_length=0;
+ break;
+ case F_APPEND_TEXT:
+ case F_APPEND_DATA:
+#ifdef WINDOWS
+ file_length=SetFilePointer (file_handle,0,NULL,FILE_END);
+
+ if (file_length==-1){
+ free_memory (file_name_s);
+ free_memory (buffer);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("fopen: can't seek to eof");
+ }
+#else
+ error=DosSetFilePtr (file_handle,0,FILE_END,&file_length);
+
+ if (error!=0){
+ free_memory (file_name_s);
+ free_memory (buffer);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("fopen: can't seek to eof");
+ }
+#endif
+ f->file_offset=file_length;
+
+ break;
+ default:
+ {
+#ifdef WINDOWS
+ file_length=GetFileSize (file_handle,NULL);
+
+ if (file_length==-1){
+ free_memory (file_name_s);
+ free_memory (buffer);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("fopen: can't get eof");
+ }
+#else
+ FILESTATUS file_status;
+
+ error=DosQueryFileInfo (file_handle,FIL_STANDARD,&file_status,sizeof (file_status));
+
+ if (error!=0){
+ free_memory (file_name_s);
+ free_memory (buffer);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("fopen: can't get eof");
+ }
+
+ file_length=file_status.cbFile;
+#endif
+ }
+ }
+
+ 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_handle;
+
+ 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];
+}
+
+struct file *open_stderr (void)
+{
+ 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){
+ OS(DWORD,APIRET) error;
+ long count;
+
+ count=f->file_write_p-buffer;
+
+ if (count==0)
+ error=0;
+ else {
+#ifdef WINDOWS
+ error=!WriteFile (f->file_refnum,buffer,count,&count,NULL);
+#else
+ error=DosWrite (f->file_refnum,buffer,count,&count);
+#endif
+ f->file_offset += count;
+ }
+
+ 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!=0 || count!=f->file_write_p-buffer){
+ f->file_write_p=buffer;
+ f->file_error=-1;
+ return 0;
+ }
+
+ f->file_write_p=buffer;
+ }
+ }
+
+ return 1;
+}
+
+CLEAN_BOOL flush_file_buffer (struct file *f)
+{
+ if (is_special_file (f))
+ return 1;
+ else
+ return flush_write_buffer (f);
+}
+
+CLEAN_BOOL 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 CLEAN_TRUE;
+ } else {
+ int result;
+
+ if (f->file_mode==0)
+ IO_error ("fclose: file not open");
+
+ result=CLEAN_TRUE;
+
+ if (f->file_error)
+ result=0;
+
+ if (! flush_write_buffer (f))
+ result=0;
+
+#ifdef WINDOWS
+ if (!CloseHandle (f->file_refnum))
+ result=0;
+#else
+ if (DosClose (f->file_refnum)!=0)
+ result=0;
+#endif
+
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+
+ f->file_mode=0;
+
+ return result;
+ }
+}
+
+static OS(DWORD,ULONG) file_action_reopen[] ={
+#ifdef WINDOWS
+ OPEN_EXISTING,
+ TRUNCATE_EXISTING,
+ OPEN_EXISTING,
+ OPEN_EXISTING,
+ TRUNCATE_EXISTING,
+ OPEN_EXISTING
+#else
+ FILE_OPEN,
+ FILE_TRUNCATE,
+ FILE_OPEN,
+ FILE_OPEN,
+ FILE_TRUNCATE,
+ FILE_OPEN
+#endif
+};
+
+CLEAN_BOOL re_open_file (struct file *f,unsigned int file_mode)
+{
+ 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 CLEAN_TRUE;
+ } else {
+ long file_length;
+ int result;
+ unsigned char *buffer;
+ HFILE file_handle;
+ OS(DWORD,APIRET) error;
+ ULONG action;
+
+ result=CLEAN_TRUE;
+
+ if (f->file_mode!=0){
+ flush_write_buffer (f);
+
+ OS(CloseHandle,DosClose) (f->file_refnum);
+ } else {
+ buffer=allocate_memory (FILE_IO_BUFFER_SIZE);
+ if (buffer==NULL)
+ IO_error ("freopen: out of memory");
+ f->file_buffer_p=buffer;
+ }
+
+ f->file_mode=0;
+
+#ifdef WINDOWS
+ file_handle=CreateFileA (f->file_name,file_permission[file_mode],file_permission[file_mode]==GENERIC_READ ? FILE_SHARE_READ : 0,NULL,
+ file_action_reopen[file_mode],FILE_ATTRIBUTE_NORMAL,NULL);
+ if (file_handle==INVALID_HANDLE_VALUE){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ return 0;
+ }
+#else
+ error=DosOpen (f->file_name,&file_handle,&action,0,FILE_NORMAL,
+ file_action_reopen[file_mode],file_permission[file_mode],NULL);
+
+ if (error!=0){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ return 0;
+ }
+#endif
+
+ f->file_offset=0;
+
+ switch (file_mode){
+ case F_WRITE_TEXT:
+ case F_WRITE_DATA:
+ file_length=0;
+ break;
+ case F_APPEND_TEXT:
+ case F_APPEND_DATA:
+#ifdef WINDOWS
+ file_length=SetFilePointer (file_handle,0,NULL,FILE_END);
+
+ if (file_length==-1){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("freopen: can't seek to eof");
+ }
+#else
+ error=DosSetFilePtr (file_handle,0,FILE_END,&file_length);
+
+ if (error!=0){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("freopen: can't seek to eof");
+ }
+#endif
+ f->file_offset=file_length;
+ break;
+ default:
+ {
+#ifdef WINDOWS
+ file_length=GetFileSize (file_handle,NULL);
+
+ if (file_length==-1){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("freopen: can't get eof");
+ }
+#else
+ FILESTATUS file_status;
+
+ error=DosQueryFileInfo (file_handle,FIL_STANDARD,&file_status,sizeof (file_status));
+
+ if (error!=0){
+ free_memory (f->file_name);
+ free_memory (f->file_buffer_p);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("freopen: can't get eof");
+ }
+
+ file_length=file_status.cbFile;
+#endif
+ }
+ }
+
+ f->file_refnum=file_handle;
+ f->file_mode=1<<file_mode;
+ 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=FILE_IO_BUFFER_SIZE - (f->file_offset & (FILE_IO_BUFFER_SIZE-1));
+ 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)
+{
+ OS(DWORD,APIRET) error;
+ long count;
+ unsigned char *buffer;
+ int c;
+
+ count=FILE_IO_BUFFER_SIZE - (f->file_offset & (FILE_IO_BUFFER_SIZE-1));
+ buffer=f->file_buffer_p;
+
+#ifdef WINDOWS
+ error=!ReadFile (f->file_refnum,buffer,count,&count,NULL);
+#else
+ error=DosRead (f->file_refnum,buffer,count,&count);
+#endif
+
+ f->file_offset += count;
+
+ if (error!=0)
+ f->file_error=-1;
+
+ if (error!=0 || 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){
+ unsigned char c;
+
+ c=*(f->file_read_p)++;
+
+ if (c=='\r' && f->file_mode & (1<<F_READ_TEXT)){
+ if (read_char (f)=='\n')
+ c='\n';
+ else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ return c;
+ } else {
+ if (is_special_file (f)){
+ if (f==file_table){
+ IO_error ("freadc: can't read from stderr");
+ return 0;
+ } else if (f==&file_table[1])
+ return w_get_char();
+ else {
+ IO_error ("freadc: can't open this file");
+ return 0;
+ }
+ } else {
+ int c;
+
+ if (f->file_mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA)))
+ IO_error ("freadc: read from an output file");
+
+ c=char_from_new_buffer (f);
+
+ if (c=='\r' && f->file_mode & (1<<F_READ_TEXT)){
+ if (read_char (f)=='\n')
+ c='\n';
+ else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ return c;
+ }
+ }
+}
+
+#define is_digit(n) ((unsigned)((n)-'0')<(unsigned)10)
+
+CLEAN_BOOL 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");
+ return 0;
+ } else if (f==&file_table[1])
+ return w_get_int (i_p);
+ else {
+ IO_error ("freadi: can't open this file");
+ return 0;
+ }
+ } 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=CLEAN_TRUE;
+
+ 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 CLEAN_TRUE;
+ }
+}
+
+extern int convert_string_to_real (char *s,double *r_p);
+
+CLEAN_BOOL 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");
+ return 0;
+ } else if (f==&file_table[1])
+ return w_get_real (r_p);
+ else {
+ IO_error ("freadr: can't open this file");
+ return 0;
+ }
+ } 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=CLEAN_TRUE;
+ 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=CLEAN_TRUE;
+ }
+ }
+
+ 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';
+ result= convert_string_to_real (s,r_p)==&s[n];
+ }
+
+ if (!result)
+ f->file_error=-1;
+
+ return result;
+ } else
+ IO_error ("freadr: read from an output file");
+
+ return CLEAN_TRUE;
+ }
+}
+
+#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");
+ return 0;
+ } 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");
+ return 0;
+ }
+ } 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;
+
+ 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-string)
+ n=end_string-string;
+
+ do {
+ *string++ = *read_p++;
+ } while (--n);
+
+ f->file_read_p=read_p;
+ } else {
+ if (end_string-string>=FILE_IO_BUFFER_SIZE && f->file_offset & (FILE_IO_BUFFER_SIZE-1)==0){
+ OS(DWORD,APIRET) error;
+ long count;
+ unsigned char *buffer;
+
+ count=(end_string-string) & (~(FILE_IO_BUFFER_SIZE-1));
+#ifdef WINDOWS
+ error=!ReadFile (f->file_refnum,string,count,&count,NULL);
+#else
+ error=DosRead (f->file_refnum,string,count,&count);
+#endif
+ f->file_offset += count;
+
+ if (error!=0)
+ 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!=0 || 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;
+ }
+ }
+ }
+ } else {
+ 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 {
+ char c;
+
+ c = *read_p++;
+ if (c=='\r'){
+ if (n>1){
+ if (*read_p=='\n'){
+ *string++='\n';
+ ++read_p;
+ --n;
+ } else
+ *string++ = c;
+ } else {
+ int c2;
+
+ f->file_read_p=read_p;
+ c2=read_char (f);
+ read_p=f->file_read_p;
+
+ if (c2=='\n')
+ *string++=c2;
+ else {
+ *string++=c;
+ if (read_p > f->file_buffer_p)
+ --read_p;
+ }
+ break;
+ }
+ } else
+ *string++ = c;
+ } while (--n);
+
+ f->file_read_p=read_p;
+ } else {
+ int c;
+
+ c=char_from_new_buffer (f);
+ if (c==EOF)
+ break;
+
+ if (c=='\r'){
+ if (read_char (f)=='\n')
+ c='\n';
+ else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ *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");
+ return 0;
+ } 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=='\n')
+ return length;
+ }
+
+ return -1;
+ } else {
+ IO_error ("freadline: can't open this file");
+ return 0;
+ }
+ } 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 ((unsigned char*)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++;
+
+ if (ch=='\r'){
+ if (n>1 || read_p < f->file_end_buffer_p){
+ if (*read_p=='\n'){
+ f->file_read_p=++read_p;
+ *string++='\n';
+ return (unsigned char*)string-begin_string;
+ } else {
+ *string++=ch;
+ }
+ } else {
+ int c;
+
+ f->file_read_p=read_p;
+ c=char_from_new_buffer(f);
+ read_p=f->file_read_p;
+
+ if (c=='\n'){
+ *string++=c;
+ return (unsigned char*)string-begin_string;
+ } else {
+ *string++=ch;
+
+ if (f->file_read_p > f->file_buffer_p)
+ --read_p;
+ }
+ }
+ } else {
+ *string++=ch;
+ if (ch=='\n'){
+ 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;
+
+ if (c=='\r'){
+ if (read_char (f)=='\n')
+ c='\n';
+ else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ *string++=c;
+ if (c=='\n')
+ 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){
+ if (c=='\n' && f->file_mode & ((1<<F_WRITE_TEXT)|(1<<F_APPEND_TEXT))){
+ *(f->file_write_p)++='\r';
+
+ if (f->file_write_p < f->file_end_buffer_p)
+ *(f->file_write_p)++=c;
+ else
+ char_to_new_buffer (c,f);
+ } else {
+ *(f->file_write_p)++=c;
+ }
+ } else {
+ if (is_special_file (f)){
+ if (f==file_table)
+ ew_print_char (c);
+ else if (f==&file_table[1])
+ w_print_char (c);
+ else
+ IO_error ("fwritec: can't open this file");
+ } else {
+ 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");
+
+ if (c=='\n' && f->file_mode & ((1<<F_WRITE_TEXT)|(1<<F_APPEND_TEXT))){
+ char_to_new_buffer ('\r',f);
+ write_char (c,f);
+ } else
+ char_to_new_buffer (c,f);
+ }
+ }
+}
+
+extern char *convert_int_to_string (char *string,int i);
+extern char *convert_real_to_string (double d,char *s_p);
+
+void file_write_int (int i,struct file *f)
+{
+ if (is_special_file (f)){
+ if (f==file_table)
+ ew_print_int (i);
+ else if (f==&file_table[1])
+ w_print_int (i);
+ else
+ IO_error ("fwritei: can't open this file");
+ } else {
+ 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))){
+ 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);
+ } else {
+ unsigned char string[24],*end_p,*s;
+ int length;
+
+ end_p=convert_int_to_string (string,i);
+ length=end_p-string;
+
+ 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);
+ else if (f==&file_table[1])
+ w_print_real (r);
+ else
+ IO_error ("fwriter: can't open this file");
+ } else {
+ 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))){
+ 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);
+ } else {
+ unsigned char string[32],*end_p,*s;
+ int length;
+
+ end_p=convert_real_to_string (r,string);
+ length=end_p-string;
+
+ 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
+ else if (f==&file_table[1])
+#if OLD_WRITE_STRING
+ w_print_text (s->characters,s->length);
+#else
+ w_print_text (p,length);
+#endif
+ else
+ IO_error ("fwrites: can't open this file");
+ } else {
+#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
+
+ if (f->file_mode & ((1<<F_WRITE_DATA)|(1<<F_APPEND_DATA))){
+ 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);
+ }
+ } else {
+ 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 {
+ char c;
+
+ c = *p++;
+ if (c=='\n'){
+ *write_p++ = '\r';
+ if (--n){
+ *write_p++ = c;
+ } else {
+ f->file_write_p=write_p;
+ write_char (c,f);
+ write_p=f->file_write_p;
+ break;
+ }
+ } else
+ *write_p++ = c;
+ } while (--n);
+
+ f->file_write_p=write_p;
+ } else {
+ char c;
+
+ c=*p++;
+ if (c=='\n'){
+ char_to_new_buffer ('\r',f);
+ write_char (c,f);
+ } else
+ char_to_new_buffer (c,f);
+ }
+ }
+ }
+ }
+}
+
+CLEAN_BOOL 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");
+ return 0;
+ } 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 CLEAN_TRUE;
+ }
+}
+
+CLEAN_BOOL file_error (struct file *f)
+{
+ if (is_special_file (f)){
+ if (f==file_table || f==&file_table[1])
+ return 0;
+ else
+ return CLEAN_TRUE;
+ } else
+ if (f->file_error)
+ return CLEAN_TRUE;
+ else
+ return 0;
+}
+
+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");
+ return 0;
+ } 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;
+ }
+}
+
+CLEAN_BOOL file_seek (struct file *f,unsigned long position,unsigned long seek_mode)
+{
+ 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");
+ return 0;
+ } 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 CLEAN_TRUE;
+ } else {
+ unsigned char *buffer;
+ OS(DWORD file_position,APIRET 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;
+
+#ifdef WINDOWS
+ file_position=SetFilePointer (f->file_refnum,position,NULL,FILE_BEGIN);
+
+ if (file_position==-1){
+ f->file_error=-1;
+ return 0;
+ }
+
+ f->file_offset=file_position;
+#else
+ error=DosSetFilePtr (f->file_refnum,position,FILE_BEGIN,&f->file_offset);
+
+ if (error!=0){
+ f->file_error=-1;
+ return 0;
+ }
+#endif
+ return CLEAN_TRUE;
+ }
+ } else {
+ OS(DWORD file_position,APIRET error);
+ int result;
+
+ result=CLEAN_TRUE;
+
+ 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 CLEAN_TRUE;
+
+ if (! flush_write_buffer (f)){
+ f->file_error=-1;
+ result=0;
+ }
+
+ if (position<0 || position>f->file_length){
+ f->file_error=-1;
+ return 0;
+ }
+#ifdef WINDOWS
+ file_position=SetFilePointer (f->file_refnum,position,NULL,FILE_BEGIN);
+
+ if (file_position==-1){
+ f->file_error=-1;
+ result=0;
+ } else
+ f->file_offset=file_position;
+#else
+ error=DosSetFilePtr (f->file_refnum,position,FILE_BEGIN,&f->file_offset);
+
+ if (error!=0){
+ f->file_error=-1;
+ result=0;
+ }
+#endif
+ return result;
+ }
+ }
+}
+
+/* added 13-1-1999 */
+static int equal_string (char *s1,char*s2)
+{
+ char c;
+
+ do {
+ c=*s1++;
+ if (c=='\0')
+ return *s2==c;
+ } while (*s2++ == c);
+
+ return 0;
+}
+
+/* */
+
+struct file *open_s_file (struct clean_string *file_name,unsigned int file_mode)
+{
+ int fn;
+ char *file_name_s;
+ struct file *f;
+ long file_length;
+ HFILE file_handle;
+ unsigned char *buffer;
+ ULONG action;
+ OS(DWORD,APIRET) error;
+
+ 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;
+ }
+
+ 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];
+
+#ifdef WINDOWS
+ file_handle=CreateFileA (file_name_s,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
+
+ if (file_handle==INVALID_HANDLE_VALUE){
+ /* added 13-1-1999 */
+ if (GetLastError()==ERROR_SHARING_VIOLATION){
+ for (fn=FIRST_REAL_FILE; fn<MAX_N_FILES; ++fn){
+ f=&file_table[fn];
+ if (f->file_mode!=0 && equal_string (file_name_s,f->file_name) && f->file_mode==1<<file_mode){
+ free_memory (file_name_s);
+ return f;
+ }
+ }
+ }
+ /* */
+
+ free_memory (file_name_s);
+ return ERROR_FILE;
+ }
+#else
+ error=DosOpen (file_name_s,&file_handle,&action,0,FILE_NORMAL,
+ FILE_OPEN,file_permission[file_mode],NULL);
+
+ if (error!=0){
+ free_memory (file_name_s);
+ return ERROR_FILE;
+ }
+#endif
+
+ buffer=allocate_memory (FILE_IO_BUFFER_SIZE);
+ if (buffer==NULL){
+ free_memory (file_name_s);
+ OS(CloseHandle,DosClose) (file_handle);
+ 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;
+
+
+#ifdef WINDOWS
+ file_length=GetFileSize (file_handle,NULL);
+
+ if (file_length==-1){
+#else
+ {
+ FILESTATUS file_status;
+
+ error=DosQueryFileInfo (file_handle,FIL_STANDARD,&file_status,sizeof (file_status));
+
+ file_length=file_status.cbFile;
+ }
+
+ if (error!=0){
+#endif
+ free_memory (file_name_s);
+ free_memory (buffer);
+ OS(CloseHandle,DosClose) (file_handle);
+ IO_error ("sfopen: can't get eof");
+ }
+
+ f->file_refnum=file_handle;
+ f->file_mode=1<<file_mode;
+ 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;
+
+ 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;
+ OS(DWORD file_position,APIRET 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;
+
+#ifdef WINDOWS
+ file_position=SetFilePointer (f->file_refnum,position,NULL,FILE_BEGIN);
+
+ if (file_position==-1){
+ f->file_error=-1;
+ result=0;
+ } else
+ f->file_offset=file_position;
+#else
+ error=DosSetFilePtr (f->file_refnum,position,FILE_BEGIN,&f->file_offset);
+
+ if (error!=0){
+ f->file_error=-1;
+ result=0;
+ }
+
+ f->file_position=position;
+#endif
+ }
+ }
+
+ 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");
+ return 0;
+ } 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;
+ }
+
+ if (c=='\r' && f->file_mode & (1<<F_READ_TEXT)){
+ if (read_char (f)=='\n'){
+ c='\n';
+ ++position;
+ } else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ f->file_position=position;
+ *position_p=position;
+
+ return c;
+ }
+}
+
+CLEAN_BOOL 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");
+ return 0;
+ } 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=CLEAN_TRUE;
+ 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;
+ }
+}
+
+CLEAN_BOOL 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");
+ return 0;
+ } 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=CLEAN_TRUE;
+ 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,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=CLEAN_TRUE;
+ 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=CLEAN_TRUE;
+ }
+ }
+
+ 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';
+ result= convert_string_to_real (s,r_p)==&s[n];
+ }
+
+ if (!result)
+ f->file_error=-1;
+ } else
+ result=0;
+
+ 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");
+ return 0;
+ } 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;
+
+ if (f->file_mode & (1<<F_READ_DATA)){
+ while (length!=max_length && ((c=read_char (f))!=EOF)){
+ *string++=c;
+ ++length;
+ }
+ position+=length;
+ } else {
+ while (length!=max_length && ((c=read_char (f))!=EOF)){
+ if (c=='\r'){
+ if (read_char (f)=='\n'){
+ ++position;
+ c='\n';
+ } else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ *string++=c;
+ ++length;
+ ++position;
+ }
+ }
+
+ s->length=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");
+ return 0;
+ } 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)){
+ if (c=='\r'){
+ if (read_char (f)=='\n'){
+ ++position;
+ c='\n';
+ } else
+ if (f->file_read_p > f->file_buffer_p)
+ --f->file_read_p;
+ }
+
+ *string++=c;
+ ++length;
+ ++position;
+ if (c=='\n')
+ break;
+ }
+
+ f->file_position=position;
+ *position_p=position;
+
+ if (c!='\n' && c!=EOF)
+ return -1;
+
+ return length;
+ }
+}
+
+CLEAN_BOOL 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");
+ return 0;
+ } 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 CLEAN_TRUE;
+ } 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) ? CLEAN_TRUE : 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");
+ return 0;
+ } 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
+
+CLEAN_BOOL file_s_seek (struct file *f,unsigned long position,unsigned long seek_mode,unsigned long *position_p)
+{
+ 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");
+ return 0;
+ } else {
+ long current_position,buffer_size;
+ int result;
+
+ result=CLEAN_TRUE;
+
+ 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;
+ OS(DWORD file_position,APIRET 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;
+
+#ifdef WINDOWS
+ file_position=SetFilePointer (f->file_refnum,position,NULL,FILE_BEGIN);
+
+ if (file_position==-1){
+ f->file_error=-1;
+ result=0;
+ } else
+ f->file_offset=file_position;
+#else
+ error=DosSetFilePtr (f->file_refnum,position,FILE_BEGIN,&f->file_offset);
+
+ if (error!=0){
+ f->file_error=-1;
+ result=0;
+ }
+#endif
+ f->file_position=position;
+ }
+ }
+
+ *position_p=position;
+
+ return result;
+ }
+}