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,39 @@
********************************************************************
*
* CP/M abort function for C Run Time Library
*
* "abort" generates an Illegal Instruction Trap to recall DDT
* (if it is loaded).
*
*********************************************************************
illegal = $4AFC
.globl _abort
.text
_abort:
move.w 4(sp),d0
a: .dc.w illegal
bra.b a * For Wise Guys
************
illegal = $4AFC
.globl _abort
.text
_abort:
move.w 4(sp),d0
a: .dc.w illegal
bra.b a * For Wse Guys
************
illegal = $4AFC
.globl _abort
.text
_abort:
move.w 4(sp),d0
a: .dc.w illegal
bra.b a * For Wse Guys
************
illegal = $4AFC
.globl _abort
.text
_abort:
move.w 4(sp),d0
a: .dc.w illegal
bra.b a * For W

View File

@@ -0,0 +1,77 @@
/*************************************************************************
*
* a c c e s s F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "access" returns 0 if access to a file is allowed, -1 o.w.
* Under CP/M, this just tests for existence.
*
* Calling sequence:
* ret = access(fname,mode)
* Where:
* ret = 0 if accessable, -1 o.w.
* fname -> file's name, NULL terminated string
* mode = test for read, write, exec, dir path access
* (ignored by CP/M)
*
* Made O/S independent 20-Aug-83 sw
* Added chmod & chown to this source module 16-Sep-83 whf
*
**************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
WORD access(fname,mode) /* CLEAR FUNCTION ***********/
BYTE *fname;
WORD mode;
{
REG WORD rval;
if ((rval=open(fname,READ)) >= 0 ) /* File must be there ... */
{
close(rval); /* Free up fd */
return(SUCCESS);
}
RETERR(FAILURE,ENOENT);
}
/***************************************/
/* chmod - change mode: NOP under CP/M */
/***************************************/
WORD chmod(name,mode) /* CLEAR FUNCTION ***********/
BYTE *name;
WORD mode;
{
return(access(name,mode));
}
/**************************************************/
/* chown - change owner: like access() under CP/M */
/**************************************************/
WORD chown(name,owner,group) /* CLEAR FUNCTION ***********/
BYTE *name;
WORD owner;
WORD group;
{
return(access(name,0));
}
EAR FUNCTION ***********/
BYTE *name;
WORD owner;
WORD group;
{
return(access(name,0));
}
EAR FUNCTION ***********/
BYTE *name;
WORD owner;
WORD group;
{
return(access(name,0));
}

View File

@@ -0,0 +1,39 @@
.globl _ldiv
.globl _aldiv
.globl aldiv
.text
_aldiv:
aldiv:
~~aldiv:
~l2=12
~al1=8
link R14,#-2
move.l 12(R14),-(sp)
move.l 8(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l 8(R14),R9
move.l R0,(R9)
L1:
unlk R14
rts
sp)
move.l 8(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l 8(R14),R9
move.l R0,(R9)
L1:
unlk R14
rts
sp)
move.l 8(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l 8(R14),R9
move.l R0,(R9)
L1:
unlk R14

View File

@@ -0,0 +1,43 @@
.text
.globl almul
.globl lmul
*
* / this routine multiplies together two 32 bit signed long integers.
* / the first arg is a pointer to the long, which is multiplied by the
* / second arg, with the result being stored at the firstarg.
* / lmul.s does the meat of the work
*
almul:
move.l A5,-(sp)
move.l 8(sp),A5
move.l 12(sp),-(sp)
move.l (A5),-(sp)
jsr lmul
add #8,sp
move.l R0,(A5)
move.l (sp)+,A5
rts

move.l 8(sp),A5
move.l 12(sp),-(sp)
move.l (A5),-(sp)
jsr lmul
ad #8,sp
move.l R0,(A5)
move.l (sp)+,A5
rts

move.l 8(sp),A5
move.l 12(sp),-(sp)
move.l (A5),-(sp)
jsr lmul
ad #8,sp
move.l R0,(A5)
move.l (sp)+,A5
rts

move.l 8(sp),A5
move.l 12(sp),-(sp)
move.l (A5),-(sp)
jsr lmul
a

View File

@@ -0,0 +1,46 @@
.globl _ldiv
.globl _ldivr
.comm _ldivr,4
.globl _alrem
.globl alrem
.text
_alrem:
alrem:
~~alrem:
~l2=12
~al1=8
link R14,#-2
move.l 12(R14),-(sp)
move.l 8(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l _ldivr,R0
move.l 8(R14),R9
move.l R0,(R9)
unlk R14
rts
(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l _ldivr,R0
move.l 8(14),R9
move.l R0,(R9)
unlk R14
rts
(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l _ldivr,R0
move.l 8(14),R9
move.l R0,(R9)
unlk R14
rts
(R14),R8
move.l (R8),-(sp)
jsr _ldiv
cmpm.l (sp)+,(sp)+
move.l _ldivr,R0
move.l 8(

View File

@@ -0,0 +1,11 @@
/* ASSERT macro */
#ifndef NDEBUG
#define ASSERT(expr) {if(!(expr)) printf("assertion failed: expr\n");}
#else
#define ASSERT(expr)
#endif
RT(expr)
#endif
RT(expr)
#endif

View File

@@ -0,0 +1,40 @@
/* atoi - convert decimal number in ascii to integer */
#include "portab.h"
#include "ctype.h"
WORD atoi(str) /* CLEAR FUNCTION ***********/
REG BYTE *str;
{
REG WORD val;
REG WORD isneg;
val = 0;
isneg = FALSE;
while( isspace(*str) )
str++;
if( *str == '+' )
str++;
else if( *str == '-' ) {
str++;
isneg++;
}
while( *str >= '0' && *str <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}
 <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}
 <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}

View File

@@ -0,0 +1,41 @@
/* atol - convert decimal number in ascii to long integer */
#include "portab.h"
#include "ctype.h"
LONG atol(str) /* CLEAR FUNCTION ***********/
REG BYTE *str;
{
REG LONG val;
REG WORD isneg;
val = 0L;
isneg = FALSE;
while( isspace(*str) )
str++;
if( *str == '+' )
str++;
else if( *str == '-' ) {
str++;
isneg++;
}
while( *str >= '0' && *str <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}
&& *str <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}
&& *str <= '9' )
val = 10 * val + ( *str++ - '0' );
if( isneg )
val = -val;
return( val );
}

View File

@@ -0,0 +1,33 @@
.globl _sw_
_sw_:
.text
tst.l d5
beq ok
move.l #-1,(sp) * Destroy the evidence
divs #$0,d5
ok: rts
*********************************************************
* *
* Copyright Notice Module *
* *
*********************************************************
.data
___cpyrt: .dc.b 'CP/M-68K(tm), Version 1.2, '
.dc.b 'Copyright (c) 1983, Digital Research '
serial: .dc.b 'XXXX-0000-654321'
.dc.w 0
.end
m), Version 1.2, '
.dc.b 'Copyright (c) 1983, Digital esearch '
serial: .dc.b 'XXXX-0000-654321'
.dc.w 0
.end
m), Version 1.2, '
.dc.b 'Copyright (c) 1983, Digital esearch '
serial: .dc.b 'XXXX-0000-654321'
.dc.w 0
.end
m), Version 1.2, '
.dc.b 'Copyright (c) 1983, Digital

Binary file not shown.

View File

@@ -0,0 +1,117 @@
/***************************************************************************
*
* _ b l k i o F u n c t i o n
* -----------------------------
* Copyright 1982,1983 by Digital Research Inc. All rights reserved.
*
* The _blkio function is used to read / write a set of contiguous
* sectors in an open file.
* Note: if CPM, it will use CP/M function 44 (Set Multi-Sector Count)
* if os_multisectorio is TRUE (BDOS versions 3.0 and above).
* Note 2: if PC-DOS, it will use block read and write functions.
*
* Edits:
* 8-Dec-83 whf handle PC-DOS changes.
*
* Calling Sequence:
* ret = _blkio(ccbp,sector,buffer,count,bdosfunc);
*
* Where:
* ret = sectors actually read/written
* ccbp -> 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 "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "osattr.h"
#define MIN(x,y) ( ((x) < (y)) ? (x) : (y) )
LONG
_blkio(ccbp,sector,buffer,count,bdosfunc)
/****************************/
FD *ccbp; /* open file pointer */
LONG sector; /* Sector number */
BYTE *buffer; /* User's buffer area */
LONG count; /* # of sectors to do */
int bdosfunc; /* BDOS function to use */
{ /****************************/
#if PCDOS /*=============================================================*/
REG WORD seccnt; /* number sectors xferred */
WORD _pc_readblk(), _pc_writeblk(); /* functions to read/write */
if( bdosfunc == B_READ )
return _pc_readblk(&(ccbp->fcb),sector,buffer,(WORD)count,SECSIZ);
else return _pc_writeblk(&(ccbp->fcb),sector,buffer,(WORD)count,SECSIZ);
}
#endif /*==============================================================*/
#if CPM /*==============================================================*/
WORD nsecs; /* # secs to xfer each time */
LONG seccnt; /* # sectors processed */
WORD xuser; /* old user number */
WORD retcode; /* return code from BDOS */
WORD Used_Multisec; /* flag for resetting msecio*/
/****************************/
seccnt = 0; /* Zero count initally */
Used_Multisec = 0; /* Haven't used it yet */
xuser = _chkuser(ccbp->user); /* Check for changed user # */
nsecs = 1; /* default: xfer singly */
/* */
while (count > 0) /* Until all sectors xferred*/
{ /* */
__OSIF(SETDMA,buffer); /* Set new DMA address */
#if HILO /*==========================================================*/
ccbp->fcb.record = sector; /* Set new record number */
#else /*----------------------------------------------------------*/
ccbp->fcb.record = sector << 8; /* Set new record number */
#endif /*==========================================================*/
/* Multi Sector I/O xfer? */
if( (count > 1 && os_multisectorio ) || nsecs > 1 )
{ /* yes! */
if( os_oldmultisec )
nsecs = MIN(16,count); /* Older version of msecio */
else nsecs = MIN(128,count);/* Later version of msecio */
++Used_Multisec; /* Flag: need to reset */
__OSIF(F_MULTISEC,nsecs); /* make the call */
} /******* */
/****************************/
retcode = __OSIF(bdosfunc,&(ccbp->fcb));/* do the read/write*/
/****************************/
if(retcode != 0)
{ /****************************/
if(nsecs>1) /* were we trying multi-sec?*/
{ /* yes! do error handling */
if( os_oldmultisec ) /* Older msecio? */
nsecs = __cpmrv >> 12; /* adjust nsecs read like so*/
else nsecs = __cpmrv >> 8;/* later versions: use AH */
} /*** */
else nsecs = 0; /* ow. assume 0 secs read */
seccnt += nsecs; /* Return nfg */
break; /* Return from bottom */
} /****************************/
/* */
sector += nsecs; /* Increment sector number */
count -= nsecs; /* Down count */
seccnt += nsecs; /* Bump sector count */
buffer += nsecs*SECSIZ; /* Increment address */
} /****************************/
_uchkuser(ccbp->user,xuser); /* Reset user # if needed */
if( Used_Multisec ) /* Need to reset msecio? */
__OSIF(F_MULTISEC,1); /* then do so... */
return(seccnt); /* All is OK */
} /****************************/
#endif /*==================================================================*/
============*/
============*/

View File

@@ -0,0 +1,43 @@
/***************************************************************************
*
* b l k m o v e F u n c t i o n
* -------------------------------
* Copyright 1983, by Digital Research Inc.
*
* "blkmove()" moves a block of bytes from one address to another.
*
* Calling sequence:
* blkmove(to,from,nn)
* Where:
* 'to' points to destination
* 'from' points to source, and
* 'nn' is the number of chars to move
*
***************************************************************************/
#include <portab.h>
VOID blkmove(to,from,nn) /* CLEAR FUNCTION ***********/
BYTE *to, *from;
WORD nn;
{
if( to < from )
while(nn--)
*to++ = *from++;
else
for( to += nn, from += nn; nn--; )
*--to = *--from;
}
from )
while(nn--)
*to++ = *from++;
else
for( to += nn, from += nn; nn--; )
*--to = *--from;
}
from )
while(nn--)
*to++ = *from++;
else
for( to += nn, from += nn; nn--; )
*--to = *--from;
}

Binary file not shown.

View File

@@ -0,0 +1,62 @@
/********************************************************************
*
* calloc.c - memory allocator for sets of elements
* zalloc - memory allocator like malloc only zeros storage.
*
* BYTE *calloc(nelem,sizelem)
* UWORD nelem, sizelem;
*
* Returns a pointer to a region of (zero filled) memory large
* enough to hold 'nelem' items each of size 'sizelem'.
* Returns NULL if not enough memory, or allocation too large
* (on 8086).
*
* BYTE *zalloc(nbytes)
* UWORD nbytes;
*
* Returns a pointer to a region of zero filled memory nbytes long.
* Returns NULL if not enough memory.
*
*********************************************************************/
#include "portab.h"
#include "osif.h"
BYTE * zalloc(nbytes) /* CLEAR FUNCTION ***********/
UWORD nbytes; /* number of bytes */
{
REG BYTE *rp; /* pointer to region */
BYTE *malloc();
if( (rp = malloc(nbytes)) == NULLPTR) return(NULLPTR);
blkfill( rp, NULL, nbytes );
return(rp);
}
BYTE * calloc(nelem,sizelem) /* CLEAR FUNCTION ***********/
UWORD nelem, /* number of elements */
sizelem; /* size of element */
{
REG LONG size;
size = sizelem*nelem;
#if I8086
if( size > 65535L )
return NULLPTR;
#endif
return zalloc((UWORD)size);
}
e = sizelem*nelem;
#if I8086
if( size > 65535L )
return NULLPTR;
#endif
return zalloc((UWORD)size);
}
e = sizelem*nelem;
#if I8086
if( size > 65535L )
return NULLPTR;
#endif
return zalloc((UWORD)size);
}

Binary file not shown.

View File

@@ -0,0 +1,153 @@
/*****************************************************************************
*
* C H A N N E L A L L O C A T I N G R O U T I N E S
* -----------------------------------------------------
* Copyright 1984 by Digital Research Inc. All rights reserved.
*
* Herein are all the routines which deal with Channel Control Block
* (CCB) allocation and initialization. These routines (documented
* individually below) are:
*
* i = _allocc();
* _freec(i);
* _chinit();
* __chinit(fd)
* ccbptr = _chkc(ch);
*
*****************************************************************************/
#include "portab.h" /* Include std definitions */
#include "osif.h" /* Also CP/M ones */
#include "osiferr.h" /* To set error vars */
#include "errno.h" /* Error return vals */
#ifdef MAXF5 /*--------------------------*/
# define MAXCCBS 5 /* Maximum Num CCBs */
maxfiles5() { ; } /* stubroutine for option.h */
#else /*--------------------------*/
#ifdef MAXF10 /*--------------------------*/
# define MAXCCBS 10 /* Maximum Num CCBs */
#else /*--------------------------*/
# define MAXCCBS 16 /* Maximum Num CCBs */
#endif /*--------------------------*/
#endif /*--------------------------*/
LONG _chvec ={0}; /* Allocate storage */
FD _fds[MAXCCBS]; /* Allocate CCB storage */
/*****************************************************************************
* _ A L L O C C / _ F R E E C R O U T I N E S
* -------------------------------------------------
* Routines "_allocc" 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.
* Note that this scheme preserves compatibility with OS's that really
* truly use channels, and allows users to inform the C Run Time Library
* routines that they are using the channel.
* It's not important to use these routines under CP/M, since CP/M
* allows you to have as many FCBs as you wish.
*
* Calling Sequence:
* i = _allocc();
* _freec(i);
*****************************************************************************/
WORD _allocc() /****************************/
{ /* */
REG WORD i; /* Define 2 temporaries */
REG LONG j; /* */
/* */
j = 1; /* Start with channel 0 */
for(i=0;i<MAXCCBS;i++) /* Look at the bits */
{ /* */
if((j & _chvec) == 0) /* If 0, then channel free */
{ /* */
_chvec |= j; /* set allocated bit */
return(i); /* and return the channel # */
} /* */
j <<= 1; /* Up to next bit */
} /* End FOR loop */
RETERR(FAILURE,EMFILE); /* All channels in use! */
} /****************************/
WORD _freec(ch) /****************************/
WORD ch; /* Channel number to free */
{ /* */
_chvec &= ~(1 << ch); /* Clear appropriate bit */
return(SUCCESS); /* Return OK */
} /****************************/
/*****************************************************************************
* 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();
*
* Routine "__chinit(fd)" is called from other low-level routines
* for single channel initialization.
* Calling sequence:
* __chinit(fd)
* where: fd = file descriptor #
*****************************************************************************/
_chinit() /****************************/
{ /* */
REG WORD i; /* Index */
for(i=0;i<MAXCCBS;i++) /* For all channels */
__chinit(i); /* Init fds(i); */
} /****************************/
/*****************************************************************************
* The __chinit routine initializes only 1 channel.
*****************************************************************************/
__chinit(i)
{ /****************************/
REG FD *ch; /* -> CCB */
REG BYTE *p; /* Byte pointer temporary */
ch = _getccb(i); /* convert fd to CCB */
ch -> chan = i; /* Load channel byte */
ch -> flags = 0; /* clear flag word */
ch -> user = 0; /* assume user 0 */
ch -> sector = -1; /* Set no sector in buff */
ch -> offset = 0; /* Clear file offset word */
ch -> hiwater = 0; /* Init hiwater mark */
blkfill(&ch->fcb.drive,NULL,32); /* Init FCB to 0's */
blkfill(&ch->fcb.fname[0],' ',11); /* Init file name fields */
} /****************************/
/*****************************************************************************
* 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:
*
* Where:
* ch Is the channel number
* ccbptr Is the returned ccb address, NULLFD if error
*****************************************************************************/
FD *_chkc(ch) /****************************/
REG UWORD ch; /* Facilitate error check */
{ /* */
REG FD *xcb; /* -> CCB */
/****************************/
if(ch >= MAXCCBS) /* Is channel in range? */
RETERR(NULLFD,EBADF); /* No, quit now. */
/* */
xcb = _getccb(ch); /* xcb -> ccb for channel */
if((xcb->flags & OPENED) == 0) /* Is channel OPEN? */
RETERR(NULLFD,EBADF); /* Noooooooo!! */
return(xcb); /* Else, return pointer */
} /****************************/
*****/
*****/

View File

@@ -0,0 +1,56 @@
/***************************************************************************
*
* _ c h k u s e r F u n c t i o n
* ---------------------------------
*
* '_chkuser' and '_uchkuser' handle user numbers under CPM before
* version 4. The user number is stored in the ccb structure;
* if a zero, the default user # is assumed, else the _chkuser()
* routine sets the user number to the desired user number (one less
* than the stored user number, since user 0 is valid - similar to the
* default drive spec for an FCB).
* '_uchkuser()' sets the user number back to its previous value.
*
****************************************************************************/
#include "portab.h"
#include "osif.h"
/****************************/
WORD _chkuser(newu) /* */
WORD newu; /* Desired user number */
{ /****************************/
#if CPM /*===============================================================*/
REG WORD prevu; /* Previous user number */
/****************************/
if( newu == 0 ) /* Default user # desired? */
return 0; /* Yes, return */
prevu = __OSIF(USER,0xFF)+1; /* Get prev and adjust */
if( newu != prevu ) /* Are they different? */
__OSIF(USER,newu-1); /* Yes, set to desired u# */
return prevu; /* Return the previous */
#else /*===============================================================*/
return 0;
#endif /*===============================================================*/
} /****************************/
/****************************/
_uchkuser(newu,prevu) /* */
WORD newu; /* Desired user number */
WORD prevu; /* Previous user number */
{ /****************************/
#if CPM /*===============================================================*/
if( newu == 0 ) /* Default user #? */
return; /* assume no change */
if( newu != prevu ) /* Are they different? */
__OSIF(USER,prevu-1); /* Yes, set to what it was*/
#else /*===============================================================*/
return 0;
#endif /*===============================================================*/
} /****************************/
==========================*/
} /****************************/
==========================*/
} /****************************/

View File

@@ -0,0 +1,27 @@
/**********************************************************************
*
* _ c l e a n u p F u n c t i o n
* ---------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "_cleanup" closes all buffered files
*
* Calling sequence:
* _cleanup()
*
***************************************************************************/
#include "stdio.h"
_cleanup()
{
REG WORD ii;
for( ii=0; ii<MAXFILES; ii++ )
fclose(&_iob[ii]);
/* _m_term(); /* CLEAR termination routine */
}
EAR termination routine */
}
EAR termination routine */
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,69 @@
/***************************************************************************
*
* C l o s e F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* 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.
*
* Modifications:
* 12/83: PC-DOS mods whf
* 10/83: changed user # handling whf
* 9/83: add steve's user # mods, change _chkc whf
* 8/83: improve error handling whf
****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
/****************************/
EXTERN BYTE __xeof; /* End of file for ASCII */
WORD close(fd) /* CLEAR FUNCTION ***********/
REG WORD fd; /* File descriptor to close */
{ /****************************/
EXTERN FD *_chkc(); /* fd -> fp conversion MGL */
REG FD *fp; /* file pointer Temporary */
REG WORD rv; /* return value */
REG WORD xuser; /* User number temporary */
/* */
if((fp=_chkc(fd)) == NULLFD) /* File Open? */
RETERR(FAILURE,EBADF); /* no, quit */
rv = SUCCESS; /* assume it will work */
if ((fp->flags & (ISTTY|ISLPT)) == 0) /* Character device? */
{ /* if not, handle file: *****/
#if CPM /*================================================================*/
if((fp->flags & ISASCII) != 0 && (fp->flags & ISREAD) == 0) /* */
{ /* ASCII file? not ReadOnly?*/
if( fp->offset < fp->hiwater ) /* Have we been seeking? */
lseek(fd,0L,2); /* Seek to EOF ifso */
write(fd,&__xeof,1); /* Write a ^Z character */
} /****************************/
if((fp->flags & DIRTY) != 0) /* Buffer dirty? */
if(_blkio(fp,fp->sector,fp->buffer,1L,B_WRITE) != 1)/* write it */
rv = FAILURE; /* can't */
xuser = _chkuser(fp->user); /* Check user # for change */
if((__OSIF(CLOSE,&(fp->fcb))&0xFF) == 0xFF)/* Close the fcb */
rv = FAILURE; /* */
_uchkuser(fp->user,xuser); /* Change user # if needed */
#endif /*================================================================*/
#if PCDOS /*================================================================*/
if((__OSIF(CLOSE,&(fp->fcb))&0xFF) == 0xFF)/* Close the fcb */
rv = FAILURE; /* */
#endif /*================================================================*/
} /* end of file handling *****/
__chinit(fd); /* Release the space */
_freec(fd); /* Release the channel */
if( rv == SUCCESS ) /* Was everything ok? */
return(rv); /* Yes, return Success */
else RETERR(FAILURE,EIO); /* else let them know */
} /****************************/
 */
} /****************************/
 */
} /****************************/

