Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
/****************************************************************************/
/* */
/* _ b l k i o F u n c t i o n */
/* ----------------------------- */
/* */
/* The _blkio function is used to read / write a set of contiguous */
/* sectors in an open file. */
/* */
/* Calling Sequence: */
/* */
/* ret = _blkio(ccb,sector,buffer,count,bdosfunc); */
/* */
/* Where: */
/* ccb -> the open file channel control block */
/* sector = The desired starting sector number */
/* buffer = The memory address to begin transfer */
/* count = the number of sectors to read/write */
/* bdosfunc= The BDOS function number (B_READ / B_WRITE) */
/* */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
LONG _blkio(ccb,sector,buffer,count,bdosfunc)
/****************************/
REG FILE *ccb; /* open file pointer */
REG LONG sector; /* Sector number */
REG BYTE *buffer; /* User's buffer area */
REG LONG count; /* # of sectors to do */
REG int bdosfunc; /* BDOS function to use */
/****************************/
{ /****************************/
REG WORD temp; /* Temp return from BDOS */
REG LONG seccnt; /* # sectors processed */
/****************************/
seccnt = 0; /* Zero count initally */
/* */
while (count > 0) /* Until all sectors xferred*/
{ /* */
__BDOS(SETDMA,buffer); /* Set new DMA address */
ccb->fcb.record = sector; /* Set new record number */
temp=__BDOS(bdosfunc,&(ccb->fcb));/* do the read */
if(temp != 0) /* Check for errors */
{ /****************************/
return(seccnt); /* Return nfg */
} /****************************/
/* */
sector++; /* Increment sector number */
count--; /* Down count */
buffer += SECSIZ; /* Increment address */
seccnt++; /* Bump sector count */
} /****************************/
return(seccnt); /* All is OK */
} /****************************/

View File

@@ -0,0 +1,60 @@
/*****************************************************************************
*
* C C B I N I T I A L I Z A T I O N
* -----------------------------------
*
* Routine "_chinit" is called from the run-time initialization to clear
* out all the CCB storage.
*
* Calling sequence:
*
* _chinit();
*
*****************************************************************************/
#include "stdio.h" /* Include std definitions */
#include "cpm.h" /* Include CP/M definitions */
FILE _iob[16]; /* Allocate CCB storage */
_chinit() /****************************/
{ /* */
REG WORD i; /* Index */
for(i=0;i<MAXFILE;i++) /* For all channels */
__chinit(i); /* Init iob(i); */
} /****************************/
/*****************************************************************************
*
* The __chinit routine initializes only 1 channel.
*
*****************************************************************************/
__chinit(i)
{ /****************************/
REG FILE *ch; /* -> CCB */
REG BYTE *p; /* Byte pointer temporary */
EXTERN FILE *_getc(); /* Converts fd to fp */
ch = _getc(i); /* Load address */
ch -> chan = i; /* Load channel byte */
ch -> flags = 0; /* clear flag word */
ch -> sector = -1; /* Set no sector in buff */
ch -> offset = 0; /* Clear file offset word */
ch -> hiwater = 0; /* Init hiwater mark */
ch -> fcb.drive = 0; /* Clear drive code */
p = &ch->fcb.fname[0]; /* Set to file var */
while (p< &ch->fcb.ftype[3]) /* Init file name fields */
*p++ = ' '; /* To spaces */
while (p < &ch->fcb.record) /* Init rest of fcb */
*p++ = 0; /* To zeros */
} /****************************/
/*****************************************************************************
*
* The _getc routine returns the address of a particular ccb.
*
*****************************************************************************/
FILE *_getc(i) /***************************/
REG WORD i; /* input channel number */
{ /***************************/
extern FILE _iob[]; /* Declare external */
return(&_iob[i]); /* Load addr, return */
} /***************************/

View File

@@ -0,0 +1,34 @@
/*****************************************************************************
*
* C H A N N E L N U M B E R V A L I D A T I O N
* -------------------------------------------------
*
* This routine is used to validate a channel number and return the
* pointer to the ccb area. The channel must be in range and open.
*
* Calling Sequence:
*
* ccbptr = _chkc(ch);
*
* Where:
*
* ch Is the channel number
* ccbptr Is the returned ccb address
*
*****************************************************************************/
#include "stdio.h" /* Include std definitions */
#include "cpm.h" /* and CP/M definitions */
FILE *_chkc(ch) /****************************/
UWORD ch; /* Facilitate error check */
{ /* */
REG FILE *xcb; /* -> CCB */
EXTERN FILE *_getc(); /* converts fd to fp */
/****************************/
if(ch >= MAXFILE) /* Is channel in range? */
return(FAILURE); /* No, quit now. */
/* */
xcb = _getc(ch); /* xcb -> ccb for channel */
if((xcb->flags & OPENED) == 0) /* Is channel OPEN? */
return (FAILURE); /* Noooooooo!! */
return(xcb); /* Else, return pointer */
} /****************************/

View File

@@ -0,0 +1,6 @@
_clenf (s) /* counts length of string */
register char *s;
{
register int n;
for (n=0; *s++ != '\0'; n++);
return (n);}

View File

@@ -0,0 +1,53 @@
/****************************************************************************/
/* */
/* C l o s e F u n c t i o n */
/* --------------------------- */
/* */
/* The close function is used to terminate access to a file / device. */
/* */
/* Calling Sequence: */
/* */
/* ret = close(fd); */
/* */
/* Where "fd" is an open file descriptor to be CLOSEd. */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
/****************************/
EXTERN BYTE __xeof; /* End of file for ASCII */
WORD close(fd) /****************************/
/* */
WORD fd; /* File descriptor to close */
/* */
{ /****************************/
EXTERN LONG _chkc(); /* fd -> fp conversion */
REG FILE *fp; /* file pointer Temporary */
/* */
if((LONG)(fp=_chkc(fd)) == FAILURE) /* File Open? */
return(FAILURE); /* no, quit */
/* */
if ((fp->flags & (ISTTY|ISLPT)) != 0) /* Character device? */
{ /* */
__chinit(fd); /* Clean the channel again */
freec(fd); /* Release the channel */
return(SUCCESS); /* All done */
} /****************************/
/* */
if((fp->flags & ISASCII) != 0 && /* ASCII file? */
(fp->flags & ISREAD) == 0) /* and not read-only */
{ /* */
lseek(fd,0L,2); /* Seek to EOF */
write(fd,&__xeof,1); /* Write a ^Z character */
} /****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector,fp->buffer, /* Write out */
1L,B_WRITE) != 1) /* buffer */
return(FAILURE); /* can't */
} /****************************/
__BDOS(CLOSE,&(fp->fcb)); /* Close the fcb */
__chinit(fd); /* Release the space */
freec(fd); /* Release the channel */
return(SUCCESS); /* Done */
} /****************************/

View File

@@ -0,0 +1,17 @@
.globl _sw
_sw:
rts
*********************************************************
* *
* Copyright Notice Module *
* *
*********************************************************
.globl ___cpyrt
.text
___cpyrt: .dc.b 'CP/M-68K(tm), Version 1.1, '
.dc.b 'Copyright (c) 1983, Digital Research'
.dc.b 'XXXX-0000-654321'
.dc.w 0
.end

View File

@@ -0,0 +1,13 @@
#define HDSIZE (sizeof couthd) /**.o file header size*/
struct hdr {
short ch_magic; /*c.out magic number 060016 = $600E*/
long ch_tsize; /*text size*/
long ch_dsize; /*data size*/
long ch_bsize; /*bss size*/
long ch_ssize; /*symbol table size*/
long ch_stksize; /*stack size*/
long ch_entry; /*entry point*/
short ch_rlbflg; /*relocation bits suppressed flag*/
} couthd;
#define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,101 @@
/****************************************************************************/
/* */
/* C P M . H */
/* --------- */
/* */
/* This file contains CP/M specific definitions for the v6 library */
/* for the Alcyon assembler / linker. */
/* */
/* "stdio.h" must be included BEFORE this file. */
/* */
/****************************************************************************/
/*
* Cp/m FCB definition
*/
struct xfcb /****************************/
{ /* */
BYTE drive; /* Disk drive field */
BYTE fname[8]; /* File name */
BYTE ftype[3]; /* File type */
BYTE extent; /* Current extent number */
BYTE s1,s2; /* "system reserved" */
BYTE reccnt; /* Record counter */
BYTE resvd[16]; /* More "system reserved" */
LONG record; /* Note -- we overlap the */
/* current record field to */
/* make this useful. */
}; /****************************/
#define SECSIZ 128 /* # bytes / CP/M sector */
/****************************/
/****************************************************************************/
/* */
/* Channel Control Block (CCB) */
/* */
/* One CCB is allocated (statically) for each of the 16 possible open */
/* files under C (including STDIN, STDOUT, STDERR). Permanent data */
/* regarding the channel is kept here. */
/* */
/* */
/****************************************************************************/
struct ccb /************************************/
{ /* */
BYTE flags; /* Flags byte */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct xfcb fcb; /* File FCB */
BYTE buffer[SECSIZ]; /* Read / write buffer */
}; /************************************/
#define MAXFILE 16 /* Maximum # files */
extern struct ccb _iob[MAXFILE]; /* Declare storage */
/* Flags word bit definitions */
/************************************/
#define OPENED 1 /* Channel is OPEN */
#define ISTTY 2 /* Channel open to TTT */
#define ISLPT 4 /* Channel open to LPT */
#define ISREAD 8 /* Channel open readonly */
#define ISASCII 16 /* ASCII file attached */
#define ATEOF 32 /* End of file encountered */
#define DIRTY 64 /* Buffer needs writing */
/************************************/
/****************************************************************************/
/* */
/* B D O S F u n c t i o n D e f i n i t i o n s */
/* ------------------------------------------------- */
/* */
/* Following are BDOS function definitions used by the C runtime */
/* library. */
/* */
/****************************************************************************/
/****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
/****************************/
/****************************************************************************/
/* Other CP/M definitions */
/****************************************************************************/
#define TERM "CON:" /* Console file name */
#define LIST "LST:" /* List device file name */
#define EOFCHAR 0x1a /* End of file character-^Z */
/****************************/

View File

@@ -0,0 +1,14 @@
# include "iodec.h"
/**
** put a single character
**/
int f_log 0;
cputc(c, fn)
char c;
int fn;
{
write(fn,&c,1);
}

View File

@@ -0,0 +1,57 @@
/****************************************************************************
*
* C F I L E C R E A T E R O U T I N E
* -----------------------------------------
*
* The "creat" routine opens a new "C" file and returns a file id.
*
* Calling Sequence:
*
* fid = creat(fname,prot,type);
*
* Where:
*
* fname is the address of a null terminated file name.
* prot is the UNIX file protection
* type is 0 for ASCII, 1 for BINARY
*
*****************************************************************************/
#include "stdio.h" /* Include std definitions */
#include "cpm.h" /* Include CP/M definitions */
extern char __tname[]; /* -> CON: */
extern char __lname[]; /* -> LST: */
WORD creat (fname,prot,type) /****************************/
BYTE *fname; /* -> File name */
WORD prot; /* Open mode */
WORD type; /* ASCII/BINARY flag */
{ /****************************/
REG WORD ich; /* Channel number for open */
REG FILE *ch; /* -> CCB for channel */
EXTERN FILE *_getc(); /* Converts fd to fp */
/* */
if((ich = igetc()) < 0) /* Allocate a channel */
return (FAILURE); /* Can't */
/* */
__chinit(ich); /* Clear out channel's ccb */
ch = _getc(ich); /* Get address of ccb */
/* */
if(type==0) /* ASCII file? */
ch -> flags |= ISASCII; /* Yes, mark it. */
/****************************/
if(_strcmp(fname,__tname) == 0) /* Terminal file? */
{ /* */
ch -> flags |= ISTTY|OPENED; /* Set flag */
return(ich); /* Return file descriptor */
} /****************************/
else if(_strcmp(fname,__lname) == 0) /* List device? */
{ /* */
ch -> flags |= ISLPT|OPENED; /* set flag */
return(ich); /* */
} /* */
/****************************/
if(_open(ich,fname,CREATE) != 0) /* Use BDOS interface */
return(FAILURE); /* If return <> 0, NFG. */
/* Else: */
ch -> flags |= OPENED; /* Set OPEN bit */
return(ich); /* Return Channel # */
} /****************************/

View File

