diff options
-rw-r--r-- | a.sed | 2 | ||||
-rw-r--r-- | c.sed | 4 | ||||
-rw-r--r-- | fixgnuasobj.exe | bin | 0 -> 54272 bytes | |||
-rw-r--r-- | fixgnuasobj.icl | 153 | ||||
-rw-r--r-- | iwrite_heap.c | 188 | ||||
-rw-r--r-- | wcon.h | 14 | ||||
-rw-r--r-- | wcon_imports.s | 21 | ||||
-rw-r--r-- | wfileIO3.c | 2468 |
8 files changed, 2850 insertions, 0 deletions
@@ -0,0 +1,2 @@ +s/@/_/ +s/?/@/ @@ -0,0 +1,4 @@ +s/call __alloca/subl %eax,%esp/ +s/call ___main// +s/gcc2_compiled.:// +s/___gnu_compiled_c:// diff --git a/fixgnuasobj.exe b/fixgnuasobj.exe Binary files differnew file mode 100644 index 0000000..d34b6eb --- /dev/null +++ b/fixgnuasobj.exe diff --git a/fixgnuasobj.icl b/fixgnuasobj.icl new file mode 100644 index 0000000..fc3a9ff --- /dev/null +++ b/fixgnuasobj.icl @@ -0,0 +1,153 @@ +module fixgnuasobj; + +import StdInt,StdChar,StdString,StdBool,StdFile,StdArray,StdMisc,StdClass; + +import ArgEnv; + +/* + swap_bytes i = ((i>>24) bitand 0xff) bitor ((i>>8) bitand 0xff00) bitor ((i<<8) bitand 0xff0000) bitor (i<<24); + + Freadi :: !*File -> (!Bool,!Int,!*File); + Freadi f0 = (b,swap_bytes i,f1); + { + (b,i,f1)=freadi f0; + } + + Fwritei i f :== fwritei (swap_bytes i) f; +*/ + +Freadi f:==freadi f; +Fwritei i f:==fwritei i f; + +read_little_endian_word_at offset f0 + | ok1 && ok2 + = (i,f2); + {}{ + (ok2,i,f2)=Freadi f1; + (ok1,f1)=fseek f0 offset FSeekSet; + } + +copy_to_offset current_offset offset i0 o0 + | offset>=current_offset + = (offset,i1,o1); + {}{ + (i1,o1)=copy_bytes (offset-current_offset) i0 o0; + } + +copy_bytes n_bytes i0 o0 + | size bytes==n_bytes + = (i1,fwrites bytes o0); + {}{ + (bytes,i1)=freads i0 n_bytes; + } + +replace_long offset v i0 o0 + | ok + = (offset+4,i1,Fwritei v o0); + {}{ + (ok,_,i1)=freadi i0; + } + +copy_and_fix_data_relocations 0 data_addr offset i0 o0 + = (offset,i0,o0); +copy_and_fix_data_relocations n data_addr offset i0 o0 + | ok1 && size bytes==6 + = copy_and_fix_data_relocations (n-1) data_addr (offset+10) i2 o1; + {}{ + o1=fwrites bytes (Fwritei new_relocation_offset o0); + new_relocation_offset=relocation_offset-data_addr; + (bytes,i2)=freads i1 6; + (ok1,relocation_offset,i1)=Freadi i0; + } + +(BYTE) string i :== toInt (string.[i]); + +(IWORD) string i = (string BYTE (i+1)<<8) bitor (string BYTE i); + +(ILONG) string i + = (string BYTE (i+3)<<24) bitor (string BYTE (i+2)<<16) bitor (string BYTE (i+1)<<8) bitor (string BYTE i); + +copy_and_fix_symbols 0 data_addr offset0 i0 o0 + = (offset0,i0,o0); +copy_and_fix_symbols n data_addr offset0 i0 o0 + | size bytes<>18 + = abort "copy_and_fix_symbols: read error\n"; + | section_n<>2 + = copy_and_fix_symbols (n-1-n_aux) data_addr offset1 i2 o2; + { + (offset1,i2,o2)=copy_aux n_aux (offset0+18) i1 o1; + o1=fwrites bytes o0; + } + = copy_and_fix_symbols (n-1-n_aux) data_addr offset1 i2 o4; + { + (offset1,i2,o4)=copy_aux n_aux (offset0+18) i1 o3; + o3=fwrites (bytes % (12,17)) o2; + o2=Fwritei (value-data_addr) o1; + o1=fwrites (bytes % (0,7)) o0; + value=bytes ILONG 8; + } + { + (bytes,i1)=freads i0 18; + n_aux=bytes BYTE 17; + section_n=bytes IWORD 12; + } + +copy_aux 0 offset i0 o0 + = (offset,i0,o0); +copy_aux n offset i0 o0 + | size bytes==aux_size + = (offset+aux_size,i1,o1); + {}{ + o1=fwrites bytes o0; + (bytes,i1)=freads i0 aux_size; + aux_size=n*18; + } + +copy_rest_of_file i0 o0 + | size bytes<16384 + = (i1,fwrites bytes o0); + = copy_rest_of_file i1 (fwrites bytes o0); + {}{ + (bytes,i1)=freads i0 16384; + } + +//input_file_name:=="_startup1.o"; +//output_file_name:=="_startup1.obj"; + +Start w0 + # command_line=getCommandLine; + | size command_line<>3 + = abort "input file name and output file name expected"; + # + input_file_name = command_line.[1]; + output_file_name = command_line.[2]; + files0=w0; + (open_ok1,f0,files1)=fopen input_file_name FReadData files0; + (symbol_table_offset,f1)=read_little_endian_word_at 0x8 f0; + (n_symbols,f2)=read_little_endian_word_at 0xc f1; + (data_addr,f3)=read_little_endian_word_at 0x44 f2; + (data_addr_,f4)=read_little_endian_word_at 0x48 f3; + (data_relocation_table_offset,f5)=read_little_endian_word_at 0x54 f4; + (n_relocations,f6)=read_little_endian_word_at 0x5c f5; + (seek_ok,i0) = fseek f6 0 FSeekSet; + (open_ok2,o0,files2)=fopen output_file_name FWriteData files1; + (new_offset0,i1,o1)=copy_to_offset 0 0x44 i0 o0; + (new_offset1,i2,o2)=replace_long new_offset0 0 i1 o1; + (new_offset2,i3,o3)=replace_long new_offset1 0 i2 o2; + (new_offset4,i5,o5) = f; + with { + f | n_relocations==0 + = (new_offset2,i3,o3); + = copy_and_fix_data_relocations n_relocations data_addr new_offset3 i4 o4; + { + (new_offset3,i4,o4)=copy_to_offset new_offset2 data_relocation_table_offset i3 o3; + } + } + (new_offset5,i6,o6)=copy_to_offset new_offset4 symbol_table_offset i5 o5; + (new_offset6,i7,o7)=copy_and_fix_symbols n_symbols data_addr new_offset5 i6 o6; + (i8,o8)=copy_rest_of_file i7 o7; + (close_ok1,files4)=fclose o8 files2; + | open_ok1 && data_addr==data_addr_ && seek_ok && open_ok2 && close_ok1 + = (symbol_table_offset,n_symbols,data_addr,data_relocation_table_offset,n_relocations,files4); +// # (stdout,files) = stdio files4; +// = stdout <<< symbol_table_offset <<< ' ' <<< n_symbols <<< ' ' <<< data_addr <<< ' ' <<< data_relocation_table_offset <<< ' ' <<< n_relocations; diff --git a/iwrite_heap.c b/iwrite_heap.c new file mode 100644 index 0000000..3ab9146 --- /dev/null +++ b/iwrite_heap.c @@ -0,0 +1,188 @@ + +#include <windows.h> + +#ifndef TCHAR +# define TCHAR char + +# if 0 +typedef struct _WIN32_FIND_DATA { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + TCHAR cFileName[ MAX_PATH ]; + TCHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATA; +# endif +#endif + +struct heap_info { + int *heap1_begin; + int *heap1_end; + int *heap2_begin; + int *heap2_end; + int *stack_begin; + int *stack_end; + int *text_begin; + int *data_begin; + int *small_integers; + int *characters; + int int_descriptor; + int char_descriptor; + int real_descriptor; + int bool_descriptor; + int string_descriptor; + int array_descriptor; +}; + +static int heap_written_count=0; + +#define MAX_N_HEAPS 10 + +extern char **global_argv; + +#define MAX_PATH_LENGTH 256 + +void write_heap (struct heap_info *h) +{ + HANDLE heap_file_h; + int NumberOfBytesWritten; + static char heap_profile_file_name_suffix[]=" Heap Profile0.hcl"; + char heap_profile_file_name[MAX_PATH_LENGTH+1]; + char *argv0,*heap_profile_file_name_p; + int length_argv0,length_argv0_copy_in_memory,length_heap_profile_file_name; + BOOL fileOk; + + if (heap_written_count >= MAX_N_HEAPS) + return; + + argv0=global_argv[0]; + { + char *arg_p; + + for (arg_p=argv0; *arg_p!='\0'; ++arg_p) + ; + length_argv0=arg_p-argv0; + } + + if (argv0[0]=='\"' && length_argv0>1 && argv0[length_argv0-1]=='\"'){ + ++argv0; + length_argv0-=2; + } + + heap_profile_file_name_p=argv0; + length_heap_profile_file_name=length_argv0; + + if (length_heap_profile_file_name<=MAX_PATH_LENGTH){ + WIN32_FIND_DATA find_data; + HANDLE find_first_file_handle; + int i; + + for (i=0; i<length_heap_profile_file_name; ++i) + heap_profile_file_name[i]=heap_profile_file_name_p[i]; + heap_profile_file_name[length_heap_profile_file_name]='\0'; + + find_first_file_handle=FindFirstFileA (heap_profile_file_name,&find_data); + if (find_first_file_handle!=INVALID_HANDLE_VALUE){ + char *file_name_p,*p; + int file_name_length; + + file_name_p=find_data.cFileName; + for (p=file_name_p; *p!='\0'; ++p) + ; + file_name_length=p-file_name_p; + + for (p=heap_profile_file_name+length_heap_profile_file_name; p>heap_profile_file_name && p[-1]!='\\' && p[-1]!='/'; --p) + ; + + if ((p-heap_profile_file_name)+file_name_length<=MAX_PATH_LENGTH){ + for (i=0; i<file_name_length; ++i) + p[i]=file_name_p[i]; + p[i]='\0'; + + heap_profile_file_name_p=heap_profile_file_name; + length_heap_profile_file_name=&p[i]-heap_profile_file_name; + } + + FindClose (find_first_file_handle); + } + } + + { + char *p; + + p=&heap_profile_file_name_p[length_heap_profile_file_name]; + if (length_heap_profile_file_name>3 && p[-4]=='.' && p[-3]=='e' && p[-2]=='x' && p[-1]=='e') + length_heap_profile_file_name-=4; + } + + if (length_heap_profile_file_name+sizeof (heap_profile_file_name_suffix)>MAX_PATH_LENGTH){ + ++heap_written_count; + ew_print_string( "Heap file could not be created because the file name is too long.\n" ); + return; + } + + { + char *p; + int i; + + if (heap_profile_file_name_p!=heap_profile_file_name) + for (i=0; i<length_heap_profile_file_name; ++i) + heap_profile_file_name[i]=heap_profile_file_name_p[i]; + + p=heap_profile_file_name+length_heap_profile_file_name; + for (i=0; i<=sizeof(heap_profile_file_name_suffix); ++i) + p[i]=heap_profile_file_name_suffix[i]; + + p[sizeof(heap_profile_file_name_suffix)-6]='0'+heap_written_count; + } + + ++heap_written_count; + + heap_file_h = CreateFileA (heap_profile_file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (heap_file_h==INVALID_HANDLE_VALUE){ + heap_written_count = MAX_N_HEAPS; + + ew_print_string( "Heap file '" ); + ew_print_string( heap_profile_file_name ); + ew_print_string( "' could not be created.\n" ); + + return; + } + + /* save application name */ + length_argv0_copy_in_memory=length_argv0; + fileOk = WriteFile (heap_file_h, &length_argv0_copy_in_memory, sizeof(int), &NumberOfBytesWritten, NULL); + if (fileOk) + fileOk = WriteFile (heap_file_h, argv0, length_argv0, &NumberOfBytesWritten, NULL); + + /* write heap_info-structure */ + if (fileOk) + fileOk = WriteFile (heap_file_h, h, sizeof(struct heap_info), &NumberOfBytesWritten, NULL); + + /* write stack */ + if (fileOk) + fileOk = WriteFile (heap_file_h, h->stack_begin, (int)(h->stack_end) - (int)(h->stack_begin), &NumberOfBytesWritten, NULL); + + /* write heap1 */ + if (fileOk) + fileOk = WriteFile (heap_file_h, h->heap1_begin, (int)(h->heap1_end) - (int)(h->heap1_begin), &NumberOfBytesWritten, NULL); + + /* write heap2 */ + if (fileOk) + fileOk = WriteFile (heap_file_h, h->heap2_begin, (int)(h->heap2_end) - (int)(h->heap2_begin), &NumberOfBytesWritten, NULL); + + if (!fileOk){ + heap_written_count = MAX_N_HEAPS; + + ew_print_string( "Heap file '" ); + ew_print_string( heap_profile_file_name ); + ew_print_string( "' could not be written.\n" ); + } + + CloseHandle (heap_file_h); +} @@ -0,0 +1,14 @@ +extern int w_get_char(); +extern int w_get_int (int *i_p); +extern int w_get_real (double *r_p); +extern unsigned long w_get_text (char *string,unsigned long max_length); +extern void w_print_char (char c); +extern void w_print_int (int i); +extern void w_print_real (double r); +extern void w_print_string (char *s); +extern void w_print_text (char *s,unsigned long length); +extern void ew_print_char (char c); +extern void ew_print_int (int i); +extern void ew_print_real (double r); +extern void ew_print_string (char *s); +extern void ew_print_text (char *s,unsigned long length); diff --git a/wcon_imports.s b/wcon_imports.s new file mode 100644 index 0000000..32d29fc --- /dev/null +++ b/wcon_imports.s @@ -0,0 +1,21 @@ + + .global _GetTickCount@0 + .global _ExitProcess@4 + .global _WriteFile@20 + .global _AllocConsole@0 + .global _GetStdHandle@4 + .global _WriteFile@20 + .global _ReadFile@20 + .global _SetConsoleTitleA@4 + .global _GetConsoleMode@8 + .global _SetConsoleMode@8 + .global _GlobalFree@4 + .global _GetLastError@0 + .global _GlobalAlloc@8 + .global _GetCommandLineA@0 + .global _CreateFileA@28 + .global _ExitProcess@4 + .global _FindFirstFileA@8 + .global _FindClose@4 + .global _CreateFileA@28 + .global _CloseHandle@4 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; + } +} |