View File

@@ -0,0 +1,257 @@
/***************************************************************************
*
* O S I F . H
* -----------
* Copyright 1982,1983 by Digital Research Inc. All rights reserved.
*
* Edits:
* 17-Jan-84 whf Moved to 68K
* 5-Jan-84 whf Moved MAXCCBS to channel.c
* 29-Dec-83 whf Add F_TRUNC for tclose()
* 12-Dec-83 whf Change from "CPM.H" to "OSIF.H"
* 9-Dec-83 whf Handle PCDOS differences
* 3-Nov-83 whf Add multi-sector i/o
* 19-Oct-83 whf Add QUEUE handling info
* 6-Oct-83 whf Redefine reserved area in fcb for parsefn() return
* 25-June-83 sw Add user number to file "fd" structure.
*
* This file contains O.S. specific definitions for the
* DRI CLEAR/C Run Time Library.
* This file is intended only for inclusion with those functions
* dealing directly with the O.S. interface, as well as any function
* which has hardware dependent code (byte storage order, for
* instance).
*
****************************************************************************/
/*
* "machine.h": to determine what kind of machine you want to run on.
*/
#define MC68000 1 /* Motorola 68000 */
#define CPM68K 1 /* CP/M 68000 ver 2.2 */
#define CPM 1 /* CP/M version 2.2 */
#define ALCYON 1 /* Alcyon C Compiler */
/*#ifdef UNdefined*/ /* Unused DEFINEs */
/*** Processor ***/
#define I8086 0 /* Intel 8086/8088 */
#define VAX 0 /* DEC VAX */
#define PDP11 0 /* DEC PDP-11 */
#define Z8000 0 /* Zilog Z8000 */
/*** Operating System ***/
#define PCDOS 0 /* IBM PC DOS */
#define CCPM 0 /* Concurrent (multi-tasking) */
#define CPM3 0 /* CP/M version 3.x (Concurrent & Plus) */
#define CPM4 0 /* CP/M version 4.x (Portable Concurrent) */
#define UNIX 0 /* UNIX */
#define VMS 0 /* DEC VMS */
/*** Compiler ***/
#define DRC 0 /* Digital Research C Compiler */
/*#endif */ /**********************/
/****************************************************************************
* CP/M FCB definition
****************************************************************************/
#if CPM /****************************/
struct fcbtab /****************************/
{ /* */
BYTE drive; /* Disk drive field [0] */
BYTE fname[8]; /* File name [1-8] */
BYTE ftype[3]; /* File type [9-11] */
BYTE extent; /* Current extent number[12]*/
BYTE s1,s2; /* "system reserved" [13-14]*/
BYTE reccnt; /* Record counter [15] */
BYTE fpasswd[8]; /* Parsefn passwd area[16-23]*/
BYTE fuser; /* Parsefn user# area [24] */
BYTE resvd[7]; /* More "system reserved" */
LONG record; /* Note -- we overlap [32-36]*/
/* current record field to */
/* make this useful. */
}; /****************************/
#endif /****************************/
/****************************************************************************
* PC-DOS FCB definition
****************************************************************************/
#if PCDOS /****************************/
struct fcbtab { /****************************/
BYTE drive; /* Disk drive field [0] */
BYTE fname[8]; /* File name [1-8] */
BYTE ftype[3]; /* File type [9-11] */
WORD fcb_curblk; /* Curr 128 byte blk [12-13]*/
WORD fcb_lrecsiz; /* Logical record size[14-15]*/
LONG fcb_filsiz; /* Num bytes in file [16-19]*/
WORD fcb_date; /* Last updated [20-21] */
BYTE fcb_resvd[10]; /* System reserved [22-31] */
BYTE fcb_currec; /* Rel Rec# within curblk[32]*/
LONG record; /* Rel Rec# from bgn file */
/* [33-36] depends on lrecsiz*/
}; /****************************/
#endif /****************************/
/* */
#define SECSIZ 128 /* size of CP/M sector */
/* to obtain nsecs on err */
/****************************/
/****************************************************************************/
/* */
/* 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 /************************************/
{ /* */
WORD flags; /*sw Flags byte */
BYTE user; /*sw User # */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct fcbtab fcb; /* File FCB (may have TTY info)*/
BYTE buffer[SECSIZ]; /* Read/write buffer */
}; /************************************/
extern struct ccb _fds[]; /* */ /* Declare storage */
#define FD struct ccb /* FD Type definition */
#define NULLFD ((FD *)0) /* NULLPTRs for FD */
/************************************/
/* Flags word bit definitions */
/************************************/
#define OPENED 0x01 /* Channel is OPEN */
#define ISTTY 0x02 /* Channel open to TTT */
#define ISLPT 0x04 /* Channel open to LPT */
#define ISREAD 0x08 /* Channel open readonly */
#define ISASCII 0x10 /* ASCII file attached */
#define ATEOF 0x20 /* End of file encountered */
#define DIRTY 0x40 /* Buffer needs writing */
#define ISSPTTY 0x80 /* Special tty info */
#define ISAUX 0x100 /*sw Auxiliary device */
#define ISQUE 0x0200 /*whf Queue device */
/************************************/
#define READ 0 /* Read mode parameter for open */
#define WRITE 1 /* Write mode */
/* CCB manipulation macros *************************************/
#define _getccb(i) (&_fds[i]) /* Get CCB addr */
/****************************************************************************/
/* */
/* O S I F F u n c t i o n D e f i n i t i o n s */
/* ------------------------------------------------- */
/* */
/* Following are OSIF function definitions used by the C runtime */
/* library. */
/* */
/****************************************************************************/
/****************************/
#if CPM68K /* */
#define __OSIF(fn,arg) __BDOS((fn),(LONG)(arg)) /* CPM68K does it this way */
#else /* */
#define __OSIF(fn,arg) __BDOS((fn),(arg)) /* DRC does it this way */
#endif /* */
#if CPM /****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONIN 1 /* direct echoing con input */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define C_WRITESTR 9 /* Console string output */
#define CONBUF 10 /* Read console buffer */
#define S_BDOSVER 12 /* Get System BDOS Ver Num */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define SEARCHF 17 /* Search for first */
#define SEARCHN 18 /* Search for next */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define F_RENAME 23 /* Rename a disk file */
#define SETDMA 26 /* Set DMA address */
#define USER 32 /*sw Get / set user number */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#define F_MULTISEC 44 /* Set Multi-Sector Count */
#define P_CHAIN 47 /* Program Chain */
#define SETVEC 61 /* Set exception vector */
#define N_NETSTAT 68 /* Get Network Status */
#define F_TRUNC 99 /* Truncate File function */
#define S_OSVER 163 /* Get OS Version Number */
#endif /****************************/
#if PCDOS /****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONIN 1 /* direct echoing con input */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define C_WRITESTR 9 /* Console string output */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define SEARCHF 17 /* Search for first */
#define SEARCHN 18 /* Search for next */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define F_RENAME 23 /* Rename a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#endif /****************************/
/****************************************************************************/
/* 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 */
/****************************/
/****************************************************************************/
/* Hardware dependencies */
/****************************************************************************/
/****************************/
#if MC68000 | Z8000 /* 68K or Z8000 */
#define HILO 1 /* used when bytes stored */
#else /* */
#define HILO 0 /* */
#endif /* */
/* */
#if HILO /* Hi/Lo storage used in */
struct long_struct{ /* 68K */
BYTE lbhihi; /* Use this for accessing */
BYTE lbhilo; /* ordered bytes in 32 bit*/
BYTE lblohi; /* LONG qtys. */
BYTE lblolo; /* */
}; /* */
struct word_struct{ /* Use this for accessing */
WORD lwhi; /* ordered words in 32 bit*/
WORD lwlo; /* LONG qtys. */
}; /* */
#else /****************************/
struct long_struct{ /* Lo/Hi storage use on */
BYTE lblolo; /* PDP-11, VAX, 8086,... */
BYTE lblohi; /* */
BYTE lbhilo; /* */
BYTE lbhihi; /* */
}; /* */
struct word_struct{ /* */
WORD lwlo; /* */
WORD lwhi; /* */
}; /* */
#endif /****************************/
/*************************** end of osif.h **********************************/
************************/
************************/


View File

@@ -0,0 +1,86 @@
/****************************************************************************
*
* C F I L E C R E A T E R O U T I N E
* -----------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* The "creat" routine opens a new "C" file and returns a file id.
* Comes in 3 flavors: ascii (CP/M text files), binary, and default
* (currently ascii).
*
* Calling Sequence:
* fid = creat(fname,prot)
* fid = creata(fname,prot)
* fid = creatb(fname,prot)
* 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 "portab.h" /* Include std definitions */
#include "osif.h" /* Include CP/M definitions */
#include "osiferr.h"
#include "errno.h" /* Error codes */
EXTERN BYTE __tname[]; /* Terminal name */
EXTERN BYTE __lname[]; /* List device name */
/****************************/
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 */
WORD _allocc(); /* gets a channel */
REG FD *ch; /* -> CCB for channel */
/* */
if((ich = _allocc()) == FAILURE) /* Allocate a channel */
return (FAILURE); /* Can't (EMFILE) */
/* */
__chinit(ich); /* Clear out channel's ccb */
ch = _getccb(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 */
RETERR(FAILURE,ENODSPC); /* Oops, No dir space. */
/* Else: */
ch -> flags |= OPENED; /* Set OPEN bit */
return(ich); /* Return Channel # */
} /****************************/
WORD creat(fname,prot) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD prot;
{ return(_creat(fname,prot,0)); } /* default to ascii */
WORD creata(fname,prot) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD prot;
{ return(_creat(fname,prot,0)); } /* ascii file open */
WORD creatb(fname,prot) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD prot;
{ return(_creat(fname,prot,1)); } /* binary file open */
*****/
BYTE *fname; WORD prot;
{ return(_creat(fname,prot,1)); } /* binary file open */
*****/
BYTE *fname; WORD prot;
{ return(_creat(fname,prot,1)); } /* binary file open */

View File

@@ -0,0 +1,86 @@
/**************************************************************************
* CTYPE.C - provides static tables for 'ctype.h' extern defs.
* Modified 10/31/82 by MGL to add ___atab() for forced loading
***************************************************************************/
#include "portab.h"
#define CTYPE /* tells ctype.h who's boss */
#include "ctype.h"
GLOBAL UBYTE __atab[] = { /* table of ascii char types */
/********************************************************************/
/* nn0 nn1 nn2 nn3 nn4 nn5 nn6 nn7 */
/* nul soh stx etx eot enq ack bel */
/*00m*/ __c, __c, __c, __c, __c, __c, __c, __c,
/* bs ht nl vt np cr so si */
/*01m*/ __c, __cs, __cs, __c, __cs, __cs, __c, __c,
/* dle dc1 dc2 dc3 dc4 nak syn etb */
/*02m*/ __c, __c, __c, __c, __c, __c, __c, __c,
/* can em sub esc fs gs rs us */
/*03m*/ __c, __c, __c, __c, __c, __c, __c, __c,
/* sp ! " # $ % & ' */
/*04m*/ __ps, __p, __p, __p, __p, __p, __p, __p,
/* ( ) * + , - . / */
/*05m*/ __p, __p, __p, __p, __p, __p, __p, __p,
/* 0 1 2 3 4 5 6 7 */
/*06m*/ __d, __d, __d, __d, __d, __d, __d, __d,
/* 8 9 : ; < = > ? */
/*07m*/ __d, __d, __p, __p, __p, __p, __p, __p,
/* @ A B C D E F G */
/*10m*/ __p, __u, __u, __u, __u, __u, __u, __u,
/* H I J K L M N O */
/*11m*/ __u, __u, __u, __u, __u, __u, __u, __u,
/* P Q R S T U V W */
/*12m*/ __u, __u, __u, __u, __u, __u, __u, __u,
/* X Y Z [ \ ] ^ _ */
/*13m*/ __u, __u, __u, __p, __p, __p, __p, __p,
/* ` a b c d e f g */
/*14m*/ __p, __l, __l, __l, __l, __l, __l, __l,
/* h i j k l m n o */
/*15m*/ __l, __l, __l, __l, __l, __l, __l, __l,
/* p q r s t u v w */
/*16m*/ __l, __l, __l, __l, __l, __l, __l, __l,
/* x y z { | } ~ del */
/*17m*/ __l, __l, __l, __p, __p, __p, __p, __c
};
___atab()
{
}
 __l, __p, __p, __p, __p, __c
};
___atab()
{
}
 __l, __p, __p, __p, __p, __c
};
___atab()
{
}

View File

@@ -0,0 +1,55 @@
/****************************************************************************/
/* */
/* CTYPE */
/* ----- */
/* */
/* CTYPE.H - macros to classify ASCII-coded integers by table lookup. */
/* */
/* */
/* Note: Integer args are undefined for all int values > 127, */
/* except for macro 'isascii()'. */
/* Assumes: */
/* User will link with standard library functions. */
/* Compiler can handle declarator initializers and */
/* '#defines' with parameters. */
/* */
/****************************************************************************/
/*
* Bit patterns for character class DEFINEs
*/
#define __c 01
#define __p 02
#define __d 04
#define __u 010
#define __l 020
#define __s 040
#define __cs 041
#define __ps 042
#ifndef CTYPE
extern char ___atab();
extern char __atab[];
#endif
/*
* Character Class Testing and Conversion DEFINEs:
*/
#define isascii(ch) ((ch) < 0200)
#define isalpha(ch) (__atab[ch] & (__u | __l))
#define isupper(ch) (__atab[ch] & __u)
#define islower(ch) (__atab[ch] & __l)
#define isdigit(ch) (__atab[ch] & __d)
#define isalnum(ch) (__atab[ch] & (__u | __l | __d))
#define isspace(ch) (__atab[ch] & __s)
#define ispunct(ch) (__atab[ch] & __p)
#define isprint(ch) (__atab[ch] & (__u | __l | __d | __p))
#define iscntrl(ch) (__atab[ch] & __c)
#define tolower(ch) (isupper(ch) ? (ch)+('a'-'A') : (ch))
#define toupper(ch) (islower(ch) ? (ch)+('A'-'a') : (ch))
#define toascii(ch) ((ch) & 0177)
ower(ch) ? (ch)+('A'-'a') : (ch))
#define toascii(ch) ((ch) & 0177)
ower(ch) ? (ch)+('A'-'a') : (ch))
#define toascii(ch) ((ch) & 0177)

View File

@@ -0,0 +1,232 @@
/*************************************************************************
*
* _ d o p r t F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Reseacrh Inc. All rights reserved.
*
* "_doprt" handles the printing for functions "printf", "fprintf",
* and "sprintf". Each of these sets up the parameters and calls _doprt.
*
* Calling sequence:
*
* nchrs = _doprt(stream,fmt,args)
* Where:
* nchrs = number of chars output by _doprt
* stream -> destination buffer (FILE *)
* fmt -> a string specifying how "args" are to be output.
* args -> a list of arguments
*
*****************************************************************************/
#include "stdio.h"
#include "osif.h"
#define ARGWIDTH (sizeof(int)) /* width of arg to function */
#define NXTARG(ptr,isl) ((ptr)+=((isl) ? MAX(ARGWIDTH,sizeof(LONG)):ARGWIDTH))
#define IARG(ptr) ((ptr)+=ARGWIDTH) /* int arg increment */
#if CPM68K
#define FARG(ptr) ((ptr)+=sizeof(float)) /* float/double arg increment */
#else
#define FARG(ptr) ((ptr)+=sizeof(double)) /* float/double arg increment */
#endif
#define CHOOSELS(isl) ((isl) ? __prtld : __prtshort ) /* prt long or short */
#define XPUTC(a1,a2) {putc(a1,a2);nchrs++;} /* count chars output */
/****************************/
_doprt(sp,fmt,pb) /* print subroutine */
FILE *sp; /* stream buffer ptr */
BYTE *fmt; /* format string */
REG BYTE *pb; /* pointer to args */
{ /****************************/
REG BYTE c; /* format char */
BYTE **ppi; /* pointer to ptr */
WORD *pw; /* pointer to word */
BYTE padchar, /* for padding */
*s, /* string ptr for output */
buf[BUFSIZ]; /* s usually points here */
WORD width; /* for format spec */
REG WORD prec, /* precision */
len; /* total length of field */
WORD n, /* counter */
nchrs; /* number chars output */
BOOLEAN left, /* pad on left? */
longf; /* a long arg? */
MLOCAL BYTE (*fn)(); /* function holder */
GLOBAL BYTE *__prtshort(), /* for 16 bit integers */
*__prtld(); /* for 32 bit integers */
double *dblptr; /* in case we need one */
/****************************/
nchrs = 0; /* init # chars output */
if (fmt) /* make sure it's not NULL */
while (TRUE) /* examine the format string*/
{ /* */
for( len=0, s=fmt; *s && *s != '%'; ++s, ++len )
; /* grab up to EOS or '%' */
if( len > 0 ) /* did we grab anything? */
{ /* yes... */
fputn(fmt,len,sp); /* put them out */
fmt = s; /* update this pointer */
nchrs += len; /* update the counter */
} /* */
if( *fmt++ != '%' ) /* Did we stop for '%'? */
break; /* no, EOS: we're finished*/
/****************************/
left = 0; /* assume no left pad */
if ((c = *fmt++) == '-') /* left pad specified */
{ /* */
c = *fmt++; /* */
left++; /* */
} /* */
padchar = ' '; /* assume blank padding */
if (c == '0') /* zero fill specified */
{ /* */
padchar = c; /* */
c = *fmt++; /* */
} /* */
width = -1; /* assume no field spc width*/
if( c== '*' ) /* get width from args */
{ /* */
pw = pb; /* use word ptr for access */
width = *pw; /* */
IARG(pb); /* */
c = *fmt++; /* */
} /* */
else while (c >= '0' && c <= '9') /* get width from fmt */
{ /* */
if (width < 0) /* */
width = 0; /* */
width = width * 10 + (c - '0'); /* */
c = *fmt++; /* */
} /* */
prec = -1; /* assume no precision */
if (c == '.') /* get precision */
{ /* */
prec = 0; /* */
c = *fmt++; /* */
} /* */
if( c== '*' ) /* get prec from args */
{ /* */
pw = pb; /* get word pointer */
prec = *pw; /* */
IARG(pb); /* */
c = *fmt++; /* */
} /* */
else while (c >= '0' && c <= '9') /* get prec from fmt */
{ /* */
prec = prec * 10 + (c - '0'); /* */
c = *fmt++; /* */
} /* */
longf = 0; /* assume short int */
if (c == 'l' || c == 'L') /* long int specified */
{ /* */
longf++; /* */
c = *fmt++; /* */
} /****************************/
/* we now have all prelims */
/* out of the way; let's see*/
/* what we want to print */
s = buf; /* assume we'll be using buf*/
switch (c) /* */
{ /* */
/****************************/
case 'D': /* decimal signed */
longf++; /* capital letter means long*/
case 'd': /* */
fn = CHOOSELS(longf); /* */
__prtint(pb, buf, 10, TRUE, fn); /* */
NXTARG(pb,longf); /* point to next arg */
break; /* finis switch */
/****************************/
case 'U': /* decimal unsigned */
longf++; /* */
case 'u': /* */
fn = CHOOSELS(longf); /* */
__prtint(pb, buf, 10, FALSE, fn); /* */
NXTARG(pb,longf); /* */
break; /* */
/****************************/
case 'O': /* octal signed */
longf++; /* */
case 'o': /* */
fn = CHOOSELS(longf); /* */
__prtint(pb, buf, 8, FALSE, fn); /* */
NXTARG(pb,longf); /* */
break; /* */
/****************************/
case 'X': /* hexadecimal unsigned */
longf++; /* */
case 'x': /* */
fn = CHOOSELS(longf); /* */
__prtint(pb, buf, 16, FALSE, fn); /* */
NXTARG(pb,longf); /* */
break; /* */
/****************************/
case 's': /* string */
case 'S': /* */
ppi = pb; /* need to deal with ptr */
s = *ppi; /* cast to pointer */
NXTARG(pb,(sizeof(char *)==sizeof(long)));
/* TRUE if pointers are long*/
/* FALSE if not */
break; /* */
/****************************/
case 'c': /* character */
case 'C': /* */
pw = pb; /* word ptr for portability */
buf[0] = (*pw & 0377); /* assume chars passed as */
buf[1] = NULL; /* ints */
IARG(pb); /* */
break; /* */
/****************************/
/****************************/
case 'E': /* E format */
case 'e': /* */
_petoa(pb, buf, prec, c);/* Do the conversion */
FARG(pb); /* Bump to next arg */
prec = -1; /* Avoid truncation */
break; /* Next */
/****************************/
case 'F': /* F format floating */
case 'f': /* */
_pftoa(pb, buf, prec, c);/* do the conversion */
FARG(pb); /* Bump to next arg */
prec = -1; /* Avoid truncation */
break; /* */
/****************************/
case 'G': /* G format floating */
case 'g': /* */
_pgtoa(pb, buf, prec, c);/* do the conversion */
FARG(pb); /* Bump to next arg */
prec = -1; /* Avoid truncation */
break; /* */
/****************************/
/****************************/
default: /* just print the character */
XPUTC(c,sp); /* */
continue; /* */
} /****************************/
len = strlen(s); /* how long is the output? */
if (prec < len && prec >= 0) /* cut off if user says so */
len = prec; /* */
n = width - len; /* how much extra room? */
if (!left) /* if left not specified */
{ /* */
if (padchar == '0' && *s == '-') /* check for neg */
{ /* */
len--; /* output minus if leading 0*/
XPUTC(*s++,sp); /* */
} /* */
while (n-- > 0) /* now pad on left */
XPUTC(padchar,sp); /* */
} /* */
fputn(s,len,sp); /* put buffered n chars */
nchrs += len; /* assume they got there */
while (n-- > 0) /* anything remain, then pad*/
XPUTC(padchar,sp); /* */
} /* */
return(nchrs); /* report on # chars output */
} /****************************/
put */
} /****************************/
put */
} /****************************/