@@ -0,0 +1,9 @@
/*
* El-Kludg-o Dup routine. Takes advantage of the fact that
* stdout is not closed by Bill Allen's stuff.
*/
dup(n)
register int n;
{
return(n);
}

View File

@@ -0,0 +1,35 @@
/****************************************************************************/
/* */
/* E x i t F u n c t i o n */
/* ------------------------- */
/* */
/* The exit function is called from anywhere to pass control back to */
/* the CCP from the executing C program. */
/* */
/* Calling Sequence: */
/* */
/* exit(code); */
/* */
/* Where: */
/* code Is the exit status (ignored) */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
exit(code) /***************************/
/* */
WORD code; /* Exit status */
{ /* */
REG WORD i; /* Counter */
/* */
for(i=0; i<MAXFILE; i++) /* Close all */
close(i); /* Open files */
/***************************/
_exit(code); /* Do the exit now */
} /***************************/
_exit(code) /* */
WORD code; /***************************/
{ /* */
__BDOS(EXIT,0L); /* Exit to BDOS */
} /***************************/

View File

@@ -0,0 +1,52 @@
#define BLEN 512
struct iob {
int fd; /*file descriptor*/
int cc; /*char count*/
char *cp; /*ptr to next char*/
char cbuf[BLEN]; /*char buffer*/
};
fopen(fname,ibuf,x)
char *fname;
register struct iob *ibuf;
int x;
{
ibuf->cc = 0; /*no chars*/
x = (x == 0) ? 0 : 1;
return(ibuf->fd=open(fname,0,x));
}
getc(ibuf)
register struct iob *ibuf;
{
if(ibuf->cc<=0) {
ibuf->cp = &(ibuf->cbuf[0]);
ibuf->cc = read(ibuf->fd,ibuf->cp,BLEN);
}
if(ibuf->cc <= 0) {
return(-1);
}
ibuf->cc--;
return((int)(*(ibuf->cp)++)&0xff);
}
getw(ibuf)
register struct iob *ibuf;
{
register int j;
register int i;
if((j=getc(ibuf)) == -1)
return(-1);
i = (j&0377) << 8;
if((j=getc(ibuf)) == -1)
return(-1);
i =| (j&0377);
if(i&0100000)
i =| 0xffff0000; /* make it negative */
return(i);
}

View File

@@ -0,0 +1,31 @@
#define BLEN 512
struct iob {
int fd; /*file descriptor*/
int cc; /*char count*/
char *cp; /*ptr to next char*/
char cbuf[BLEN]; /*char buffer*/
} fin;
getchar()
{
char c;
register int i;
if(fin.fd==0) {
if(read(0,&c,1)<=0 || c==4)
return(0);
i = c;
return(i&0xff);
}
if(fin.cc<=0) {
fin.cp = &(fin.cbuf[0]);
fin.cc = read(fin.fd,fin.cp,BLEN);
}
if(fin.cc <= 0) {
return(0);
}
fin.cc--;
i = *(fin.cp)++;
return(i&0xff);
}

View File

@@ -0,0 +1,7 @@
/*
* Getpid.c -- Whitesmith's version of UNIX getpid function
*/
getpid()
{
return(1);
}

View File

@@ -0,0 +1,45 @@
/*****************************************************************************
*
* I G E T C / F R E E C R O U T I N E S
* -------------------------------------------
*
* Routines "igetc" and "freec" are used to allocate / deallocate a
* channel number so that the user may do I/O directly without the OTS
* getting in the way.
*
* Calling Sequence:
*
* i = getc();
* freec(i);
*
*****************************************************************************/
#include "stdio.h" /* Include std definitions */
#include "cpm.h" /* Also CP/M ones */
WORD chmask = 0; /* Allocate storage */
WORD igetc() /****************************/
{ /* */
REG i,j; /* Define 2 temporaries */
/* */
j = 1; /* Start with channel 0 */
for(i=0;i<MAXFILE;i++) /* Look at all 16 bits */
{ /* */
if((j & chmask) == 0) /* If 0, then channel free */
{ /* */
chmask |= j; /* set allocated bit */
return(i); /* and return the channel # */
} /* */
j = j << 1; /* Up to next bit */
} /* End FOR loop */
return(FAILURE); /* All channels in use! */
} /****************************/
WORD freec(ch) /****************************/
{ /* */
REG i,j; /* Define 2 temporaries */
/* */
j = 1; /* Start with channel 0 */
for (i=0; i<ch; i++) /* Compute */
j = j << 1; /* bit mask */
chmask &= (~j); /* clear allocation bit */
return(SUCCESS); /* Return OK */
} /****************************/

View File

@@ -0,0 +1,24 @@
# define MAXFILES 15
struct fileps
{
char *buff; /* beginning of buffer */
char *bptr; /* current position */
int nchars; /* number of characters internal */
int bsize; /* size of buffer */
char eoferr; /* end of file flag */
char wrflag; /* mode flag */
char *pbuff; /* bottom of peek buffer */
};
struct fileps __filehdr[MAXFILES];
struct param
{
int bufsize; /* initial buffer size */
int peeksize; /* initial peek size */
};
extern struct param __param;
int __statbuf[MAXFILES];

View File

@@ -0,0 +1,84 @@
.globl _ldivr
.comm _ldivr,4
.globl _ldiv
.globl ldiv
.text
_ldiv:
ldiv:
~~ldiv:
~b=R4
~q=R5
~l1=R7
~l2=R6
~al1=8
~al2=12
~sign=R3
link R14,#-2
movem.l R2-R7,-(sp)
clr R3
clr.l R5
move.l 8(R14),R7
move.l 12(R14),R6
bne L2
move.l #$80000000,_ldivr
move.l #$80000000,R0
bra L1
L2:
bge L3
neg.l R6
add #1,R3
L3:
tst.l R7
bge L4
neg.l R7
add #1,R3
L4:
cmp.l R7,R6
bgt L6
bne L7
move.l #1,R5
clr.l R7
bra L6
L7:
cmp.l #$10000,R7
bge L9
divu R6,R7
move R7,R5
swap R7
ext.l R7
bra L6
L9:
move.l #1,R4
L12:
cmp.l R6,R7
blo L11
asl.l #1,R6
asl.l #1,R4
bra L12
L11:
tst.l R4
beq L6
cmp.l R6,R7
blo L15
or.l R4,R5
sub.l R6,R7
L15:
lsr.l #1,R4
lsr.l #1,R6
bra L11
L6:
cmp #1,R3
bne L16
neg.l R7
move.l R7,_ldivr
move.l R5,R0
neg.l R0
bra L1
L16:
move.l R7,_ldivr
move.l R5,R0
L1:
tst.l (sp)+
movem.l (sp)+,R3-R7
unlk R14
rts

View File

@@ -0,0 +1,12 @@
__length(s)
char *s;
{
register int l;
register char *p;
p = s;
l = 0;
while (*p++)
l++;
return(l);
}

View File

@@ -0,0 +1,123 @@
$ set noon
$ num
BLKIO.C
BLKIO.lis
$ num
CHINIT.C
CHINIT.lis
$ num
CHKC.C
CHKC.lis
$ num
CLENF.C
CLENF.lis
$ num
CLOSE.C
CLOSE.lis
$ num
CPUTC.C
CPUTC.lis
$ num
CREAT.C
CREAT.lis
$ num
DUP.C
DUP.lis
$ num
EXIT.C
EXIT.lis
$ num
GETC.C
GETC.lis
$ num
GETCHAR.C
GETCHAR.lis
$ num
GETPID.C
GETPID.lis
$ num
IGETC.C
IGETC.lis
$ num
LENGTH.C
LENGTH.lis
$ num
LSEEK.C
LSEEK.lis
$ num
MAIN.C
MAIN.lis
$ num
OPEN.C
OPEN.lis
$ num
PRINTF.C
PRINTF.lis
$ num
PRTINT.C
PRTINT.lis
$ num
PUTC.C
PUTC.lis
$ num
PUTCHAR.C
PUTCHAR.lis
$ num
READ.C
READ.lis
$ num
SBRK.C
SBRK.lis
$ num
SEEK.C
SEEK.lis
$ num
STRCAT.C
STRCAT.lis
$ num
STRCMP.C
STRCMP.lis
$ num
STRLEN.C
STRLEN.lis
$ num
TTYIN.C
TTYIN.lis
$ num
UNLINK.C
UNLINK.lis
$ num
WRITE.C
WRITE.lis
$ num
XOPEN.C
XOPEN.lis
$ num
XSTRCMP.C
XSTRCMP.lis
$ num
XTTYIN.C
XTTYIN.lis
$ num
COUT.H
COUT.lst
$ num
CPM.H
CPM.lst
$ num
IODEC.H
IODEC.lst
$ num
PORTAB.H
PORTAB.lst
$ num
SENDC68.H
SENDC68.lst
$ num
STDIO.H
STDIO.lst
$ as68 -l -u -p COPYRT.S >COPYRT.lis
$ as68 -l -u -p LDIV.S >LDIV.lis
$ as68 -l -u -p LMUL.S >LMUL.lis
$ as68 -l -u -p LREM.S >LREM.lis
$ as68 -l -u -p STARTUP.S >STARTUP.lis

View File

@@ -0,0 +1,74 @@
*// long multiply routine without floating point
*// call with:
*// two long values on stack
*// returns:
*// long value in R0 and R1
*//
*// warning: no overflow checking or indication!!!!
*struct {
* int hiword;
* int loword;
*};
*long lmul(l1,l2)
*long l1,l2;
*{
*
* long t1;
* register int sign;
* register int t2;
*
* sign = 0;
* if(l1 < 0) {
* l1 = -l1; //make it positive
* sign++;
* }
* if(l2 < 0) {
* l2 = -l2; //make it positive
* sign++;
* }
* t1 = l1.loword*l2.loword;
* t2 = l1.hiword*l2.loword + l2.hiword*l1.loword;
* t1.hiword = t1.hiword + t2;
* if(sign&1)
* t1 = -t1; //negate results
* return(t1);
*}
*
*
.globl lmul
.text
lmul:
_lmul:
~~lmul:
~sign=R2
~l1=8
~l2=12
~t1=-4
~t2=R6
link R14,#-4
clr R2
tst.l 8(R14) //is first arg negative?
bge L2
neg.l 8(R14) //yes, negate it
inc R2 // increment sign flag
L2:tst.l 12(R14) //is second arg negative?
bge L3
neg.l 12(R14) //yes, make it positive
inc R2 //increment sign flag
L3:move 10(R14),R0 //arg1.loword
mulu 14(R14),R0 //arg2.loword
move.l R0,-4(R14) //save in temp
move 8(R14),R0 //arg1.hiword
mulu 14(R14),R0 //arg2.loword
move 12(R14),R1 //arg2.hiword
mulu 10(R14),R1 //arg1.loword
add R1,R0 //form the sum of 2 lo-hi products
add -4(R14),R0 //add to temp hiword
move R0,-4(R14) //store back in temp hiword
move.l -4(R14),R0 //long results
btst #0,R2 //test sign flag
beq L4
neg.l R0 //complement the results
L4:
unlk R14
rts

View File

@@ -0,0 +1,19 @@
.globl _ldiv
.globl _ldivr
.comm _ldivr,4
.globl _lrem
.globl lrem
.text
_lrem:
lrem:
~~lrem:
~l2=12
~al1=8
link R14,#-2
move.l 12(R14),-(sp)
move.l 8(R14),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l _ldivr,R0
unlk R14
rts

View File

@@ -0,0 +1,61 @@
/****************************************************************************/
/* */
/* L s e e k F u n c t i o n */
/* --------------------------- */
/* */
/* The lseek function simulates the UNIX lseek system call. */
/* */
/* Calling sequence: */
/* */
/* ret = lseek(fd,offset,sense); */
/* */
/* Where: */
/* */
/* fd Is an open file descriptor */
/* offset Is the (long) file offset */
/* sense Is the meaning of offset */
/* 0 => From the beginning of the file */
/* 1 => From the present file position */
/* 2 => From the end of the file */
/* */
/* ret Is the resulting absolute file offset */
/* -1 indicates failure */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
LONG lseek(fd,offs,sense) /****************************/
/* */
WORD fd; /* Open file descriptor */
LONG offs; /* File offset */
WORD sense; /* Sense of offset */
/* */
/****************************/
{
/****************************/
REG FILE *fp; /* File pointer */
EXTERN LONG _chkc(); /* fd to fp translation */
/* */
if((LONG)(fp = _chkc(fd)) == FAILURE) /* Convert to pointer */
return(FAILURE); /* Can't */
/* */
switch(sense) /****************************/
{ /* */
case 0: /* From beginning of file */
fp->offset = offs; /* Just set to offset */
break; /* Then quit */
/****************************/
case 1: /* From present position */
fp->offset += offs; /* */
break; /* */
/****************************/
case 2: /* From end of file */
fp->offset = fp->hiwater + offs;/* compute end of file */
break; /* */
/****************************/
default: /* All others NFG */
return(FAILURE); /* */
} /****************************/
fp->flags &= ~ATEOF; /* any seek clears EOF */
return(fp->offset); /* Return resultant offset */
} /****************************/

