home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
118_01
/
toolib1.bds
< prev
next >
Wrap
Text File
|
1980-07-09
|
14KB
|
706 lines
/* New BDS library for use with software tools
* source: toolib1.bds
* version: November 26, 1981
*/
#include tools.h
/*
This file contains all the standard BDS C library functions
which are written in C that are used by the software tools
programs.
These library functions are identical to the functions
which were on files stdlib1 and stdlib2.c
EXCEPT that these functions call some routines whose names
have changed.
The object code for these functions used to be on deff.crl.
Now the object code is on toolib1.crl.
The functions on this file ONLY use functions on toolib2.crl
All the functions with new names are on file toolib2.crl.
All functions on toolib2.crl came from deff2.crl.
The names have all been changed in the same way,
viz., by adding a leading underscore character to the
name. The following functions have been renamed:
( * denotes that a call to the function is in this file)
_getchar _ungetch _putchar * _putch
_gets * _call _read * _write
_open * _close * _creat (_unlink)
_seek (_tell) _rename _exit
_rread _rwrite _rseek _rtell
_rsrec _rcfsiz
The following functions were on stdlib1.c but
have been deleted from this file.
getc(), putc(), and ungetc() are now defined on file.bds.
They had to be completely rewritten to allow for I/O
redirection.
fopen getc ungetc getw
fcreat putc putw
fflush fclose
strcat strcmp strcpy strlen
qsort
initw initb getval
The following functions from stdlib1.c are on this file:
qsort
atoi
isalpha isupper islower isdigit
isspace toupper tolower
alloc free
abs max min
*/
/*
This is the new qsort routine, utilizing the shell sort
technique given in the Software Tools book (by Kernighan
& Plauger.)
NOTE: this "qsort" function is different from the "qsort" given
in some old releases (pre 1.32) -- here, the items are sorted
in ASCENDING order.
*/
qsort(base, nel, width, compar)
char *base; int (*compar)();
{ int gap,ngap, i, j;
int jd, t1, t2;
t1 = nel * width;
for (ngap = nel / 2; ngap > 0; ngap /= 2) {
gap = ngap * width;
t2 = gap + width;
jd = base + gap;
for (i = t2; i <= t1; i += width)
for (j = i - t2; j >= 0; j -= gap) {
if ((*compar)(base+j, jd+j) <=0) break;
_swp(width, base+j, jd+j);
}
}
}
_swp(w,a,b)
char *a,*b;
int w;
{
char tmp;
while(w--) {tmp=*a; *a++=*b; *b++=tmp;}
}
/*
Some string functions
*/
int atoi(n)
char *n;
{
int val;
char c;
int sign;
val=0;
sign=1;
while ((c = *n) == '\t' || c== ' ') ++n;
if (c== '-') {sign = -1; n++;}
while ( isdigit(c = *n++)) val = val * 10 + c - '0';
return sign*val;
}
/*
Some character diddling functions
*/
int isalpha(c)
char c;
{
return isupper(c) || islower(c);
}
int isupper(c)
char c;
{
return c>='A' && c<='Z';
}
int islower(c)
char c;
{
return c>='a' && c<='z';
}
int isdigit(c)
char c;
{
return c>='0' && c<='9';
}
int isspace(c)
char c;
{
return c==' ' || c=='\t' || c=='\n';
}
char toupper(c)
char c;
{
return islower(c) ? c-32 : c;
}
char tolower(c)
char c;
{
return isupper(c) ? c+32 : c;
}
/*
Storage allocation routines, taken from chapter 8 of K&R, but
simplified to ignore the storage allignment problem and not
bother with the "morecore" hack (a call to "sbrk" under CP/M is
a relatively CHEAP operation, and can be done on every call to
"alloc" without degrading efficiency.)
*/
char *alloc(nbytes)
unsigned nbytes;
{
struct _header *p, *q, *cp;
int nunits;
/* comment out -----
printf("In alloc: nbytes = %d\n", nbytes);
----- end comment out */
nunits = 1 + (nbytes + (sizeof (_base) - 1)) / sizeof (_base);
if ((q = _allocp) == NULL) {
_base._ptr = _allocp = q = &_base;
_base._size = 0;
}
for (p = q -> _ptr; ; q = p, p = p -> _ptr) {
if (p -> _size >= nunits) {
if (p -> _size == nunits)
q -> _ptr = p -> _ptr;
else {
p -> _size -= nunits;
p += p -> _size;
p -> _size = nunits;
}
_allocp = q;
/* comment out -----
printf("Alloc returns: %x\n", p+1);
----- end comment out */
return p + 1;
}
if (p == _allocp) {
cp = sbrk(nunits * sizeof (_base));
if (cp == ERROR) {
printf("Alloc: Out of memory");
return NULL;
}
cp -> _size = nunits;
/* remember: pointer arithmetic ! */
free(cp+1);
p = _allocp;
}
}
}
free(ap)
struct _header *ap;
{
struct _header *p, *q;
/* comment out -----
printf("In free: ap = %x\n", ap);
----- end comment out */
p = ap - 1; /* No need for the cast when "ap" is a struct ptr */
for (q = _allocp; !(p > q && p < q -> _ptr); q = q -> _ptr)
if (q >= q -> _ptr && (p > q || p < q -> _ptr))
break;
if (p + p -> _size == q -> _ptr) {
p -> _size += q -> _ptr -> _size;
p -> _ptr = q -> _ptr -> _ptr;
}
else p -> _ptr = q -> _ptr;
if (q + q -> _size == p) {
q -> _size += p -> _size;
q -> _ptr = p -> _ptr;
}
else q -> _ptr = p;
_allocp = q;
/* comment out -----
printf("In free: new _allocp = %x\n", q);
----- end comment out */
}
/*
define max(), min(), abs()
*/
int abs(n)
{
return (n<0) ? -n : n;
}
int max(a,b)
{
return (a > b) ? a : b;
}
int min(a,b)
{
return (a <= b) ? a : b;
}
/*
The following functions from stdlib2.c are on this file:
printf _spr
scanf _scn
_puts (renamed by analogy to _get)
swapin
The following functions from stdlib2 have been deleted:
fprintf sprintf
scanf sscanf
fputs fgets
Many comments have been deleted from these functions.
See STDLIB2.C if you are really interested.
Each function uses an array of dimension MAXLINE.
Make sure MAXLINE is longer than the largest line
ever printed!
Remember to put out a 0x1a (control-Z, CPMEOF) at
the end of text files being written out to disk.
Also remember that there are two end of file
conditions: -1 and CPMEOF.
*/
/*
printf
usage:
printf(format, arg1, arg2, ...);
Exactly the same as in Kernighan & Ritchie.
*/
printf(format)
char *format;
{
char line[MAXLINE];
_spr(line,&format); /* use "_spr" to form the output */
/* comment out -----
_puts(line); /* and print out the line */
----- end comment out */
putlin(line, STDOUT);
}
/*
scanf:
This one accepts a line of input text from the
console, and converts the text to the required
binary or alphanumeric form. (see K & R)
Usage:
scanf(format, ptr1, ptr2, ...);
Returns number of items matched.
Since a new line of text must be entered from the
console each time scanf is called, any unprocessed
text left over from the last call is lost forever.
This is a difference between BDS and UNIX.
The field width specification is not supported.
*/
int scanf(format)
char *format;
{
char line[MAXLINE];
/* comment out -----
_gets(line); /* get a line of input from user */
----- end comment out */
getlin(line, STDIN);
return _scn(line,&format); /* and scan it with "_scn" */
}
/*
sprintf:
Like fprintf, except a string pointer is specified
instead of a buffer pointer. The text is written
directly into memory where the string pointer points.
Usage:
sprintf(string,format,arg1, arg2, ...);
*/
sprintf(buffer,format)
char *buffer, *format;
{
_spr(buffer,&format); /* call _spr to do all the work */
}
/*
sscanf:
Reads a line of text in from the console and scans it
for variable values specified in the format string.
See the comments below in _scn()
Usage:
sscanf(format,&arg1,&arg2,...);
*/
int sscanf(line,format)
char *line, *format;
{
return _scn(line,&format); /* let _scn do all the work */
}
/*
General formatted output conversion routine, used by
fprintf and sprintf..."line" is where the output is
written, and "fmt" is a pointer to an argument list
which must consist of a format string pointer and
subsequent list of (optional) values.
The arguments are, of course, passed on the stack.
*/
_spr(line,fmt)
char *line, **fmt;
{
char _uspr(), c, base, *sptr, *format;
char wbuf[MAXLINE], *wptr, pf, ljflag, zfflag;
int width, precision, *args;
format = *fmt++; /* fmt first points to the format string */
args = fmt; /* now fmt points to the first arg value */
while (c = *format++)
if (c == '%') {
wptr = wbuf;
precision = 6;
ljflag = pf = zfflag = 0;
if (*format == '-') {
format++;
ljflag++;
}
if (*format == '0') zfflag++; /* zero-fill feature test */
width = (isdigit(*format)) ? _gv2(&format) : 1;
if ((c = *format++) == '.') {
precision = _gv2(&format);
pf++;
c = *format++;
}
switch(toupper(c)) {
case 'D': if (*args < 0) {
*wptr++ = '-';
*args = -*args;
width--;
}
case 'U': base = 10; goto val;
case 'X': base = 16; goto val;
case 'O': base = 8; /* note that arbitrary bases can be
added easily before this line */
val: width -= _uspr(&wptr,*args++,base);
goto pad;
case 'C': *wptr++ = *args++;
width--;
goto pad;
case 'S': if (!pf) precision = 200;
sptr = *args++;
while (*sptr && precision) {
*wptr++ = *sptr++;
precision--;
width--;
}
pad: *wptr = '\0';
pad2: wptr = wbuf;
if (!ljflag)
while (width-- > 0)
*line++ = zfflag ? '0' : ' ';
while (*line = *wptr++)
line++;
if (ljflag)
while (width-- > 0)
*line++ = ' ';
break;
default: *line++ = c;
}
}
else *line++ = c;
*line = '\0';
}
/*
Internal routine used by "_spr" to perform ascii-
to-decimal conversion and update an associated pointer:
*/
int _gv2(sptr)
char **sptr;
{
int n;
n = 0;
while (isdigit(**sptr)) n = 10 * n + *(*sptr)++ - '0';
return n;
}
/*
Internal function which converts n into an ASCII
base `base' representation and places the text
at the location pointed to by the pointer pointed
to by `string'. Yes, you read that correctly.
*/
char _uspr(string, n, base)
char **string;
unsigned n;
{
char length;
if (n<base) {
*(*string)++ = (n < 10) ? n + '0' : n + 55;
return 1;
}
length = _uspr(string, n/base, base);
_uspr(string, n%base, base);
return length + 1;
}
/*
General formatted input conversion routine. "line" points
to a string containing ascii text to be converted, and "fmt"
points to an argument list consisting of first a format
string and then a list of pointers to the destination objects.
Appropriate data is picked up from the text string and stored
where the pointer arguments point according to the format string.
See K&R for more info.
The field width specification is not supported.
NOTE: the "%s" termination character has been changed
from "any white space" to the character following the
the %s specification in the format string.
That is, the call
sscanf(string, "%s:", &str);
would ignore leading white space (as is the case with
all format conversions), and then read in ALL following
text (including newlines) into the buffer "str"
until a COLON or null byte is encountered.
*/
int _scn(line,fmt)
char *line, **fmt;
{
char sf, c, base, n, *sptr, *format;
int sign, val, **args;
format = *fmt++; /* fmt first points to the format string */
args = fmt; /* now it points to the arg list */
n = 0;
while (c = *format++) {
if (!*line) return n; /* if end of input string, return */
if (isspace(c)) continue; /* skip white space in format string */
if (c != '%') { /* if not %, must match text */
if (c != _igs(&line)) return n;
else line++;
}
else { /* process conversion */
sign = 1;
base = 10;
sf = 0;
if ((c = *format++) == '*') {
sf++; /* if "*" given, supress assignment */
c = *format++;
}
switch (toupper(c)) {
case 'X': base = 16;
goto doval;
case 'O': base = 8;
goto doval;
case 'D': if (_igs(&line) == '-') {
sign = -1;
line++;
}
doval: case 'U': val = 0;
if (_bc(_igs(&line),base) == ERROR)
return n;
while ((c = _bc(*line++,base)) != 255)
val = val * base + c;
line--;
break;
case 'S': _igs(&line);
sptr = *args;
while (c = *line++) {
if (c == *format) {
format++;
break;
}
if (!sf) *sptr++ = c;
}
if (!sf) {
n++;
*sptr = '\0';
args++;
}
continue;
case 'C': if (!sf) {
poke(*args++, *line);
n++;
}
line++;
continue;
default: return n;
}
if (!sf) {
**args++ = val * sign;
n++;
}
}}
return n;
}
/*
Internal function to position the character
pointer argument to the next non white-space
character in the string:
*/
char _igs(sptr)
char **sptr;
{
char c;
while (isspace(c = **sptr)) ++*sptr;
return (c);
}
/*
Internal function to convert character c to value
in base b , or return ERROR if illegal character for that
base:
*/
int _bc(c,b)
char c,b;
{
if (isalpha(c = toupper(c))) c -= 55;
else if (isdigit(c)) c -= 0x30;
else return ERROR;
if (c > b-1) return ERROR;
else return c;
}
/*
_puts:
Write out the given string to the console.
A newline is NOT automatically appended:
*/
_puts(s)
char *s;
{
while (*s) _putchar(*s++);
}
swapin(name,addr)
char *name; /* the file to swap in */
{
int fd;
if (( fd = _open(name,0)) == ERROR) {
printf("Swapin: cannot open %s\n",name);
return ERROR;
}
if ((_read(fd,addr,512)) < 0) {
printf("Swapin: read error on %s\n",name);
_close(fd);
return ERROR;
}
_close(fd);
return OK;
}