View File

@@ -0,0 +1,183 @@
/***************************************************************************
*
* d o p r t f p R o u t i n e
* -----------------------------
*
* This file contains subroutines called from "_doprt()" which are
* specific to floating point. The purpose of having a separate file
* is so that these routines may be declared global in a special
* version of "s.o", to allow running without the floating point
* library routines.
*
* Entry Points:
*
* _petoa(^float, ^buff, prec);
* _pftoa(^float, ^buff, prec);
* _pgtoa(^float, ^buff, prec);
*
* ^float is a pointer to the floating number to convert
* ^buff is a pointer to the buffer
* prec is the precision specifier
*
* Modifications:
* 1/84 whf - change to include "osif.h"
* 8/83 whf - add in DRC floating point call
* 10/83 whf - get it to work on DRC
*
*****************************************************************************/
/* */
#include "portab.h" /* */
#include "osif.h" /* */
/* */
/****************************************************************************/
#if CPM68K /* I hope to resolve these differences someday. whf 8/83 */
/****************************************************************************/
BYTE *ftoa(); /* Converts float to ascii "F" fmt */
BYTE *etoa(); /* Converts float to ascii "E" fmt */
/************************************/
BYTE *_pftoa(addr,buf,prec) /* Print "F" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
{ /************************************/
FLOAT fp; /* Float temp */
/************************************/
prec = (prec < 0) ? 6 : prec; /* If < 0, make it 6 */
fp = *addr; /* Load float number */
return(ftoa(fp,buf,prec)); /* Do conversion */
} /************************************/
/* */
BYTE *_petoa(addr,buf,prec) /* Print "E" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
{ /************************************/
FLOAT fp; /* Floating temp */
prec = (prec < 0) ? 6 : prec; /* If < 0, make it 6 */
fp = *addr; /* Load temp */
return(etoa(fp,buf,prec)); /* Do conversion */
} /************************************/
/* */
BYTE *_pgtoa(addr,buf,prec) /* Print "G" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
{ /************************************/
BYTE *sp; /* String temp */
/************************************/
sp = _pftoa(addr, buf, prec); /* Try F first */
if(strlen(buf) > (7+prec)) /* Smallest FP string */
sp = _petoa(addr,buf,prec); /* Do E format instead */
return sp; /* */
} /************************************/
/* */
/****************************************************************************/
#else /* for DRC */
/****************************************************************************/
/* */
BYTE *ftoa(); /* General purpose floating point */
/* */
BYTE *_drcftoa(addr,buf,prec,kind) /* Use DRC ftoa routine */
DOUBLE *addr; /* -> Number to convert */
REG BYTE *buf; /* -> Output buffer */
REG WORD prec; /* Fraction precision specifier */
BYTE kind; /* Kind of convert (f, e, or g) */
{ /************************************/
REG BYTE *ss; /* Temp pointer for adjustment */
REG WORD nn; /* Counter */
WORD len; /* */
/* */
ss = buf; /* Save til later */
if( prec < 0) prec = 6; /* If <0, make it 6 */
if( prec > 17 ) prec = 17; /* If >17, make it 17 */
if( kind == 'f' ) nn = 17; /* use max. precision */
else if( kind == 'e' || kind == 'E' )
nn = prec + 1;
else if( (nn = prec) == 0 ) /* G format */
++nn;
if (nn > 17) nn = 17;
*buf = ' ';
ftoa(addr, &buf[1], 80, nn, kind); /* go convert */
if( kind == 'f' )
_ffmt(ss,prec);
len = strlen(buf);
if(buf[len-1] == '.') /* Zap trailing decimal point */
buf[len-1] = NULL; /* */
while( *buf == ' ' ) /* Zap leading blanks */
++buf; /* */
if( ss != buf ) /* Did we zap leading blanks? */
strcpy(ss,buf); /* Ifso, shift everything into place*/
return ss; /* */
} /************************************/
BYTE *_pftoa(addr,buf,prec,ch) /* Print "F" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
BYTE ch; /* Char format specifier */
{ /************************************/
return(_drcftoa(addr,buf,prec,ch));/* Do conversion */
} /************************************/
/* */
BYTE *_petoa(addr,buf,prec,ch) /* Print "E" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
BYTE ch; /* Char format specifier */
{ /************************************/
return(_drcftoa(addr,buf,prec,ch));/* Do conversion */
} /************************************/
/* */
BYTE *_pgtoa(addr,buf,prec,ch) /* Print "G" format */
FLOAT *addr; /* -> Number to convert */
BYTE *buf; /* -> Output buffer */
WORD prec; /* Fraction precision specifier */
BYTE ch; /* Char format specifier */
{ /************************************/
return(_drcftoa(addr,buf,prec,ch));/* Do conversion */
} /************************************/
/****************************************************************************/
MLOCAL _ffmt(s, prec)
char *s;
register prec;
{
register char *p;
register int i;
char *dot, lastdig;
p = s;
while (*++p) {
if (*p == '.') dot = p; /* found decimal pt. */
else if (*p == 'e') {
s = dot + prec + 1;
if (s < p)
while (*s++ = *p++); /* remove extra zeros */
return;
}
}
i = p - dot - 1;
while (i++ < prec)
*p++ = '0'; /* fill trailing zeros */
p = dot + prec + 1;
lastdig = *p;
*p = '\0';
if (lastdig >= '5') {
while (1) { /* round preceeding digit */
if (*--p == '.') p--;
if ((*p += 1) <= '9') break;
*p = '0';
}
if (*p < '1') {
if (*p == '.') *(p-1) = '-';
*p = '1';
}
}
}
#endif
/****************************************************************************/
*******/
*******/

View File

@@ -0,0 +1,282 @@
/*****************************************************************************
*
* _ d o s c a n F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "_doscan" is the common subroutine to "scanf", "fscanf", and
* "sscanf".
*
* Calling sequence:
* ret = _doscan(sp,fmt,aps)
* Where:
* WORD ret number items matched AND assigned
* EOF when encountered on stream sp
* FILE *sp pointer to input stream
* BYTE *fmt input specification string
* BYTE **aps pointer to (pointers to) arguments
*
* Edits:
* 3/15/84 sw Fix Atof / Nofloat problem
* 1/11/84 whf fix "%1s" bug
* 12/02/83 HY ???
*****************************************************************************/
#include "stdio.h"
#include "ctype.h"
#define INFINITY 32767
#define NXTNI(d) if( ((d)=getc(sp)) == EOF ) return(EOF)
WORD _doscan(sp,fmt,aps) /****************************/
REG FILE *sp; /* Stream ptr */
BYTE *fmt; /* Input format spec ptr */
BYTE **aps; /* Argument ptrs ptr */
{ /****************************/
REG BYTE c; /* Spec character */
REG WORD ni; /* Input char */
BOOLEAN noassign, /* Suppress assignment flag */
invert, /* Invert flag (_ismember) */
numfound, /* Number found flag */
longf, /* Long ptr flag */
shortf; /* Short ptr flag */
REG WORD width; /* Max field width */
WORD tval, /* Temp val holder */
base, /* For numeric conversion */
nitems; /* Number items mtchd & assd*/
LONG val, /* For numeric conversion */
locval; /* Local value area */
BYTE locbuf[BUFSIZ], /* Local buffer area */
*db, /* Destination ptr */
setbuf[128], /* Area for '[...]' sets */
*sb; /* Ptr into setbuf */
DOUBLE _atof(); /* */
/****************************/
nitems = 0; /* */
while( c = *fmt++ )
{
if( isspace(c) ) /* if space in spec str */
{ /* */
do{ /* deblank leading blanks */
c = *fmt++; /* */
} while( isspace(c) ); /* */
do{ /* deblank input stream */
NXTNI(ni); /* */
} while( isspace(ni) ); /* read past space in input */
ungetc(ni,sp); /* back up once */
if( c == NULL ) /* check for this here */
break; /* */
} /* c points to non space */
/****************************/
if( c != '%' ) /* match spec char (non'%')?*/
{ /* */
NXTNI(ni); /* grab from input */
if( ni != c ) /* & test */
{ /* */
ungetc(ni,sp); /* nope, put it back */
return(nitems); /* return early */
} /* */
continue; /* yup, do the next char */
} else /****************************/
c = *fmt++; /* look for an assignment */
noassign = FALSE; /* assume we will assign */
if( c == '*' ) /* unless they say otherwise*/
{
noassign++;
c = *fmt++;
}
width = INFINITY; /* assume no special width */
while( c >= '0' && c <= '9' ) /* unless they say otherwise*/
{
if( width == INFINITY )
width = 0;
width = 10 * width + (c - '0');
c = *fmt++;
}
longf = FALSE; /* assume ptrs not to LONGs */
shortf = FALSE; /* and not to SHORTs */
if( c == 'l' ) /* unless they say otherwise*/
{
longf++;
c = *fmt++;
} else if( c=='h' )
{
shortf++;
c = *fmt++;
}
/****************************/
switch( c ) /* which conversion char? */
{ /****************************/
case 'D': /* decimal input */
case 'd':
base = 10; goto procnum;
case 'O': /* octal input */
case 'o':
base = 8; goto procnum;
case 'X': /* hex input */
case 'x':
base = 16;
procnum: /****************************/
if( isupper(c) ) /* upper case means long */
longf++;
do{
NXTNI(ni); /* grab a char from input */
} while( isspace(ni) ); /* until non-blank */
if( noassign )
db = &locval; /* got to put it somewhere */
else db = *aps++; /* like to put it here */
invert = FALSE; /* assume pos number */
if( ni=='+' || ni=='-' ) { /* leading plus or minus */
if( ni == '-' )
invert++;
width--;
NXTNI(ni);
}
val = 0L; /* initial value */
numfound = FALSE; /* assume guilty til proven */
while( width-- > 0 ) { /* for each char ************/
tval = ni = toupper(ni); /* should work for numbers */
if( tval<'0' || tval>'F')
break;
if( tval>'9' && tval<'A')
break;
tval -= '0';
if( tval>9 )
tval = tval+('0'-'A'+10);
if( tval >= base )
break;
numfound++; /* is a number */
val = base * val + tval; /* */
NXTNI(ni); /* next input, please */
} /* *********************/
ungetc(ni,sp); /* back off input */
if( numfound == FALSE ) /* was it there? */
return(nitems); /* no, too bad */
if( invert ) /* leading minus? */
val = -val; /* */
if( longf ) /* store this value */
*( long *)db = val; /* somewhere */
else if( shortf ) /* */
*( short *)db = val; /* somehow */
else /* */
*( int *)db = val; /* sometime */
if( !noassign ) /* increment only if assign */
nitems++; /* */
break; /****************************/
case 's': /* string input */
case 'c': /* char input */
case '[': /* input 'one of' */
NXTNI(ni); /* grab a character */
if( c== 's' ) /* scan string **************/
{
sb = " \t\n"; /* point set to white chars */
while(_ismem(ni,sb,FALSE)) /* keep reading whitespace */
NXTNI(ni); /* if there is any */
invert = TRUE; /* after, read until whites */
} else if( c == 'c' ) /* scan char ****************/
{
sb = ""; /* Null set */
if( width == INFINITY ) /* handle default width */
width = 1;
invert = TRUE; /* invert "_ismem" func */
} else /* scan set *****************/
{ /* must be a '[' */
invert = FALSE;
if( (c = *fmt++) == '^' ) /* invert "_ismem" ??? */
{
invert = TRUE;
c = *fmt++;
}
for( sb=setbuf; c != NULL && c != ']'; sb++, c = *fmt++)
*sb = c;
*sb = NULL;
sb = setbuf;
}
if( noassign )
db = locbuf; /* give rtn somewhere to pt */
else db = *aps++; /* o.w. grab the desired ptr*/
while( width-- > 0 && _ismem(ni,sb,invert) )
{
*db++ = ni;
NXTNI(ni);
}
ungetc(ni,sp); /* we've always read 1 past */
if( c != 'c' ) /* not char type? */
*db = NULL; /* then null terminate */
if( !noassign )
nitems++; /* successful assignment */
break; /****************************/
/****************************/
case 'E': /*********** not fully implemented **********/
case 'e':
case 'F':
case 'f':
if( isupper(c) ) /* upper case means long */
longf++;
do {
NXTNI(ni); /* grab a char from input */
} while( isspace(ni) ); /* until non-blank */
if( noassign )
db = &locval; /* got to put it somewhere */
else db = *aps++; /* like to put it here */
sb = setbuf; /* setup up addr to hold string */
while (width-- > 0)
{
*sb++ = ni;
if ((ni < '0' || ni > '9') && (ni != '.')
&& (ni != 'e')
&& (ni != 'E')
&& (ni != '-')
&& (ni != '+'))
break;
NXTNI(ni);
}
ungetc(ni,sp);
*--sb = '\0';
if (longf)
*(double *)db = _atof(setbuf);
else
*(float *)db = (float) _atof(setbuf);
if (!noassign)
nitems++;
break;
case '%':
default:
NXTNI(ni);
if( ni != c ) /* must match c */
{
ungetc(ni,sp);
return(nitems);
}
break;
} /***** end switch ***********/
} /***** end while loop *******/
return(nitems); /* */
} /****************************/
/****************************/
MLOCAL WORD _ismem(c,set,invert) /* is_member of a set */
BYTE c; /* candidate for set element*/
BYTE *set; /* null terminated string */
BOOLEAN invert; /* invert sense of function */
{ /****************************/
REG WORD rv; /* temp return val */
rv = strchr(set,c); /* look for c in set */
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/
return( invert ? !rv : rv ); /* return (maybe inverted) #*/
} /****************************/


View File

@@ -0,0 +1,14 @@
/*
* errno.c : declares storage for errno, a variable containing the last
* system error.
*/
#include "portab.h"
#include "osif.h"
WORD errno = 0; /* set by low level i/o, unset by user (if at all) */
WORD _errcpm = 0; /* assign BDOS return val when assigning errno */
l when assigning errno */
l when assigning errno */

View File

@@ -0,0 +1,59 @@
/*
* errno.h - error codes
*/
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
/* math software */
#define EDOM 33
#define ERANGE 34
/* hereafter is available to CP/M specials */
#define ENODSPC 35
#define ERENAME 36
/****** end of errno.h ******/
ME 36
/****** end of errno.h ******/
ME 36
/****** end of errno.h ******/

Binary file not shown.

View File

@@ -0,0 +1,33 @@
/***************************************************************************
*
* E x i t F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* The exit function is called from anywhere to pass control back to
* the CCP from the executing C program.
* Note that the stream files are closed via '_cleanup()'.
*
* Calling Sequence:
*
* exit(code);
*
* Where:
* code Is the exit status (ignored)
*
****************************************************************************/
#include "portab.h"
VOID exit(code) /* CLEAR FUNCTION ***********/
WORD code; /* Exit status */
{ /* */
_cleanup(); /* Close all (stream) files*/
_exit(code); /* return to O.S. */
} /***************************/
stream) files*/
_exit(code); /* return to O.S. */
} /***************************/
stream) files*/
_exit(code); /* return to O.S. */
} /***************************/

View File

@@ -0,0 +1,38 @@
/*********************************************************************
*
* f c l o s e F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fclose" flushes a stream (buffered file) and releases the
* channel and any allocated buffers.
*
* Calling sequence:
* ret = fclose(stream)
* Where:
* stream -> file to be closed (FILE *)
* ret = SUCCESS or FAILURE (if IO error)
*
*****************************************************************************/
#include "stdio.h"
WORD fclose(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* stream to close */
{ /* */
/****************************/
if( sp->_flag & (_IOREAD|_IOWRT) ) /* is it closeable? */
{ /* yup... */
fflush(sp); /* do the flush */
if( sp->_flag & _IOABUF ) /* was buf alloc'd? */
free(sp->_base); /* free it ifso */
sp->_base = sp->_ptr = NULL; /* reset these */
sp->_cnt = 0; /* */
} /* reset all flags */
sp->_flag &= ~(_IOREAD|_IOWRT|_IOABUF|_IONBUF|_IOERR|_IOEOF|_IOLBUF);
return(close(sp->_fd)); /* and return */
} /****************************/
(sp->_fd)); /* and return */
} /****************************/
(sp->_fd)); /* and return */
} /****************************/

View File

@@ -0,0 +1,48 @@
/****************************************************************************
*
* D a t a D e c l a r a t i o n s M o d u l e
* -----------------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* Herein lie the data definitions for the stdio.h functions.
* Note: function __fdecls() is here so _main can force this module to
* be loaded.
*
*****************************************************************************/
#define FILE /* avoid duplicate decls */
#include "stdio.h"
#if MAXFILES != 16
compile snafu: fix following table
#endif
struct _iobuf _iob[16] ={
{ 0, _IOREAD, NULLPTR, NULLPTR, 0},
{ 1, _IOWRT+_IONBUF, NULLPTR, NULLPTR, 0},
{ 2, _IOWRT+_IONBUF, NULLPTR, NULLPTR, 0},
{ 3, 0, NULLPTR, NULLPTR, 0 },
{ 4, 0, NULLPTR, NULLPTR, 0 },
{ 5, 0, NULLPTR, NULLPTR, 0 },
{ 6, 0, NULLPTR, NULLPTR, 0 },
{ 7, 0, NULLPTR, NULLPTR, 0 },
{ 8, 0, NULLPTR, NULLPTR, 0 },
{ 9, 0, NULLPTR, NULLPTR, 0 },
{ 10, 0, NULLPTR, NULLPTR, 0 },
{ 11, 0, NULLPTR, NULLPTR, 0 },
{ 12, 0, NULLPTR, NULLPTR, 0 },
{ 13, 0, NULLPTR, NULLPTR, 0 },
{ 14, 0, NULLPTR, NULLPTR, 0 },
{ 15, 0, NULLPTR, NULLPTR, 0 }
};
__fdecls()
{
}

}

}

View File

@@ -0,0 +1,53 @@
/***************************************************************************
*
* f d o p e n F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fdopen" associates a file which was opened by a file descriptor
* (using "open" or "creat") with a stream.
*
* Calling sequence:
* stream = fdopen( fd, mode )
* Where:
* stream -> stream info (FILE *) (NULLPTR returned on fail)
* fd = small int returned by open or creat
* mode = "r" for read-only, "w" for write, "a" for append
*
*****************************************************************************/
#include "stdio.h"
FILE * fdopen( fd, mode ) /* CLEAR FUNCTION ***********/
REG WORD fd;
REG BYTE *mode;
{
REG FILE *sp;
REG WORD ii;
/****************************/
if( fd<0 || lseek(fd,0L,1)==FAILURE ) /* is fd valid? */
return(NULLFILE); /* no, oh well */
for( ii=0; /* look at _iob table */
(sp=(&_iob[ii]))->_flag&(_IOREAD|_IOWRT); /* not marked rd/wrt */
ii++ ) /* */
if( ii >= MAXFILES ) /* if off end of table */
break; /* */
if( ii >= MAXFILES ) /* */
return(NULLFILE); /* fail */
if( *mode != 'r' && *mode != 'R') /* not 'r'ead mode? */
{ /* */
sp->_flag |= _IOWRT; /* set this flag */
if( *mode == 'a' || /* 'a'ppend mode? */
*mode == 'A' ) /* */
lseek(fd,0L,2); /* its out there, seef EOF */
} /* ************************/
else sp->_flag |= _IOREAD; /* 'r'ead mode */
/****************************/
sp->_cnt = 0; /* init count */
sp->_fd = fd; /* and file des */
sp->_base = sp->_ptr = NULLPTR; /* and buffer pointers */
/****************************/
return(sp); /* return the stream ptr */
} /****************************/
*******/
*******/

View File