View File

@@ -0,0 +1,79 @@
/*****************************************************************************
*
* R U N T I M E S T A R T O F F R O U T I N E
* -----------------------------------------------
*
* Routine "_main" is entered from the C header routine to start a C
* program. The command string from CP/M is parsed into
* a UNIX-like "argc/argv" setup, including simple I/O redirection.
*
* Calling Sequence:
*
* return = _main(command,length);
*
* Where:
*
* command Is the address of the command line from CP/M
* length Is the number of characters in the line,
* excluding the termination character (CR/LF).
*
*****************************************************************************/
#include "stdio.h" /* Include std definitions */
#include "cpm.h" /* Include CP/M Definitions */
extern char __tname[]; /* -> terminal name */
extern char __pname[]; /* -> Program name */
_main(com, len) /****************************/
char *com; /* Command address */
int len; /* Command length */
{ /****************************/
char *av[30]; /* Unix's "ARGV" for main */
register i; /* Define a count var. */
register char *s; /* Temp byte pointer */
int ac; /* Number of args we find */
/****************************/
_chinit(); /* Initialize channels */
open(__tname,READ); /* Open STDIN */
open(__tname,WRITE); /* Open STDOUT */
open(__tname,WRITE); /* Open STDERR */
av[0] = __pname; /* */
com[len] = '\0'; /* Insure null at line end */
ac = 1; /* Initialize count */
for (s = com; *s; s =+ i) /* One arg at a time */
{ /* */
while (*s && iswhite(*s)) /* Skip leading spaces */
++s; /* */
if (!*s) /* End of line? */
break; /* Yes, don't continue */
for (i = 0; !iswhite(s[i]); ++i)/* How many characters? */
s[i] = tolower(s[i]); /* lower case please ... */
if (s[i]) /* If last is space, etc... */
s[i++] = '\0'; /* Make it a null for C */
/****************************/
if (*s == '<') /* Redirecting input?? */
{ /* */
close(STDIN); /* Yes, close TTY */
if (open(s + 1, READ,0) != STDIN) /* Open New */
_err("Cannot open ", s + 1) ;/* Can't ... */
} /****************************/
else if (*s == '>') /* Redirecting output?? */
{ /* */
close(STDOUT); /* Close output */
if (creat(s+1,0,0)!=STDOUT) /* Try to open new */
_err("Cannot create ", s + 1);/* Can't */
} /****************************/
else /* Just a regular arg */
av[ac++] = s; /* save in argv */
} /****************************/
av[ac] = NULL; /* Insure terminator */
return (main(ac, av)); /* Invoke C program */
} /****************************/
_err(s1,s2) /* Error routine */
char *s1; /* Message text */
char *s2; /* Filename */
{ /****************************/
write(STDERR,s1,_clenf(s1)); /* Output error message */
write(STDERR,s2,_clenf(s2)); /* And filename */
write(STDERR,"\n",1); /* + Newline */
exit(-1); /* And fail hard */
} /****************************/

View File

@@ -0,0 +1,38 @@
$ set noon
$ set def drb0:[steve.cpm68k.klib]
$ delete *.o;*,lib6.a;*,*.ic;*,*.st;*,*.i;*
$ cc68 BLKIO
$ cc68 CHINIT
$ cc68 CHKC
$ cc68 CLENF
$ cc68 CLOSE
$ cc68 cputc
$ cc68 CREAT
$ cc68 dup
$ cc68 EXIT
$ cc68 getc
$ cc68 getchar
$ cc68 getpid
$ cc68 IGETC
$ cc68 length
$ cc68 LSEEK
$ cc68 MAIN
$ cc68 OPEN
$ cc68 printf
$ cc68 prtint
$ cc68 putc
$ cc68 putchar
$ cc68 READ
$ cc68 SBRK
$ cc68 seek
$ cc68 xSTRCMP
$ cc68 strlen
$ cc68 strcat
$ cc68 UNLINK
$ cc68 WRITE
$ cc68 XOPEN
$ as68 -l startup.s
$ as68 -l lmul.s
$ as68 -l ldiv.s
$ as68 -l lrem.s
$ @rear

View File

