/*
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
# include "wfileIO3.h"
# 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*);
extern int std_input_from_file;
extern int std_output_to_file;
extern HANDLE std_input_handle,std_output_handle,std_error_handle;
#define EOF (-1)
#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 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_read_buffer_p=buffer;
f->file_write_buffer_p=buffer;
f->file_end_read_buffer_p=buffer;
f->file_end_write_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_read_refnum=file_handle;
f->file_write_refnum=file_handle;
if (fn>=number_of_files)
number_of_files=fn+1;
return f;
}
static int stdio_open=0;
void init_std_io_from_or_to_file (void)
{
struct file *f;
unsigned char *buffer;
f=&file_table[1];
buffer=allocate_memory (FILE_IO_BUFFER_SIZE<<1);
if (buffer==NULL){
std_input_from_file=0;
std_output_to_file=0;
return;
}
f->file_read_buffer_p=buffer;
f->file_end_read_buffer_p=buffer;
f->file_read_p=buffer;
buffer+=FILE_IO_BUFFER_SIZE;
f->file_write_buffer_p=buffer;
f->file_end_write_buffer_p=buffer;
f->file_write_p=buffer;
f->file_mode=(1<<F_READ_TEXT) | (1<<F_WRITE_TEXT);
f->file_unique=1;
f->file_error=0;
f->file_offset=0;
f->file_length=0;
f->file_name="stdio";
f->file_position=-2;
f->file_position_2=-1;
f->file_read_refnum=std_input_handle;
f->file_write_refnum=std_output_handle;
}
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_write_buffer_p;
if (buffer!=f->file_end_write_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_write_refnum,buffer,count,&count,NULL);
#else
error=DosWrite (f->file_write_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_write_buffer_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)){
if (f==&file_table[1] && std_output_to_file)
return flush_write_buffer (f);
return 1;
}
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;
if (std_input_from_file || std_output_to_file){
int result;
result=CLEAN_TRUE;
if (f->file_error)
result=0;
if (std_output_to_file)
if (! flush_write_buffer (f))
result=0;
return result;
}
}
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_read_refnum))
result=0;
#else
if (DosClose (f->file_read_refnum)!=0)
result=0;
#endif
free_memory (f->file_name);
free_memory (f->file_read_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
};
static int clear_masks_for_stdio_reopen[6]={
~ (1<<F_READ_DATA), /* F_READ_TEXT */
~ ((1<<F_WRITE_DATA) | (1<<F_APPEND_DATA)), /* F_WRITE_TEXT */
~ ((1<<F_WRITE_DATA) | (1<<F_APPEND_DATA)), /* F_APPEND_TEXT */
~ (1<<F_READ_TEXT), /* F_READ_DATA */
~ ((1<<F_WRITE_TEXT) | (1<<F_APPEND_TEXT)), /* F_WRITE_DATA */
~ ((1<<F_WRITE_TEXT) | (1<<F_APPEND_TEXT)) /* F_APPEND_DATA */
};
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");
if (f==&file_table[1]){
int m;
m=file_table[1].file_mode;
m &= clear_masks_for_stdio_reopen[file_mode];
m |= 1<<file_mode;
file_table[1].file_mode=m;
}
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_read_refnum);
} else {
buffer=allocate_memory (FILE_IO_BUFFER_SIZE);
if (buffer==NULL)
IO_error ("freopen: out of memory");
f->file_read_buffer_p=buffer;
f->file_write_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_read_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_read_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_read_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_read_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_read_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_read_buffer_p);
OS(CloseHandle,DosClose) (file_handle);
IO_error ("freopen: can't get eof");
}
file_length=file_status.cbFile;
#endif
}
}
f->file_read_refnum=file_handle;
f->file_write_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_read_buffer_p;
f->file_end_read_buffer_p=buffer;
f->file_end_write_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_write_buffer_p;
*buffer=c;
f->file_write_p=buffer+1;
buffer+=count;
f->file_end_write_buffer_p=buffer;
}
#if defined (__MWERKS__) || defined (powerc)
#define write_char(c,f) if ((f)->file_write_p<(f)->file_end_write_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_write_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_read_buffer_p;
#ifdef WINDOWS
error=!ReadFile (f->file_read_refnum,buffer,count,&count,NULL);
#else
error=DosRead (f->file_read_refnum,buffer,count,&count);
#endif
f->file_offset += count;
if (error!=0)
f->file_error=-1;
if (error!=0 || count==0){
f->file_end_read_buffer_p=buffer;
f->file_read_p=buffer;
return EOF;
}
c=*buffer;
f->file_read_p=buffer+1;
buffer+=count;
f->file_end_read_buffer_p=buffer;
return c;
}
#define read_char(f) ((f)->file_read_p<(f)->file_end_read_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_read_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_read_buffer_p)
--f->file_read_p;
}
return c;
} else {
if (is_special_file (f)){
if (f==&file_table[1]){
if (std_input_from_file){
int c;
c=char_from_new_buffer (f);
if (c=='\r'){
if (read_char (f)=='\n')
c='\n';
else
if (f->file_read_p > f->file_read_buffer_p)
--f->file_read_p;
}
return c;
} else
return w_get_char();
} else if (f==file_table){
IO_error ("freadc: can't read from stderr");
return 0;
} 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_read_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[1]){
if (!std_input_from_file)
return w_get_int (i_p);
} else if (f==file_table){
IO_error ("freadi: can't read from stderr");
return 0;
} else {
IO_error ("freadi: can't open this file");
return 0;
}
}
*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_read_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[1]){
if (!std_input_from_file)
return w_get_real (r_p);
} else if (f==file_table){
IO_error ("freadr: can't read from stderr");
return 0;
} else {
IO_error ("freadr: can't open this file");
return 0;
}
}
*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_read_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[1]){
if (!std_input_from_file){
char *string;
unsigned long length;
int c;
length=0;
#if OLD_READ_STRING
string=s->characters;
#else
string=s;
#endif
while (length!=max_length && (c=w_get_char(),c!=-1)){
*string++=c;
++length;
}
#if OLD_READ_STRING
s->length=length;
#else
*length_p=length;
#endif
return length;
}
} else if (f==file_table){
IO_error ("freads: can't read from stderr");
return 0;
} else {
IO_error ("freads: can't open this file");
return 0;
}
} else {
if (f->file_mode & ~((1<<F_READ_TEXT) | (1<<F_READ_DATA)))
IO_error ("freads: read from an output file");
}
{
unsigned char *string,*end_string,*begin_string;
#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_read_buffer_p){
unsigned char *read_p;
long n;
read_p=f->file_read_p;
n=f->file_end_read_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_read_refnum,string,count,&count,NULL);
#else
error=DosRead (f->file_read_refnum,string,count,&count);
#endif
f->file_offset += count;
if (error!=0)
f->file_error=-1;
buffer=f->file_read_buffer_p;
f->file_end_read_buffer_p=buffer;
f->file_read_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_read_buffer_p){
unsigned char *read_p;
long n;
read_p=f->file_read_p;
n=f->file_end_read_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_read_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_read_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[1]){
if (!std_input_from_file){
unsigned long length;
int c;
length=0;
c=0;
while (length!=max_length && (c=w_get_char(),c!=-1)){
*string++=c;
++length;
if (c=='\n')
return length;
}
if (c!=-1)
return -1;
return length;
}
} else if (f==file_table){
IO_error ("freadline: can't read from stderr");
return 0;
} else {
IO_error ("freadline: can't open this file");
return 0;
}
}
{
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_read_buffer_p){
unsigned char *read_p;
long n;
read_p=f->file_read_p;
n=f->file_end_read_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_read_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_read_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_read_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_read_buffer_p){
unsigned char *read_p;
long n;
read_p=f->file_read_p;
n=f->file_end_read_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_read_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_read_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_read_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_read_buffer_p)
--f->file_read_p;
} else {
if (f->file_read_p > f->file_read_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_write_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_write_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[1]){
if (!std_output_to_file)
w_print_char (c);
else {
if (c=='\n'){
char_to_new_buffer ('\r',f);
write_char (c,f);
} else
char_to_new_buffer (c,f);
}
} else if (f==file_table)
ew_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[1]){
if (!std_output_to_file){
w_print_int (i);
return;
}
} else if (f==file_table){
ew_print_int (i);
return;
} 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[1]){
if (!std_output_to_file){
w_print_real (r);
return;
}
} else if (f==file_table){
ew_print_real (r);
return;
} 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[1]){
if (!std_output_to_file){
#if OLD_WRITE_STRING
w_print_text (s->characters,s->length);
#else
w_print_text (p,length);
#endif
return;
}
} else if (f==file_table){
#if OLD_WRITE_STRING
ew_print_text (s->characters,s->length);
#else
ew_print_text (p,length);
#endif
return;
} else
IO_error ("fwrites: 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 ("fwrites: write to an input file");
}
{
#if OLD_WRITE_STRING
unsigned char *p,*end_p;
#else
unsigned char *end_p;
#endif
#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_write_buffer_p){
unsigned char *write_p;
long n;
write_p=f->file_write_p;
n=f->file_end_write_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_write_buffer_p){
unsigned char *write_p;
long n;
write_p=f->file_write_p;
n=f->file_end_write_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_read_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[1]){
if ((std_input_from_file || std_output_to_file) && f->file_error)
return CLEAN_TRUE;
else
return 0;
} else if (f==file_table)
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_read_buffer_p - f->file_read_p);
else
position=f->file_offset + (f->file_write_p - f->file_write_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_read_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_read_buffer_p - f->file_read_buffer_p;
if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){
f->file_read_p = f->file_read_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_read_buffer_p;
f->file_end_read_buffer_p=buffer;
f->file_read_p=buffer;
#ifdef WINDOWS
file_position=SetFilePointer (f->file_read_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_read_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_write_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_write_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_write_refnum,position,FILE_BEGIN,&f->file_offset);
if (error!=0){
f->file_error=-1;
result=0;
}
#endif
return result;
}
}
}
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_read_buffer_p=buffer;
f->file_write_buffer_p=buffer;
f->file_end_read_buffer_p=buffer;
f->file_end_write_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_read_refnum=file_handle;
f->file_write_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_read_buffer_p - f->file_read_buffer_p;
if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){
f->file_read_p = f->file_read_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_read_buffer_p;
f->file_end_read_buffer_p=buffer;
f->file_read_p=buffer;
#ifdef WINDOWS
file_position=SetFilePointer (f->file_read_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_read_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_write_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_read_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_read_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=f->file_offset + (f->file_write_p - f->file_write_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_read_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=f->file_offset + (f->file_write_p - f->file_write_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_read_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_write_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_read_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_write_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_read_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_read_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_read_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_read_buffer_p - f->file_read_p);
else
position=f->file_offset + (f->file_write_p - f->file_write_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_read_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_read_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_read_buffer_p - f->file_read_buffer_p;
if ((unsigned long)(position - (f->file_offset-buffer_size)) < buffer_size){
f->file_read_p = f->file_read_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_read_buffer_p;
f->file_end_read_buffer_p=buffer;
f->file_read_p=buffer;
#ifdef WINDOWS
file_position=SetFilePointer (f->file_read_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_read_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;
}
}