@@ -0,0 +1,54 @@
/****************************************************************************
*
* f f l u s h F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* 'fflush' causes any buffered data in a stream to be written out
* to the file. The stream remains open.
*
* Calling sequence:
* ret = fflush(stream)
* Where:
* stream is a (FILE *)
* ret = SUCCESS or FAILURE (I/O error)
*
* 9/83 fix fseek(stream,xx,1) bug whf
*
*****************************************************************************/
#include "stdio.h"
WORD fflush(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* stream to flush */
{ /****************************/
REG WORD n, /* num written */
ns; /* num sposed to be written */
/****************************/
if((sp->_flag&(_IONBUF|_IOWRT))==_IOWRT /* does it have a wrt buf? */
&& (ns=(WORD)(sp->_ptr-sp->_base)) > 0)/* and does buf need wrt?*/
{ /* yes! */
n=write(sp->_fd,sp->_base,ns); /* do it */
if(ns!=n) /* did they all git writ? */
{ /* oooops */
sp->_flag |= _IOERR; /* this stream no good */
return(FAILURE); /* let em know */
} /* */
} /****************************/
if( sp->_flag & _IOWRT ) /* is this a writable file? */
{ /* */
if( sp->_base != NULL ) /* written to already? */
{ /* */
if(sp->_flag&_IONBUF) /* is this a nobuf stream? */
sp->_cnt = 1; /* yes */
else sp->_cnt = BUFSIZ-1; /* standard size */
} /* */
} else { /* is a readable file */
lseek(sp->_fd,(LONG) -(sp->_cnt),1);/* back up cur position ptr */
sp->_cnt = 0; /* zap out count */
} /* */
sp->_ptr=sp->_base; /* reset buf */
return(SUCCESS); /* */
} /****************************/
**********************/
**********************/

View File

@@ -0,0 +1,32 @@
/**************************************************************************
*
* f g e t c F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* Function "fgetc" does the yanking of a char out of the stream.
*
* Calling sequence:
* ch = fgetc(s)
* Where:
* ch = a (WORD) character (-1 on EOF)
* s -> a stream file (FILE *)
*
*****************************************************************************/
#include "stdio.h"
#define CMASK 0xFF
WORD fgetc(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* stream pointer */
{ /****************************/
EXTERN WORD _filbuf(); /* use this when we run shrt*/
if( --sp->_cnt >= 0 ) /* any chars left in buf? */
return(((WORD) *sp->_ptr++) & CMASK);/* return & advance ptr ifso*/
else /* */
return( _filbuf(sp) ); /* o.w. whatever happens */
} /****************************/
p) ); /* o.w. whatever happens */
} /****************************/
p) ); /* o.w. whatever happens */
} /****************************/

View File

@@ -0,0 +1,48 @@
/***********************************************************************
*
* f g e t s F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fgets" reads a string from a stream file (up to n-1 chars), and
* returns pointer s (NULLPTR on end of file). The newline at the
* end of line is included, NOT replaced, and the string is terminated
* by a NULL.
*
* Calling sequence:
* addr = fgets(saddr,n,stream)
* Where:
* saddr -> where the string is to go (no bounds check)
* n = max # chars (inc. NULL) for saddr (assumed > 0)
* stream-> where to get from
* addr = saddr if all ok, NULLPTR o.w.
*
*****************************************************************************/
#include "stdio.h"
BYTE * fgets(str,maxc,sp) /* CLEAR FUNCTION ***********/
REG BYTE *str; /* string save area */
REG WORD maxc; /* max size of string */
REG FILE *sp; /* where to get from */
{ /****************************/
REG WORD c; /* char to test for eof */
REG BYTE *sav; /* sav pointer for return */
sav = str; /* remember this */
while( --maxc > 0 && /* while there's still room */
/* for getc and NULL */
(c=getc(sp)) != FAILURE ) /* and read_char ok */
{ /* */
*str++ = c; /* store it */
if( c == '\n' ) /* if end of line */
break; /* stop the presses */
} /* */
*str = NULL; /* clean up string */
if(c == FAILURE) /* if not cool */
return(NULLPTR); /* then tell them so */
return(sav); /* tell them is cool */
} /****************************/
* tell them is cool */
} /****************************/
* tell them is cool */
} /****************************/

View File

@@ -0,0 +1,62 @@
/****************************************************************************
*
* _ f i l b u f F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "_filbuf" function is called by getc to fill the buffer.
* It performs any initialization of the buffered on the first
* call.
*
* Calling sequence:
* char = _filbuf(stream)
* Where:
* stream -> file info
* char = the first character returned, or FAILURE (-1)
* on error or EOF
*
*****************************************************************************/
#include "stdio.h"
#define CMASK 0xFF
WORD _filbuf(sp) /* fill buffer */
REG FILE *sp; /* from this stream */
{ /****************************/
static BYTE onebuf[MAXFILES]; /* a place if no mem avail. */
/* small buf for ungetc */
EXTERN BYTE *malloc(); /* someplace to get mem */
/****************************/
if((sp->_flag & _IOREAD) == 0) /* is readable file? */
return(FAILURE); /* no */
if( sp->_flag & _IOSTRI ) /* is this stream a string? */
{ /* yes: handle EOS as EOF*/
sp->_flag |= _IOEOF; /* */
return(FAILURE); /* */
} /****************************/
if( sp->_base == NULL ) /* has this been done? */
{ /* no...*********************/
if( sp->_flag & _IONBUF || /* is the No Buf flag set? */
(sp->_base=malloc(BUFSIZ))==NULL) /* can't we get buffer? */
sp->_flag |= _IONBUF; /* set No Buf flag */
else sp->_flag |= _IOABUF; /* we're all set */
} /****************************/
if( sp->_flag & _IONBUF ) /* insure this set right */
sp->_base = &onebuf[sp->_fd]; /* set 'buf' to small buf */
if( sp==stdin && (stdout->_flag&_IOLBUF))/* console i/o? */
fflush(stdout); /* output whatever to con */
sp->_cnt = read(sp->_fd, sp->_base, /* read to our buffer */
sp->_flag & _IONBUF ? 1 : BUFSIZ); /* the right # of bytes */
if( sp->_cnt <= 0 ) /* did read screw up? */
{ /* yup...********************/
if( sp->_cnt == FAILURE ) /* really bad? */
sp->_flag |= _IOERR|_IOEOF; /* say so */
else sp->_flag |= _IOEOF; /* or just say we can't read*/
return(FAILURE); /* */
} /****************************/
sp->_cnt--; /* take the 1st item */
sp->_ptr=sp->_base; /* set up stream */
return(((WORD)(*sp->_ptr++) & CMASK)); /* and return the char */
} /****************************/
} /****************************/
} /****************************/

View File

@@ -0,0 +1,98 @@
/**********************************************************************
*
* _ f i l e s z f u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This routine computes the size of a CP/M file, and leaves the fd
* pointing to the end of file.
* Note that the file must have been previously opened.
*
* Calling sequence:
* size = _filesz(fd)
* where:
* size = # bytes in file;
* 0 if not disk file;
* -1 if I/O error
* fd = file descriptor returned by open.
*
***********************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
LONG _filesz(fd) /****************************/
WORD fd; /* file descriptor */
{
REG FD *fp; /* file's ccb pointer */
REG BYTE *p1, *p2; /* temps for buffer work */
REG LONG xsector; /* where we are in file */
FD *_chkc(); /* cvt & check fd to fp */
REG WORD xuser; /* Current user # */
/****************************/
if((fp = _chkc(fd)) == NULLFD) /* Convert to pointer */
return(FAILURE); /* Can't: EBADF */
if(fp->flags&(ISTTY|ISLPT)) /* Non disk file? */
return(0); /* */
#if PCDOS /*================================================================*/
fp->offset = (fp->fcb).fcb_filsiz; /* simple, eh? */
#endif /*================================================================*/
#if CPM /*================================================================*/
if( fp->flags & DIRTY ) { /* File been used? */
fp->offset = fp->hiwater; /* yes: this must be right */
} else { /****************************/
xuser = _chkuser(fp->user); /* Check user # for change */
__OSIF(FILSIZ,&(fp->fcb)); /* Do BDOS call */
_uchkuser(fp->user,xuser); /* Change back if needed */
#if HILO /*--------------------------*/
fp->fcb.record &= 0xFFFFFFL; /* mask off cr byte */
xsector = fp->fcb.record - 1; /* last sector in file */
#else /*--------------------------*/
xsector = (fp->fcb.record >>8) - 1; /* last sector in file */
#endif /*--------------------------*/
if( fp->flags & ISASCII ) /****************************/
{ /* Ascii file: posit to EOF */
if(xsector >= 0) /* if any size at all */
{ /* *********************/
if( xsector != fp->sector ) /* need to change sector? */
{ /* get correct sector********/
if((fp->flags & DIRTY) != 0) /* Something to write 1st? */
{ /* */
if(_blkio(fp,fp->sector,fp->buffer, /* Write out */
1L,B_WRITE) != 1) /* the buffer */
RETERR(FAILURE,EIO); /* */
fp->flags &= ~DIRTY; /* turn off this bit */
} /* */
if(_blkio(fp,xsector,fp->buffer, /* scan this last sector */
1L,B_READ) != 1) /* for EOFCHAR */
RETERR(FAILURE,EIO); /* */
} /* got correct sector********/
fp->sector = xsector; /* */
fp->offset = xsector << 7; /* */
p1 = &(fp->buffer[0]); /* start of buf */
p2 = &(fp->buffer[SECSIZ]); /* end of buf */
while( p1<p2 && *p1 != EOFCHAR) /* look for EOFCHAR */
p1++; /* */
fp->offset += p1-&(fp->buffer[0]); /* update offset to EOF */
} /* *********************/
else fp->offset=0; /* o.w. beginning of file */
/****************************/
} else { /* Binary file:compute size */
fp->offset = (xsector+1) << 7; /* set to end of last record*/
} /****************************/
} /****************************/
#endif /*================================================================*/
fp->hiwater = fp->offset; /* whatever happened, set it*/
fp->flags |= ATEOF; /* make sure they know */
return(fp->offset); /* this is it */
} /****************************/
w */
return(fp->offset); /* this is it */
} /****************************/
w */
return(fp->offset); /* this is it */
} /****************************/

View File

@@ -0,0 +1,88 @@
/************************************************************************
*
* _ f l s b u f F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* '_flsbuf' handles writes to the stream when its buffer is full.
* Included is the ability to handle 'non-buffered' (_IONBUF), as
* well as line buffered (_IOLBUF) output. It is supposed to be
* called by 'putc'. It will init the buffers, as needed.
*
* Calling sequence:
* chr = _flsbuf( ch, stream )
* Where:
* ch = the 1st char to be buffered
* stream -> where its going (FILE *)
* chr = ch if write ok, FAILURE (-1 WORD) o.w.
*
* Modifications:
* 19-Oct-83 whf Handle IONBUF differently
*****************************************************************************/
#include "stdio.h"
WORD _flsbuf(c,sp) /****************************/
REG BYTE c; /* char to be written */
REG FILE *sp; /* stream to write to */
{ /****************************/
BYTE csave; /* a temp save area */
BYTE *malloc(); /* alloc memory */
REG WORD n, /* number chars written */
ns; /* num chars sposed to be w.*/
/* */
ns = n = 0; /* init them */
if( (sp->_flag & _IOWRT) == 0 ) /* is this file writeable? */
return(FAILURE); /* no! */
if( sp->_base == NULLPTR && /* if no init yet and */
(sp->_flag & _IONBUF) == 0 ) /* and not a no buff file */
{ /* ifso...*******************/
if( (sp->_ptr=sp->_base=malloc(BUFSIZ)) == NULLPTR ) /* alloc ok?*/
sp->_flag |= _IONBUF; /* set to a no buff file */
else { /* o.w. we have a buffer! */
sp->_flag |= _IOABUF; /* mark it as alloc'd */
if( isatty(sp->_fd) ) /* do we handle newlines? */
sp->_flag |= _IOLBUF; /* yessir, this is a linbuf */
else { /* o.w. *********************/
sp->_cnt = BUFSIZ-2; /* lv room for 1st & last ch*/
return(*sp->_ptr++ = c); /* store 1st & quit */
} /*tty chk********************/
} /*malloc*********************/
} /*NULL buff******************/
if( sp->_flag & _IONBUF ) /* insure this pts ok */
sp->_ptr = sp->_base = &csave; /* give buff a temp place */
*sp->_ptr++ = c; /* put this somewhere */
if( sp->_flag & _IONBUF ) /* if a no buff file */
{ /* */
n=write(sp->_fd,sp->_base,(ns=1)); /* write single char */
sp->_cnt = 0; /* enforce coming back again*/
} /****************************/
else if( sp->_flag & _IOLBUF ) /* if a line buff file */
{ /* */
if(c=='\n' || sp->_ptr >= sp->_base+BUFSIZ ) /* buf full or '\n'*/
{ /* */
n=write(sp->_fd,sp->_base, /* output the line */
(ns=sp->_ptr-sp->_base)); /* */
sp->_ptr = sp->_base; /* reset the buffer */
} /* */
sp->_cnt = 0; /* enforce coming right back*/
} /****************************/
else /* o.w. we really have a */
{ /* full buffer */
n=write(sp->_fd,sp->_base, /* output the whole buff */
(ns=sp->_ptr-sp->_base)); /* */
sp->_cnt = BUFSIZ-1; /* lv room for last char */
sp->_ptr = sp->_base; /* init ptr */
} /* end buf handlers**********/
if( ns != n ) /* error on write? */
{ /* */
sp->_flag |= _IOERR; /* mark stream */
return(FAILURE); /* and die */
} /****************************/
return(((WORD) c) & 0xff ); /* everything ok, quit */
} /****************************/
 /* everything ok, quit */
} /****************************/
 /* everything ok, quit */
} /****************************/

View File

@@ -0,0 +1,100 @@
/**************************************************************************
*
* f o p e n F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fopen" opens a buffered stream file, either on disk, console, or
* line printer.
* Note that "fopen" comes in three (3) flavors, one for ascii CP/M
* files, another for binary files, and the default (presently to
* ascii files).
*
* Calling sequence:
* stream = fopena(name,mode) (ascii files)
* stream = fopenb(name,mode) (binary files)
* stream = fopen(name,mode) (default-ascii files)
* stream = _fopen(name,mode,ascii)
* Where:
* stream -> file opened (FILE *), NULLPTR if failure
* name -> NULL terminated string containing filename,
* name="CON:" means the console,
* name="LST:" goes to the line printer, and
* otherwise a disk file is assumed.
* mode -> "r" for read only,
* "w" for write only,
* "a" to append (write only) to end of file.
* ascii = 0 if the file is handled as a CP/M text file
* (newline -> CRLF xlation, ^Z EOF convention).
* Otherwise, file is treated as a binary file.
*
*****************************************************************************/
#include "stdio.h" /****************************/
#define READ 0 /* read mode val */
#define WRITE 1 /* write mode val */
#define CREATMODE 1 /* mode to use for 'creat' */
/****************************/
FILE * _fopen(name,mode,ascii) /* */
REG BYTE *name, /* file name */
*mode; /* "r","w", or "a" */
BOOLEAN ascii; /* CP/M text file */
{ /****************************/
REG FILE *sp; /* stream pointer */
REG WORD ii, /* index into _iob */
fd; /* file descriptor */
/****************************/
for( ii=0; /* look at _iob table */
(sp=(&_iob[ii]))->_flag&(_IOREAD|_IOWRT); /* not marked rd/wrt */
ii++ ) /* */
if( ii >= MAXFILES ) /* if off end of table */
break; /* */
if( ii >= MAXFILES ) /* */
return(NULLFILE); /* fail */
if( *mode == 'w' || *mode == 'W' ) /* 'w'rite mode? */
fd=_creat(name,CREATMODE,ascii);/* create file *********/
else if( *mode == 'a' || *mode == 'A' ) /* 'a'ppend mode? */
{ /* */
if( (fd=_open(name,WRITE,ascii)) < 0 ) /* try open */
fd=_creat(name,CREATMODE,ascii);/* ow. do create */
else lseek(fd,0L,2); /* its out there, seef EOF */
} /* ************************/
else if( *mode == 'r' || *mode == 'R' ) /* 'r'ead mode? */
fd=_open(name,READ,ascii); /* try open ************/
else return(NULLFILE); /* bad mode barf... */
/****************************/
if(fd<0) /* did one of those work? */
return(NULLFILE); /* no, oh well */
sp->_cnt = 0; /* init count */
sp->_fd = fd; /* and file des */
sp->_base = sp->_ptr = NULLPTR; /* and buffer pointers */
if( *mode == 'r' || *mode == 'R' ) /* 'r'ead mode? */
sp->_flag = _IOREAD; /* say so */
else sp->_flag = _IOWRT; /* else 'w'rite mode */
if( ascii == 0 ) /* ascii mode? */
sp->_flag |= _IOASCI; /* */
/****************************/
return(sp); /* return the stream ptr */
} /****************************/
/****************************/
FILE * fopen(name,mode) /* CLEAR FUNCTION ***********/
BYTE *name, *mode; /* */
{ /* */
return(_fopen(name,mode,0)); } /* ascii file open */
/****************************/
FILE * fopena(name,mode) /* CLEAR FUNCTION ***********/
BYTE *name,*mode; /* */
{ /* */
return(_fopen(name,mode,0)); } /* ascii file open */
/****************************/
FILE * fopenb(name,mode) /* CLEAR FUNCTION ***********/
BYTE *name, *mode; /* */
{ /* */
return(_fopen(name,mode,1)); } /* binary file open */
 */
{ /* */
return(_fopen(name,mode,1)); } /* binary file open */
 */
{ /* */
return(_fopen(name,mode,1)); } /* binary file open */

View File

@@ -0,0 +1,32 @@
/*****************************************************************************
*
* f p u t c F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fputc" does the inserting of a char into a stream buffer,
* calling _flsbuf when the buffer fills up.
* Returns the character put, or FAILURE (-1) if any errors.
*
* Calling sequence:
* ret=fputc(ch,s)
* Where:
* ch = the char to put
* s -> the stream (FILE *)
* ret= ch or FAILURE
*
*****************************************************************************/
#include "stdio.h"
WORD fputc(ch,sp) /* CLEAR FUNCTION ***********/
REG BYTE ch; /* char to put */
REG FILE *sp; /* stream to put it to */
{ /****************************/
if( --(sp->_cnt) >= 0 ) /* if there's room in buf */
return(((WORD)(*sp->_ptr++ = ch)) & 0377);/* put it! */
else return(_flsbuf(ch,sp)); /* o.w. flush & put */
/****************************/
}



View File

@@ -0,0 +1,48 @@
/************************************************************************
*
* f p u t n F u n c t i o n
* ---------------------------
* Copyright 1983 by Digital Research Inc. All rights reserved.
*
* 'fputn()' writes 'n' chars to a buffered file. It optimizes
* for 'non-buffered' (_IONBUF) output.
*
* Calling sequence:
* rv = fputn(cp,n,stream)
* Where:
* cp -> chars to be put
* n = num chars to be put
* stream -> where its going (FILE *)
* rv = SUCCESS if write ok, FAILURE (-1 WORD) o.w.
*
*****************************************************************************/
#include "stdio.h"
WORD fputn(buf,num,sp) /* CLEAR FUNCTION ***********/
REG BYTE *buf; /* chars to be written */
REG WORD num; /* num chars to be written */
REG FILE *sp; /* stream to write to */
{ /****************************/
if( sp->_flag & _IONBUF ) /* Non-buffered file? */
{ /* */
sp->_cnt = 0; /* Always force to zero */
if(num!=write(sp->_fd,buf,num)) /* try to write */
{ /* no good */
sp->_flag |= _IOERR; /* mark this file */
return FAILURE; /* and complain */
} /* */
return SUCCESS; /* */
} /****************************/
/* */
while(num--) /* Buffered output */
if( FAILURE==fputc(*buf++,sp)) /* try to put in buf */
return FAILURE; /* no good */
return SUCCESS; /* everything a-ok */
} /****************************/
n FAILURE; /* no good */
return SUCCESS; /* everything a-ok */
} /****************************/
n FAILURE; /* no good */
return SUCCESS; /* everything a-ok */
} /****************************/

View File

@@ -0,0 +1,35 @@
/**************************************************************************
*
* f p u t s F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fputs" copies a null terminated string to a stream file.
* To be compatible with Unix, it does NOT append a newline.
*
* Calling sequence:
* ret = fputs(s,stream)
* Where:
* ret = last char out, on error FAILURE
* s = string to put
* stream -> stream (FILE *)
*
*****************************************************************************/
#include "stdio.h"
WORD fputs(str,sp) /* CLEAR FUNCTION ***********/
REG BYTE *str; /* null term string */
REG FILE *sp; /* stream file pointer */
{ /****************************/
REG WORD rv; /* return val */
rv = NULL; /* init for *s==NULL */
while(*str) /* for all chars in s */
if((rv=putc(*str++,sp))==FAILURE) /* if putc fouls up */
return(FAILURE); /* give up */
return(rv); /* it worked */
} /****************************/
return(rv); /* it worked */
} /****************************/
return(rv); /* it worked */
} /****************************/

View File

@@ -0,0 +1,52 @@
/**************************************************************************
*
* f r e a d F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fread" reads NI items of size SZ from stream SP and deposits them
* at BUFF.
*
* Calling sequence:
* rval = fread(buff,size,nitems,stream)
* Where:
* buff -> where to read to
* size = number bytes in each item
* nitems = number bytes read/to read
* stream -> file
*
* rval = number items successfully read
*
* Edits:
* 8-Feb-84 whf return nitems actually read for EOF.
*
*****************************************************************************/
#include "stdio.h"
WORD fread(buff,siz,num,sp) /* CLEAR FUNCTION ***********/
REG BYTE *buff;
WORD siz,
num;
REG FILE *sp;
{
REG WORD jj, kk, ch;
for( jj=0; jj<num; jj++ )
for( kk=0; kk<siz; kk++ )
{
if( (ch = getc(sp)) == FAILURE )
return(jj); /* # items successfully read */
else *buff++ = ch;
}
return(num);
}
*buff++ = ch;
}
return(num);
}
*buff++ = ch;
}
return(num);
}

View File