@@ -0,0 +1,312 @@
$1pip d:=$1as68symb.dat[g0
$1cp68 BLKIO.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic BLKIO.s -l
$1as68 -f $1 -l -u BLKIO.s
era $1x.i
era $1x.ic
era $1x.st
era BLKIO.s
$1cp68 CHINIT.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic CHINIT.s -l
$1as68 -f $1 -l -u CHINIT.s
era $1x.i
era $1x.ic
era $1x.st
era CHINIT.s
$1cp68 CHKC.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic CHKC.s -l
$1as68 -f $1 -l -u CHKC.s
era $1x.i
era $1x.ic
era $1x.st
era CHKC.s
$1cp68 CLENF.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic CLENF.s -l
$1as68 -f $1 -l -u CLENF.s
era $1x.i
era $1x.ic
era $1x.st
era CLENF.s
$1cp68 CLOSE.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic CLOSE.s -l
$1as68 -f $1 -l -u CLOSE.s
era $1x.i
era $1x.ic
era $1x.st
era CLOSE.s
$1cp68 cputc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic cputc.s -l
$1as68 -f $1 -l -u cputc.s
era $1x.i
era $1x.ic
era $1x.st
era cputc.s
$1cp68 CREAT.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic CREAT.s -l
$1as68 -f $1 -l -u CREAT.s
era $1x.i
era $1x.ic
era $1x.st
era CREAT.s
$1cp68 dup.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic dup.s -l
$1as68 -f $1 -l -u dup.s
era $1x.i
era $1x.ic
era $1x.st
era dup.s
$1cp68 EXIT.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic EXIT.s -l
$1as68 -f $1 -l -u EXIT.s
era $1x.i
era $1x.ic
era $1x.st
era EXIT.s
$1cp68 getc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic getc.s -l
$1as68 -f $1 -l -u getc.s
era $1x.i
era $1x.ic
era $1x.st
era getc.s
$1cp68 getchar.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic getchar.s -l
$1as68 -f $1 -l -u getchar.s
era $1x.i
era $1x.ic
era $1x.st
era getchar.s
$1cp68 getpid.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic getpid.s -l
$1as68 -f $1 -l -u getpid.s
era $1x.i
era $1x.ic
era $1x.st
era getpid.s
$1cp68 IGETC.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic IGETC.s -l
$1as68 -f $1 -l -u IGETC.s
era $1x.i
era $1x.ic
era $1x.st
era IGETC.s
$1cp68 length.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic length.s -l
$1as68 -f $1 -l -u length.s
era $1x.i
era $1x.ic
era $1x.st
era length.s
$1cp68 LSEEK.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic LSEEK.s -l
$1as68 -f $1 -l -u LSEEK.s
era $1x.i
era $1x.ic
era $1x.st
era LSEEK.s
$1cp68 MAIN.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic MAIN.s -l
$1as68 -f $1 -l -u MAIN.s
era $1x.i
era $1x.ic
era $1x.st
era MAIN.s
$1cp68 OPEN.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic OPEN.s -l
$1as68 -f $1 -l -u OPEN.s
era $1x.i
era $1x.ic
era $1x.st
era OPEN.s
$1cp68 printf.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic printf.s -l
$1as68 -f $1 -l -u printf.s
era $1x.i
era $1x.ic
era $1x.st
era printf.s
$1cp68 prtint.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic prtint.s -l
$1as68 -f $1 -l -u prtint.s
era $1x.i
era $1x.ic
era $1x.st
era prtint.s
$1cp68 putc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic putc.s -l
$1as68 -f $1 -l -u putc.s
era $1x.i
era $1x.ic
era $1x.st
era putc.s
$1cp68 putchar.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic putchar.s -l
$1as68 -f $1 -l -u putchar.s
era $1x.i
era $1x.ic
era $1x.st
era putchar.s
$1cp68 READ.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic READ.s -l
$1as68 -f $1 -l -u READ.s
era $1x.i
era $1x.ic
era $1x.st
era READ.s
$1cp68 SBRK.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic SBRK.s -l
$1as68 -f $1 -l -u SBRK.s
era $1x.i
era $1x.ic
era $1x.st
era SBRK.s
$1cp68 seek.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic seek.s -l
$1as68 -f $1 -l -u seek.s
era $1x.i
era $1x.ic
era $1x.st
era seek.s
$1cp68 STRCMP.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic STRCMP.s -l
$1as68 -f $1 -l -u STRCMP.s
era $1x.i
era $1x.ic
era $1x.st
era STRCMP.s
$1cp68 strlen.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic strlen.s -l
$1as68 -f $1 -l -u strlen.s
era $1x.i
era $1x.ic
era $1x.st
era strlen.s
$1cp68 strcat.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic strcat.s -l
$1as68 -f $1 -l -u strcat.s
era $1x.i
era $1x.ic
era $1x.st
era strcat.s
$1cp68 UNLINK.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic UNLINK.s -l
$1as68 -f $1 -l -u UNLINK.s
era $1x.i
era $1x.ic
era $1x.st
era UNLINK.s
$1cp68 WRITE.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic WRITE.s -l
$1as68 -f $1 -l -u WRITE.s
era $1x.i
era $1x.ic
era $1x.st
era WRITE.s
$1cp68 XOPEN.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic XOPEN.s -l
$1as68 -f $1 -l -u XOPEN.s
era $1x.i
era $1x.ic
era $1x.st
era XOPEN.s
$1cp68 XSTRCMP.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic XSTRCMP.s -l
$1as68 -f $1 -l -u XSTRCMP.s
era $1x.i
era $1x.ic
era $1x.st
era XSTRCMP.s
$1as68 -f $1 -l startup.s
$1as68 -f $1 -l ldiv.s
$1as68 -f $1 -l lmul.s
$1as68 -f $1 -l lrem.s
$1as68 -f $1 -l copyrt.s
era lib6.a
$1ar68 rf $1 lib6.a main.o printf.o prtint.o cputc.o putchar.o putc.o getchar.o
$1ar68 rf $1 lib6.a getc.o exit.o close.o open.o creat.o read.o write.o seek.o
$1ar68 rf $1 lib6.a lseek.o xopen.o unlink.o blkio.o chinit.o chkc.o igetc.o
$1ar68 rf $1 lib6.a strcmp.o sbrk.o xstrcmp.o length.o clenf.o lrem.o ldiv.o
$1ar68 rf $1 lib6.a lmul.o dup.o strlen.o strcat.o copyrt.o
era as68symb.dat
user 6!make e:

View File

@@ -0,0 +1 @@
user 7 ! make

View File

@@ -0,0 +1,64 @@
/****************************************************************************
*
* C F I L E O P E N R O U T I N E
* -------------------------------------
*
* The "open" routine opens a "C" file and returns a file id.
*
* Calling Sequence:
*
* fid = open(fname,mode,type);
*
* Where:
*
* fname is the address of a null terminated file name.
* mode is the open mode:
*
* 0 => READ access only
* 1 => WRITE access only
* 2 => Both READ and WRITE
* type is 0 for ASCII files, 1 for BINARY
*
*
*****************************************************************************/
#include "stdio.h" /* Include Whitesmith's */
#include "cpm.h" /* + CP/M */
EXTERN BYTE __tname[]; /* -> CON: */
EXTERN BYTE __lname[]; /* -> LST: */
WORD open (fname,mode,xtype) /****************************/
BYTE *fname; /* -> File name */
WORD mode; /* Open mode */
WORD xtype; /* File type */
{ /****************************/
REG WORD ich; /* Channel number for open */
REG FILE *ch; /* -> CCB for channel */
EXTERN FILE *_getc(); /* fd to fp converter */
/* */
if((ich = igetc()) < 0) /* Allocate a channel */
return (FAILURE); /* Can't */
/* */
__chinit(ich); /* Clear out channel's ccb */
ch = _getc(ich); /* Get address of ccb */
/* */
if(mode == READ) /* If read only, */
ch -> flags |= ISREAD; /* set READONLY bit*/
if(xtype == 0) /* Is ASCII file? */
ch -> flags |= ISASCII; /* Yes, mark it */
/* */
if(_strcmp(fname,__tname) == 0) /* if a terminal */
{ /* */
ch->flags |= ISTTY|OPENED; /* mark as tty */
return(ich); /* Return file descriptor */
} /****************************/
else if(_strcmp(fname,__lname) == 0) /* List device? */
{ /* */
ch->flags |= ISLPT|OPENED; /* Mark as printer */
return(ich); /* Return file descriptor */
} /* */
/****************************/
if(_open(ich,fname,OPEN) != 0) /* Use POS SVC interface */
return(FAILURE); /* If return <> 0, NFG. */
/* Else: */
ch -> flags |= OPENED; /* Set OPEN bit */
return(ich); /* Return Channel # */
} /****************************/

View File

@@ -0,0 +1,51 @@
/*****************************************************************************
*
* C P / M C R U N T I M E L I B H E A D E R F I L E
* -------------------------------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This is an include file for assisting the user to write portable
* programs for C.
*
*****************************************************************************/
#define ALCYON 1 /* using Alcyon compiler */
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define BOOLEAN char /* 2 valued (true/false) */
#define WORD short /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG unsigned long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
#define DEFAULT int /* Default size */
/***************************/
#ifdef ALCYON
#define UBYTE char
#else
#define UBYTE unsigned char /* Unsigned byte */
#endif
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL (BYTE *)0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
/*************************** end of portab.h ********************************/

View File

@@ -0,0 +1,275 @@
# include "iodec.h"
# define BUFSIZ 80
/**
** formated print
**/
printf(parlist)
char *parlist;
{
register char *fmt, c;
char buf[BUFSIZ];
extern char *__prtshort(), *__prtld(), *__prtld();
// double *dblptr;
int mode;
char *fd;
register char **p;
register int *pi;
int width, prec;
int left, longf;
char padchar;
char *s;
int n;
auto (*fn)();
int len;
p = &parlist;
fd = 0;
mode = 0; /* mode zero, putchar */
if (parlist + 1 < MAXFILES + 1)
{
mode++; /* mode one, cputc */
fd = *p++;
}
if (fd == -1)
{
mode++; /* mode two, string */
fd = *p++;
}
fmt = *p++;
pi = p;
while (c = *fmt++)
{
p = pi;
if (c != '%')
{
__putch(mode, &fd, c);
continue;
}
left = 0;
if ((c = *fmt++) == '-')
{
c = *fmt++;
left++;
}
padchar = ' ';
if (c == '0')
{
padchar = c;
c = *fmt++;
}
width = -1;
while (c >= '0' && c <= '9')
{
if (width < 0)
width = 0;
width = width * 10 + (c - '0');
c = *fmt++;
}
prec = -1;
if (c == '.')
{
prec = 0;
c = *fmt++;
}
while (c >= '0' && c <= '9')
{
prec = prec * 10 + (c - '0');
c = *fmt++;
}
longf = 0;
if (c == 'l')
{
longf++;
c = *fmt++;
}
/* we now have all the prelims out of the way;
let's see what we want to print */
s = buf;
switch (c)
{
case 'd': /* decimal signed */
case 'D':
if (longf)
fn = __prtld;
else
fn = __prtshort;
__prtint(pi++, buf, 10, 1, fn, 0);
if (longf)
pi++;
break;
case 'u': /* decimal unsigned */
case 'U':
__prtint(pi++, buf, 10, 0, __prtshort, 0);
break;
case 'o': /* octal unsigned */
case 'O':
if (longf)
fn = __prtld;
else
fn = __prtshort;
__prtint(pi++, buf, 8, 0, fn, 0);
if (longf)
pi++;
break;
case 'x': /* hexadecimal unsigned */
case 'X':
if (longf)
fn = __prtld;
else
fn = __prtshort;
__prtint(pi++, buf, 16, 0, fn, c == 'X');
if (longf)
pi++;
break;
case 's': /* string */
case 'S':
s = *p++;
pi = p;
break;
case 'c': /* character */
case 'C':
n = *pi++;
buf[0] = n;
buf[1] = '\0';
break;
// case 'e': /* exponential */
// case 'E':
// case 'f': /* floating */
// case 'F':
// case 'g': /* e or f */
// case 'G':
// case 'n':
// case 'N':
// dblptr = p;
// if (prec < 0)
// prec = 7;
// ftoa(*dblptr, buf, sizeof buf - 1, prec, c);
// while (*s == ' ')
// s++;
// p =+ 4;
// prec = -1;
// break;
default: /* just print the character */
__putch(mode, &fd, c);
continue;
}
len = __length(s);
if (prec < len && prec >= 0)
len = prec;
n = width - len;
if (!left)
{
if (padchar != ' ' && *s == '-')
{
len--;
__putch(mode, &fd, *s++);
}
while (n-- > 0)
__putch(mode, &fd, padchar);
}
while (len--)
__putch(mode, &fd, *s++);
while (n-- > 0)
__putch(mode, &fd, padchar);
}
if (mode == 2)
*fd = '\0';
}
__putch(mode, pfd, c)
int mode;
char c;
char **pfd;
{
switch (mode)
{
case 0:
putchar(c);
break;
case 1:
cputc(c, *pfd);
break;
case 2:
*(*pfd)++ = c;
break;
}
return (c);
}
char *__prtld(pobj, pbuf, base, signed, digs)
long *pobj;
char **pbuf;
int base;
int signed;
char *digs;
{
register long n;
register long b;
register char *p;
struct {
char cbyte0;
char cbyte1;
char cbyte2;
char cbyte3;
};
extern long ldiv();
extern long ldivr;
register i;
struct {
int wd1;
int wd2;
};
p = digs;
b = base;
n = *pobj;
if(base == 16) { //special because of negatives
i = 8;
while(n && i) {
*p++ = n & 0xf;
n =>> 4;
i--;
}
}
else if(base == 8) {
i = 11;
while(n && i) {
*p++ = n & 7;
n =>> 3;
i--;
}
if(i==0) {
*(p-1) =& 3; //only 2 bits in upper octal digit
}
}
else {
if (signed && n < 0) {
*(*pbuf)++ = '-';
n = -n;
}
while(n) {
n = ldiv(n,b);
*p++ = ldivr.cbyte3;
}
}
return (p);
}

View File

@@ -0,0 +1,62 @@
char *__prtint(pobj, buf, base, signed, f, upper)
int *pobj;
char *buf;
int base;
int signed;
int upper;
char *(*f)();
{
char digs[15];
register char *dp;
register int k;
register char *p;
dp = (*f)(pobj, &buf, base, signed, digs);
if (dp == digs)
*dp++ = 0;
p = buf;
while (dp != digs)
{
k = *--dp;
if (k < 10)
k =+ '0';
else
k =+ upper ? 'A'-10 : 'a'-10;
*p++ = k;
}
*p = 0;
return (p);
}
char *__prtshort(pobj, pbuf, base, signed, digs)
int *pobj;
char **pbuf;
int base;
int signed;
char *digs;
{
extern long ldivr;
register long n;
register char *p;
register long b;
p = digs;
b = base;
n = *pobj;
if (signed && n < 0)
{
n = -n;
*(*pbuf)++ = '-';
}
else {
n =& 0xffffL; //clear upper half
}
while (n != 0)
{
n = ldiv(n,b);
*p++ = ldivr;
}
return (p);
}

View File

@@ -0,0 +1,63 @@
#define BLEN 512
struct iob {
int fd; /*file descriptor*/
int cc; /*char count*/
char *cp; /*ptr to next char*/
char cbuf[BLEN]; /*char buffer*/
};
fcreat(fname,ibuf,x)
char *fname;
int x;
register struct iob *ibuf;
{
ibuf->cc = BLEN; /*no chars*/
ibuf->cp = &(ibuf->cbuf[0]);
x = (x == 0) ? 0 : 1;
return(ibuf->fd=creat(fname,2,x));
}
putc(c,ibuf)
char c;
register struct iob *ibuf;
{
if(ibuf->cc<=0) {
ibuf->cp = &(ibuf->cbuf[0]);
if(write(ibuf->fd,ibuf->cp,BLEN) != BLEN)
return(-1);
ibuf->cc = BLEN;
}
*(ibuf->cp)++ = c;
ibuf->cc--;
return(c);
}
putw(w,ibuf)
int w;
register struct iob *ibuf;
{
register j;
int i;
putc((w>>8)&0xff,ibuf);
putc(w&0xff,ibuf);
return(w);
}
myfflush(ibuf)
register struct iob *ibuf;
{
register i;
i = BLEN - ibuf->cc;
ibuf->cc = BLEN;
ibuf->cp = &(ibuf->cbuf[0]);
if(write(ibuf->fd,ibuf->cp,i) != i)
return(-1);
return(0);
}

View File

@@ -0,0 +1,42 @@
#define BLEN 512
struct iob {
int fd; /*file descriptor*/
int cc; /*char count*/
char *cp; /*ptr to next char*/
char cbuf[BLEN]; /*char buffer*/
} fout = {0,BLEN,&fout.cbuf[0]};
putchar(cc)
char cc;
{
if(fout.fd <= 1) {
if(write(1,&cc,1) != 1)
return(-1);
return(cc);
}
/* buffered output*/
if(fout.cc<=0) {
fout.cp = &(fout.cbuf[0]);
if(write(fout.fd,fout.cp,BLEN) != BLEN)
return(-1);
fout.cc = BLEN;
}
*(fout.cp)++ = cc;
fout.cc--;
return(cc);
}
myflush()
{
register i;
i = BLEN - fout.cc;
fout.cc = BLEN;
fout.cp = &(fout.cbuf[0]);
if(write(fout.fd,fout.cp,i) != i)
return(-1);
return(0);
}

View File

@@ -0,0 +1,280 @@
#define RETERR(x,y) return(x)
/****************************************************************************/
/* */
/* R e a d F u n c t i o n */
/* ------------------------- */
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
/* */
/* The read function simulates the UNIX read system call. Any */
/* arbitrary number of bytes may be read at any arbitrary offset in */
/* the file. */
/* The terminal handler for read has been set up to simulate some of */
/* the functions provided by "ioctl". */
/* */
/* Calling Sequence: */
/* ret = read(fd,buffer,bytes); */
/* Where: */
/* ret Is the number of bytes which were actually read */
/* fd Is an open file descriptor */
/* buffer Is the buffer address */
/* bytes Is the number of bytes to read */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
WORD read(fd,buff,pbytes) /****************************/
WORD fd; /* File descriptor */
REG BYTE *buff; /* -> buffer start */
WORD pbytes; /* = byte count to read */
{ /****************************/
REG FILE *fp; /* -> ccb to read from */
EXTERN LONG _chkc(); /* Converts fd to fp */
LOCAL LONG ofs; /* Offset temporary */
LOCAL LONG xbytes; /* Bytes temporary */
REG LONG xsector; /* Sector temporary */
REG BYTE c; /* Character temporary */
REG BYTE *p1; /* Char pointer temporary */
REG LONG bytes; /* Byte convertor */
/****************************/
bytes = (LONG) pbytes; /* Convert to long */
/* */
if((LONG)(fp=_chkc(fd)) == FAILURE) /* File open & OK?? */
return(FAILURE); /* */
if((fp->flags & ATEOF) != 0) /* End of file already? */
return(0); /* Yes, quit now */
if((fp->flags & ISLPT) != 0) /* A wise guy?? */
RETERR(FAILURE,EBADF); /* A wise guy!! */
/****************************/
if((fp->flags & ISTTY) != 0) /* TTY? */
return(_ttyin(fp,buff,bytes)); /* Yes, read 1 line */
/****************************/
if((fp->flags & ISASCII) == 0) /* ASCII?? */
return(_rdbin(fp,buff,bytes)); /* No, read binary */
/****************************/
/****************************************************************************/
/* Read loop for ASCII data ... */
/****************************************************************************/
xbytes = bytes; /* Remember org. request */
while(bytes > 0) /* Until read is satisfied */
{ /****************************/
xsector = fp->offset >> 7; /* Calc starting sector */
if(xsector != fp->sector) /* Match sector in buffer?? */
{ /* No, must read first */
/****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty?? */
{ /* Yes, must write it */
if(_blkio(fp,fp->sector,fp->buffer, /* Try to write buffer */
1L,B_WRITE) != 1) /* */
RETERR(FAILURE,EIO); /* Unable to write, quit */
fp->flags &= ~DIRTY; /* Wipe dirty bit */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Read proper sector */
B_READ) != 1) /* */
{ /* Assume no sparse ascii fs*/
fp->flags |= ATEOF; /* Set EOF flag */
return(xbytes-bytes); /* Do partial read */
}
fp->sector = xsector; /* Mark buffer correctly */
} /****************************/
ofs = fp->offset & (SECSIZ-1); /* correct buffer offset */
p1 = &(fp->buffer[ofs]); /* Load byte pointer */
/* */
while(p1 < &(fp->buffer[SECSIZ]) && /* Ie, more data in buffer */
bytes > 0) /* And request not satisfied*/
{ /* */
c = *p1; /* Pick up next character */
if(c==EOFCHAR) /* ^Z?? */
{ /* Yes, */
fp->flags |= ATEOF; /* Set EOF flag */
if(fp->offset > fp->hiwater) /* set hiwater mark */
fp->hiwater = fp->offset; /* if necessary */
return(xbytes-bytes); /* Return number read */
} /****************************/
else if (c == '\r') /* Carriage return? */
{ /* */
p1++; /* Yes, just ignore that */
fp->offset++; /* Increment file offset */
} /* */
else /****************************/
{ /* Regular character */
*buff++ = c; /* Load buffer with byte */
bytes--; /* Decrement count */
p1++; /* increment counter */
fp->offset++; /* Increment file offset */
} /****************************/
} /* */
} /* While bytes > 0 */
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
return(xbytes); /* Read fully satisfied */
} /****************************/
/****************************************************************************/
/* */
/* R d b i n F u n c t i o n */
/* --------------------------- */
/* */
/* The "_rdbin" function performs a read operation for binary files. */
/* */
/* Calling Sequence: */
/* ret = _rdbin(fp,buffer,bytes); */
/* Where: */
/* fp -> to the open CCB */
/* buffer -> the user's buffer */
/* bytes = the number of bytes to be read */
/* */
/* ret = the number of bytes actually read */
/* */
/****************************************************************************/
WORD _rdbin(fp,buff,bytes) /****************************/
/* */
REG FILE *fp; /* -> ccb for the file */
REG BYTE *buff; /* -> buffer to receive data*/
REG LONG bytes; /* = # bytes to xfer */
{ /****************************/
REG BYTE *p; /* Temp byte pointer */
LOCAL LONG xsector; /* Temp sector number */
LOCAL LONG nsector; /* Multi-sector count */
LOCAL LONG xbytes; /* byte count temp */
REG LONG i; /* Temp index */
/****************************/
xbytes = bytes; /* Preserve org byte cnt */
xsector = fp->offset >> 7; /* Calculate starting sector*/
/* */
if((fp->offset & (SECSIZ-1)) != 0) /* If not on boundary, */
{ /* must buffer */
if(fp->sector != xsector) /* Do sectors match? */
{ /* */
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Try to write old buffer */
RETERR(FAILURE,EIO); /* Can't; just quit. */
fp->flags &= ~DIRTY; /* not dirty anymore */
} /****************************/
if(_blkio(fp,xsector,fp->buffer, /* Now read the */
1L,B_READ) != 1) /* next sector */
RETERR(FAILURE,EIO); /* Must be EOF */
fp->sector = xsector; /* Mark buffer */
} /****************************/
p = &fp->buffer[fp->offset&(SECSIZ-1)];/* Compute buffer offset */
/* */
while(p < &(fp->buffer[SECSIZ]) && /* Move the bytes */
bytes > 0) /* */
{ /* */
*buff++ = *p++; /* Copy data byte */
bytes--; /* Decrement byte counter */
fp->offset++; /* Increment offset */
} /****************************/
if(bytes == 0) /* Zero byte count now? */
{ /* */
if(fp->offset > fp->hiwater) /* Adjust hiwater if */
fp->hiwater=fp->offset; /* necessary */
return(xbytes); /* Yes, just return */
} /* */
xsector++; /* Bump sector pointer */
} /****************************/
/****************************************************************************/
/* At this point, a multi-sector transfer may be accomplished. */
/****************************************************************************/
/* */
i = 0; /* In case no xfer */
nsector = bytes >> 7; /* Compute number of sectors*/
if(nsector > 0) /* need to transfer?? */
i=_blkio(fp,xsector,buff,nsector, /* Do the */
B_READ); /* transfer */
/* */
xsector += i; /* Update sector counter */
fp->offset += i*SECSIZ; /* Update offset */
bytes -= i*SECSIZ; /* Update byte count */
buff += i*SECSIZ; /* Update buffer address */
/* */
if(fp->offset > fp->hiwater) /* Adjust hiwater */
fp->hiwater = fp->offset; /* if needed */
if (i != nsector) /* Short read?? */
{ /* */
fp->flags |= ATEOF; /* set EOF Flag */
return(xbytes - bytes); /* Return actual read count */
} /****************************/
if(bytes == 0) /* Done? */
return(xbytes); /* Yes, return */
/****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
{ /* This can be true for */
if(_blkio(fp,fp->sector, /* boundary conditions */
fp->buffer,1L,B_WRITE) != 1) /* Try to write old buffer */
RETERR(FAILURE,EIO); /* Can't; just quit. */
fp->flags &= ~DIRTY; /* not dirty anymore */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Read into buffer */
B_READ) != 1) /* */
{ /* */
fp->flags |= ATEOF; /* End of file */
return(xbytes-bytes); /* return corrected count */
} /****************************/
/* */
fp->offset += bytes; /* Increment offset */
if(fp->offset > fp->hiwater) /* Adjust high water mark */
fp->hiwater = fp->offset; /* if necessary */
p = &fp->buffer[0]; /* Start with 1st byte */
while (bytes > 0) /* Count down */
{ /* bytes */
*buff++ = *p++; /* Move a byte */
bytes--; /* Down count */
} /****************************/
return(xbytes); /* Return requested length */
} /****************************/
/****************************************************************************/
/* */
/* _ t t y i n F u n c t i o n */
/* ----------------------------- */
/* */
/* Function "_ttyin" is used to read a line from the terminal. */
/* */
/* Calling Sequence: */
/* */
/* ret = _ttyin(buffer,bytes); */
/* */
/* Where: */
/* */
/* buffer -> the user's input buffer */
/* bytes = the (maximum) number of bytes to read */
/* */
/* ret = the number of bytes actually read */
/* */
/****************************************************************************/
WORD _ttyin(buff,bytes) /****************************/
/* */
REG BYTE *buff; /* -> user's buffer */
REG LONG bytes; /* = requested byte count */
/* */
{ /****************************/
LOCAL BYTE ttybuf[257]; /* Biggest line from tty */
REG LONG xbytes; /* Returned byte count */
REG BYTE *p; /* Temp pointer */
/* */
ttybuf[0] = 255; /* Max # bytes */
__BDOS(CONBUF,&ttybuf[0]); /* Read line from BDOS */
__BDOS(CONOUT,(LONG)'\n'); /* Pop a line feed */
/****************************/
xbytes = ttybuf[1] & 0xffL; /* # characters read */
p = &ttybuf[2]; /* p -> First character */
while( bytes > 0 && xbytes > 0) /* */
{ /* Copy 1 byte / time */
*buff++ = *p++; /* */
bytes--; /* Decrement request */
xbytes--; /* Decrement bytes in buff */
} /****************************/
if(bytes > 0) /* Terminate on count? */
{ /* */
*buff++ = '\n'; /* No, plug in newline */
p++; /* Bump pointer */
} /****************************/
return(p-&ttybuf[2]); /* Return # bytes moved */
} /****************************/

