home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
bdsc-4
/
bdslib.ark
/
FORMAT.C
< prev
next >
Wrap
Text File
|
1983-07-15
|
6KB
|
287 lines
/*
* This file contains all of the formatted I/O functions. They
* are essentially those from BDS C 1.5 with some alterations
* to accomodate the I/O primitives of the standard library.
* Last Edit 7/1/83
*/
printf(format)
char *format;
{
void fputc();
_spr(&format, &fputc, stdout); /* use "_spr" to form the output */
}
sprintf(buffer,format)
char *buffer, *format;
{
int _sspr();
_spr(&format, &_sspr, &buffer); /* call _spr to do all the work */
*buffer = '\0';
}
_sspr(c,strptr)
char **strptr;
{
*(*strptr)++ = c;
}
int fprintf(stream,format)
char *format;
FILE *stream;
{
void fputc();
_spr(&format, &fputc, stream);
}
int scanf(format)
char *format;
{
char line[MAXLINE];
gets(line); /* get a line of input from user */
return _scn(line,&format); /* and scan it with "_scn" */
}
int sscanf(line,format)
char *line, *format;
{
return _scn(line,&format); /* let _scn do all the work */
}
int
fscanf(stream,format)
char *format;
FILE *stream;
{
char text[MAXLINE];
if (fgets(text,stream) == NULL)
return 0;
return _scn(text,&format);
}
_spr(fmt,putcf,arg1)
int (*putcf)();
char **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++; /* test for zero-fill */
width = (isdigit(*format)) ? _gv2(&format) : 0;
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; goto val;
case 'B': base = 2; /* 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)
(*putcf)(zfflag ? '0' : ' ',arg1);
while (*wptr)
(*putcf)(*wptr++,arg1) ;
if (ljflag)
while (width-- > 0)
(*putcf)(' ',arg1) ;
break;
default: (*putcf)(c,arg1) ;
}
}
else (*putcf)(c,arg1) ;
}
/*
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;
}
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.
*/
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 (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 'B': base = 2;
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++;
}
}
if (!*line) return n; /* if end of input string, return */
}
return n;
}
char _igs(sptr)
char **sptr;
{
char c;
while (isspace((c = **sptr))) ++*sptr;
return (c);
}
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;
}