summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--a.sed2
-rw-r--r--c.sed4
-rw-r--r--fixgnuasobj.exebin0 -> 54272 bytes
-rw-r--r--fixgnuasobj.icl153
-rw-r--r--iwrite_heap.c188
-rw-r--r--wcon.h14
-rw-r--r--wcon_imports.s21
-rw-r--r--wfileIO3.c2468
8 files changed, 2850 insertions, 0 deletions
diff --git a/a.sed b/a.sed
new file mode 100644
index 0000000..32e0211
--- /dev/null
+++ b/a.sed
@@ -0,0 +1,2 @@
+s/@/_/
+s/?/@/
diff --git a/c.sed b/c.sed
new file mode 100644
index 0000000..fbb1823
--- /dev/null
+++ b/c.sed
@@ -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
new file mode 100644
index 0000000..d34b6eb
--- /dev/null
+++ b/fixgnuasobj.exe
Binary files differ
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);
+}
diff --git a/wcon.h b/wcon.h
new file mode 100644
index 0000000..570ab32
--- /dev/null
+++ b/wcon.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;
+ }
+}