View File

@@ -0,0 +1,9 @@
$ set noon
$ delete lib6.a;*
$ ar68 r lib6.a main.o printf.o prtint.o cputc.o putchar.o putc.o getchar.o -
getc.o exit.o close.o open.o creat.o read.o write.o seek.o lseek.o -
xopen.o unlink.o blkio.o chinit.o chkc.o igetc.o sbrk.o xstrcmp.o
$ ar68 r lib6.a length.o clenf.o lrem.o ldiv.o lmul.o lrem.o -
dup.o strlen.o strcat.o
$ copy lib6.a lib:
$ purge lib:

View File

@@ -0,0 +1,40 @@
/****************************************************************************/
/* */
/* s b r k F u n c t i o n */
/* ------------------------- */
/* */
/* The "sbrk" function is used to allocate memory dynamically. */
/* */
/* Calling Sequence: */
/* */
/* addr = sbrk(incr); */
/* */
/* Where: */
/* incr Is the incremental number of bytes to be added to */
/* the program heap area. */
/* */
/* addr Is the beginning address of the allocated area. */
/* -1 is returned if allocation failed */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
EXTERN BYTE *_break; /* Old break address */
/****************************/
BYTE *sbrk(incr) /* */
WORD incr; /* Incremental storage */
/* */
{ /****************************/
REG BYTE *t1; /* Temporary */
if(incr & 1) /* Disallow odd incr's */
incr++; /* Round up to next */
/* */
t1 = _break + incr; /* New break value */
/****************************/
if(brk(t1) == FAILURE) /* Allocate */
return(FAILURE); /* Can't */
/****************************/
t1 = _break; /* Save old break */
_break += incr; /* Set new break */
return(t1); /* And return */
} /****************************/

View File

@@ -0,0 +1,18 @@
/*
* Seek.c -- Whitesmith's equivalent of V6 seek
*/
long lseek();
seek(fildes,offset,ptrname)
int fildes; /* UNIX / WS file descriptor */
int offset; /* File offset, bytes */
int ptrname; /* Sense variable */
{
offset &= 0xffff; /* Clear sign extension problems*/
if(ptrname > 2) /* Not byte sense seek */
{ /* */
offset = offset << 9; /* Multiply by 512 */
ptrname -= 3; /* reset to range 0 .. 2 */
} /********************************/
return(lseek(fildes,(long)offset,ptrname));
}

View File

@@ -0,0 +1,52 @@
$ set noon
$ vsend BLKIO.C
$ vsend CHINIT.C
$ vsend CHKC.C
$ vsend CLENF.C
$ vsend CLOSE.C
$ vsend CPUTC.C
$ vsend CREAT.C
$ vsend DUP.C
$ vsend EXIT.C
$ vsend GETC.C
$ vsend GETCHAR.C
$ vsend GETPID.C
$ vsend IGETC.C
$ vsend LDIV.C
$ vsend LENGTH.C
$ vsend LSEEK.C
$ vsend MAIN.C
$ vsend OPEN.C
$ vsend PRINTF.C
$ vsend PRTINT.C
$ vsend PUTC.C
$ vsend PUTCHAR.C
$ vsend READ.C
$ vsend SBRK.C
$ vsend SEEK.C
$ vsend STRCAT.C
$ vsend STRCMP.C
$ vsend STRLEN.C
$ vsend TTYIN.C
$ vsend UNLINK.C
$ vsend WRITE.C
$ vsend XOPEN.C
$ vsend XSTRCMP.C
$ vsend XTTYIN.C
$ vsend ALDIV.S
$ vsend ALMUL.S
$ vsend ALREM.S
$ vsend COPYRT.S
$ vsend LDIV.S
$ vsend LMUL.S
$ vsend LREM.S
$ vsend STARTUP.S
$ vsend COUT.H
$ vsend CPM.H
$ vsend IODEC.H
$ vsend PORTAB.H
$ vsend SENDC68.H
$ vsend STDIO.H
$ vsend DOWNLOAD.SUB
$ vsend MAKE.SUB
$ vsend NEXT.SUB

View File