@@ -0,0 +1,86 @@
/*****************************************************************************
*
* f r e o p e n F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "freopen" opens a buffered stream file, either on disk, console, or
* line printer. It first closes the given stream, and reuses that slot.
* Comes in 3 flavors, like "fopen".
*
* Calling sequence:
* stream = freopen(name,mode,stream)
* stream = freopa(name,mode,stream)
* stream = freopb(name,mode,stream)
* stream = _freopen(name,mode,stream,ascii)
* Where:
* stream -> file reopened (FILE *), NULLPTR if failure
* name -> NULL terminated string containing filename,
* name="CON:" means the console,
* name="LST:" goes to the line printer, and
* otherwise a disk file is assumed.
* mode -> "r" for read only,
* "w" for write only,
* "a" to append (write only) to end of file.
* ascii = 0 if the file is handled as a CP/M text file
* (newline -> CRLF xlation, ^Z EOF convention).
* Otherwise, file is treated as a binary file.
*
*****************************************************************************/
#include "stdio.h" /****************************/
#define READ 0 /* read mode val */
#define WRITE 1 /* write mode val */
FILE *_freope(name,mode,sp,ascii) /****************************/
REG BYTE *name, /* file name */
*mode; /* "r","w", or "a" */
REG FILE *sp; /* stream pointer */
BOOLEAN ascii; /* CP/M text file */
{ /****************************/
REG WORD fd; /* file descriptor */
/****************************/
if( fclose(sp) == FAILURE ) /* try closing the file 1st */
return(NULLFILE); /* oops, it failed */
if( *mode == 'w' || *mode == 'W' ) /* 'w'rite mode? */
fd=_creat(name,0,ascii); /* create file *********/
else if( *mode == 'a' || *mode == 'A' ) /* 'a'ppend mode? */
{ /* */
if( (fd=_open(name,WRITE,ascii)) < 0 ) /* try open */
fd=_creat(name,0,ascii);/* do create if needed */
else lseek(fd,0L,2); /* its out there, seef EOF */
} /* ************************/
else if( *mode == 'r' || *mode == 'R' ) /* 'r'ead mode? */
fd=_open(name,READ,ascii); /* try open ************/
else return(NULLFILE); /* bad mode barf... */
/****************************/
if(fd<0) /* did one of those work? */
return(NULLFILE); /* no, oh well */
sp->_cnt = 0; /* init count */
sp->_fd = fd; /* and file des */
sp->_base = sp->_ptr = NULLPTR; /* and buffer pointers */
if( *mode == 'r' || *mode == 'R' ) /* 'r'ead mode? */
sp->_flag = _IOREAD; /* say so */
else sp->_flag = _IOWRT; /* else 'w'rite mode */
if( ascii == 0 ) /* ascii file? */
sp->_flag |= _IOASCI; /* */
/****************************/
return(sp); /* return the stream ptr */
} /****************************/
FILE * freopen(name,mode,sp) /* CLEAR FUNCTION ***********/
BYTE *name, *mode; FILE *sp;
{ return(_freope(name,mode,sp,0)); } /* reopen ascii file */
FILE * freopa(name,mode,sp) /* CLEAR FUNCTION ***********/
BYTE *name, *mode; FILE *sp;
{ return(_freope(name,mode,sp,0)); } /* reopen ascii file */
FILE * freopb(name,mode,sp) /* CLEAR FUNCTION ***********/
BYTE *name, *mode; FILE *sp;
{ return(_freope(name,mode,sp,1)); } /* reopen binary file */
E *sp;
{ return(_freope(name,mode,sp,1)); } /* reopen binary file */
E *sp;
{ return(_freope(name,mode,sp,1)); } /* reopen binary file */

View File

@@ -0,0 +1,71 @@
/**************************************************************************
*
* f s e e k F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fseek" sets the read/write pointer of a stream to an arbitrary
* offset.
*
* Calling sequence:
* ret = fseek(sp,offset,sense)
* Where:
* sp -> (FILE *) stream to seek on
* offset = signed number of bytes
* sense = 0 => offset from beginning of file
* 1 => offset from current position
* 2 => from end of file
* ret = 0 for success, -1 for failure
*
*****************************************************************************/
#include "stdio.h"
WORD fseek(sp,offs,sense) /* CLEAR FUNCTION ***********/
REG FILE *sp;
LONG offs;
WORD sense;
{
LONG p, lseek();
if ( fflush(sp) == FAILURE )
return( FAILURE );
p = lseek(fileno(sp),offs,sense);
sp->_flag &= ~_IOEOF; /* any seek clears EOF flag */
return( p==(LONG) FAILURE ? FAILURE : SUCCESS);
}
/************************************************************************
*
* r e w i n d F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "rewind" sets the read/write pointer of a stream file to the
* beginning of the stream.
*
* Calling sequence:
* ret = rewind(sp)
* Where:
* sp -> a stream file (FILE *)
* ret = 0 for success, -1 for failure
*
*************************************************************************/
WORD rewind(sp) /* CLEAR FUNCTION ***********/
FILE *sp;
{
return(fseek(sp,0L,0));
}

WORD rewind(sp) /* CLEAR FUNCTION ***********/
FILE *sp;
{
return(fseek(sp,0L,0));
}

WORD rewind(sp) /* CLEAR FUNCTION ***********/
FILE *sp;
{
return(fseek(sp,0L,0));
}

View File

@@ -0,0 +1,71 @@
/***********************************************************************
*
* f t e l l F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "ftell" returns the present value of the read/write pointer
* within the stream. This is a meaningless number for console
* and list devices.
*
* Calling sequence:
* offset = ftell(sp)
* Where:
* sp -> (FILE *) stream
* offset = (LONG) where stream is reading from/writing to
*
******************************************************************************/
#include "stdio.h"
LONG ftell(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* stream pointer */
{ /* */
REG LONG filepos; /* file position */
REG BYTE *bp; /* Buffer ptr */
LONG nread; /* Temp var */
LONG lseek(); /* byte offset into buf */
/* */
if( isatty(fileno(sp)) ) /* are we talking to a tty? */
return(0L); /* quit now if so */
filepos = FAILURE; /* default return value */
if( sp->_flag & (_IOREAD|_IOWRT) ) /* if file is open */
{ /* */
if((filepos=lseek(fileno(sp),0L,1)) /* get where next byte read */
== FAILURE ) /* from or written to */
return((LONG)FAILURE); /* quit if bad lseek */
if( sp->_base == NULLPTR ) /* if file hasn't had i/o */
return(filepos); /* return this position */
nread = sp->_ptr - sp->_base; /* calc for # read/written */
filepos += nread; /* correct for # read/wrtn */
if( sp->_flag & _IOREAD ) /* if reading from file */
if( filepos > 0 ) /* and we've read from file*/
filepos -= nread + sp->_cnt; /* adjust file position */
/* to reflect read ahead */
if( sp->_flag & _IOASCI ) /* ascii file? **************/
{ /* count the newlines */
if( sp->_flag & _IOWRT ) /* add in newline's cr's */
{ /* */
for( bp=sp->_base; bp < sp->_ptr; bp++ ) /* */
if( *bp == '\n' ) /* count newlines in stuff */
filepos++; /* written/read so far */
} else { /* we're reading... */
if( filepos > 0 ) /* check to see we've read */
for(bp= &(sp->_ptr[sp->_cnt-1]);/* start at end of buffer */
bp >= sp->_ptr; bp-- ) /* back up to next read char*/
if( *bp == '\n' ) /* count off for newlines */
filepos--; /* */
} /* */
} /* fini ascii ***************/
} /****************************/
return(filepos); /* */
} /****************************/
*********************/
return(filepos); /* */
} /****************************/
*********************/
return(filepos); /* */
} /****************************/

View File

@@ -0,0 +1,45 @@
/**************************************************************************
*
* f w r i t e F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fwrite" writes NI items of size SZ from memory at BUFF into stream
* SP.
*
* Calling sequence:
* nitems = fwrite(buff,size,nitems,stream)
* Where:
* buff -> where to write from
* size = number bytes in each item
* nitems = number bytes written/to write
* stream -> file
*
* nitems is set to 0 if an error occurs (including EOF).
*
*****************************************************************************/
#include "stdio.h"
WORD fwrite(buff,siz,num,sp) /* CLEAR FUNCTION ***********/
REG BYTE *buff;
WORD siz,
num;
REG FILE *sp;
{
REG WORD jj, kk;
for( jj=0; jj<num; jj++ )
for( kk=0; kk<siz; kk++ )
if( fputc(*buff++,sp) == FAILURE ) /* used for side effects */
return(NULL);
return(num);
}
p) == FAILURE ) /* used for side effects */
return(NULL);
return(num);
}
p) == FAILURE ) /* used for side effects */
return(NULL);
return(num);
}

View File

@@ -0,0 +1,38 @@
/**************************************************************************
*
* g e t l F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "getl" gets an LONG (4 byte) value from the input stream.
* Note that what's written (binary) by a PDP 11 (UNIX: lo byte, hi byte)
* system will NOT be compatible with what's written by a
* 68K (NUXI: hi byte, lo byte) system.
*
* Calling sequence:
* l = getl(stream)
* Where:
* l = a 32-bit long value
* stream-> a (FILE *) input stream
*
*****************************************************************************/
#include "stdio.h"
LONG getl(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* the stream to get from */
{ /* */
LONG l; /* place to get to */
REG BYTE *p; /* make ptr to l */
/****************************/
p = (char *)&l; /* point to l */
*p++ = getc(sp); /* no way to distinguish */
*p++ = getc(sp); /* twixt EOF & -1 */
*p++ = getc(sp); /* */
*p++ = getc(sp); /* */
return(l); /* there it is */
} /****************************/
 */
} /****************************/
 */
} /****************************/

View File

@@ -0,0 +1,95 @@
/***********************************************************************
*
* g e t p a s s F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "getpass" writes a prompt to the console (NOT stdout) and accepts
* a string of 1-8 chars from the console (NOT stdin) without
* echoing the input to the terminal. Only limited CP/M line edit
* commands are available (CTL H, DEL, CTL X) on input.
*
* Calling sequence:
* pret = getpass(prompt)
* Where:
* pret -> ptr to 1-8 chars of null terminated password
* prompt -> null teminated console out msg.
*
* Modified:
* Feb 84 whf - _ttyinraw() => ttyinraw()
* Oct 83 whf - handle OS Independent Raw Input
*
**************************************************************************/
#include "portab.h"
#include "osif.h"
BYTE * getpass(prompt) /* CLEAR FUNCTION ***********/
BYTE *prompt;
{
MLOCAL BYTE ibuf[9];
_conout(prompt,strlen(prompt),CONOUT); /* same fn write uses */
_noecho(ibuf,9);
return(ibuf);
}
#define CMASK 0x7F
#define DEL 0x7F
#define CTRLX 0x18
#define CTRLC 0x03
MLOCAL _noecho(bf,ln)
REG BYTE *bf;
WORD ln;
{
REG WORD cur;
WORD ch;
WORD ttyinraw();
cur = 0;
FOREVER {
switch( ch = CMASK & ttyinraw(0)) {
case '\b':
case DEL:
if( cur>0 ) {
cur--;
bf--;
}
break;
case CTRLX:
bf -= cur;
cur = 0;
break;
case '\r':
case '\n':
*bf = NULL;
return;
case CTRLC:
exit(1);
default:
*bf++ = ch;
cur++;
if( cur+1 >= ln ) {
*bf = NULL;
return;
}
}
}
}
/****************************************************************************/
MLOCAL _conout(buffer,count,os_func) /***************************/
REG BYTE *buffer; /* -> 1st char output */
REG WORD count; /* = # bytes to xfer */
REG WORD os_func; /* OS function to use */
{ /***************************/
WORD xcount; /* save area for count */
/* */
while(count-- > 0) /* Until all written */
__OSIF(os_func,*buffer++); /* Output next character */
} /***************************/
*************************/
*************************/

View File

@@ -0,0 +1,17 @@
/* getpid - return process ID */
/* returns phony number under CP/M */
#include "portab.h"
#define PHONYPID 222
WORD getpid() /* CLEAR FUNCTION ***********/
{
return(PHONYPID);
}
() /* CLEAR FUNCTION ***********/
{
return(PHONYPID);
}
() /* CLEAR FUNCTION ***********/
{
return(PHONYPID);
}

View File

@@ -0,0 +1,36 @@
/***********************************************************************
*
* g e t s F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "gets" reads a string from the standard input, and returns
* its argument (NULL on end of file). The newline at the
* end of the string is replaced by a NULL.
*
* Calling sequence:
* addr = gets(saddr)
* Where:
* saddr -> where the string is to go (no bounds check)
* addr = saddr if all ok, NULLPTR o.w.
*
*****************************************************************************/
#include "stdio.h"
BYTE * gets(str) /* CLEAR FUNCTION ***********/
REG BYTE *str; /* string save area */
{ /****************************/
REG WORD c; /* char to test for eof */
BYTE *sav; /* sav pointer for return */
sav = str; /* remember this */
while( (c=getc(stdin)) != FAILURE && /* while everything ok */
c != '\n' ) /* and not end of line */
*str++ = c; /* store it */
*str = NULL; /* clean up string */
if( c == FAILURE ) /* if not cool */
return(NULLPTR); /* then tell them so */
return(sav); /* tell them is cool */
} /****************************/
************/
************/

View File

@@ -0,0 +1,38 @@
/**************************************************************************
*
* g e t w F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "getw" gets an WORD (2 byte) value from the input stream.
* Note that what's written (binary) by a PDP 11 (UNIX: lo byte, hi byte)
* system will NOT be compatible with what's written by a
* 68K (NUXI: hi byte, lo byte) system.
*
* Calling sequence:
* w = getw(stream)
* Where:
* w = a 16-bit word value
* stream-> a (FILE *) input stream
*
*****************************************************************************/
#include "stdio.h"
WORD getw(sp) /* CLEAR FUNCTION ***********/
REG FILE *sp; /* the stream to get from */
{ /* */
WORD w; /* place to get to */
REG BYTE *p; /* make ptr to w */
/****************************/
p = (char *)&w; /* point to w */
*p++ = getc(sp); /* no way to distinguish */
*p++ = getc(sp); /* twixt EOF & -1 */
return(w); /* there it is */
} /****************************/
 /* twixt EOF & -1 */
return(w); /* there it is */
} /****************************/
 /* twixt EOF & -1 */
return(w); /* there it is */
} /****************************/

View File

@@ -0,0 +1,27 @@
/*********************************************************************
* INDEX - returns a pointer to first occurrence of char in string.
*
* BYTE *index(s,c)
* BYTE *s, c;
*
* Returns pointer to first c in s, or zero if c not in s.
**********************************************************************/
#include <portab.h>
BYTE * index(str,ch) /* CLEAR FUNCTION ***********/
REG BYTE *str, ch;
{
for( ; ch != *str ; str++ ) /* look for c in s. */
if( *str == NULL ) /* if we get to eos, we've gone */
return(0); /* too far. */
return(str); /* found c. note that 'index' */
/* works to find NULL, (ie. */
/* eos), if c==NULL. */
}
ULL, (ie. */
/* eos), if c==NULL. */
}
ULL, (ie. */
/* eos), if c==NULL. */
}

View File

@@ -0,0 +1,58 @@
/*************************************************************************
*
* Channel Info Functions
* ----------------------
* Copyright 1982,83 by Digital Reserach Inc. All rights reserved.
*
* "isatty(fd)" == TRUE iff the file on channel fd is a 'CON:' device.
* "isdev(fd)" == TRUE iff fd is 'CON:', 'LST:', 'AUX:'
*
* Where:
* fd = file descriptor returned by 'open'
*
**************************************************************************/
#include "portab.h"
#include "osif.h"
BOOLEAN isatty(fd) /* CLEAR FUNCTION ***********/
WORD fd; /* file des returned by open*/
{ /****************************/
REG FD *fp; /* ptr to ccb */
FD *_chkc(); /* validates fd, cvt to fp */
/* */
if((fp=_chkc(fd)) == NULLFD) /* make sure its open MGL */
return(FALSE); /* isno TTY ifnot open */
return( (fp->flags & ISTTY) != 0 ); /* test this flag */
} /****************************/
BOOLEAN isdev(fd) /* CLEAR FUNCTION ***********/
WORD fd; /* file des returned by open*/
{ /****************************/
REG FD *fp; /* ptr to ccb */
FD *_chkc(); /* validates fd, cvt to fp */
/* */
if((fp=_chkc(fd)) == NULLFD) /* make sure its open MGL */
return(FALSE); /* isno TTY ifnot open */
return(fp->flags&(ISTTY|ISLPT|ISAUX)); /* test these flags */
} /****************************/
/* ttyname - find name of a terminal */
/* returns "CON:" if isatty, NULLPTR o.w., under CP/M */
EXTERN BYTE __tname[]; /* CON: String */
BYTE * ttyname(fd) /* CLEAR FUNCTION ***********/
WORD fd;
{
if( isatty(fd) )
return(__tname);
return(NULLPTR);
}
satty(fd) )
return(__tname);
return(NULLPTR);
}
satty(fd) )
return(__tname);
return(NULLPTR);
}

Binary file not shown.

View File

@@ -0,0 +1,89 @@
*// 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:
~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
ve.l -4(R14),R0 //long results
btst #,R2 //test sign flag
beq L4
neg.l R0 //complement the results
L4:
unlk R14
rts
ve.l -4(R14),R0 //long results
btst #,R2 //test sign flag
beq L4
neg.l R0 //complement the results
L4:
unlk R14
rts
ve.l -4(R14),R0 //long results
btst #

View File

@@ -0,0 +1,45 @@
.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

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

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

link R14,

View File

@@ -0,0 +1,83 @@
/***************************************************************************
*
* L s e e k F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* The lseek function changes the present position of reading
* to or writing from a file.
* The tell function returns the present position in a file.
*
* Calling sequence:
*
* ret = lseek(fd,offset,sense);
* or ret = tell(fd);
*
* 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 "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
LONG lseek(fd,offs,sense) /* CLEAR FUNCTION ***********/
/* */
WORD fd; /* Open file descriptor */
LONG offs; /* File offset */
WORD sense; /* Sense of offset */
/* */
/****************************/
{
/****************************/
REG FD *fp; /* File pointer */
EXTERN FD *_chkc(); /* fd to fp translation MGL */
EXTERN LONG _filesz(); /* computes CP/M file size */
/* */
if((fp = _chkc(fd)) == NULLFD) /* Convert to pointer */
RETERR(FAILURE,EBADF); /* 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->hiwater = _filesz(fd); /* go find the end of file */
fp->offset = fp->hiwater + offs;/* compute from end of file */
break; /* */
/****************************/
default: /* All others NFG */
RETERR(FAILURE,EINVAL); /* */
} /****************************/
fp->flags &= ~ATEOF; /* any seek clears EOF */
if( fp->offset < 0 ) /* bad seek call? */
fp->offset = -1; /* set to uniform value */
return(fp->offset); /* Return resultant offset */
} /****************************/
/****************************/
LONG tell(fd) /* CLEAR FUNCTION ***********/
WORD fd; /* this file here */
{ /* */
return(lseek(fd,0L,1)); /* is that all? */
} /****************************/
is that all? */
} /****************************/
is that all? */
} /****************************/

View File

@@ -0,0 +1,36 @@
/***************************************************************************
*
* _ l s t o u t F u n c t i o n
* -------------------------------
*
* Function "_lstout" is called to perform "write" operations to the
* list device.
*
* Calling Sequence:
* ret = _lstout(buffer,count,func);
*
* Where:
* buffer -> the output buffer (byte 0 is count)
* ret = count on return
*
****************************************************************************/
#include "portab.h"
#include "osif.h"
WORD _lstout(buffer) /***************************/
REG BYTE *buffer; /* -> 1st char output */
{ /***************************/
REG WORD count; /* = # bytes to xfer */
WORD xcount; /* save area for count */
/* */
xcount = count = (0xFF & *buffer++); /* Copy for later */
/* */
while(count-- > 0) /* Until all written */
__OSIF(LSTOUT,*buffer++); /* Output next character */
return(xcount); /* return original count */
} /***************************/
al count */
} /***************************/
al count */
} /***************************/

View File

