AltairZ80: Replaced platform specific directory scanning with SCP API (update 2)

This commit is contained in:
Peter Schorn 2018-05-19 15:53:42 +02:00
parent 4734454bac
commit b3136d2d6d

View file

@ -56,11 +56,6 @@
#include "sim_tmxr.h"
#include <time.h>
#include <assert.h>
#if UNIX_PLATFORM
#include <glob.h>
#elif defined (_WIN32)
#include <windows.h>
#endif
uint8 *URLContents(const char *URL, uint32 *length);
#ifndef URL_READER_SUPPORT
@ -123,7 +118,8 @@ uint8 *URLContents(const char *URL, uint32 *length) {
#define PORT_TABLE_SIZE 256 /* size of port mapping table */
#define SLEEP_ALLOWED_START_DEFAULT 100 /* default initial value for sleepAllowedCounter*/
#define DEFAULT_TIMER_DELTA 100 /* default value for timer delta in ms */
#define DEFAULT_TIMER_DELTA 100 /* default value for timer delta in ms */
#define CPM_COMMAND_LINE_LENGTH 128
static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
@ -231,23 +227,56 @@ static uint32 newClockFrequency;
static int32 setClockFrequencyPos = 0; /* determines state for sending the clock frequency */
static int32 getClockFrequencyPos = 0; /* determines state for receiving the clock frequency */
/* support for wild card expansion */
#if UNIX_PLATFORM
static glob_t globS;
static uint32 globPosNameList = 0;
static int32 globPosName = 0;
static int32 globValid = FALSE;
static int32 globError = 0;
/* support for wild card file expansion */
#if defined (__MWERKS__) && defined (macintosh)
const static char hostPathSeparator = ':'; /* colon on Macintosh OS 9 */
const static char hostPathSeparatorAlt = ':'; /* no alternative */
#elif defined (_WIN32)
static WIN32_FIND_DATA FindFileData;
static HANDLE hFind = INVALID_HANDLE_VALUE;
static int32 globFinished = FALSE;
static int32 globValid = FALSE;
static int32 globPosName = 0;
static int32 lastPathSeparator = 0;
static int32 firstPathCharacter = 0;
const static char hostPathSeparator = '\\'; /* back slash in Windows */
const static char hostPathSeparatorAlt = '/'; /* '/' is an alternative */
#else
const static char hostPathSeparator = '/'; /* slash in UNIX */
const static char hostPathSeparatorAlt = '/'; /* no alternative */
#endif
typedef struct NameNode {
char *name;
struct NameNode *next;
} NameNode_t;
static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH];
static NameNode_t *nameListHead = NULL;
static NameNode_t *currentName = NULL;
static int32 currentNameIndex = 0;
static int32 lastPathSeparatorIndex = 0;
static int32 firstPathCharacterIndex = 0;
static void deleteNameList() {
while (nameListHead != NULL) {
NameNode_t *next = nameListHead -> next;
free(nameListHead -> name);
free(nameListHead);
nameListHead = next;
}
currentName = NULL;
currentNameIndex = 0;
}
static void processDirEntry (const char *directory,
const char *filename,
t_offset FileSize,
const struct stat *filestat,
void *context) {
if (filename != NULL) {
NameNode_t *top = (NameNode_t *)malloc(sizeof(NameNode_t));
top -> name = strdup(filename);
top -> next = nameListHead;
nameListHead = top;
}
}
/* SIO status registers */
static int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */
static int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to
@ -1224,7 +1253,6 @@ static const char *cmdNames[kSimhPseudoDeviceCommands] = {
"setCPUClockFrequency",
};
#define CPM_COMMAND_LINE_LENGTH 128
#define TIMER_STACK_LIMIT 10 /* stack depth of timer stack */
static uint32 markTime[TIMER_STACK_LIMIT]; /* timer stack */
static struct tm currentTime;
@ -1309,7 +1337,6 @@ static t_stat simh_svc(UNIT *uptr) {
return SCPE_OK;
}
static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH];
static void createCPMCommandLine(void) {
int32 i, len = (GetBYTEWrapper(0x80) & 0x7f); /* 0x80 contains length of command line, discard first char */
for (i = 0; i < len - 1; i++)
@ -1317,18 +1344,6 @@ static void createCPMCommandLine(void) {
cpmCommandLine[i] = 0; /* make C string */
}
#if defined (_WIN32)
static void setLastPathSeparator(void) {
int32 i = 0;
while (cpmCommandLine[i])
i++;
while ((i >= 0) && (cpmCommandLine[i] != '\\'))
i--;
lastPathSeparator = i;
firstPathCharacter = 0;
}
#endif
/* The CP/M command line is used as the name of a file and UNIT* uptr is attached to it. */
static void attachCPM(UNIT *uptr) {
createCPMCommandLine();
@ -1419,37 +1434,23 @@ static int32 simh_in(const int32 port) {
break;
case getHostFilenamesCmd:
#if UNIX_PLATFORM
if (globValid) {
if (globPosNameList < globS.gl_pathc) {
if (!(result = globS.gl_pathv[globPosNameList][globPosName++])) {
globPosNameList++;
globPosName = 0;
}
}
else {
globValid = FALSE;
if (nameListHead != NULL) {
if (currentName == NULL) {
deleteNameList();
lastCommand = 0;
globfree(&globS);
}
else if (firstPathCharacterIndex <= lastPathSeparatorIndex)
result = cpmCommandLine[firstPathCharacterIndex++];
else {
result = currentName -> name[currentNameIndex];
if (result == 0) {
currentName = currentName -> next;
firstPathCharacterIndex = currentNameIndex = 0;
}
else
currentNameIndex++;
}
}
#elif defined (_WIN32)
if (globValid)
if (globFinished)
globValid = FALSE;
else if (firstPathCharacter <= lastPathSeparator)
result = cpmCommandLine[firstPathCharacter++];
else if (!(result = FindFileData.cFileName[globPosName++])) {
globPosName = firstPathCharacter = 0;
if (!FindNextFile(hFind, &FindFileData)) {
globFinished = TRUE;
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
#else
lastCommand = 0;
#endif
break;
case attachPTRCmd:
@ -1586,13 +1587,7 @@ static int32 simh_in(const int32 port) {
break;
case getHostOSPathSeparatorCmd:
#if defined (__MWERKS__) && defined (macintosh)
result = ':'; /* colon on Macintosh OS 9 */
#elif defined (_WIN32)
result = '\\'; /* back slash in Windows */
#else
result = '/'; /* slash in UNIX */
#endif
result = hostPathSeparator;
break;
default:
@ -1728,39 +1723,30 @@ static int32 simh_out(const int32 port, const int32 data) {
isInReadPhase = FALSE;
break;
case getHostFilenamesCmd:
#if UNIX_PLATFORM
if (!globValid) {
globValid = TRUE;
globPosNameList = globPosName = 0;
case getHostFilenamesCmd: /* list files of host file directory */
if (nameListHead == NULL) {
t_stat result;
createCPMCommandLine();
globError = glob(cpmCommandLine, GLOB_ERR, NULL, &globS);
if (globError) {
lastPathSeparatorIndex = 0;
while (cpmCommandLine[lastPathSeparatorIndex])
lastPathSeparatorIndex++;
while ((lastPathSeparatorIndex >= 0) && (cpmCommandLine[lastPathSeparatorIndex] != hostPathSeparator) && (cpmCommandLine[lastPathSeparatorIndex] != hostPathSeparatorAlt))
lastPathSeparatorIndex--;
firstPathCharacterIndex = 0;
deleteNameList();
result = sim_dir_scan(cpmCommandLine, processDirEntry, NULL);
if (result == SCPE_OK) {
currentName = nameListHead;
currentNameIndex = 0;
} else {
deleteNameList();
sim_debug(VERBOSE_MSG, &simh_device,
"SIMH: " ADDRESS_FORMAT
" Cannot expand '%s'. Error is %i.\n",
PCX, cpmCommandLine, globError);
globfree(&globS);
globValid = FALSE;
" Cannot expand '%s'. Error is %s.\n",
PCX, cpmCommandLine, sim_error_text(result));
}
}
#elif defined (_WIN32)
if (!globValid) {
globValid = TRUE;
globPosName = 0;
globFinished = FALSE;
createCPMCommandLine();
setLastPathSeparator();
hFind = FindFirstFile(cpmCommandLine, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE) {
sim_debug(VERBOSE_MSG, &simh_device,
"SIMH: " ADDRESS_FORMAT
" Cannot expand '%s'. Error is %lu.\n",
PCX, cpmCommandLine, GetLastError());
globValid = FALSE;
}
}
#endif
break;
case SIMHSleepCmd:
@ -1858,19 +1844,7 @@ static int32 simh_out(const int32 port, const int32 data) {
case resetSIMHInterfaceCmd:
markTimeSP = 0;
lastCommand = 0;
#if UNIX_PLATFORM
if (globValid) {
globValid = FALSE;
globfree(&globS);
}
#elif defined (_WIN32)
if (globValid) {
globValid = FALSE;
if (hFind != INVALID_HANDLE_VALUE) {
FindClose(hFind);
}
}
#endif
deleteNameList();
break;
case showTimerCmd: /* show time difference to timer on top of stack */