@@ -0,0 +1,72 @@
#
/* format of a symbol entry in the main table*/
#define SEEKREL 1 /*relative seek flag*/
#define OSTSIZE 14 /*symbol table entry length on object file*/
/* without table link*/
# define STESIZE 18 /*byte length of symbol table entry*/
struct symtab {
char name[8]; /*symbol name*/
short flags; /*bit flags*/
long vl1; /*symbol value*/
char *tlnk; /*table link*/
};
struct symtab *symptr;
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYDA 0002000 /*DATA based relocatable*/
# define SYTX 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
/*
struct {
short loword;
short hiword;
};
*/
struct {
short hiword;
short loword;
};
/*
struct {
char lobyte;
char hibyte;
};
*/
struct {
char hibyte;
char lobyte;
};
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf ibuf;
char *ifilname=0;

View File

@@ -0,0 +1,99 @@
******************************************************************************
*
* C runtime startup for CP/M-68k.
*
******************************************************************************
*
ltpa=0 * Low TPA address
htpa=4 * High TPA address
lcode=8 * Code segment start
codelen=12 * Code segment length
ldata=16 * Data segment start
datalen=20 * Data segment length
lbss=24 * Bss segment start
bsslen=28 * Bss segment length
freelen=32 * free segment length
resvd=36 * Reserved
fcb2=56 * 2nd parsed fcb
fcb1=92 * 1st parsed fcb
command=128 * Command tail
prtstr=9 * Print string BDOS Call
exit=0 * BDOS exit call
.globl __main
.globl _exit
.globl __break
.globl __start
.globl ___cpyrt
.text
__start: bra start1 * jump around copyright
*
.dc.b 'CP/M-68K(tm), Version 1.1, Copyright (c) 1983, '
.dc.b 'Digital Research' * copyright notice
.dc.b 'XXXX-0000-654321' * serial number
*
.even
start1: move.l 4(a7),a0 * a0 -> Base page
move.l lbss(a0),a1 * a1 -> bss region
move.l a1,a3 * Save this
adda.l bsslen(a0),a1 * a1 -> 1st heap loc
xclear: * Clear heap area
clr.w (a3)+ * clear a word
cmpa.l a3,sp * See if done
bhi xclear * Not yet, continue
move.l a1,__break * Put in "break" loc
lea.l command(a0),a2 * a2 -> command line
move.b (a2)+,d0 * d0 = byte count
andi.l #$ff,d0 * clear junk
move.w d0,-(a7) * push length
move.l a2,-(a7) * Push commnd
clr.l a6 * Clear frame pointer
jsr __main * call main routine
jsr _exit * call "exit"
*
*
.bss
__break: .ds.l 1 * Break function
*
*
.globl _brk
.text
_brk: link a6,#0 * preserve conventions
clr.l d0 * clear return
movea.l 8(sp),a0 * New break?
adda.l #$100,a0 * Chicken factor
cmpa.l a0,sp * Compare
bhis brkok * OK, continue
move.l #-1,d0 * Load return reg
brkok:
unlk a6 * Unlink
rts * return
.globl ___BDOS
___BDOS: link a6,#0 * link
move.w 8(sp),d0 * Load func code
move.l 10(sp),d1 * Load Paramter
trap #2 * Enter BDOS
cmpa.l __break,sp * Check for stack ovf
bhis noovf * NO overflow, continue
move.w #prtstr,d0 * String print
lea ovf,a0 * a0-> message
move.l a0,d1 * load proper reg
trap #2 * Issue message
move.w #exit,d0 * Exit
trap #2 * now
noovf: * Here if all OK
unlk a6 *
rts * Back to caller
*
* Data area
*
.data
.globl ___pname * Program Name
.globl ___tname * Terminal Name
.globl ___lname * List device name
.globl ___xeof * ^Z byte
ovf: .dc.b 'Stack Overflow$' * Error message
___pname: .dc.b 'C runtime',0 * Program name
___tname: .dc.b 'CON:',0 * Console name
___lname: .dc.b 'LST:',0 * List device name
___xeof: .dc.b $1a * Control-Z

View File

@@ -0,0 +1,80 @@
/*****************************************************************************
*
* C P / M C H E A D E R F I L E
* -----------------------------------
*
* This is the standard include file for the CP/M-68K assembler / linker
* kludge package.
*
*****************************************************************************/
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define UBYTE unsigned char /* Unsigned byte */
#define WORD short /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG unsigned long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
/***************************/
/* Open Mode Definitions */
/************************************/
#define READ 0 /* Open for READ only */
#define WRITE 1 /* Open for WRITE only */
#define IO 2 /* Open for READ and WRITE */
#define UPDATE 2 /* Same as IO */
/************************************/
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FILE struct ccb /* Define FILE pointer */
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL 0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
#define STDIN 0 /* File */
#define STDOUT 1 /* numbers */
#define STDERR 2 /* for std i/o */
/****************************************************************************/
/* */
/* M A C R O S */
/* ----------- */
/* */
/* Define some stuff as macros .... */
/* */
/****************************************************************************/
#define stdin (&_iob[0]) /* Standard input channel */
#define stdout (&_iob[1]) /* Standard output channel */
#define stderr (&_iob[2]) /* Standard error channel */
#define fileno(p) p->chan /* File # of a channel */
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
#define isalpha(c) (islower(c)||isupper(c)) /* true if "c" a letter */
#define isdigit(c) ('0' <= (c) && (c) <= '9') /* Ascii only!! */
#define islower(c) ('a' <= (c) && (c) <= 'z') /* Ascii only!! */
#define isupper(c) ('A' <= (c) && (c) <= 'Z') /* Ascii only!! */
#define iswhite(c) ((c) <= ' ' || 0177<= (c)) /* Is control / funny char */
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
#define tolower(c) (isupper(c) ? ((c)+040):(c)) /* translate to lower case */
#define toupper(c) (islower(c) ? ((c)-040):(c)) /* translate to upper case */

View File

@@ -0,0 +1,24 @@
/****************************************************************************
* STRCAT - concatenate strings
*
* BYTE *strcat(s1,s2) copies s2 to end of s1
* BYTE *s1, *s2;
*
* Assumes null terminated strings. No check is made for string area
* overflow.
****************************************************************************/
#include <portab.h>
BYTE *strcat(s1,s2)
REG BYTE *s1, *s2;
{
REG BYTE *cp;
for( cp=s1; *cp; cp++ ) /* save s1 for return. */
;
while( (*cp++ = *s2++) ) /* copy until eos(s2). */
;
return(s1);
}

View File

@@ -0,0 +1,37 @@
/*********************************************************************
* STRCMP - compares strings
*
* Special version which is case - insensitive.
*
* WORD strcmp(s1,s2)
* BYTE *s1, *s2;
*
* 'strcmp' compares null terminated strings s1 and s2.
* Returns:
* strcmp < 0 if s1<s2
* strcmp = 0 if s1=s2
* strcmp > 0 if s1>s2
*********************************************************************/
#include <portab.h>
WORD strcmp(s1,s2)
REG BYTE *s1, *s2;
{
REG BYTE a,b;
while (*s1 && *s2)
{
a = _toupper(*s1++);
b = _toupper(*s2++);
if (a > b) return (1);
if (a < b) return (-1);
}
return(0);
}
MLOCAL BYTE _toupper(c)
REG BYTE c;
{
if(c >= 'a' && c <= 'z')
c -= 'a' - 'A';
return(c);
}

View File

@@ -0,0 +1,18 @@
/**********************************************************************
* STRLEN - finds the number of non-null characters in s.
*
* WORD strlen(s)
* BYTE *s;
**********************************************************************/
#include <portab.h>
WORD strlen(s)
REG BYTE *s;
{
REG BYTE *p;
for( p = s; *p; p++ ) /* advance *p until NULL. */
;
return(p-s);
}

View File