@@ -0,0 +1,60 @@
/*****************************************************************************
*
* R U N T I M E S T A R T O F F R O U T I N E
* -----------------------------------------------
* Copyright 1982,83 by Digital Research Inc. All rights reserved.
*
* Routine "_main" is entered from the C header routine to start a C
* program. It opens STDIN, STDOUT and STDERR to the console, and
* translates the command line to lower case. Then it calls "__main()".
* There are two versions of "__main()" (one compiled for wildcards
* and the other compiled without) compiled from the source module
* "XMAIN.C".
*
* 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).
*
* Modfications:
* 11-Oct-83 whf converted to DRC from CPM68K
*
*****************************************************************************/
#include "portab.h" /* Include std definitions */
#include "osif.h" /* */
#include "ctype.h" /* */
EXTERN BYTE __tname[]; /* Name of terminal device */
EXTERN BYTE __fdecls(); /* force loading of _iob */
EXTERN BYTE ___atab(); /* force loading of ___atab */
#define STDIN 0 /* file descriptors */
#define STDOUT 1 /* */
#define STDERR 2 /* */
/* */
_main(com, len) /****************************/
BYTE *com; /* Command address */
WORD len; /* Command length */
{ /****************************/
REG BYTE *s; /* Temp byte pointer */
/****************************/
_chinit(); /* Initialize channels */
open(__tname,READ); /* Open STDIN */
open(__tname,WRITE); /* Open STDOUT */
open(__tname,WRITE); /* Open STDERR */
com[len] = NULL; /* Insure null at line end */
for (s = com; *s; s++) /* Convert string to */
*s = tolower(*s); /* lower case */
__main(com,len); /* Do rest (replaceable) */
} /****************************/
in(com,len); /* Do rest (replaceable) */
} /****************************/
in(com,len); /* Do rest (replaceable) */
} /****************************/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
/********************************************************************
* malloc, free - memory allocator mechanism
*
* 9/83: fixed free bug, added check word whf
* 10/83: added debugging features: DEBUGMEM and MALLOCND hooks whf
*
* BYTE *malloc(numbytes)
* WORD numbytes
* Returns a pointer to an area of memory at least 'numbytes'
* in length. Returns NULLPTR if out of memory or corrupted freelist.
* Warning: the size of the area is right below the region:
* do not overwrite!
*
*
* WORD free(mptr)
* BYTE *mptr
* Frees the region pointed to by 'mptr'. Returns 0 (SUCCESS) if ok,
* FAILURE (-1) if corrupted freelist (or if mptr was not previously
* allocated by malloc).
*
*
* BYTE *realloc(mptr,numbytes)
* BYTE *mptr
* WORD numbytes
* Returns a pointer to a (probably different) region of memory
* (numbytes long) containing the same data as the old region
* pointed to by mptr. Returns NULLPTR if not enough memory, or
* if freelist was corrupted.
*
************************************************************************/
#include "portab.h"
/************************* #include "malloc.h" *****************************/
#define FB_HDR struct hdr /* free block header type */
#define NULLFBH ((FB_HDR *)0) /* Null of above struct */
/* */
FB_HDR { /* mem_block header */
struct hdr *ptr; /* ptr next blk (when freed)*/
UWORD size; /* block size (always) */
UWORD chksize; /* 1's complement of size */
}; /****************************/
/* */
FB_HDR _afreebase = {&_afreebase,0,~0 }; /* initial (empty) block */
FB_HDR *_aflistptr = &_afreebase; /* ptr into ring of freeblks*/
/* */
#define AOFFS 1L /* alignment offset: 0=byte, 1=word, 3=quad */
#define AMASK(c) ((char *)((long)(c) & ~AOFFS)) /* mask alignment bits */
#define AFUDGE 4 /* leeway for passing block as is */
#define ACHUNKS 64 /* chunks to alloc from O.S.*/
/* */
#define ERR_FINDBLOCK 1 /* error in 'findblock()' */
#define ERR_GETMEM 2 /* error in 'getmemory()' */
#define ERR_FREE 3 /* error in 'free()' */
/* */
/*** end of "malloc.h" ******/
/****************************************************************************/
/* malloc - general purpose memory allocator
* This function allocates the requested number of bytes (nbytes) and returns
* a pointer to this space to the calling function.
* The memory is requested from the O.S. in larger chunks, and
* free space is managed as a ring of free blocks. Each block
* contains a pointer to the next block (s.ptr), a block size (s.size),
* a check word (1's complement of size), and the space itself.
* Alignment is handled by assuming that sizeof(FB_HDR) is an aligned
* quantity, and allocating in multiples of that size.
************************************************** */
BYTE * malloc(nbytes) /* CLEAR FUNCTION ***********/
UWORD nbytes; /* number bytes requested */
{ /****************************/
REG UWORD nmults; /* multiples of FB_HDR size */
REG FB_HDR *pp; /* temporary ptr */
FB_HDR *findblock(); /* find free block */
BYTE *cutup(); /* cut free block to fit */
/* */
nmults = (nbytes+sizeof(FB_HDR)-1)/sizeof(FB_HDR)+1; /* */
if( (pp=findblock(nmults)) == NULLFBH ) /* find ptr to ptr to block */
return NULLPTR; /* no luck... */
return cutup(pp,nmults); /* cut block to fit & return*/
} /****************************/
/****************************************************************************/
/* findblock - local subr to find a free block that's big enough. */
/* It returns a pointer to the freeblock BEFORE the desired freeblock, */
/* in order to fix the pointer of the this freeblock. */
/************************************************* */
MLOCAL FB_HDR * /* */
findblock(units) /* find a free block */
UWORD units; /* at least this big */
{ /****************************/
REG FB_HDR *cp; /* ptr to current block */
REG FB_HDR *pp; /* ptr to previous block */
FB_HDR *getmemory(); /* get from OS, add to list */
/* */
pp = _aflistptr; /* start search here */
cp = pp->ptr; /* init current ptr */
while(1) /* do forever */
{ /* */
if(~(cp->size^cp->chksize)) /* does cp pt to valid blk? */
{ /* no... */
_errmalloc(ERR_FINDBLOCK); /* handle this error */
return NULLFBH; /* */
} /* */
if( cp->size >= units ) /* is this block big enough?*/
return pp; /* yes! NOTE: return prevptr*/
if( cp == _aflistptr ) /* end of list? */
if( (cp=getmemory(units)) == NULLFBH ) /* is there more? */
{ /* */
_errmalloc(ERR_GETMEM); /* */
return NULLFBH; /* no more memory... */
} /* */
pp = cp; /* */
cp = cp->ptr; /* move on down the list */
} /* */
} /****************************/
/****************************************************************************/
/* cutup - a local fn to cut up the free block (if its much bigger than the */
/* number of units requested), and to convert blk ptr to byte ptr. */
/************************************************* */
MLOCAL BYTE * /* */
cutup(pp,units) /* cut the block to fit */
FB_HDR *pp; /* ptr to ptr to block */
UWORD units; /* num units to cut to */
{ /****************************/
REG FB_HDR *cp; /* cur ptr */
REG FB_HDR *np; /* new ptr (if needed) */
/* */
cp = pp->ptr; /* get ptr to big block */
if( cp->size <= units+AFUDGE ) /* is size close enough? */
pp->ptr = cp->ptr; /* yes: cut cp from list */
else { /* o.w. cut block up */
np = cp + units; /* where it starts */
np->size = cp->size - units; /* how big it is */
np->chksize = ~np->size; /* it's a valid blk */
np->ptr = cp->ptr; /* it's linked into freelist*/
pp->ptr = np; /* from both sides */
cp->size = units; /* new size for cur block */
cp->chksize = ~cp->size; /* and make valid */
} /****************************/
_aflistptr = pp; /* search from here next tim*/
return cp+1; /* point to after header */
} /****************************/
/****************************************************************************/
/* getmemory - gets memory from O.S. */
/* This function requests memory from the O.S. in multiples (ACHUNKS) */
/* of the requested number of units (numu), in order to minimize */
/* the number of calls to the O.S. */
/* Function cleans up pointer alignment and adds to free list. */
/************************************************* */
MLOCAL FB_HDR *
getmemory(numu)
UWORD numu; /* number of units */
{
BYTE *sbrk(); /* obtain memory from O.S. */
REG BYTE *mmp; /* more memory pointer */
REG FB_HDR *fbp; /* free block pointer */
REG WORD utg; /* units to get */
utg = ((numu+(ACHUNKS-1)) / ACHUNKS) * ACHUNKS;
mmp = sbrk(utg * sizeof(FB_HDR)); /* sbrk wants number of bytes */
if( mmp == (char *)-1 ) /* sbrk = -1 means no memory available */
return( NULLFBH );
mmp = AMASK(mmp + AOFFS); /* alignment handling: nop if good sbrk */
fbp = (FB_HDR *)mmp;
fbp->size = utg;
fbp->chksize = ~fbp->size;
free( (BYTE *)(fbp+1) ); /* add to free list */
return(_aflistptr); /* set in 'free' */
}
/****************************************************************************/
/* free - adds memory back to free block list.
* This function assumes freed memory pointer (fmp) points to free space
* preceeded by a FB_HDR structure.
* Note that free block is inserted in memory address order,
* to facilitate compaction.
* Fails (-1 return) if you link in a random ptr.
************************************************* */
WORD free(fmp) /* CLEAR FUNCTION ***********/
BYTE *fmp; /* freed memory ptr */
{ /****************************/
REG FB_HDR *cp, /* current freeblk ptr */
*pp; /* previous freeblk ptr */
/****************************/
cp = (FB_HDR *)fmp - 1; /* ptr to (hdr of) freed blk*/
if(~(cp->size^cp->chksize)) /* is blk valid? */
{ /* */
_errmalloc(ERR_FREE); /* */
return FAILURE; /* no: fail... */
} /****************************/
for( pp=_aflistptr; ; pp=pp->ptr ) /* start through the list */
{ /* */
if( cp >= pp && cp < pp->ptr ) /* are we at correct place? */
break; /* yes... */
if( pp >= pp->ptr && /* at end of list? and */
(cp <= pp->ptr || cp >= pp) ) /* blk is off either end? */
break; /* yes... */
} /****************************/
if( cp>=pp && cp+cp->size <= pp+pp->size )/* block already freed? */
{ /* */
_aflistptr = pp; /* search from here next */
return SUCCESS; /* and do no more */
} /****************************/
/************************************************* */
/* Insert freed block back into list. Try to coalesce (merge) adjacent */
/* regions. */
/************************************************* */
if( cp+cp->size == pp->ptr ) /* end freed blk==start nxt?*/
{ /* then merge with nxt */
cp->size += pp->ptr->size; /* */
cp->chksize = ~cp->size; /* */
cp->ptr = pp->ptr->ptr; /* */
} else /***** */
cp->ptr = pp->ptr; /* else just point to nxt */
/****************************/
if( pp+pp->size == cp ) /* end prev plk==start cur? */
{ /* then merge with prev*/
pp->size += cp->size; /* */
pp->chksize = ~pp->size; /* */
pp->ptr = cp->ptr; /* */
} else /***** */
pp->ptr = cp; /* else point prev to cur */
/****************************/
_aflistptr = pp; /* search from here next time*/
return SUCCESS; /* say its ok */
} /****************************/
/****************************************************************************/
/* realloc - free memory, allocate again (with changed size maybe), */
/* preserve contents. */
/************************************************* */
BYTE * realloc(ptr,siz) /* CLEAR FUNCTION ***********/
REG BYTE *ptr; /* ptr to (prev malloc'd)mem*/
UWORD siz; /* size of mem */
{ /****************************/
REG BYTE *np; /* ptr to new allocation */
REG UWORD nmults; /* multiples if FB_HDR size */
FB_HDR *pp, *findblock(); /* find free block */
BYTE *cutup(); /* cut free block to fit */
/* */
free(ptr); /* stuff back into free list: any coalesce will not */
/* affect original data region */
nmults = (siz+sizeof(FB_HDR)-1)/sizeof(FB_HDR)+1; /* */
if( (pp=findblock(nmults)) == NULLFBH ) /* find ptr to ptr to block */
return NULLPTR; /* no luck... */
np = (pp->ptr)+1; /* convert to BYTE ptr */
if( ptr != np ) { /* if ptr changed */
if( np < ptr ) /* if new ptr in lower mem */
for( ; siz; siz-- ) /* copy up */
*np++ = *ptr++; /* */
else /* if new ptr in higher mem */
for( np+=siz, ptr+=siz; siz; siz-- ) /* copy down */
*--np = *--ptr; /* */
} /****************************/
return cutup(pp,nmults); /* cut block to fit & return*/
} /****************************/
************************/
************************/

View File

@@ -0,0 +1,80 @@
/************************************************************************
* _errmalloc / MALLOCDB.C : prints error messages for malloc()
* To be included in OPTION?.lib
*
* 10/83 whf
************************************************************************/
#include <portab.h>
/************************* #include "malloc.h" *****************************/
#define FB_HDR struct hdr /* free block header type */
/* */
FB_HDR { /* mem_block header */
struct hdr *ptr; /* ptr next blk (when freed)*/
UWORD size; /* block size (always) */
UWORD chksize; /* 1's complement of size */
}; /****************************/
/* */
EXTERN FB_HDR _afreebase; /* initial (empty) block */
EXTERN FB_HDR *_aflistptr; /* ptr into ring of freeblks*/
/* */
#define AOFFS 1L /* alignment offset: 0=byte, 1=word, 3=quad */
#define AMASK(c) ((char *)((long)(c) & ~AOFFS)) /* mask alignment bits */
#define AFUDGE 4 /* leeway for passing block as is */
#define ACHUNKS 64 /* chunks to alloc from O.S.*/
/* */
#define ERR_FINDBLOCK 1 /* error in 'findblock()' */
#define ERR_GETMEM 2 /* error in 'getmemory()' */
#define ERR_FREE 3 /* error in 'free()' */
/* */
/*** end of "malloc.h" ******/
/****************************************************************************/
_errmalloc(etype)
int etype; /* type of error */
{
switch(etype)
{
case ERR_FINDBLOCK:
printf("malloc() error: corrupt arena\n");
break;
case ERR_GETMEM:
printf("malloc() error: out of memory\n");
break;
case ERR_FREE:
printf("free() error: pointer was not from malloc()\n");
break;
}
exit(1);
}
/****************************************************************************/
/* malloc_debug(): checks the free list to see if everything is ok. */
/************************************************* */
WORD malloc_debug() /* */
{ /****************************/
REG FB_HDR *cp; /* ptr to current block */
/* */
cp = _aflistptr; /* start search here */
while(1) /* do forever */
{ /* */
if(~(cp->size^cp->chksize)) /* does cp pt to valid blk? */
{ /* no... */
_errmalloc(ERR_FINDBLOCK); /* handle this error */
return FAILURE; /* */
} /* */
cp = cp->ptr; /* move on down the list */
if( cp == _aflistptr ) /* end of list? */
return SUCCESS; /* */
} /* */
} /****************************/
f list? */
return SUCCESS; /* */
} /* */
} /****************************/
f list? */
return SUCCESS; /* */
} /* */

View File

@@ -0,0 +1,20 @@
/****************************************************************************
* _errmalloc / MALLOCND.C : stubroutine for malloc() error handler
* Let the user program handle it.
*
* 10/83 whf
*****************************************************************************/
malloc_debug() {} /* stubroutine tag */
_errmalloc() {}
*********************/
malloc_debug() {} /* stubroutine tag */
_errmalloc() {}
*********************/
malloc_debug() {} /* stubroutine tag */

View File

@@ -0,0 +1,46 @@
/***********************************************************************
*
* m k t e m p F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "mktemp" assumes it is called with a string ending in 6 X's.
* It will replace the last 6 chars with the process id
* and a letter (different on each invocation).
* REALLY "mktemp" replaces everything after the 1st x...
* this is a feature...
* Note that the process id does not change under CP/M,
* therefore the name itself will not be very unique...
*
* Calling sequence:
* string = mktemp(string)
* Where:
*
* string -> null terminated string with 6 x's
*
*************************************************************************/
#include "portab.h"
MLOCAL BYTE _mktchar = { 'A' };
BYTE * mktemp(template) /* CLEAR FUNCTION ***********/
REG BYTE *template;
{
REG BYTE *ss;
for( ss=template; *ss != 'x' && *ss != 'X'; ss++)
if(*ss == NULL)
return(template); /* resign */
if( _mktchar < 'A' || _mktchar >'Z' )
_mktchar = 'A';
sprintf(ss,"X%04.4d%c",getpid(),_mktchar);
_mktchar++;
return(template);
}
char++;
return(template);
}
char++;
return(template);
}

View File

@@ -0,0 +1,14 @@
/* NOASCII: pulls out as much ASCII disk i/o as possible. */
noascii() { ; } /* stubroutine 'tag' */
char * __noascii_io_msg = "ascii disk i/o rtns";
_rdasc() { _optoff(__noascii_io_msg); }
_wrtasc() { _optoff(__noascii_io_msg); }



View File

@@ -0,0 +1,18 @@
/* NOBINARY: pulls out as much BINARY disk i/o as possible. */
nobinary() { ; } /* stubroutine 'tag' */
char * __nobinary_io_msg = "binary disk i/o rtns";
_rdbin() { _optoff(__nobinary_io_msg); }
_wrtbin() { _optoff(__nobinary_io_msg); }
 }
 }

View File

@@ -0,0 +1,22 @@
/* NODISK: pulls out as much disk i/o as possible. */
nodisk() { ; } /* stubroutine 'tag' */
char * __nodisk_io_msg = "disk i/o rtns";
_rdasc() { _optoff(__nodisk_io_msg); }
_rdbin() { _optoff(__nodisk_io_msg); }
_wrtasc() { _optoff(__nodisk_io_msg); }
_wrtbin() { _optoff(__nodisk_io_msg); }
_nodisk_io_msg); }
_wrtbin() { _optoff(__nodisk_io_msg); }
_nodisk_io_msg); }
_wrtbin() { _optoff(__nodisk_io_msg); }

View File

@@ -0,0 +1,16 @@
/* NOFILESZ: eliminates routine to calculate filesize (used in lseek()) */
nofilesz() { ; } /* stubroutine 'tag' */
int _filesz() { return 32767; }

int _filesz() { return 32767; }

int _filesz() { return 32767; }

Binary file not shown.

View File

@@ -0,0 +1,17 @@
/* NOLONG: provides 'stubroutines' to satisfy long int conversion
library references from 'printf' et al.
*/
nolong() { ; } /* stubroutine 'tag' */
char * __nolong_msg = "long int conversion";
__prtld(){ _optoff(__nolong_msg); }} /* stubroutine 'tag' */
char * __nolong_msg = "long int conversion";
__prtld(){ _optoff(__nolong_msg); }} /* stubroutine 'tag' */
char * __nolong_msg = "long int conversion";
__prtld(){ _optoff(__nolong_msg); }

View File

@@ -0,0 +1,22 @@
/* NOSTART.C - provides a routine to prevent the linkage of the */
/* 'normal' RTL startup routine, '_main()'. */
/* When this module is linked in, there will be no redirected */
/* i/o, the command line will not be parsed into argc/argv, standard */
/* i/o channels will not be opened, and files will not be closed */
/* automatically on termination. */
/* NOTE: 'argc/argv' is replaced by 'cmd/len', where cmd -> command tail */
/* and len is the length of this string. */
nostart() { ; } /* stubroutine tag */
_main(cmd,len) /* stubroutine for starup '_main()' */
char *cmd; /* ptr to CP/M command tail */
int len; /* length of CP/M command tail */
{
_exit(main(cmd,len)); /* call the main program */
}
ll the main program */
}
ll the main program */

View File

@@ -0,0 +1,67 @@
/* NOTTYIN: eliminates console input functions from read(). */
nottyin() { ; } /* stubroutine 'tag' */
static char * __nottyin_msg = "tty input";
_ttyin() { _optoff(__nottyin_msg); }
only 9 files instead of 16
* chkc.c - (to be consistent with chinit()
* doprt.c - stripped down, does not support longs & floats
* _ttyin.c - dummy routine
* _filesz - dummy rtn
*
* (last mod 12/21/83 WHF )
*/
/*****************************************************************************
*
* C C B I N I T I A L I Z A T I O N
* -----------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* Routine "_chinit" is called from the run-time initialization to clear
* out all the CCB storage.
* Calling sequence:
* _chinit();
*
* Routine "__chinit(fd)" is called from other low-level routines
* for single channel initialization.
* Calling sequence:
* __chinit(fd)
* where: fd = file descriptor #
*
*****************************************************************************/
#include <portab.h> /* Include std definitions */
#include <cpm.h> /* Include CP/M definitions */
#define MAXCCBS 9
FD _fds[MAXCCBS]; /* Allocate CCB storage */
_chinit() /****************************/
{ /* */
REG WORD i; /* Index */
for(i=0;i<MAXCCBS;i++) /* For all channels */
__chinit(i); /* Init fds(i); */
} /****************************/
/*****************************************************************************
* The __chinit routine initializes only 1 channel.
*****************************************************************************/
__chinit(i)
{ /****************************/
REG FD *ch; /* -> CCB */
REG BYTE *p; /* Byte pointer temporary */
ch = _getccb(i); /* convert fd to CCB */
ch -> chan = i; /* Load channel byte */
ch -> flags = 0; /* clear flag word */
* convert fd to CCB */
ch -> chan = i; /* Load channel byte */
ch -> flags = 0; /* clear flag word */
* convert fd to CCB */
ch -> chan = i; /* Load channel byte */
ch -> flags = 0; /* clear flag word */

View File

@@ -0,0 +1,95 @@
/****************************************************************************
*
* C F I L E O P E N R O U T I N E
* -------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* The "open" routine opens a "C" file and returns a file id.
* Comes in 3 flavors, one for ascii, one for binary, and the default
* (currently to ascii).
*
* Calling Sequence:
* fid = open(fname,mode)
* fid = opena(fname,mode)
* fid = openb(fname,mode)
* 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 "portab.h" /* */
#include "osif.h" /* */
#include "osiferr.h" /* */
#include "errno.h" /* */
EXTERN BYTE __tname[]; /* -> Terminal name */
EXTERN BYTE __lname[]; /* -> List device name */
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 FD *ch; /* -> CCB for channel */
/* */
if((ich = _allocc()) == FAILURE) /* Allocate a channel */
return(FAILURE); /* Can't: EMFILE */
/* */
__chinit(ich); /* Clear out channel's ccb */
ch = _getccb(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 */
{ /* */
_freec(ich); /* deallocate channel */
RETERR(FAILURE,ENOENT); /* If return <> 0, NFG. */
} /****************************/
/* Else: */
ch -> flags |= OPENED; /* Set OPEN bit */
lseek(ch->chan, 0L, 2); /* Kludge to set */
lseek(ch->chan, 0L, 0); /* hi water mark */
return(ich); /* Return Channel # */
} /****************************/
WORD open(fname,mode) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD mode;
{ return(_open(fname,mode,0)); } /* default to ascii */
WORD opena(fname,mode) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD mode;
{ return(_open(fname,mode,0)); } /* open ascii file */
WORD openb(fname,mode) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD mode;
{ return(_open(fname,mode,1)); } /* open binary file */
de) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD mode;
{ return(_open(fname,mode,1)); } /* open binary file */
de) /* CLEAR FUNCTION ***********/
BYTE *fname; WORD mode;
{ return(_open(fname,mode,1)); } /* open binary file */

