mirror of
https://github.com/simh/simh.git
synced 2026-05-03 06:28:41 +00:00
Bob Supnik's state as of 5/9/2015 after backporting some things from the master branch
This commit is contained in:
215
sim_fio.c
215
sim_fio.c
@@ -1,6 +1,6 @@
|
||||
/* sim_fio.c: simulator file I/O library
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2015, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,6 +23,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
02-Apr-15 RMS Backported from GitHub master
|
||||
28-Jun-07 RMS Added VMS IA64 support (from Norm Lastovica)
|
||||
10-Jul-06 RMS Fixed linux conditionalization (from Chaskiel Grundman)
|
||||
15-May-06 RMS Added sim_fsize_name
|
||||
@@ -35,22 +36,27 @@
|
||||
|
||||
This library includes:
|
||||
|
||||
sim_finit - initialize package
|
||||
sim_fopen - open file
|
||||
sim_fread - endian independent read (formerly fxread)
|
||||
sim_write - endian independent write (formerly fxwrite)
|
||||
sim_fseek - extended (>32b) seek (formerly fseek_ext)
|
||||
sim_fsize - get file size
|
||||
sim_finit initialize package
|
||||
sim_fopen open file
|
||||
sim_fread endian independent read (formerly fxread)
|
||||
sim_write endian independent write (formerly fxwrite)
|
||||
sim_fseek (now a macro using fseeko)
|
||||
sim_fseeko extended seek (>32b if available)
|
||||
sim_ftell extended tell (>32b if available)
|
||||
sim_fsize (now a macro using sim_fsize_ex)
|
||||
sim_fsize_name (now a macro using sim_fsize_ex)
|
||||
sim_fsize_ex get file size as a t_offset
|
||||
sim_fsize_name get file size as a t_offset of named file
|
||||
|
||||
sim_fopen and sim_fseek are OS-dependent. The other routines are not.
|
||||
sim_fsize is always a 32b routine (it is used only with small capacity random
|
||||
access devices like fixed head disks and DECtapes).
|
||||
sim_fopen, sim_fseeko, sim_ftell are OS-dependent. The other routines are not.
|
||||
*/
|
||||
|
||||
#include "sim_defs.h"
|
||||
|
||||
static unsigned char sim_flip[FLIP_SIZE];
|
||||
int32 sim_end = 1; /* 1 = little */
|
||||
t_bool sim_end; /* TRUE = little endian, FALSE = big endian */
|
||||
t_bool sim_taddr_64; /* t_addr is > 32b and large file support available */
|
||||
t_bool sim_toffset_64; /* large file (>2GB) support available */
|
||||
|
||||
/* OS-independent, endian independent binary I/O package
|
||||
|
||||
@@ -74,7 +80,9 @@ int32 sim_finit (void)
|
||||
union {int32 i; char c[sizeof (int32)]; } end_test;
|
||||
|
||||
end_test.i = 1; /* test endian-ness */
|
||||
sim_end = end_test.c[0];
|
||||
sim_end = (end_test.c[0] != 0);
|
||||
sim_toffset_64 = (sizeof(t_offset) > sizeof(int32)); /* large file (>2GB) support */
|
||||
sim_taddr_64 = sim_toffset_64 && (sizeof(t_addr) > sizeof(int32));
|
||||
return sim_end;
|
||||
}
|
||||
|
||||
@@ -134,113 +142,70 @@ return total;
|
||||
|
||||
/* Get file size */
|
||||
|
||||
uint32 sim_fsize_name (char *fname)
|
||||
t_offset sim_fsize_ex (FILE *fp)
|
||||
{
|
||||
t_offset pos, sz;
|
||||
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
pos = sim_ftell (fp);
|
||||
sim_fseek (fp, 0, SEEK_END);
|
||||
sz = sim_ftell (fp);
|
||||
sim_fseeko (fp, pos, SEEK_SET);
|
||||
return sz;
|
||||
}
|
||||
|
||||
t_offset sim_fsize_name_ex (char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
uint32 sz;
|
||||
t_offset sz;
|
||||
|
||||
if ((fp = sim_fopen (fname, "rb")) == NULL)
|
||||
return 0;
|
||||
sz = sim_fsize (fp);
|
||||
sz = sim_fsize_ex (fp);
|
||||
fclose (fp);
|
||||
return sz;
|
||||
}
|
||||
|
||||
uint32 sim_fsize (FILE *fp)
|
||||
{
|
||||
uint32 pos, sz;
|
||||
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
pos = ftell (fp);
|
||||
fseek (fp, 0, SEEK_END);
|
||||
sz = ftell (fp);
|
||||
fseek (fp, pos, SEEK_SET);
|
||||
return sz;
|
||||
}
|
||||
|
||||
/* OS-dependent routines */
|
||||
|
||||
/* Optimized file open */
|
||||
/* Optimized file open
|
||||
|
||||
VMS - specify extra goodies
|
||||
Linux, HP/UX, AIX - use a 64b open if necessary
|
||||
Others - ordinary open works for 32b or 64b */
|
||||
|
||||
FILE *sim_fopen (const char *file, const char *mode)
|
||||
{
|
||||
#if defined (VMS)
|
||||
return fopen (file, mode, "ALQ=32", "DEQ=4096",
|
||||
"MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm");
|
||||
#elif defined (USE_INT64) && defined (USE_ADDR64) && defined (__linux)
|
||||
#elif (defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX)) && !defined (DONT_DO_LARGEFILE)
|
||||
return fopen64 (file, mode);
|
||||
#else
|
||||
return fopen (file, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Long seek */
|
||||
/* Now define sim_fseeko and sim_ftell */
|
||||
|
||||
#if defined (USE_INT64) && defined (USE_ADDR64)
|
||||
#if !defined (DONT_DO_LARGEFILE)
|
||||
|
||||
/* 64b VMS */
|
||||
/* 64b VMS or Solaris */
|
||||
|
||||
#if (defined (__ALPHA) || defined (__ia64)) && defined (VMS) /* 64b VMS */
|
||||
#define _SIM_IO_FSEEK_EXT_ 1
|
||||
#if ((defined (__ALPHA) || defined (__ia64)) && defined (VMS) && (__DECC_VER >= 60590001)) || \
|
||||
((defined(__sun) || defined(__sun__)) && defined(_LARGEFILE_SOURCE))
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
|
||||
static t_int64 fpos_t_to_int64 (fpos_t *pos)
|
||||
int sim_fseeko (FILE *st, t_offset offset, int whence)
|
||||
{
|
||||
unsigned short *w = (unsigned short *) pos; /* endian dep! */
|
||||
t_int64 result;
|
||||
|
||||
result = w[1];
|
||||
result <<= 16;
|
||||
result += w[0];
|
||||
result <<= 9;
|
||||
result += w[2];
|
||||
return result;
|
||||
return fseeko (st, (off_t)offset, whence);
|
||||
}
|
||||
|
||||
static void int64_to_fpos_t (t_int64 ipos, fpos_t *pos, size_t mbc)
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
unsigned short *w = (unsigned short *) pos;
|
||||
int bufsize = mbc << 9;
|
||||
|
||||
w[3] = 0;
|
||||
w[2] = (unsigned short) (ipos % bufsize);
|
||||
ipos -= w[2];
|
||||
ipos >>= 9;
|
||||
w[0] = (unsigned short) ipos;
|
||||
ipos >>= 16;
|
||||
w[1] = (unsigned short) ipos;
|
||||
if ((w[2] == 0) && (w[0] || w[1])) {
|
||||
w[2] = bufsize;
|
||||
w[0] -= mbc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int sim_fseek (FILE *st, t_addr offset, int whence)
|
||||
{
|
||||
t_addr fileaddr;
|
||||
fpos_t filepos;
|
||||
|
||||
switch (whence) {
|
||||
|
||||
case SEEK_SET:
|
||||
fileaddr = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if (fgetpos (st, &filepos))
|
||||
return (-1);
|
||||
fileaddr = fpos_t_to_int64 (&filepos);
|
||||
fileaddr = fileaddr + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int64_to_fpos_t (fileaddr, &filepos, 127);
|
||||
return fsetpos (st, &filepos);
|
||||
return (t_offset)(ftello (st));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -248,30 +213,42 @@ return fsetpos (st, &filepos);
|
||||
/* Alpha UNIX - natively 64b */
|
||||
|
||||
#if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */
|
||||
#define _SIM_IO_FSEEK_EXT_ 1
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
|
||||
int sim_fseek (FILE *st, t_addr offset, int whence)
|
||||
int sim_fseeko (FILE *st, t_offset offset, int whence)
|
||||
{
|
||||
return fseek (st, offset, whence);
|
||||
}
|
||||
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
return (t_offset)(ftell (st));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Windows */
|
||||
|
||||
#if defined (_WIN32)
|
||||
#define _SIM_IO_FSEEK_EXT_ 1
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
#include <sys/stat.h>
|
||||
|
||||
int sim_fseek (FILE *st, t_addr offset, int whence)
|
||||
int sim_fseeko (FILE *st, t_offset offset, int whence)
|
||||
{
|
||||
fpos_t fileaddr;
|
||||
struct _stati64 statb;
|
||||
|
||||
switch (whence) {
|
||||
|
||||
case SEEK_SET:
|
||||
fileaddr = offset;
|
||||
fileaddr = (fpos_t)offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (_fstati64 (_fileno (st), &statb))
|
||||
return (-1);
|
||||
fileaddr = statb.st_size + offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
if (fgetpos (st, &fileaddr))
|
||||
return (-1);
|
||||
@@ -286,44 +263,62 @@ switch (whence) {
|
||||
return fsetpos (st, &fileaddr);
|
||||
}
|
||||
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
fpos_t fileaddr;
|
||||
if (fgetpos (st, &fileaddr))
|
||||
return (-1);
|
||||
return (t_offset)fileaddr;
|
||||
}
|
||||
|
||||
#endif /* end Windows */
|
||||
|
||||
/* Linux */
|
||||
/* Linux, HP/UX, and AIX */
|
||||
|
||||
#if defined (__linux)
|
||||
#define _SIM_IO_FSEEK_EXT_ 1
|
||||
#if defined (__linux) || defined (__linux__) || defined (__hpux) || defined (_AIX)
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
|
||||
int sim_fseek (FILE *st, t_addr xpos, int origin)
|
||||
int sim_fseeko (FILE *st, t_offset xpos, int origin)
|
||||
{
|
||||
return fseeko64 (st, xpos, origin);
|
||||
return fseeko64 (st, (off64_t)xpos, origin);
|
||||
}
|
||||
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
return (t_offset)(ftello64 (st));
|
||||
}
|
||||
|
||||
#endif /* end Linux with LFS */
|
||||
|
||||
/* Apple OS/X */
|
||||
/* Apple OS/X and the BSD family */
|
||||
|
||||
#if defined (__APPLE__) || defined (__FreeBSD__)
|
||||
#define _SIM_IO_FSEEK_EXT_ 1
|
||||
#if defined (__APPLE__) || defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__)
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
|
||||
int sim_fseek (FILE *st, t_addr xpos, int origin)
|
||||
int sim_fseeko (FILE *st, t_offset xpos, int origin)
|
||||
{
|
||||
return fseeko (st, xpos, origin);
|
||||
return fseeko (st, (off_t)xpos, origin);
|
||||
}
|
||||
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
return (t_offset)(ftello (st));
|
||||
}
|
||||
|
||||
#endif /* end Apple OS/X */
|
||||
|
||||
#endif /* end 64b seek defs */
|
||||
#endif /* !DONT_DO_LARGEFILE */
|
||||
|
||||
/* Default: no OS-specific routine has been defined */
|
||||
|
||||
#if !defined (_SIM_IO_FSEEK_EXT_)
|
||||
#define _SIM_IO_FSEEK_EXT_ 0
|
||||
|
||||
int sim_fseek (FILE *st, t_addr xpos, int origin)
|
||||
#if !defined (S_SIM_IO_FSEEK_EXT_)
|
||||
int sim_fseeko (FILE *st, t_offset xpos, int origin)
|
||||
{
|
||||
return fseek (st, (int32) xpos, origin);
|
||||
return fseek (st, (long) xpos, origin);
|
||||
}
|
||||
|
||||
t_offset sim_ftell (FILE *st)
|
||||
{
|
||||
return (t_offset)(ftell (st));
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32 sim_taddr_64 = _SIM_IO_FSEEK_EXT_;
|
||||
|
||||
Reference in New Issue
Block a user