@@ -0,0 +1,288 @@
/****************************************************************************/
/* */
/* R e a d F u n c t i o n */
/* ------------------------- */
/* */
/* The read function simulates the UNIX read system call. Any */
/* arbitrary number of bytes may be read at any arbitrary offset in */
/* the file. */
/* */
/* Calling Sequence: */
/* */
/* ret = read(fd,buffer,bytes); */
/* */
/* Where: */
/* */
/* fd Is an open file descriptor */
/* buffer Is the buffer address */
/* bytes Is the number of bytes to read */
/* */
/* ret Is the number of bytes which were actually read */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
WORD read(fd,buff,pbytes) /****************************/
/* */
WORD fd; /* File descriptor */
REG BYTE *buff; /* -> buffer start */
WORD pbytes; /* = byte count to read */
/* */
/****************************/
{
/****************************/
REG FILE *fp; /* -> ccb to read from */
EXTERN LONG _chkc(); /* Converts fd to fp */
LOCAL LONG ofs; /* Offset temporary */
LOCAL LONG xbytes; /* Bytes temporary */
REG LONG xsector; /* Sector temporary */
REG BYTE c; /* Character temporary */
REG BYTE *p1; /* Char pointer temporary */
REG LONG bytes; /* Byte convertor */
/****************************/
bytes = (LONG) pbytes; /* Convert to long */
/****************************/
if((LONG)(fp=_chkc(fd)) == FAILURE) /* File open & OK?? */
return(FAILURE); /* */
if((fp->flags & ATEOF) != 0) /* End of file already? */
return(0); /* Yes, quit now */
/* */
if((fp->flags & ISLPT) != 0) /* A wise guy?? */
return(FAILURE); /* A wise guy!! */
/****************************/
if((fp->flags & ISTTY) != 0) /* TTY? */
return(_ttyin(buff,bytes)); /* Yes, read 1 line */
/****************************/
if((fp->flags & ISASCII) == 0) /* ASCII?? */
return(_rdbin(fp,buff,bytes)); /* No, read binary */
/****************************/
/****************************************************************************/
/* Read loop for ASCII data ... */
/****************************************************************************/
xbytes = bytes; /* Remember org. request */
while(bytes > 0) /* Until read is satisfied */
{ /****************************/
xsector = fp->offset >> 7; /* Calc starting sector */
if(xsector != fp->sector) /* Match sector in buffer?? */
{ /* No, must read first */
/****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty?? */
{ /* Yes, must write it */
if(_blkio(fp,fp->sector,fp->buffer, /* Try to write buffer */
1L,B_WRITE) != 1) /* */
return(FAILURE); /* Unable to write, quit */
fp->flags &= ~DIRTY; /* Wipe dirty bit */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Read proper sector */
B_READ) != 1) /* */
{ /* */
fp->flags |= ATEOF; /* Set EOF flag */
return(xbytes-bytes); /* Do partial read */
}
fp->sector = xsector; /* Mark buffer correctly */
} /****************************/
ofs = fp->offset & (SECSIZ-1); /* correct buffer offset */
p1 = &(fp->buffer[ofs]); /* Load byte pointer */
/* */
while(p1 < &(fp->buffer[SECSIZ]) && /* Ie, more data in buffer */
bytes > 0) /* And request not satisfied*/
{ /* */
c = *p1; /* Pick up next character */
if(c==EOFCHAR) /* ^Z?? */
{ /* Yes, */
fp->flags |= ATEOF; /* Set EOF flag */
if(fp->offset > fp->hiwater) /* set hiwater mark */
fp->hiwater = fp->offset; /* if necessary */
return(xbytes-bytes); /* Return number read */
} /****************************/
else if (c == '\r') /* Carriage return? */
{ /* */
p1++; /* Yes, just ignore that */
fp->offset++; /* Increment file offset */
} /* */
else /****************************/
{ /* Regular character */
*buff++ = c; /* Load buffer with byte */
bytes--; /* Decrement count */
p1++; /* increment counter */
fp->offset++; /* Increment file offset */
} /****************************/
} /* */
} /* While bytes > 0 */
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
return(xbytes); /* Read fully satisfied */
} /****************************/
/****************************************************************************/
/* */
/* R d b i n F u n c t i o n */
/* --------------------------- */
/* */
/* The "_rdbin" function performs a read operation for binary files. */
/* */
/* Calling Sequence: */
/* */
/* ret = _rdbin(fp,buffer,bytes); */
/* */
/* Where: */
/* fp -> to the open CCB */
/* buffer -> the user's buffer */
/* bytes = the number of bytes to be read */
/* */
/* ret = the number of bytes actually read */
/* */
/****************************************************************************/
_rdbin(fp,buff,bytes) /****************************/
/* */
REG FILE *fp; /* -> ccb for the file */
REG BYTE *buff; /* -> buffer to receive data*/
REG LONG bytes; /* = # bytes to xfer */
/* */
{ /****************************/
REG BYTE *p; /* Temp byte pointer */
LOCAL LONG xsector; /* Temp sector number */
LOCAL LONG nsector; /* Multi-sector count */
LOCAL LONG xbytes; /* byte count temp */
REG LONG i; /* Temp index */
/****************************/
xbytes = bytes; /* Preserve org byte cnt */
xsector = fp->offset >> 7; /* Calculate starting sector*/
/* */
if((fp->offset & (SECSIZ-1)) != 0) /* If not on boundary, */
{ /* must buffer */
if(fp->sector != xsector) /* Do sectors match? */
{ /* */
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Try to write old buffer */
return(FAILURE); /* Can't; just quit. */
fp->flags &= ~DIRTY; /* Buffer now clean */
} /****************************/
if(_blkio(fp,xsector,fp->buffer, /* Now read the */
1L,B_READ) != 1) /* next sector */
return(FAILURE); /* Can't */
fp->sector = xsector; /* Mark buffer */
} /****************************/
p = &fp->buffer[fp->offset&(SECSIZ-1)];/* Compute buffer offset */
/* */
while(p < &(fp->buffer[SECSIZ]) && /* Move the bytes */
bytes > 0) /* */
{ /* */
*buff++ = *p++; /* Copy data byte */
bytes--; /* Decrement byte counter */
fp->offset++; /* Increment offset */
} /****************************/
if(bytes == 0) /* Zero byte count now? */
{ /* */
if(fp->offset > fp->hiwater) /* Adjust hiwater if */
fp->hiwater=fp->offset; /* necessary */
return(xbytes); /* Yes, just return */
} /* */
xsector++; /* Bump sector pointer */
} /****************************/
/****************************************************************************/
/* At this point, a multi-sector transfer may be accomplished. */
/****************************************************************************/
/* */
i = 0; /* In case no xfer */
nsector = bytes >> 7; /* Compute number of sectors*/
if(nsector > 0) /* need to transfer?? */
i=_blkio(fp,xsector,buff,nsector, /* Do the */
B_READ); /* transfer */
/* */
xsector += i; /* Update sector counter */
fp->offset += i*SECSIZ; /* Update offset */
bytes -= i*SECSIZ; /* Update byte count */
buff += i*SECSIZ; /* Update buffer address */
/* */
if(fp->offset > fp->hiwater) /* Adjust hiwater */
fp->hiwater = fp->offset; /* if needed */
if (i != nsector) /* Short read?? */
{ /* */
fp->flags |= ATEOF; /* set EOF Flag */
return(xbytes - bytes); /* Return actual read count */
} /****************************/
if(bytes == 0) /* Done? */
return(xbytes); /* Yes, return */
/****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Try to write old buffer */
return(FAILURE); /* Can't; just quit. */
fp->flags &= ~DIRTY; /* Clear dirty bit */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Read into buffer */
B_READ) != 1) /* */
{ /* */
fp->flags |= ATEOF; /* End of file */
return(xbytes-bytes); /* return corrected count */
} /****************************/
/* */
fp->offset += bytes; /* Increment offset */
if(fp->offset > fp->hiwater) /* Adjust high water mark */
fp->hiwater = fp->offset; /* if necessary */
p = &fp->buffer[0]; /* Start with 1st byte */
while (bytes > 0) /* Count down */
{ /* bytes */
*buff++ = *p++; /* Move a byte */
bytes--; /* Down count */
} /****************************/
return(xbytes); /* Return requested length */
} /****************************/
/****************************************************************************/
/* */
/* _ t t y i n F u n c t i o n */
/* ----------------------------- */
/* */
/* Function "_ttyin" is used to read a line from the terminal. */
/* */
/* Calling Sequence: */
/* */
/* ret = _ttyin(buffer,bytes); */
/* */
/* Where: */
/* */
/* buffer -> the user's input buffer */
/* bytes = the (maximum) number of bytes to read */
/* */
/* ret = the number of bytes actually read */
/* */
/****************************************************************************/
WORD _ttyin(buff,bytes) /****************************/
/* */
REG BYTE *buff; /* -> user's buffer */
REG LONG bytes; /* = requested byte count */
/* */
{ /****************************/
LOCAL BYTE ttybuf[257]; /* Biggest line from tty */
REG LONG xbytes; /* Returned byte count */
REG BYTE *p; /* Temp pointer */
/* */
ttybuf[0] = 255; /* Max # bytes */
__BDOS(CONBUF,&ttybuf[0]); /* Read line from BDOS */
__BDOS(CONOUT,(LONG)'\n'); /* Pop a line feed */
/****************************/
xbytes = ttybuf[1] & 0xffL; /* # characters read */
p = &ttybuf[2]; /* p -> First character */
while( bytes > 0 && xbytes > 0) /* */
{ /* Copy 1 byte / time */
*buff++ = *p++; /* */
bytes--; /* Decrement request */
xbytes--; /* Decrement bytes in buff */
} /****************************/
if(bytes > 0) /* Terminate on count? */
{ /* */
*buff++ = '\n'; /* No, plug in newline */
p++; /* Bump pointer */
} /****************************/
return(p-&ttybuf[2]); /* Return # bytes moved */
} /****************************/

View File

@@ -0,0 +1,35 @@
/****************************************************************************/
/* */
/* U n l i n k F u n c t i o n */
/* ----------------------------- */
/* */
/* The unlink function is used to delete a CP/M file by name. */
/* */
/* Calling Sequence: */
/* */
/* ret = unlink(filename); */
/* */
/* Where: */
/* filename Is the null-terminated name of the file */
/* */
/* ret Is 0 for success, -1 for failure */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
WORD unlink(filename)
/****************************/
BYTE *filename; /* -> filename */
{ /****************************/
REG WORD ch; /* Channel number */
REG WORD ret; /* Temp return value */
/****************************/
if((ch=igetc()) < 0) /* Allocate a channel */
return(FAILURE); /* Can't */
/* */
__chinit(ch); /* Init fcb and ccb */
ret = _open(ch,filename,DELETE); /* Delete the file */
freec(ch); /* Free the channel */
return(ret); /* Return result of DELETE */
} /****************************/

View File

@@ -0,0 +1,315 @@
#define RETERR(x,y) return(x)
/****************************************************************************/
/* */
/* W r i t e F u n c t i o n */
/* --------------------------- */
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
/* */
/* Function "write" simulates the UNIX write system call. Any */
/* arbitrary number of bytes are written to the file specified by */
/* file descriptor. No special alignment of file or buffer is */
/* required. */
/* */
/* Calling Sequence: */
/* */
/* ret = write(fd,buffer,bytes); */
/* */
/* Where: */
/* */
/* fd is an open file descriptor */
/* buffer is the buffer address */
/* bytes is the number of bytes to be written */
/* */
/* ret is the number of bytes actually written */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
WORD write(fd,buff,pbytes) /****************************/
/* */
WORD fd; /* File descriptor */
REG BYTE *buff; /* Buffer address */
WORD pbytes; /* Number of bytes to xfer */
/* */
{ /****************************/
REG FILE *fp; /* File (ccb) pointer */
EXTERN LONG _chkc(); /* fd -> fp Convertor */
LOCAL LONG ofs; /* Buffer offset */
LOCAL LONG written; /* Number of bytes written */
LOCAL LONG xsector; /* Sector number temporary */
REG BYTE *p1; /* Move loop pointers */
REG BYTE c; /* Character temp */
REG LONG xbytes; /* Saved bytes */
REG LONG bytes; /* Bytes for everyone else */
/****************************/
/* */
bytes = (LONG)pbytes; /* Convert to long */
/****************************/
if((LONG)(fp=_chkc(fd)) == FAILURE) /* Get CCB address */
return(FAILURE); /* Can't */
/* */
if(bytes <= 0) /* Trying to write 0 or less*/
return(0); /* Yes, a wise guy! */
/* */
if((fp->flags & ISREAD) != 0) /* Check for readonly file */
RETERR(FAILURE,EBADF); /* Barf if so */
/* */
if((fp->flags & ISTTY) != 0) /* TTY File? */
return(_chrout(buff,bytes,CONOUT));/* Yes, out to TTY */
/* */
if((fp->flags & ISLPT) != 0) /* LIST file? */
return(_chrout(buff,bytes,LSTOUT));/* Yes, out to LST: */
/****************************/
if((fp->flags & ISASCII) == 0) /* If binary file */
return(_wrtbin(fp,buff,bytes)); /* do binary style */
/****************************/
written = bytes; /* Remember original request*/
/****************************/
/* */
/****************************************************************************/
/* Here begins the actual write loop */
/****************************************************************************/
/* */
c = 0; /* Init to garbage value */
/* */
while(bytes >0) /* While more bytes to write*/
{ /* */
xsector = fp->offset >> 7; /* Compute beginning sector */
ofs = 0; /* start on sector boundary */
/* */
if(xsector != fp -> sector) /* Have to read it first */
{ /* */
if((fp->flags & DIRTY) != 0) /* Buffer has data? */
{ /* Yes */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Try to write */
RETERR(FAILURE,EIO); /* Couldn't */
fp->flags &= ~DIRTY; /* Nice clean buffer now */
} /****************************/
} /* */
/* */
if((fp-> offset & (SECSIZ-1)) != 0 /* Beginning on crazy offset*/
&& (fp -> offset < fp -> hiwater)) /* and below hiwater mark */
{ /* */
if(_blkio(fp,xsector,fp->buffer, /* */
1L,B_READ) != 1) /* Now read the correct sec */
RETERR(FAILURE,EIO); /* Couldn't */
} /****************************/
fp->sector = xsector; /* Mark buffer correctly */
ofs = fp->offset & (SECSIZ-1); /* Compute 1st char offset */
/* */
p1 = &(fp->buffer[ofs]); /* first char to write */
/* */
xbytes = bytes; /* Save byte count remaining*/
while (p1 < &(fp->buffer[SECSIZ]) /* Until buffer is full */
&& (bytes > 0)) /* or until request done */
{ /****************************/
if(*buff == '\n' && c != '\r') /* need to insert C/R */
c = '\r'; /* */
else /* Don't need to */
{ /* */
c = *buff++; /* */
bytes--; /* */
} /****************************/
*p1++ = c; /* Put char in buffer */
fp->offset++; /* Increment file offset */
} /****************************/
if(p1 >= &(fp->buffer[SECSIZ])) /* Need to write buffer */
{ /* */
if(_blkio(fp,xsector,fp->buffer, /* */
1L,B_WRITE) !=1) /* Try the write */
return(written-xbytes); /* return # actually written*/
} /****************************/
else /* */
fp -> flags |= DIRTY; /* Buffer dirty again */
if(bytes == 0) /* If done, */
{ /* Check offset here */
if(fp->offset > fp->hiwater) /* */
fp->hiwater = fp->offset; /* Fix hiwater if necessary */
return(written); /* return */
} /* */
} /****************************/
}
/****************************************************************************/
/* */
/* W r t b i n F u n c t i o n */
/* ------------------------------ */
/* */
/* Function "wrtbin" is called from "write" to take advantage of a */
/* potential multi-sector transfer for binary files. */
/* */
/* Calling sequence: */
/* */
/* ret = _wrtbin(fp,buffer,bytes); */
/* */
/* Where: */
/* */
/* fp Points to the affected ccb. */
/* buffer Is the buffer address */
/* bytes Is the number of bytes to write */
/* */
/* ret Is the number of bytes actually written */
/* */
/****************************************************************************/
LONG _wrtbin(fp,buff,bytes) /****************************/
/* */
REG FILE *fp; /* -> CCB */
REG BYTE *buff; /* -> User's buffer */
REG LONG bytes; /* # bytes to write */
{ /****************************/
LOCAL LONG xsector; /* Sector temp */
LOCAL LONG nsector; /* Multi-sector count */
LOCAL LONG written; /* # bytes to write */
REG BYTE *p1; /* Temp buffer pointer */
/****************************/
written = bytes; /* Remember request length */
xsector = fp->offset >> 7; /* Calculate present sector */
/****************************/
if((fp -> offset & (SECSIZ-1)) != 0) /* Are we at a boundary? */
{ /* */
if(xsector != fp->sector) /* No, do sectors match? */
{ /* */
if((fp->flags & DIRTY) != 0) /* No, is buffer dirty? */
{ /* */
if(_blkio(fp,fp->sector, /* */
fp->buffer,1L,B_WRITE) != 1) /* Yes, write it */
RETERR(FAILURE,EIO); /* Couldn't write buffer */
fp->flags &= ~DIRTY; /* Clear dirty bit */
} /****************************/
/* */
if(fp->offset < fp->hiwater) /* Within the hiwater area? */
{ /* If yes, then read it */
if(_blkio(fp,xsector,fp->buffer, /* */
1L,B_READ) != 1) /* Try to read the correct */
RETERR(FAILURE,EIO); /* Can't */
} /****************************/
else _clear(fp->buffer,SECSIZ); /* Zero out the buffer */
/* */
/* */
fp->sector = xsector; /* Label buffer */
/* */
} /****************************/
p1 = &fp->buffer[fp->offset&(SECSIZ-1)];/* p1->1st loc in buffer */
/* */
while (p1 < &(fp->buffer[SECSIZ]) && /* while still in buffer */
bytes > 0) /* And still writing */
{ /* */
*p1++ = *buff++; /* Move a byte */
bytes--; /* Decrement counter */
} /****************************/
if (bytes <= 0) /* Byte count exhausted?? */
{ /* */
fp->flags |= DIRTY; /* Yes, buffer is now dirty */
fp->offset += written; /* fix offset */
if(fp->offset > fp->hiwater) /* See if above hiwater mark*/
fp->hiwater = fp->offset; /* Fix if necessary */
return(written); /* Return original byte cnt */
} /****************************/
if(_blkio(fp,xsector,fp->buffer,1L, /* Write full buffer */
B_WRITE) != 1) /* */
RETERR(FAILURE,EIO); /* Couldn't */
xsector++; /* Bump sector counter */
} /* End boundary problem code*/
/****************************/
/* */
/************************************************* */
/* The observant reader will note that after the above malarkey, we are now */
/* aligned on a sector boundary. The following code exploits the oppor- */
/* tunity to do a multi-sector write. */
/************************************************* */
/* */
nsector = bytes >> 7; /* divide by 128 for sectors*/
if(nsector > 0) /* Check for no more left */
if(_blkio(fp,xsector,buff, /* */
nsector,B_WRITE) != nsector) /* Multi-sector xfer */
RETERR(FAILURE,EIO); /* Just quit on error */
/****************************/
bytes -= (nsector << 7); /* Subtract multi-sector */
/* Byte count */
buff += (nsector << 7); /* Update address */
fp->offset += written; /* Update offset now */
/* (All I/O is complete) */
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
if(bytes == 0) /* If done, */
return(written); /* return success */
/****************************/
if((fp->flags & DIRTY) != 0) /* Is buffer dirty? */
{ /* Test (again) here in case*/
if(_blkio(fp,fp->sector, /* of boundary condition */
fp->buffer,1L,B_WRITE) != 1) /* Yes, write it */
RETERR(FAILURE,EIO); /* Couldn't write buffer */
} /****************************/
fp -> flags |= DIRTY; /* Let's dirty the buffer */
fp -> sector = fp -> offset >> 7; /* Mark sector number */
/****************************/
if(fp->offset < fp->hiwater) /* Sector in high water area*/
_blkio(fp,fp->sector,fp->buffer,1L, /* Read sector */
B_READ); /* */
else _clear(fp->buffer,SECSIZ); /* Or clear it */
/****************************/
p1 = &(fp->buffer[0]); /* p1 -> address */
while(bytes > 0) /* Move the bytes */
{ /* */
*p1++ = *buff++; /* One at a time */
bytes--; /* Decrement count */
} /****************************/
/* */
return(written); /* Return requested # */
} /****************************/
_clear(ptr,bytes) /****************************/
/* Clear a memory area */
REG BYTE *ptr; /* -> area to be cleared */
REG WORD bytes; /* # of bytes to zero */
{ /****************************/
while (bytes-- > 0) /* Until all exhausted */
*ptr++ = 0; /* Clear 1 byte */
} /****************************/
/****************************************************************************/
/* */
/* _ c h r o u t F u n c t i o n */
/* ------------------------------- */
/* */
/* Function "_chrout" is called to perform "write" operations to the */
/* console or list device. */
/* */
/* Calling Sequence: */
/* */
/* ret = _chrout(buffer,count,func); */
/* */
/* Where: */
/* */
/* buffer -> the output buffer */
/* count = the number of bytes to output */
/* func = BDOS function to use */
/* */
/* ret = count on return */
/* */
/****************************************************************************/
_chrout(buffer,count,func) /***************************/
/* */
REG BYTE *buffer; /* -> 1st char output */
REG LONG count; /* = # bytes to xfer */
REG WORD func; /* BDOS Function */
/* */
{ /***************************/
LONG xcount; /* save area for count */
/* */
xcount = count; /* Copy for later */
/* */
while(count > 0) /* Until all written */
{ /* */
if(*buffer == '\n') /* New line char?? */
{ /* */
__BDOS(func,(LONG)'\r'); /* Output carriage return */
} /* */
__BDOS(func,(LONG)*buffer++); /* Output next character */
count--; /* Decrement count */
} /* */
return(xcount); /* return original count */
} /***************************/