View File

@@ -0,0 +1,148 @@
/***************************************************************************
*
* O P T I O N H e a d e r F i l e
* -----------------------------------
* Copyright 1983 by Digital Research Inc.
*
* Date: 1/5/84
*
* The CLEAR*.L86 libraries provide a large number of functions which
* are not needed by every program, but which must be linked into the program
* because their usage is data driven. One example is the floating point
* conversion routines in the "printf()" function. The programmer can specify
* "%f", "%g" or "%e" conversions which the linker can not detect. If the
* program never needs or uses these conversions, the code in the "printf()"
* routine will never be used. The "option.h" module gives the programmer
* a mechanism of communicating to the linker that certain low level functions
* are optional (not used by the program), and can be left out to save space
* in the program load image (.CMD file).
*
* "option.h" provides a set of definitions which allow the programmer
* to specify certain options of the CLEAR* Run Time libraries (CLEARS.L86 or
* CLEARL.L86) which the program does not use. The programmer can
* choose broad sets of options (i.e. "MINIMAL"), or can choose specific
* options to stub out of the final program (i.e. "NOFLOAT").
*
* Each definition contains a "tag declaration". The tag declaration
* will link in a module from the OPTION*.L86 (OPTIONS.L86 or OPTIONL.L86)
* library which also contains a "stubroutine" for some internal
* function of the CLEAR* Run Time Library.
*
* For example, the definition of NOFLOAT is "int nofloat();". When
* the programmer specifies "NOFLOAT" in the source file and then links the
* final program with the OPTION* library, the linker links in the module from
* the OPTION* library which contains "nofloat()". This module also contains
* certain stubroutines which satisfy functional references to the floating
* point conversion routines in "printf()". Thus, the code for these
* conversions will not be linked into the final program load image. If
* the program happens to use the "%f", "%g" or "%e" printf() conversions,
* the stubroutines provided will print an error message and exit.
*
* We recommend that the programmer compile a separate module containing
* the tag definitions, and then link this module and the OPTION* library
* along with the rest of the program. For example, to reduce the size of
* the "hello.c" program load image, the programmer could prepare a file
* (named "opt.c" in this example) that looks like:
* opt.c:
* #include "option.h"
* MINIMAL
* Then, after compiling hello.c and opt.c, the link command should look like:
* LINK86 HELLO,OPT,OPTIONS.L86[SEARCH
* Note that the "[SEARCH]" option is very important, since LINK86 will pull
* in all routines in OPTIONS.L86 if you do not use this option.
*
*
* Specific options are documented below.
*
****************************************************************************/
/*************
* NOFLOAT: link out floating point conversion routines in "printf()",
* "fprintf()", and "sprintf()".
**************/
#define NOFLOAT int nofloat();
/*************
* NOLONG: link out long integer conversion routines in "printf()",
* "fprintf()", and "sprintf()".
* Saves: CPM small 3200, big 3500
**************/
#define NOLONG int nolong();
/*************
* NOTTYIN: eliminates the functions to "read()" from the console.
* Watch out when you use STDIN on reads.
* Saves: CPM small 300, big 350
*************/
#define NOTTYIN int nottyin();
/*************
* NOWILDCARDS: eliminates wildcard expansion on command line.
* Saves: CPM small 500, big 650
*************/
#define NOWILDCARDS int nowildcards();
/*************************************************************************
* DISK I/O Options
*************************************************************************/
/*************
* MAXFILES5: reduces the maximum number of open files allowed from 16 to 5.
* Note: this includes console files.
* Saves: CPM small 1950, big 1950
*************/
#define MAXFILES5 int maxfiles5();
/*************
* NOFILESZ: eliminates the functions to calculate the size of a file.
* Watch out when you append 'fopen(name,"a")' or use 'lseek(fd,xx,2)'.
* Saves: CPM small 550, big 800
*************/
#define NOFILESZ int nofilesz();
/*************
* NOBINARY: eliminates BINARY low level Disk I/O subroutines.
* Watch out when you do binary file i/o: openb(), creatb(),
* fopenb(), freopb().
* Saves: CPM small 2200, big 2900
*************/
#define NOBINARY int nobinary();
/*************
* NOASCII: eliminates ASCII low level Disk I/O subroutines.
* Watch out when you redirect output to a file, or do any ascii file i/o:
* open(), opena(), creat(), creatb(), fopen(), fopena(), freopen().
* Saves: CPM small 1100, big 1500
*************/
#define NOASCII int noascii();
/*************
* MINIMAL: tags to make "hello.c" as small as possible.
*************/
#define MINIMAL NOFLOAT NOTTYIN NOFILESZ MAXFILES5 NOWILDCARDS \
NOASCII NOBINARY
/*************
* NOSTARTUP: links out all of the CLEAR initialization routines, including
* command line redirection (">", "<", and ">>" command line ops) and
* wildcard expansion. Also leaves out opening STDIN, STDOUT, and STDERR.
* Warning: this could have peculiar side effects, and should be used only
* by experienced programmers.
**************/
#define NOSTARTUP int nostartup();
programmers.
**************/
#define NOSTARTUP int nostartup();
programmers.
**************/
#define NOSTARTUP int nostartup();

View File

@@ -0,0 +1,23 @@
/* OPTOFF.C: prints a message in case someone tries to use a part of the */
/* RTL which was OPTIONally linked out. */
#include "portab.h"
#include "osif.h"
_optoff(msg)
BYTE *msg;
{
BYTE buf[200]; /* ought to be big enough */
strcpy(buf,"C RTL - program not linked for ");
strcat(buf,msg);
strcat(buf,"\r\nProgram terminating\r\n$");
__OSIF(C_WRITESTR,buf);
_exit(FAILURE);
}
TESTR,buf);
_exit(FAILURE);
}
TESTR,buf);
_exit(FAILURE);
}

View File

@@ -0,0 +1,107 @@
/****************************************************************************
* OSATTR.C - sets "os_abilities" word, depending on which OS we are running.
*
* Last modified:
* 2/28/84 whf - add os_interrupts
* 1/25/84 whf - handle 68K linker problem
* 1/4/83 whf & rsw - add CPMZ8KV11
* 12/29/83 whf - add os_truncates
* 11/4/83 whf - handle CCPM3.1 and networking
*****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#define OSATTR
#include "osattr.h"
unsigned short os_abilities = 0;
unsigned short os_version = 0;
WORD osattr()
{
#if CPM /*================================================================*/
/* */
__OSIF(S_BDOSVER,0); /* What OS are we running? */
os_version = __cpmrv; /* Use AX, not AL ret by OSIF*/
/* */
switch( os_version ) /* What kind of OS? */
{ /* */
case CCPM86V10: /* CCP/M-86 PC v1.0 */
case MPM86V21: /* MP/M-86 v2.0, v2.1 */
os_abilities |= _os_multitasking|_os_oldmultisec|_os_f_parse|
_os_filesharing|_os_datetime|_os_interrupts;
break; /* */
/****************************/
case CCPM86V20: /* CCP/M-86 v2.0 */
__OSIF(S_OSVER,0); /* Get the truth */
switch(__cpmrv) /* Which OS really? */
{ /* */
case CPM86V31: /* Fooled by the network! */
os_abilities |= _os_fastconio; /* plus all of this: */
case CPM86V11: /* Fooled by the network! */
/* Network will emulate these*/
os_abilities |= _os_newmultisec|_os_f_parse|
_os_filesharing|_os_datetime|_os_loadtime;
break; /* */
/****** */
case 0x1431: /* Fooled! CCP/M-86 v3.1 */
os_abilities |= _os_swaps8087; /* 8087 support? */
/* plus all the rest: */
case 0x1420: /* Definitely CCP/M-86 v2.0 */
default: /* Maybe CCP/M-86 v2.0 */
os_abilities |= _os_multitasking|_os_newmultisec|_os_f_parse|
_os_filesharing|_os_datetime|_os_loadtime|
_os_truncates|_os_fastconio|_os_interrupts;
} /* */
net_check(); /* is there a network? */
break; /****************************/
case CPM86V31: /* CP/M-86 Plus */
os_abilities |= _os_multitasking|_os_newmultisec|_os_f_parse|
_os_truncates|_os_datetime|_os_fastconio|_os_interrupts;
break; /* */
/* case 0x0014: /* CP/M-80 v1.4 */
/* case 0x0022: /* CP/M-80 v2.2 */
/* case 0x0031: /* CP/M-80 Plus */
/* case 0x0122: /* MP/M-80 v1.1 */
/* case 0x0130: /* MP/M-80 v2.0, v2.1 */
default: /* */
case CPM86V11: /* CP/M-86 v1.0, v1.1 */
case CPM68KV11: /* CP/M-68K v1.1 */
case CPMZ8KV11: /* CP/M-Z8000 v1.1 */
break; /* no attributes... */
} /****************************/
#endif /*=================================================================*/
#if PCDOS /*================================================================*/
#endif /*=================================================================*/
}
#if CPM /*=================================================================*/
net_check() /****************************/
{ /* */
__OSIF(N_NETSTAT,0); /* Is net installed? */
if( __cpmrv != 0xFFFF && __cpmrv != 0 ) /* non bogus return? */
{ /* */
os_abilities|=_os_netinstalled; /* Yes, there's a net */
return SUCCESS; /* If called by someone else*/
} else return FAILURE; /* */
} /****************************/
#endif /*=================================================================*/
***************************/
#endif /*=================================================================*/
***************************/
#endif /*=================================================================*/

View File

@@ -0,0 +1,78 @@
/****************************************************************************
* OSATTR.H - include file to define abilities of the O.S. the program is
* executing on.
*
* Last modified:
* 2/28/84 whf add 'os_interrupts'
* 1/24/84 whf handle link problem on 68K
* 1/5/84 whf & rsw add CPMZ8KV11
* 12/29/83 whf add os_truncates
* 11/4/83 whf handle CCPM 3.1 & networking
****************************************************************************/
#ifndef OSATTR
extern unsigned short os_version; /* A contrived version num */
extern unsigned short os_abilities; /* Flags indicating abilitys*/
#endif
/*****************************************************************************
* OS Ability Bits definitions
*****************************************************************************/
#define _os_multitasking 0x0001 /* multi tasking OS */
#define _os_netinstalled 0x0002 /* Net installed locally? */
#define _os_interrupts 0x0004 /* O.S. supports CTRL C? */
#define _os_0x0008 0x0008
#define _os_is8087 0x0010 /* Machine has real 8087 */
#define _os_oldmultisec 0x0020 /* does 3.0 multi-sector i/o*/
#define _os_newmultisec 0x0040 /* does 3.1 multi-sector i/o*/
#define _os_multisectorio 0x0060 /* does multi-sector i/o */
#define _os_truncates 0x0080 /* truncate file func */
/* capabilities for OSATTR.C documentation (not used in RTL): */
#define _os_f_parse 0x0000 /* F_PARSE func available? */
#define _os_filesharing 0x0000 /* BDOS File Sharing funcs? */
#define _os_loadtime 0x0000 /* OS supports load time fix*/
#define _os_swaps8087 0x0000 /* OS swaps 8087 registers? */
#define _os_fastconio 0x0000 /* CPM+ fast Con I/O funcs */
#define _os_datetime 0x0000 /* OS keeps system time */
/****************************************************************************
* OS Ability Test Macros
****************************************************************************/
#define os_multitasking (os_abilities & _os_multitasking)
#define os_netinstalled (os_abilities & _os_netinstalled)
#define os_interrupts (os_abilities & _os_interrupts)
#define os_datetime (os_abilities & _os_datetime)
#define os_fastconio (os_abilities & _os_fastconio)
#define os_is8087 (os_abilities & _os_is8087)
#define os_multisectorio (os_abilities & _os_multisectorio)
#define os_oldmultisec (os_abilities & _os_oldmultisec)
#define os_newmultisec (os_abilities & _os_newmultisec)
#define os_truncates (os_abilities & _os_truncates)
#define os_f_parse (os_abilities & _os_f_parse)
#define os_filesharing (os_abilities & _os_filesharing)
#define os_loadtime (os_abilities & _os_loadtime)
#define os_swaps8087 (os_abilities & _os_swaps8087)
/****************************************************************************
* OS (Func 12) version numbers
*****************************************************************************/
#define CPM86V11 0x1022 /* CP/M-86 v1.0, v1.1 */
#define CPM68KV11 0x2022 /* CP/M-68K v1.1 */
#define CCPM86V10 0x1430 /* CCP/M-86 PC v1.0 */
#define CCPM86V20 0x1431 /* CCP/M-86 v2.0 */
#define MPM86V21 0x1130 /* MP/M-86 v2.0, v2.1 */
#define CPM86V31 0x1031 /* CP/M-86 Plus */
#define CPMZ8KV11 0x3022 /* CP/M-Z8000 v1.1 */
/* end of osattr.h ********************************************************/
 */
/* end of osattr.h ********************************************************/
 */
/* end of osattr.h ********************************************************/

View File

@@ -0,0 +1,269 @@
/***************************************************************************
*
* O S I F . H
* -----------
* Copyright 1982,1983 by Digital Research Inc. All rights reserved.
*
* Edits:
* 7-Mar-84 sw Fix for 68K
* 28-Feb-84 whf Add C_STAT for ttyinraw()
* 5-Jan-84 whf Moved MAXCCBS to channel.c
* 29-Dec-83 whf Added F_TRUNC for tclose()
* 12-Dec-83 whf Change from "CPM.H" to "OSIF.H"
* 9-Dec-83 whf Handle PCDOS differences
* 3-Nov-83 whf Add multi-sector i/o
* 19-Oct-83 whf Add QUEUE handling info
* 6-Oct-83 whf Redefine reserved area in fcb for parsefn() return
* 25-June-83 sw Add user number to file "fd" structure.
*
* This file contains O.S. specific definitions for the
* DRI CLEAR/C Run Time Library.
* This file is intended only for inclusion with those functions
* dealing directly with the O.S. interface, as well as any function
* which has hardware dependent code (byte storage order, for
* instance).
*
****************************************************************************/
/*
* "machine.h": to determine what kind of machine you want to run on.
*/
#ifdef pcdos
#define PCDOS 1 /* IBM PC DOS */
#define CPM 0 /* CP/M version 2.2 */
#else /* assume CP/M: */
#define CPM 1 /* CP/M version 2.2 */
#define PCDOS 0 /* IBM PC DOS */
#endif
#define I8086 0 /* Intel 8086/8088 */
#define DRC 0 /* Digital Research C Compiler */
/**** Unused DEFINEs: ****/
/* #ifdef UNdefined */
/*** Processor ***/
#define MC68000 1 /* Motorola 68000 */
#define VAX 0 /* DEC VAX */
#define PDP11 0 /* DEC PDP-11 */
#define Z8000 0 /* Zilog Z8000 */
/*** Operating System ***/
#define CPM68K 1 /* CP/M 68000 ver 2.2 */
#define CCPM 0 /* Concurrent (multi-tasking) */
#define CPM3 0 /* CP/M version 3.x (Concurrent & Plus) */
#define CPM4 0 /* CP/M version 4.x (Portable Concurrent) */
#define UNIX 0 /* UNIX */
#define VMS 0 /* DEC VMS */
/*** Compiler ***/
#define ALCYON 1 /* Alcyon C Compiler */
/* #endif */
/************************/
/****************************************************************************
* CP/M FCB definition
****************************************************************************/
#if CPM /****************************/
struct fcbtab /****************************/
{ /* */
BYTE drive; /* Disk drive field [0] */
BYTE fname[8]; /* File name [1-8] */
BYTE ftype[3]; /* File type [9-11] */
BYTE extent; /* Current extent number[12]*/
BYTE s1,s2; /* "system reserved" [13-14]*/
BYTE reccnt; /* Record counter [15] */
BYTE fpasswd[8]; /* Parsefn passwd area[16-23]*/
BYTE fuser; /* Parsefn user# area [24] */
BYTE resvd[7]; /* More "system reserved" */
LONG record; /* Note -- we overlap [32-36]*/
/* current record field to */
/* make this useful. */
}; /****************************/
#endif /****************************/
/****************************************************************************
* PC-DOS FCB definition
****************************************************************************/
#if PCDOS /****************************/
struct fcbtab { /****************************/
BYTE drive; /* Disk drive field [0] */
BYTE fname[8]; /* File name [1-8] */
BYTE ftype[3]; /* File type [9-11] */
WORD fcb_curblk; /* Curr 128 byte blk [12-13]*/
WORD fcb_lrecsiz; /* Logical record size[14-15]*/
LONG fcb_filsiz; /* Num bytes in file [16-19]*/
WORD fcb_date; /* Last updated [20-21] */
BYTE fcb_resvd[10]; /* System reserved [22-31] */
BYTE fcb_currec; /* Rel Rec# within curblk[32]*/
LONG record; /* Rel Rec# from bgn file */
/* [33-36] depends on lrecsiz*/
}; /****************************/
#endif /****************************/
/* */
#define SECSIZ 128 /* size of CP/M sector */
/* to obtain nsecs on err */
/****************************/
/***************************************************************************
*
* 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 /************************************/
{ /* */
WORD flags; /*sw Flags byte */
BYTE user; /*sw User # */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct fcbtab fcb; /* File FCB (may have TTY info)*/
BYTE buffer[SECSIZ]; /* Read/write buffer */
}; /************************************/
extern struct ccb _fds[]; /* */ /* Declare storage */
#define FD struct ccb /* FD Type definition */
#define NULLFD ((FD *)0) /* NULLPTR for FD */
/************************************/
/* Flags word bit definitions */
/************************************/
#define OPENED 0x01 /* Channel is OPEN */
#define ISTTY 0x02 /* Channel open to TTT */
#define ISLPT 0x04 /* Channel open to LPT */
#define ISREAD 0x08 /* Channel open readonly */
#define ISASCII 0x10 /* ASCII file attached */
#define ATEOF 0x20 /* End of file encountered */
#define DIRTY 0x40 /* Buffer needs writing */
#define ISSPTTY 0x80 /* Special tty info */
#define ISAUX 0x100 /*sw Auxiliary device */
#define ISQUE 0x0200 /*whf Queue device */
/************************************/
#define READ 0 /* Read mode parameter for open */
#define WRITE 1 /* Write mode */
/* CCB manipulation macros *************************************/
#define _getccb(i) (&_fds[i]) /* Get CCB addr */
/***************************************************************************
*
* O S I F F u n c t i o n D e f i n i t i o n s
* -------------------------------------------------
*
* Following are OSIF function definitions used by the C runtime
* library.
*
****************************************************************************/
/****************************/
#if CPM68K /* */
#define __OSIF(fn,arg) __BDOS((fn),(LONG)(arg)) /* CPM68K does it this way */
#else /* */
#define __OSIF(fn,arg) __BDOS((fn),(arg)) /* DRC does it this way */
#endif /* */
#if CPM /****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONIN 1 /* direct echoing con input */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define C_WRITESTR 9 /* Console string output */
#define CONBUF 10 /* Read console buffer */
#define C_STAT 11 /* Get console status */
#define S_BDOSVER 12 /* Get System BDOS Ver Num */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define SEARCHF 17 /* Search for first */
#define SEARCHN 18 /* Search for next */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define F_RENAME 23 /* Rename a disk file */
#define SETDMA 26 /* Set DMA address */
#define USER 32 /*sw Get / set user number */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#define F_MULTISEC 44 /* Set Multi-Sector Count */
#define P_CHAIN 47 /* Program Chain */
#define SETVEC 61 /* Set exception vector */
#define N_NETSTAT 68 /* Get Network Status */
#define F_TRUNC 99 /* Truncate file function */
#define S_OSVER 163 /* Get OS Version Number */
#endif /****************************/
#if PCDOS /****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONIN 1 /* direct echoing con input */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define C_WRITESTR 9 /* Console string output */
#define CONBUF 10 /* Read console buffer */
#define C_STAT 11 /* Get console status */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define SEARCHF 17 /* Search for first */
#define SEARCHN 18 /* Search for next */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define F_RENAME 23 /* Rename a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#endif /****************************/
/****************************************************************************/
/* 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 */
/****************************/
/****************************************************************************/
/* Hardware dependencies */
/****************************************************************************/
/****************************/
#if MC68000 | Z8000 /* 68K or Z8000 */
#define HILO 1 /* used when bytes stored */
#else /* */
#define HILO 0 /* used when bytes stored */
#endif /* */
/* */
#if HILO /* Hi/Lo storage used in */
struct long_struct{ /* 68K */
BYTE lbhihi; /* Use this for accessing */
BYTE lbhilo; /* ordered bytes in 32 bit*/
BYTE lblohi; /* LONG qtys. */
BYTE lblolo; /* */
}; /* */
struct word_struct{ /* Use this for accessing */
WORD lwhi; /* ordered words in 32 bit*/
WORD lwlo; /* LONG qtys. */
}; /* */
#else /****************************/
struct long_struct{ /* Lo/Hi storage use on */
BYTE lblolo; /* PDP-11, VAX, 8086,... */
BYTE lblohi; /* */
BYTE lbhilo; /* */
BYTE lbhihi; /* */
}; /* */
struct word_struct{ /* */
WORD lwlo; /* */
WORD lwhi; /* */
}; /* */
#endif /****************************/
/*************************** end of osif.h **********************************/
*********************** end of osif.h **********************************/
*********************** end of osif.h **********************************/


View File

@@ -0,0 +1,11 @@
/* OSIF Error handling *************************************/
EXTERN WORD errno; /* error place for assigning */
EXTERN WORD __cpmrv; /* the last BDOS return value (AX) */
EXTERN WORD _errcpm; /* place to save __cpmrv */
#define RETERR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
/************************************/
RR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
/************************************/
RR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
/************************************/

Binary file not shown.

View File

