home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_300
/
318_01
/
redsys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-18
|
14KB
|
756 lines
/*
RED operating system module -- Full C version
Source: redsys.c
Version: June 18, 1986; January 18, 1990.
Written by
Edward K. Ream
166 N. Prospect
Madison WI 53705
(608) 257-0802
PUBLIC DOMAIN SOFTWARE
This software is in the public domain.
See red.h for a disclaimer of warranties and other information.
*/
#include "red.h"
#ifdef MICRO_SOFT
#include <bios.h>
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys\types.h>
#include <sys\stat.h>
#endif
#ifdef TURBOC
#include <alloc.h>
#include <conio.h>
#include <fcntl.h>
#include <io.h>
#include <mem.h>
#include <sys\stat.h>
#endif
static char sysinbuf[128]; /* file buffer */
static int sysincnt; /* index to sysinbuf[] */
static char syscbuf[MAXLEN]; /* typeahead buffer */
static int sysccnt; /* index for syscbuf[] */
static int sysrcnt; /* repeat count */
static int syslastc; /* last character */
static int systopl,systopy,sysnl; /* interrupt info */
/*
NOTE: This module should contain all routines that
might have to be changed for different compilers or
different operating systems.
Some routines in this module probably will probably
work regardless of operating system. These I have
called PORTABLE routines.
*/
/*
Return a pointer to a block of n contiguous bytes.
Return NULL (i.e., 0) if fewer than n bytes remain.
*/
char *
sysalloc(n)
int n;
{
char * p;
p = (char *) malloc(n);
TRACEP("sysalloc",
sl_lpout(); sl_iout(n);
sl_sout(") returns "); sl_pout(p); sl_cout('\n'));
return p;
}
/*
o Wait for next character from the console.
o Do NOT echo the character.
o Print any waiting lines if there is no input ready.
o Swap out any dirty blocks if nothing else is happening.
(The SWAP constant enables this feature)
*/
int
syscin(void)
{
int c;
int main_byte, aux_byte;
SL_DISABLE();
for(;;) {
c = syscstat();
if (c != -1) {
break;
}
/* Output queued ? */
if (hasint && sysnl > 0) {
/* Print one line. */
bufout(systopl, systopy, sysnl);
}
#ifdef SWAP
/* Do not interrupt screen activity. */
if (sysnl == 0) {
/* Swap out one dirty buffer. */
swap_one();
}
#endif
}
#ifdef IBM
main_byte = c & 0xff;
aux_byte = (c & 0xff00) >> 8;
TRACEP("syscin",
sl_sout(" main: "); sl_iout(main_byte);
sl_sout(" aux: "); sl_iout(aux_byte);
sl_cout('\n'));
/* Handle cursor keys and the numeric keypad. */
if (main_byte == 0) switch (aux_byte) {
case 71: return HOME_KEY; /* Home key. */
case 79: return END_KEY; /* End key. */
case 73: return PAGE_UP; /* Page up key. */
case 81: return PAGE_DN; /* Page down key. */
case 82: return UP_INS; /* Insert key */
case 83: return DEL2; /* Delete Key */
case 77: return RIGHT; /* Arrow keys. */
case 75: return LEFT;
case 72: return UP;
case 80: return DOWN;
}
#endif
return c & 0x7f;
}
/*
Close an unbuffered file.
Return OK (0) or ERROR (-1).
*/
int
sysclose(int fd)
{
TRACEP("sysclose", sl_lpout(); sl_iout(fd); sl_rpout());
close(fd);
}
/*
Copy a file name from args to buffer.
This routine is SEMI-PORTABLE, since it depends,
to a certain extent, on what constitutes a file name.
*/
void
syscopfn(char *args, char *buffer)
{
int n;
TRACEP("syscopfn", sl_lpout();
sl_sout(args); sl_csout();
sl_pout(buffer); sl_rpout());
for (n = 0;
n < SYSFNMAX -1 && args [n] != '\0' && args [n] != ' ';
n++) {
buffer [n] = args [n];
}
buffer[n] = '\0';
}
/*
Create an file for use by sysread and syswrite.
Erase it if it exists and leave it open for read/write access.
Return a small positive int or ERROR (-1).
*/
int
syscreat(char * filename)
{
int result;
TRACEP("syscreat", sl_lpout(); sl_sout(filename));
#ifdef MICRO_SOFT
_fmode = O_BINARY;
result = creat(filename, S_IREAD | S_IWRITE);
_fmode = O_TEXT;
#endif
#ifdef TURBOC
_fmode = O_BINARY;
result = creat(filename, S_IREAD | S_IWRITE);
_fmode = O_TEXT;
#endif
TRACE("syscreat",
sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
return result;
}
/*
Return -1 if no character is ready from the keyboard.
Otherwise, return the character itself.
This routine handles typeahead buffering. It would
also handle the repeat key, if that feature is used,
which it is NOT at present. The code enclosed in
comments handles the repeat key.
*/
int
syscstat(void)
{
int c;
SL_DISABLE();
/* Always look for another character. */
#ifdef MICRO_SOFT
c = _bios_keybrd(_KEYBRD_READY);
if (c == 0) {
c = -1;
}
else {
_bios_keybrd(_KEYBRD_READ);
}
#endif
#ifdef TURBOC
c = bioskey(1);
if (c == 0) {
c = -1;
}
else {
bioskey(0);
}
#endif
return c;
}
/*
Execute args as if they were entered from the command line.
*/
void
sysexec(char *args)
{
SL_DISABLE();
#ifdef MICRO_SOFT
system(args);
puts("\nPress any key to resume editing: ");
syscin();
#endif
#ifdef TURBOC
system(args);
puts("\nPress any key to resume editing: ");
syscin();
#endif
}
/*
Return TRUE if the file exists and FALSE otherwise.
This routine is PORTABLE.
*/
int
sysexists(char * filename)
{
int fd;
TRACEPB("sysexists", sl_lpout(); sl_sout(filename); sl_rpout());
if ((fd = sysopen(filename)) != ERROR) {
sysclose(fd);
RETURN_BOOL("sysexists", TRUE);
}
else {
RETURN_BOOL("sysexists", FALSE);
}
}
/*
Close and flush a file opened with sysfopen or sysfcreat.
Return OK (0) or ERROR (-1).
*/
int
sysfclose(FILE *fd)
{
TRACEP("sysfclose", sl_lpout(); sl_pout(fd); sl_rpout());
return fclose(fd);
}
/*
Create a buffered output file for use with sysfputs.
The file is cleared (erased) if it already exists.
A pointer to FILE is returned if all goes well.
NULL (0), is returned if the file can not be created.
*/
FILE *
sysfcreat(char *filename)
{
FILE * f;
TRACEP("sysfcreat", sl_lpout(); sl_sout(filename));
#ifdef MICRO_SOFT
f = fopen(filename, "w");
#endif
#ifdef TURBOC
f = fopen(filename, "w");
#endif
TRACE("sysfcreat",
sl_sout(") returns "); sl_pout(f); sl_cout('\n'));
return f;
}
/*
Read the next line from buffered input file.
End the line with an '\n'.
Return the count of the characters read.
Return ERROR (-1) on end-of-file.
*/
int
sysfgets(FILE *fd, char *buffer, int maxlen)
{
int c, count;
TRACEP("sysfgets", sl_lpout();
sl_pout(fd); sl_csout();
sl_pout(buffer); sl_csout();
sl_iout(maxlen));
count = 0;
while(1) {
c = sysgetc(fd);
if (c == '\r') {
/* Ignore pseudo newline. */
continue;
}
else if (c == EOF_MARK || c == ERROR) {
buffer [min(count, maxlen-2)] = '\n';
buffer [min(count, maxlen-1)] = '\0';
TRACE("sysfgets", sl_sout(") returns ERROR\n"));
return ERROR;
}
else if (c == '\n') {
buffer [min(count, maxlen-2)] = '\n';
buffer [min(count, maxlen-1)] = '\0';
TRACE("sysfgets",
sl_sout(") returns ");
sl_iout(count);
sl_cout('\n'));
return count;
}
else if (count < maxlen - 2) {
buffer [count++] = c;
}
else {
count++;
}
}
}
/*
Write n BYTES from the buffer to the END of an unbuffered file.
Return ERROR (-1) or 1.
*/
int
sysflush(int fd, char * buffer, int n)
{
int result;
#ifdef MICRO_SOFT
result = (write(fd, buffer, n) == -1) ? ERROR : 1;
#endif
#ifdef TURBOC
result = (write(fd, buffer, n) == -1) ? ERROR : 1;
#endif
return result;
}
/*
Open a buffered input file for use by sysfgets and sysgetc.
Return FILE or NULL if the file does not exist.
*/
FILE *
sysfopen(char *filename)
{
FILE * f;
#ifdef MICRO_SOFT
f = fopen(filename, "r");
#endif
#ifdef TURBOC
f = fopen(filename, "r");
#endif
return f;
}
/*
Get the next characer from a file opened by sysfopen.
Mask off the high bit of the character.
return ERROR on end of file.
*/
int
sysgetc(FILE *fd)
{
int c;
SL_DISABLE();
c = getc(fd);
/* Be careful not to mask off bit on EOF. */
return ((c == ERROR) ? ERROR : c & 0x7f);
}
/*
Initialize the system module.
The storage allocation routines are a real problem.
The AZTEC and DRI compilers completely botch it.
*/
void
sysinit(void)
{
TICK("sysinit");
/*
System dependent part.
This code sets the "moat" (in Unix terminology),
i.e., the amount of space that is guarenteed for
use by the stack by the memory allocation routines.
If you don't reserve enough space for the stack
the inject, extract, move and copy commands will crash.
*/
#ifdef DESMET
scr_setup();
freeall(4000);
#endif
#ifdef TURBOC
/* Use raw input. */
setcbrk(0);
#endif
/*
PORTABLE part.
*/
sysnl = 0;
sysccnt = 0;
sysrcnt = 0;
syslastc = 0;
}
/*
Save info for interrupted screen update.
This routine is PORTABLE.
*/
void
sysintr(int systl, int systy, int sysn)
{
SL_DISABLE();
systopl = systl;
systopy = systy;
sysnl = max(0,sysn);
}
/*
Print character on the printer.
*/
int
syslout(char c)
{
SL_DISABLE();
#ifdef DESMET
_os(5, c);
#endif
return c;
}
/*
Move a block of memory.
This code MUST work regardless of whether the
source pointer is above or below the dest pointer.
The for loop below is PORTABLE, but this is time-
critical code; it should work as fast as possible.
It may be worth your while to rewrite it in assembly
language.
*/
void
sysmove(char source [], char dest [], int count)
{
#ifdef TURBOC
movmem(source, dest, count);
#endif
#ifdef MICRO_SOFT
memmove(dest, source, (int) count);
#endif
#ifndef MICRO_SOFT
#ifndef TURBOC
int i;
TRACEP("sysmove", sl_lpout();
sl_pout(source); sl_csout();
sl_pout(dest); sl_csout();
sl_iout(count); sl_rpout());
if (count <= 0) {
return;
}
else if (source > dest) {
/* Copy head first. */
for (i = 0; i < count; i++) {
dest [i] = source [i];
}
}
else {
/* Copy tail first. */
for (i = count - 1; i >= 0; i--) {
dest [i] = source [i];
}
}
#endif
#endif
}
/*
Open an existing file for unbuffered i/o.
Return OK (0) or ERROR (-1).
*/
int
sysopen(char *name)
{
int result;
SL_DISABLE();
#ifdef MICRO_SOFT
result = open(name, O_RDWR | O_BINARY);
#endif
#ifdef TURBOC
result = open(name, O_RDWR | O_BINARY);
#endif
return result;
}
/*
Put one character to a buffered output file.
Returns the character itself, or ERROR if the
disk becomes full.
*/
int
sysputc(char c, FILE *fd)
{
SL_DISABLE();
return putc(c, fd);
}
/*
Read one block (DATA_SIZE bytes) from an unbuffered
file into the buffer of size DATA_SIZE.
Return the number of bytes read or -1 if an
end-of-file occurs immediately.
If less than a full block is read, put an EOF_MARK mark
after the last byte.
*/
int
sysread(int fd, char * buffer)
{
int n, result;
TRACEP("sysread", sl_lpout();
sl_iout(fd); sl_csout();
sl_pout(buffer));
#ifdef MICRO_SOFT
n = read(fd, buffer, DATA_SIZE);
#endif
#ifdef TURBOC
n = read(fd, buffer, DATA_SIZE);
#endif
if (n == ERROR) {
result = 0;
}
else if (n == DATA_SIZE) {
result = n;
}
else {
/* Force an end-of-file mark */
buffer [n] = EOF_MARK;
result = n;
}
TRACE("sysread",
sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
return result;
}
/*
Rename the old file to be the new file.
RED makes sure that the file is NOT open when
sysrename() is called.
*/
void
sysrename(char *oldname, char *newname)
{
TRACEP("sysrename", sl_lpout();
sl_sout(oldname); sl_csout();
sl_sout(newname); sl_rpout());
rename(oldname, newname);
}
/*
Seek to the specified block of an unbuffered file.
Return OK (0) or ERROR (-1).
*/
int
sysseek(int fd, int block)
{
int result;
long lresult;
long temp;
TRACEP("sysseek",
sl_lpout(); sl_iout(fd); sl_csout(); sl_iout(block));
#ifdef MICRO_SOFT
temp = ((long) block) * DATA_SIZE;
lresult = lseek(fd, temp, SEEK_SET);
result = (lresult == -1L) ? ERROR : OK;
#endif
#ifdef TURBOC
/*
The following line is a workaround a bug in the compiler.
Without the cast, the code does not work if block == 32.
*/
temp = ((long) block) * DATA_SIZE;
lresult = lseek(fd, temp, 0);
result = (lresult == -1L) ? ERROR : OK;
#endif
TRACE("sysseek",
sl_sout(") returns "); sl_lout(lresult); sl_cout('\n'));
return result;
}
/*
Write n bytes from the buffer to an unbuffered file.
Return the number of bytes written or ERROR (-1).
*/
int
syswrite(int fd, char * buffer, int n)
{
int result;
TRACEP("syswrite", sl_lpout();
sl_iout(fd); sl_csout();
sl_pout(buffer); sl_csout();
sl_iout(n));
#ifdef MICRO_SOFT
result = write(fd, buffer, n);
#endif
#ifdef TURBOC
result = write(fd, buffer, n);
#endif
TRACE("syswrite",
sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
return result;
}
/*
Erase the file from the file system.
Return ERROR (-1) if the file does not exist or
can not be erased.
*/
int
sysunlink(char * filename)
{
TRACEP("sysunlink", sl_lpout(); sl_sout(filename); sl_rpout());
unlink(filename);
}
/*
Wait for all console output to be finished.
This routine is PORTABLE.
*/
void
syswait(void)
{
SL_DISABLE();
while (hasint && sysnl > 0) {
bufout(systopl, systopy, sysnl);
}
}