View File

@@ -0,0 +1,73 @@
/****************************************************************************/
/* */
/* _ o p e n F u n c t i o n */
/* --------------------------- */
/* */
/* Function "_open" is used to parse the CP/M fcb and open or create */
/* the requested file. Created files are deleted first, to avoid */
/* directory problems. */
/* */
/* Calling Sequence: */
/* */
/* ret = _open(ch,filnam,bdosfunc); */
/* */
/* Where: */
/* ch Is a vacant channel number */
/* filnam Is a null-terminated CP/M filename */
/* bdosfunc Is the desired BDOS function to perform */
/* */
/* This routine may also be used to delete files as well. */
/* */
/****************************************************************************/
#include "stdio.h"
#include "cpm.h"
WORD _open(ch,filnam,bdosfunc) /****************************/
/* */
WORD ch; /* Channel number */
REG BYTE *filnam; /* -> filename */
WORD bdosfunc; /* BDOS Function */
{ /****************************/
EXTERN FILE *_getc(); /* fd -> fp xlate routine */
REG FILE *fp; /* -> ccb area */
REG struct xfcb *fcbp; /* -> FCB area in ccb */
REG BYTE *p; /* Temp character pointer */
REG WORD i; /* Character index */
/****************************/
fp = _getc(ch); /* Fetch ccb pointer */
fcbp = &(fp ->fcb); /* Fetch fcb pointer */
/****************************/
if(*(filnam+1) == ':') /* Drive ID present? */
{ /* If here, yes */
fcbp->drive = toupper(*filnam) /* Load drive ID */
- 'A' + 1; /* 1 for a:, 2 for b:, ... */
filnam += 2; /* Bump past ':' */
} /****************************/
/* */
i = 0; /* index */
/****************************/
while (*filnam > ' ' && i < 8 && /* */
*filnam != '.') /* Terminate on ext. */
{ /* */
fcbp -> fname[i++] = /* Load next character */
toupper(*filnam); /* */
filnam++; /* Increment */
} /* */
/****************************/
if (*filnam == '.') /* Extension specified? */
{ /* Yes */
filnam++; /* Bump past '.' */
i = 0; /* set index to 0 */
while(*filnam > ' ' && i < 3) /* copy */
{ /* */
fcbp -> ftype[i++] = /* */
toupper(*filnam); /* file type */
filnam++; /* */
} /* */
} /****************************/
/* */
if(bdosfunc == CREATE) /* Creating file? */
__BDOS(DELETE,fcbp); /* Yes, delete it first */
/****************************/
i = __BDOS(bdosfunc,fcbp); /* Do requested operation */
return((i<=3) ? SUCCESS : FAILURE); /* Binary return code */
} /****************************/

View File

@@ -0,0 +1,37 @@
/*********************************************************************
* STRCMP - compares strings
*
* Special version which is case - insensitive.
*
* WORD strcmp(s1,s2)
* BYTE *s1, *s2;
*
* 'strcmp' compares null terminated strings s1 and s2.
* Returns:
* strcmp < 0 if s1<s2
* strcmp = 0 if s1=s2
* strcmp > 0 if s1>s2
*********************************************************************/
#include <portab.h>
WORD _strcmp(s1,s2)
REG BYTE *s1, *s2;
{
REG BYTE a,b;
while (*s1 && *s2)
{
a = _toupper(*s1++);
b = _toupper(*s2++);
if (a > b) return (1);
if (a < b) return (-1);
}
return(0);
}
MLOCAL BYTE _toupper(c)
REG BYTE c;
{
if(c >= 'a' && c <= 'z')
c -= 'a' - 'A';
return(c);
}

View File

@@ -0,0 +1,89 @@
/****************************************************************************/
/* */
/* _ t t y i n F u n c t i o n */
/* ----------------------------- */
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
/* */
/* Function "_ttyin" is used to read a line from the terminal. */
/* It looks for the ISSPTTY flag set in the ccb: if set, it assumes */
/* the fcb really contains sgttyb information (see <sgtty.h>), and */
/* behaves accordingly. */
/* Otherwise, it grabs a line at a time from the BDOS. */
/* */
/* Calling Sequence: */
/* ret = _ttyin(fp,buffer,bytes); */
/* Where: */
/* fp -> ccb pointer & channel info */
/* buffer -> the user's input buffer */
/* bytes = the (maximum) number of bytes to read */
/* ret = the number of bytes actually read */
/* */
/****************************************************************************/
#include <portab.h>
#include <cpm.h>
#include <sgtty.h>
#define Conin 0xFFL
#define Constat 0xFEL
WORD _ttyin(fp,buff,bytes) /****************************/
REG FD *fp; /* -> filedes */
REG BYTE *buff; /* -> user's buffer */
REG LONG bytes; /* = requested byte count */
{ /****************************/
LOCAL BYTE ttybuf[257]; /* Biggest line from tty */
REG LONG xbytes, /* Returned byte count */
nbs; /* Number to read */
REG BYTE *p; /* Temp pointer */
LOCAL struct sgttyb *tyb; /* TTY info ptr (at fp->fcb)*/
/* */
if(fp->flags & ISSPTTY) /* is this a special tty? */
{ /****************************/
tyb = &(fp->fcb); /* assume info stored here */
if(tyb->sg_flags & RAW) /* are we in raw mode? */
{ /* */
*buff = __BDOS(CONIO,Conin);/* grab a char */
return(1); /* return number bytes read */
} /* ************************/
if(tyb->sg_flags & CBREAK) /* are we half baked? */
{ /* */
p = buff; /* use ptr */
*p = __BDOS(CONIO,Conin); /* get char */
if( *p == tyb->sg_kill ) /* kill char typed? */
exit(1); /* yes: DIE, PROGRAM! */
if(tyb->sg_flags & LCASE) /* they want lower case? */
*p = (*p>='A'&& *p<='Z' /* */
? *p-'A'+'a' : *p); /* give them lower case */
if((tyb->sg_flags & CRMOD) /* xlate returns? */
&& *p == '\r' ) /* */
{ /* */
if(tyb->sg_flags & ECHO) /* */
__BDOS(CONIO,(LONG)*p); /* out before xlate */
*p = '\n'; /* yes, do xlation */
} /* */
if(tyb->sg_flags & ECHO) /* echo chars? */
__BDOS(CONIO,(LONG)*p); /* */
return(1); /* return number read */
} /* ************************/
/* nothing really special...*/
} /****************************/
nbs = bytes < 255 ? bytes : 255; /* don't read more than they*/
ttybuf[0] = nbs; /* asked for/we have room fr*/
__BDOS(CONBUF,&ttybuf[0]); /* Read line from BDOS */
/****************************/
xbytes = ttybuf[1] & 0xffL; /* # characters read */
if( xbytes<nbs ) /* # read < #asked for,assum*/
__BDOS(CONOUT,(LONG)'\n'); /* CR/LF line terminated */
p = &ttybuf[2]; /* p -> First character */
while( bytes > 0 && xbytes > 0) /* */
{ /* Copy 1 byte / time */
*buff++ = *p++; /* */
bytes--; /* Decrement request */
xbytes--; /* Decrement bytes in buff */
} /****************************/
if(bytes > 0) /* Terminate on count? */
{ /* */
*buff++ = '\n'; /* No, plug in newline */
p++; /* Bump pointer */
} /****************************/
return((WORD)(p-&ttybuf[2])); /* Return # bytes moved */
} /****************************/