@@ -0,0 +1,114 @@
/***********************************************************************
*
* p e r r o r F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "perror" produces a short error message on stderr describing
* the last error encountered during a call to the system.
* It assumes the variable "errno" contains this error.
* Note: "errno" is set when errors occur, but is not cleared.
* Note also that some of the UNIX errors are meaningless under
* CP/M, and will print an undefined message (defined below).
* Finally, note that the defines in """errno.h""" will index
* appropriately into the sys_errlist table, below.
*
* Calling sequence:
* ret = perror(s)
* Where:
* ret = errno
* s -> a string containing a message printed with
* the explanatory error message.
*
**************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#define NUMERRS 37
#define STDERR 2
MLOCAL BYTE _undeferr[] = "Error undefined" ;
WORD sys_nerr = NUMERRS;
VOID perror(str) /* CLEAR FUNCTION ***********/
BYTE *str;
{
REG BYTE *err;
BYTE lbuf[20], *buf, *_itoa();
EXTERN BYTE *sys_errlist[];
if( errno<0 || errno>=sys_nerr )
err = _undeferr;
else err = sys_errlist[errno];
write(STDERR,str,strlen(str));
write(STDERR,": ",2);
write(STDERR,err,strlen(err));
write(STDERR," (",2);
buf = _itoa(errno,lbuf);
if( _errcpm != 0 ) /* assume this had something to do */
{
*buf++ = '.';
buf = _itoa(_errcpm,buf);
}
*buf++ = ')'; *buf++ = '\n'; *buf = NULL;
write(STDERR,lbuf,strlen(lbuf));
return(errno);
}
MLOCAL BYTE *_itoa(nm,bp)
WORD nm;
REG BYTE *bp;
{
/* temporary... */
sprintf(bp,"%d",nm);
while(*bp) bp++;
return(bp);
}
BYTE *sys_errlist[NUMERRS] = {
_undeferr, /* 0 */
_undeferr, /* 1 */
"ENOENT No such file", /* 2 */
_undeferr, /* 3 */
_undeferr, /* 4 */
"EIO I/O error", /* 5 */
_undeferr, /* 6 */
"E2BIG Arg list too long", /* 7 */
_undeferr, /* 8 */
"EBADF Bad file number", /* 9 */
_undeferr, /* 10 */
_undeferr, /* 11 */
"ENOMEM Not enough core", /* 12 */
"EACCES Permission denied", /* 13 */
_undeferr, /* 14 */
_undeferr, /* 15 */
_undeferr, /* 16 */
_undeferr, /* 17 */
_undeferr, /* 18 */
_undeferr, /* 19 */
_undeferr, /* 20 */
_undeferr, /* 21 */
"EINVAL Invalid argument", /* 22 */
"ENFILE File table overflow", /* 23 */
"EMFILE Too many open files", /* 24 */
"ENOTTY Not a typewriter", /* 25 */
_undeferr, /* 26 */
"EFBIG File too big", /* 27 */
"ENOSPC No space left on device",/* 28 */
_undeferr, /* 29 */
"EROFS Read-only file system", /* 30 */
_undeferr, /* 31 */
_undeferr, /* 32 */
_undeferr, /* 33 */
_undeferr, /* 34 */
/* end of UNIX v7, start of CPM specific */
"ENODSPC No directory space", /* 35 */
"ERENAME Can't rename file" /* 36 */
};
ODSPC No directory space", /* 35 */
"ERENAME Can't rename file" /* 36 */
};
ODSPC No directory space", /* 35 */
"ERENAME Can't rename file" /* 36 */
};

Binary file not shown.

View File

@@ -0,0 +1,62 @@
/************************************************************************
*
* p r i n t f F u n c t i o n
* -----------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "printf" prints args specified in format string to stdout.
*
* Calling sequence:
* nchrs = printf(fmt,arg1,arg2,...argn);
* Where:
* nchrs = # chars output by printf
* fmt -> a string specifying how arg1-n are to be printed.
*
**************************************************************************/
#include "stdio.h"
WORD printf(fmt,args) /* CLEAR FUNCTION ***********/
BYTE *fmt,
*args;
{
return(_doprt(stdout,fmt,&args));
}
/************************************************************************
*
* f p r i n t f F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "fprintf" prints args specified in format string to a stream file.
*
* Calling sequence:
* nchrs = fprintf(fmt,arg1,arg2,...argn);
* Where:
* nchrs = number of chars output
* fmt -> a string specifying how arg1-n are to be printed.
*
**************************************************************************/
WORD fprintf(sp,fmt,args) /* CLEAR FUNCTION ***********/
FILE *sp;
BYTE *fmt,
*args;
{
return(_doprt(sp,fmt,&args));
}
******/
FILE *sp;
BYTE *fmt,
*args;
{
return(_doprt(sp,fmt,&args));
}
******/
FILE *sp;
BYTE *fmt,
*args;
{
return(_doprt(sp,fmt,&args));
}

View File

@@ -0,0 +1,48 @@
#include "portab.h"
BYTE *__prtint(pobj, buf, base, signed, f)
WORD *pobj;
BYTE *buf;
WORD base;
WORD signed;
BYTE *(*f)();
{
BYTE digs[15];
REG BYTE *dp;
REG WORD k;
REG BYTE *p;
dp = (*f)(pobj, &buf, base, signed, digs);
if (dp == digs)
*dp++ = 0;
p = buf;
while (dp != digs)
{
k = *--dp + '0'; /* HY */
if (k > '9')
k += 'A'-10-'0';
*p++ = k;
}
*p = 0;
return (p);
}

*p++ = k;
}
*p = 0;
return (p);
}

*p++ = k;
}
*p = 0;
return (p);
}

View File

@@ -0,0 +1,76 @@
/*************************************************************************
*
* _ _ p r t l d F u n c t i o n
* -------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "__prtld" prints LONGs, for use with "_doprt".
*
**************************************************************************/
#include "portab.h"
#include "osif.h" /* used for hardware dependencies: byte store order */
BYTE *__prtld(pobj, pbuf, base, signed, digs)
LONG *pobj;
BYTE **pbuf;
WORD base;
WORD signed;
BYTE *digs;
{
REG LONG n;
REG LONG b;
REG BYTE *p;
REG WORD ii;
extern long uldiv();
extern long uldivr;
struct long_struct *p_uldivr;
p_uldivr = &uldivr;
p = digs;
b = base;
n = *pobj;
if (base == 16) { /* special because of negatives */
ii = 8;
while (n && ii) {
*p++ = (int)n & 0xf; /* HY */
n >>= 4; /* MGL */
ii--;
}
}
else if (base == 8) {
ii = 11;
while (n && ii) {
*p++ = (int)n & 7; /* HY */
n >>= 3; /* MGL */
ii--;
}
if (ii==0) {
*(p-1) &= 3; /* only 2 bits in upper octal digit */
/* MGL */
}
}
else {
if (signed && n < 0) {
*(*pbuf)++ = '-';
n = -n;
}
while (n) {
n = uldiv(n,b); /* n>0 (or unsigned), do unsigned div*/
*p++ = p_uldivr->lblolo;
}
}
return (p);
}
 unsigned div*/
*p++ = p_uldivr->lblolo;
}
}
return (p);
}
 unsigned div*/
*p++ = p_uldivr->lblolo;
}
}
return (p);
}

View File

@@ -0,0 +1,57 @@
#include "portab.h"
#include "osif.h"
BYTE *__prtshort(pobj, pbuf, base, signed, digs)
WORD *pobj;
BYTE **pbuf;
WORD base;
WORD signed;
BYTE *digs;
{
/* 05/27/83 - changed to do divide in short (HY) */
/* 08/11/83 - changed to handle 68K arg passing (as longs) (WHF) */
REG UWORD n;
REG BYTE *p;
REG WORD b;
#if HILO /*--------------------------*/
LONG ln; /* declare a placeholder */
/* */
ln = *pobj; /* assign arg to long */
n = ln & 0xFFFFL; /* then to WORD */
#else /*--------------------------*/
n = *pobj; /* assign arg to WORD */
#endif /*--------------------------*/
p = digs;
b = base;
if (signed)
if ((int)n < 0) {
n = -n;
*(*pbuf)++ = '-';
}
while (n != 0)
{
*p++ = n % b;
n = n / b;
}
return (p);
}
 }
while (n != 0)
{
*p++ = n % b;
n = n / b;
}
return (p);
}
 }
while (n != 0)
{
*p++ = n % b;
n = n / b;
}
return (p);
}

View File

@@ -0,0 +1,41 @@
/**************************************************************************
*
* p u t l F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "putl" puts a LONG (4 byte) value into the output stream.
* Note that what's written (binary) by a UNIX (lo byte, hi byte)
* system (PDP 11) will NOT be compatible with what's written by a
* NUXI (hi byte, lo byte) system (68K).
*
* Calling sequence:
* ret = putl(l, stream)
* Where:
* ret = l or FAILURE on error
* l = an LONG value
* stream-> a (FILE *) output stream
*
*****************************************************************************/
#include "stdio.h"
LONG putl(lnum,sp) /* CLEAR FUNCTION ***********/
LONG lnum; /* the LONG to be put */
FILE *sp; /* the stream to put to */
{ /* */
REG WORD i; /* index */
REG BYTE *p; /* make ptr to w */
/****************************/
p = (char *)&lnum; /* point to l */
for( i=0; i<4; i++ ) /* for all the 4 bytes in l */
if( putc(*p++,sp)== FAILURE ) /* put dem */
return(FAILURE); /* */
return(lnum); /* it worked */
} /****************************/
FAILURE); /* */
return(lnum); /* it worked */
} /****************************/
FAILURE); /* */
return(lnum); /* it worked */
} /****************************/

View File

@@ -0,0 +1,31 @@
/**************************************************************************
*
* p u t s F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "puts" copies a null terminated string to the standard output.
* It copies a newline char after the end of the string.
*
* Calling sequence:
* ret = puts(s)
* Where:
* s = string to put
* ret = last char output
*
*****************************************************************************/
#include "stdio.h"
WORD puts(str) /* CLEAR FUNCTION ***********/
REG BYTE *str; /* null term string */
{ /****************************/
while(*str) /* for all chars in s */
if(putc(*str++,stdout) == FAILURE) /* if putc fouls up */
return(FAILURE); /* give up */
return( putc('\n',stdout) ); /* append newline & return */
} /****************************/
*/
} /****************************/
*/
} /****************************/

View File

@@ -0,0 +1,41 @@
/**************************************************************************
*
* p u t w F u n c t i o n
* -------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "putw" puts a word (2 byte) value into the output stream.
* Note that what's written (binary) by a UNIX (lo byte, hi byte)
* system (PDP 11) will NOT be compatible with what's written by a
* NUXI (hi byte, lo byte) system (68K).
*
* Calling sequence:
* ret = putw(w, stream)
* Where:
* ret = w or FAILURE on error
* w = an int word value
* stream-> a (FILE *) output stream
*
******************************************************************************/
#include "stdio.h"
WORD putw(wrd,sp) /* CLEAR FUNCTION ***********/
int wrd; /* the word to be put */
FILE *sp; /* the stream to put to */
{ /* */
REG WORD i; /* index */
REG BYTE *p; /* make ptr to w */
/****************************/
p = (char *)&wrd; /* point to w */
for( i=0; i<2; i++ ) /* for all the 2 bytes in w */
if( putc(*p++,sp)==FAILURE ) /* put dem */
return(FAILURE); /* */
return(wrd); /* it worked */
} /****************************/
FAILURE); /* */
return(wrd); /* it worked */
} /****************************/
FAILURE); /* */
return(wrd); /* it worked */
} /****************************/

View File

@@ -0,0 +1,100 @@
/**************************************************************************
*
* q s o r t F u n c t i o n
* ---------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* "qsort" sorts the "number" of items, each of length "size", starting
* at "base", using function "compare" to compare 2 items in the vector.
*
* Calling sequence:
* ret = qsort(base,number,size,compar)
* Where:
* ret = always 0
* base -> start of items vector
* number = number of elements in vector
* size = number of bytes per item in vector
* compar -> comparator function, taking ptrs to items,
* returning WORD:
* compar(a,b) < 0 if *a < *b
* compar(a,b) == 0 if *a == *b
* compar(a,b) > 0 if *a > *b
*
* "qsort" uses the quicksort algorithm by C.A.R. Hoare.
* Ref: "Software Tools in Pascal" by Kernighan & Plauger.
*****************************************************************************/
#include "portab.h"
#define LINEPOS(nn) ((nn)*siz+bas)
#define EXCHANGE(aa,bb) _swap(aa,bb,siz)
WORD qsort(bas,num,siz,cmp) /* CLEAR FUNCTION ***********/
BYTE *bas;
WORD num;
WORD siz;
WORD (*cmp)();
{
REG WORD i,j;
REG BYTE *pivline;
if( num > 1 )
{
i = 0;
j = num-1;
pivline = LINEPOS(j); /* choose last line for pvt */
do{
while( i<j && (*cmp)(LINEPOS(i),pivline) <= 0 )
i++;
while( j>i && (*cmp)(LINEPOS(j),pivline) >= 0 )
j--;
if( i<j ) /* out of order pair */
EXCHANGE(LINEPOS(i),LINEPOS(j));
}while( i<j );
EXCHANGE(LINEPOS(i),pivline);
if( i < num-1-i ) /* sort shorter subset 1st */
{
qsort( bas, i, siz, cmp);
qsort( LINEPOS(i+1), num-1-i, siz, cmp);
} else
{
qsort( LINEPOS(i+1), num-1-i, siz, cmp);
qsort( bas, i, siz, cmp);
}
}
return(0);
}
MLOCAL
VOID _swap(a,b,wid)
REG BYTE *a;
REG BYTE *b;
REG WORD wid;
{
REG BYTE tmp;
if( a != b )
for( ; wid-- > 0; a++, b++ )
{
tmp = *a;
*a = *b;
*b = tmp;
}
}
REG BYTE tmp;
if( a != b )
for( ; wid-- > 0; a++, b++ )
{
tmp = *a;
*a = *b;
*b = tmp;
}
}
REG BYTE tmp;
if( a != b )
for( ; wid-- > 0; a++, b++ )
{
tmp = *a;
*a = *b;
*b = tmp;
}
}

View File

@@ -0,0 +1,50 @@
/* rand.c - kluges a random number generator with addition & overflow */
#include "portab.h"
#define NSEEDS 7
MLOCAL WORD _seeds[NSEEDS] =
{ 0, 24213, 12345, 4622, 2143, 32010, 7942 };
MLOCAL WORD _seedptr=0;
WORD rand() /* CLEAR FUNCTION ***********/
{
REG UWORD tot, ii;
for( tot=0, ii=0; ii<NSEEDS; ii++)
tot += _seeds[ii]; /* ignore overflow */
if( ++_seedptr >= NSEEDS )
_seedptr = 0;
_seeds[_seedptr] = tot;
return( tot >> 1 ); /* ignore lo bit because of addition */
}
WORD srand(seed1) /* CLEAR FUNCTION ***********/
int seed1;
{
REG WORD ncs;
_seeds[0] = seed1;
for( ncs = seed1&077; ncs; ncs-- )
rand();
return(rand());
}
ncs = seed1&077; ncs; ncs-- )
rand();
return(rand());
}
ncs = seed1&077; ncs; ncs-- )
rand();
return(rand());
}

View File

@@ -0,0 +1,62 @@
/***************************************************************************
*
* 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".
*
* Edits:
* 11-Dec-83 whf Divide into separate files, do PC-DOS I/O
*
* 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 "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
UWORD read(fd,buff,bytes) /* CLEAR FUNCTION ***********/
WORD fd; /* File descriptor */
BYTE *buff; /* -> buffer start */
UWORD bytes; /* = byte count to read */
{ /****************************/
REG FD *fp; /* -> ccb to read from */
FD *_chkc(); /* Converts fd to fp */
UWORD _ttyin(); /* Read from tty rtn */
UWORD _rdasc(); /* Read ascii rtn */
UWORD _rdbin(); /* Read binary rtn */
/****************************/
if((fp=_chkc(fd)) == NULLFD) /* File open & OK?? */
return(FAILURE); /* No: EBADF */
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) /* ASCII?? */
return(_rdasc(fp,buff,(LONG)bytes)); /* Yes, read ascii */
else return(_rdbin(fp,buff,(LONG)bytes)); /* No, read binary */
/****************************/
}
* No, read binary */
/****************************/
}
* No, read binary */
/****************************/
}

View File

@@ -0,0 +1,146 @@
/***************************************************************************
*
* R d a s c F u n c t i o n
* ---------------------------
*
* The "_rdasc" function performs a read operation for ascii files.
* All Return chars (0x13) are eliminated (and not counted) from input.
*
* Calling Sequence:
* ret = _rdasc(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
*
* Edits:
* 20-jan-84 whf Handle PCDOS ^Z bug
****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
UWORD _rdasc(fp,buff,bytes) /****************************/
/* */
REG FD *fp; /* -> ccb for the file */
REG BYTE *buff; /* -> buffer to receive data*/
REG LONG bytes; /* = # bytes to xfer */
{ /****************************/
#if CPM /*===============================================================*/
REG BYTE *p1; /* Temp byte pointer */
BYTE c; /* Temp char */
LONG xsector; /* Temp sector number */
LONG xbytes; /* byte count temp */
/****************************/
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 */
} /****************************/
p1 = &(fp->buffer[(int)fp->offset&(SECSIZ-1)]); /* 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 */
#endif /*===============================================================*/
#if PCDOS /*===============================================================*/
LONG xbytes; /* byte count save */
UWORD ii, jj; /* More byte count temps */
UWORD _cr_collapse(); /* Zaps CRs in buff */
/****************************/
xbytes = bytes; /* Remember org. request */
while(bytes > 0 && (fp->flags&ATEOF)==0 ) /* Until read is satisfied */
{ /****************************/
ii = _pc_readblk(&(fp->fcb),fp->offset,buff,(WORD)bytes,1); /* */
for( jj=0; jj<ii; ++jj ) /* EOF scan */
if( buff[jj] == EOFCHAR ) break; /* Last char EOF? */
if( ii==0 || buff[jj] == EOFCHAR ) { /* No chars or Last char EOF?*/
ii = jj; /* Num valid chars */
fp->flags |= ATEOF; /* Yes, mark file */
} /**** */
jj = _cr_collapse(buff,ii); /* Stomp out Returns (0x13) */
fp->offset += ii; /* Calculate new offset */
buff += jj; /* advance the buffer ptr */
bytes -= jj; /* discount by bytes in buff*/
} /* While bytes > 0 */
xbytes -= bytes; /* Number really read */
#endif /*===============================================================*/
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
return(xbytes); /* Read fully satisfied */
} /****************************/
#if PCDOS /*===============================================================*/
/****************************/
UWORD _cr_collapse(buf,cnt) /* Stomp out Returns (0x13) */
REG BYTE *buf; /* Where to stomp */
UWORD cnt; /* How much of buf to stomp */
{ /****************************/
REG BYTE *chk; /* Check pointer */
BYTE *savbuf; /* Save pointer */
BYTE *endbuf; /* Move to pointer */
/* */
savbuf = buf; /* save for return val calc */
endbuf = buf + cnt; /* after last char in buf */
for( chk = buf; chk < endbuf; chk++ ) /* Check out entire buffer */
if( *chk != '\r' ) /* if NOT a Return: */
*buf++ = *chk; /* move it down */
return buf-savbuf; /* New num chars in buf */
} /****************************/
#endif /*===============================================================*/
=====================================*/
=====================================*/

View File

@@ -0,0 +1,142 @@
/***************************************************************************
*
* 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
*
****************************************************************************/
#include "portab.h"
#include "osif.h"
#include "osiferr.h"
#include "errno.h"
WORD _rdbin(fp,buff,bytes) /****************************/
/* */
REG FD *fp; /* -> ccb for the file */
REG BYTE *buff; /* -> buffer to receive data*/
REG LONG bytes; /* = # bytes to xfer */
{ /****************************/
#if CPM /*===============================================================*/
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[(int)fp->offset&(SECSIZ-1)];/* 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->sector = xsector; /* Update data area */
fp->offset += bytes; /* Increment offset */
p = &fp->buffer[0]; /* Start with 1st byte */
while (bytes > 0) /* Count down */
{ /* bytes */
*buff++ = *p++; /* Move a byte */
bytes--; /* Down count */
} /****************************/
#endif /*===============================================================*/
#if PCDOS /*===============================================================*/
UWORD xbytes; /* More byte count temps */
/****************************/
xbytes = _pc_readblk(&(fp->fcb),fp->offset,buff,(WORD)bytes,1); /* */
if( xbytes==0 ) /* EOF or error condition */
fp->flags |= ATEOF; /* Set EOF flag */
fp->offset += xbytes; /* Calculate new offset */
#endif /*===============================================================*/
if(fp->offset > fp->hiwater) /* Fix up hiwater mark */
fp->hiwater = fp->offset; /* */
return(xbytes); /* Read fully satisfied */
} /****************************/
ead fully satisfied */
} /****************************/
ead fully satisfied */
} /****************************/

View File

@@ -0,0 +1,25 @@
#include "portab.h"
LONG readl(fd,buf,lnum) /* CLEAR FUNCTION ***********/
WORD fd; /* file descriptor */
REG BYTE *buf; /* addr */
LONG lnum; /* size */
{
LONG R;
REG UWORD tmp;
R = lnum;
while (lnum != 0)
{
tmp = (lnum < 32768L)? (int)lnum : 32768;
if (read(fd,buf,tmp) != tmp)
break;
buf += tmp;
lnum -= tmp;
}
return(R-lnum); /* number of bytes read */
}
 /* number of bytes read */
}
 /* number of bytes read */
}

Some files were not shown because too many files have changed in this diff Show More