home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
pd6.lzh
/
SRC
/
io.c
< prev
next >
Wrap
Text File
|
1990-05-16
|
13KB
|
429 lines
/*
C BASED FORTH-83 MULTI-TASKING IO MANAGEMENT
Copyright (c) 1989 by Mikael Patel
Computer Aided Design Laboratory (CADLAB)
Department of Computer and Information Science
Linkoping University
S-581 83 LINKOPING
SWEDEN
Email: mip@ida.liu.se
Started on: 30 June 1988
Last updated on: 17 December 1989
Dependencies:
(cc) fcntl.h, errno.h, kernel.h, error.h, memory.h and io.h
Description:
Handles low level access to Operating System to allow asynchronous
input and multi-tasking of Forth level processes while waiting for
buffer filling. File names are saved so that files are not reloaded.
Copying:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef OSK
# include <fcntl.h>
#else
# include <modes.h>
#endif
#include <errno.h>
#include "kernel.h"
#include "memory.h"
#include "error.h"
#include "io.h"
/* MAXIMUM FILE AND PATH NAME STRING SIZES */
#define FILENAMESIZE 128
#define PATHNAMESIZE 128
/* FILE BUFFERS STACK AND STACK POINTER */
#define FSTACKSIZE 32
FILE_BUFFER *io_fstack[FSTACKSIZE];
int io_fsp = -1;
/* STACK OF LOADED FILE NAMES */
#define INFILESSIZE 64
static char *infiles[INFILESSIZE];
static int infsp = -1;
/* STACK OF FILE SEARCH PATHS AND HOME ADDRESS */
#define PATHSSIZE 64
static char *paths[PATHSSIZE];
static int psp = -1;
static char *home;
/* EXTERNAL DEFININED IO DISPATCH ROUTINE AND ENVIRONMENT ACCESS */
extern void io_dispatch();
extern char *getenv();
/* IO MANAGEMENT DEFINITONS */
int io_path(pname, pos)
char *pname; /* Pointer to path name */
int pos; /* Position to append */
{
char pathname[PATHNAMESIZE];
long plen = strlen(pname);
long i;
/* Check for null path. Dont add these */
if (plen == 0) return IO_NO_ERROR;
/* Check if the path name is an environment variable */
if (pname[0] == '$') {
/* Fetch the environment variables value */
char *paths = (char *) getenv((char *) pname + 1);
/* If paths are available recursivly add them to the path list */
if (paths) {
while (*paths) {
char *p = pathname;
/* Parse list of paths; directories seperated by colon */
while (*paths && *paths != ':') *p++ = *paths++;
*p++ = '\0';
/* Append recursively */
(void) io_path(pathname, pos);
/* Access next path if available */
if (*paths) paths++;
}
return IO_NO_ERROR;
}
else
return IO_UNKNOWN_PATH;
}
/* Check if the path contains a home directory character first */
if (pname[0] == '~' && pname[1] == '/') {
(void) strcpy(pathname, home);
(void) strcpy((char *) pathname + strlen(home), (char *) pname + 2);
pname = pathname;
plen = strlen(pathname);
}
/* Check that the last character is a slash if not add it */
if (pname[plen - 1] != '/') {
pname[plen++] = '/';
pname[plen] = '\0';
}
/* Check if the path has already been defined */
for (i = 0; i <= psp; i++)
if (STREQ(paths[i], pname)) return IO_PATH_DEFINED;
/* Check if space is available on path stack */
if (psp + 1 == PATHSSIZE) return IO_TOO_MANY_PATHS;
/* Make space for the new path */
psp = psp + 1;
/* Check where the path should be appended */
if (pos == IO_PATH_FIRST) {
for (i = psp; i > 1; i--) paths[i] = paths[i - 1];
pos = 0;
}
else pos = psp;
/* Add path string att position given */
paths[pos] = strcpy((char *) malloc((unsigned) plen), pname);
return IO_NO_ERROR;
}
void io_flush()
{
/* Flush any waiting output */
(void) fflush(stdout);
/* Close all open files if not end of input stream */
if (io_not_eof()) {
/* Close all files but lowest */
while (io_fsp > 0) (void) close(io_fstack[io_fsp--] -> fd);
/* Close lowest file on file stack if not tty */
if (!isatty(io_fstack[io_fsp] -> fd))
(void) close(io_fstack[io_fsp--] -> fd);
}
}
int io_infile(fname)
char *fname; /* Pointer to file name to open as input */
{
char filename[FILENAMESIZE];
long i, j;
long fd;
/* Check for standard input as source */
if (fname == STDIN) {
/* Check if space is available on file stack */
if (io_fsp + 1 == FSTACKSIZE) return IO_TOO_MANY_FILES;
/* Push standard input as source onto the file buffer stack */
io_fsp = io_fsp + 1;
io_fstack[io_fsp] -> fd = STDIN;
io_fstack[io_fsp] -> bufp = 0;
io_fstack[io_fsp] -> cc = 0;
return IO_NO_ERROR;
}
/* Check if the file name contains a home directory character first */
if (fname[0] == '~' && fname[1] == '/') fname += 2;
/* Expand the file name using the path stack and try opening the file */
for (i = 0; i <= psp; i++) {
/* Build the new file name using a path */
(void) strcpy(filename, paths[i]);
(void) strcpy(filename + strlen(paths[i]), fname);
/* Check if this file has already been loaded */
for (j = 0; j <= infsp; j++)
if (STREQ(infiles[j], filename)) return IO_FILE_INCLUDED;
/* Try opening the file */
fd = open(filename, S_IREAD);
/* If no errors then save the file name and return file descriptor */
if (fd != -1) {
/* Check if space is available on file stack */
if (io_fsp + 1 == FSTACKSIZE) return IO_TOO_MANY_FILES;
/* Push file onto the file buffer stack and use it as source */
infsp = infsp + 1;
infiles[infsp] = strcpy((char *) malloc((unsigned) strlen(filename) + 1), filename);
io_fstack[++io_fsp] -> fd = fd;
io_fstack[io_fsp] -> bufp = 0;
io_fstack[io_fsp] -> cc = 0;
return fd;
}
}
/* The file was not available so return error */
return IO_UNKNOWN_FILE;
}
int io_fillbuf()
{
long nonblocking;
/* Check io consistency and foreground task input only */
if (io_eof() || tp != foreground) error_fatal(0);
/* Flush any waiting output if filling buffer from a terminal */
if (isatty(io_fstack[io_fsp] -> fd)) (void) fflush(stdout);
/* Check for multi-tasking input operation */
if (tp != ((TASK *) tp -> queue.succ)) {
#ifndef OSK
(void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, FNDELAY);
#else
if (!isatty(io_fstack[io_fsp] -> fd))
(void) _ss_tiks(io_fstack[io_fsp] -> fd,1);
#endif
tp -> status = IOWAITING;
nonblocking = TRUE;
}
else
nonblocking = FALSE;
/* Allow multi-tasking during waiting for input */
for (;;) {
/* Try reading a block from the current input stream */
#ifndef OSK
if ((io_fstack[io_fsp] -> cc = read(io_fstack[io_fsp] -> fd,
io_fstack[io_fsp] -> buf,
BUFSIZE)) > 0) {
#else
io_fstack[io_fsp]->cc = (nonblocking ?
(_gs_rdy(io_fstack[io_fsp]->fd) < 0 ? -1 :
(isatty(io_fstack[io_fsp]->fd) ? readln(io_fstack[io_fsp] -> fd,
io_fstack[io_fsp] -> buf,
BUFSIZE) :
read(io_fstack[io_fsp] -> fd,
io_fstack[io_fsp] -> buf,
BUFSIZE) ) ) :
(isatty(io_fstack[io_fsp]->fd) ? readln(io_fstack[io_fsp] -> fd,
io_fstack[io_fsp] -> buf,
BUFSIZE) :
read(io_fstack[io_fsp] -> fd,
io_fstack[io_fsp] -> buf,
BUFSIZE) ) );
if (io_fstack[io_fsp] -> cc > 0) {
#endif
/* Restore to non-blocking input from file and foreground */
if (nonblocking) {
#ifndef OSK
(void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0);
#endif
spush(foreground);
doresume();
tp -> status = RUNNING;
}
/* Initiate the buffer pointer and return the first character */
io_fstack[io_fsp] -> bufp = 0;
return io_getchar();
}
/* Did the read operation result in an end of file */
#ifndef OSK
if (io_fstack[io_fsp] -> cc == 0 && errno != EWOULDBLOCK) {
#else
if (io_fstack[io_fsp] -> cc == 0 && errno != E_LOCK) {
#endif
/* Set back the file mode to synchronous and close the file */
if (nonblocking) {
#ifndef OSK
(void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0);
#else
(void) _ss_tiks(io_fstack[io_fsp] -> fd,0);
#endif
spush(foreground);
doresume();
tp -> status = RUNNING;
}
(void) close(io_fstack[io_fsp--] -> fd);
/* Check if end of input source */
if (io_eof()) return IO_EOF;
/* Get character from previous file buffer */
return io_getchar();
}
/* Run forth level tasks while waiting for input */
if (tp == foreground) dodetach(); else doinner();
/* Check if the task for empty, i.e., only the foreground */
if (tp == foreground && tp == ((TASK *) tp -> queue.succ)) {
#ifndef OSK
(void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0);
#else
(void) _ss_tiks(io_fstack[io_fsp] -> fd,0);
#endif
nonblocking = FALSE;
}
/* Allow user extension of the io wait loop */
io_dispatch();
}
}
void io_skip(skpchr)
char skpchr; /* Skip character */
{
/* Skip all characters until skip termination character or end of file */
while (io_not_eof() && io_getchar() != skpchr);
}
void io_scan(buf, brkchr)
char *buf; /* Pointer to scan buffer */
char brkchr; /* Break character */
{
/* Initiate buffer as null string */
*buf = '\0';
/* Check for scanning until white space or special break character */
if (brkchr == ' ') {
/* While not white space or end of file */
while (io_not_eof() && !ISSPACE(*buf = io_getchar())) buf++;
}
else {
/* While not the break character or end of file */
while (io_not_eof() && (*buf = io_getchar()) != brkchr) buf++;
}
/* End the string and return */
*buf = '\0';
return;
}
void io_skipspace()
{
/* Skip all white spaces */
while (io_not_eof() && ISSPACE(io_getchar()));
/* Step back the buffer pointer */
if (io_not_eof()) io_fstack[io_fsp] -> bufp -= 1;
}
void io_initiate(banner)
char *banner; /* Initiate application message */
{
long i;
/* Print banner and add initial paths */
(void) printf(banner);
(void) io_path(".", IO_PATH_LAST);
(void) io_path("$PWD", IO_PATH_LAST);
(void) io_path(home = (char *) getenv("HOME"), IO_PATH_LAST);
(void) io_path("$TILEPATH", IO_PATH_LAST);
#ifdef OSK
(void) io_path("/dd/lib/tile", IO_PATH_LAST);
#endif
/* Allocate file buffers */
for (i = 0; i < FSTACKSIZE; i++) {
io_fstack[i] = (FILE_BUFFER *) malloc((unsigned) sizeof(FILE_BUFFER));
if (io_fstack[i] == NIL) {
(void) printf("io: can not allocate file buffers\n");
exit(0);
}
}
}
void io_finish()
{
/* Flush any waiting output */
(void) fflush(stdout);
/* Close all open files */
while (io_not_eof()) (void) close(io_fstack[io_fsp--] -> fd);
}