home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
109.lha
/
PD_C
/
lib
/
format.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-20
|
16KB
|
388 lines
/**************************************************************************/
/*** format.c: format routines ***/
/*** Author: Christopher M. Caldwell of IO Software, Inc. ***/
/*** Created: 09-Jul-86 ***/
/*** "Do with as ye may" ***/
/**************************************************************************/
#include <stdio.h>
#include <ctype.h>
#define PF_COUNT 0
#define PF_ARRAY 1
#define PF_PUTC 2
#define then
#define TRUE 1
#define FALSE 0
static char *al;
extern char *malloc();
int lcase(c) char c; { return( isupper(c) ? tolower(c) : c ); }
int ucase(c) char c; { return( islower(c) ? toupper(c) : c ); }
int digtobin(c) char c; { return( c<='9' ? c-'0' : lcase(c)-'a'+10 ); }
char bintodig(i)int i; { return ( i<=9 ? i+'0' : i+'a'-10 ); }
int isbase( c, b )
/* Return TRUE if character c is digit of base b. Similar to isdigit,
but allows bases with letters and won't except "9" in base 8, etc.
*/
char c;
int b;
{
if( !isdigit(c) && !isalpha(c) )
then return FALSE;
else return( c<='9' ? (c-'0'<b) : (lcase(c)-'a'<b-10) );
}
int cformat(fmt,arglist) char *fmt; int arglist;
/* Return number of characters generated by "printing" fmt. Used by
things that need to malloc space for strings.
*/
{
int pf_count;
al = (char *)&arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
return pf_count;
}
int cxformat(fmt,arglist) char *fmt, *arglist;
/* Same as above but argument list is pointed to by second argument */
{
int pf_count;
al = arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
return pf_count;
}
char *mformat(fmt,arglist) char *fmt; int arglist;
/* Return pointer to malloced array of characters */
{
int pf_count;
char *res;
al = (char *)&arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
if( (res=malloc(pf_count+1)) == NULL ) then return NULL;
al = (char *)&arglist;
pf( fmt, PF_ARRAY, NULL, res, NULL );
return res;
}
char *mxformat(fmt,arglist) char *fmt, *arglist;
/* Same as above but argument list is pointed to by second argument */
{
int pf_count;
char *res;
al = arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
if( (res=malloc(pf_count+1)) == NULL ) then return NULL;
al = arglist;
pf( fmt, PF_ARRAY, NULL, res, NULL );
return res;
}
char *sformat(res,fmt,arglist) char *fmt, *res; int arglist;
/* Return pointer to malloced array of characters if res==NULL,
else fill array res with characters.
*/
{
int pf_count;
if( res==NULL )
then
{
al = (char *)&arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
if( (res=malloc(pf_count+1)) == NULL ) then return NULL;
}
al = (char *)&arglist;
pf( fmt, PF_ARRAY, NULL, res, NULL );
return res;
}
char *sxformat(res,fmt,arglist) char *fmt, *res, *arglist;
/* Same as above but argument list is pointed to by second argument */
{
int pf_count;
if( res==NULL )
then
{
al = arglist;
pf( fmt, PF_COUNT, &pf_count, NULL, NULL );
if( (res=malloc(pf_count+1)) == NULL ) then return NULL;
}
al = arglist;
pf( fmt, PF_ARRAY, NULL, res, NULL );
return res;
}
int format(fmt,arglist) char *fmt; int arglist;
/* Print characters to standard out. */
{
al = (char *)&arglist;
return pf( fmt, PF_PUTC, NULL, NULL, stdout );
}
int xformat(fmt,arglist) char *fmt, *arglist;
/* Same as above but argument list is pointed to by second argument */
{
al = arglist;
return pf( fmt, PF_PUTC, NULL, NULL, stdout );
}
int fformat(outfile,fmt,arglist) FILE *outfile; char *fmt; int arglist;
/* Print characters to specified file stream. */
{
al = (char *)&arglist;
return pf( fmt, PF_PUTC, NULL, NULL, outfile );
}
int fxformat(outfile,fmt,arglist) FILE *outfile; char *fmt, *arglist;
/* Same as above but argument list is pointed to by second argument */
{
al = arglist;
return pf( fmt, PF_PUTC, NULL, NULL, outfile );
}
#define NEXT(mode) ((mode *)(al += sizeof(mode)))[-1]
static int pf( fs, pf_func, pf_count, pf_addr, pf_file )
/* This routine is called to parse the format string. If pf_func
is PF_COUNT, that would be generated is returned. If pf_func
is PF_ARRAY, an array is filled. If pf_func is PF_FILE, characters
are sent to the stream pf_file.
*/
char *fs;
int pf_func;
int *pf_count;
char *pf_addr;
FILE *pf_file;
{
int pf_right, pf_left, pf_center, pf_dec, pf_max;
int pf_base, pf_iter, pf_pad, pf_unsigned;
char *pf_string, pf_char;
int pf_int;
long pf_long;
double pf_double;
double pnum;
int ind;
char t, c, buf[512], *cp;
int bufcnt;
int pbase;
int nm;
char *saveal;
while( c = *fs++ )
if( c != '{' || (t = *fs++) == '{' )
then
switch( pf_func )
{
case PF_COUNT: (*pf_count)++; break;
case PF_ARRAY: *pf_addr++ = c; break;
case PF_PUTC: if( putc(c,pf_file) == EOF )
then return EOF;
else break;
}
else
{
pf_right = 0;
pf_left = 0;
pf_center = 0;
pf_dec = 6;
pf_max = 0;
pf_base = 10;
pf_iter = 1;
pf_pad = ' ';
pf_unsigned = FALSE;
switch( t )
{
case 'S': pf_string = NEXT(char *); break;
case 's': pf_string = NEXT(char *); break;
case 'c': pf_char = NEXT(int); break;
case 'i': pf_int = NEXT(int); break;
case 'l': pf_long = NEXT(long); break;
case 'f': pf_double = NEXT(double); break;
default: /* $$$ added during port to Amiga */
break;
}
while( (c = *fs++) != '}' )
{
nm = 0;
pbase = 10;
if( !isbase(*fs,pbase) )
then nm = NEXT(int);
else
{
while( TRUE )
{
while( isbase(*fs,pbase) )
nm = pbase*nm + digtobin(*fs++);
if( nm<2 || nm>36 || *fs!='_' ) then break;
pbase = nm;
fs++;
}
}
switch( c )
{
case 'r': pf_right = nm; break;
case 'l': pf_left = nm; break;
case 'c': pf_center = nm; break;
case '.': pf_dec = nm; break;
case 'm': pf_max = nm; break;
case 'b': pf_base = nm; break;
case 'n': pf_iter = nm; break;
case 'p': pf_pad = nm; break;
case 'u': pf_unsigned = nm; break;
}
}
bufcnt = 0;
switch( t )
{
case 's': if( pf_string == NULL )
then cp = "(null)";
else cp = pf_string;
bufcnt = strlen( cp );
break;
case 'S': saveal = al;
pf(pf_string,PF_COUNT,&bufcnt,NULL,NULL);
al = saveal;
cp = malloc( bufcnt+1 );
pf(pf_string,PF_ARRAY,NULL,cp,NULL);
break;
case 'c': buf[bufcnt++] = pf_char;
cp = buf;
break;
case 'i': pf_char = ( pf_int < 0 );
if( pf_int >= 0 || !pf_unsigned )
then
{
do {
buf[100-(++bufcnt)]
= bintodig( abs(pf_int%pf_base) );
pf_int /= pf_base;
} while( pf_int != 0 );
if(pf_char) then buf[100-(++bufcnt)]='-';
cp = buf;
cp += (100 - bufcnt);
}
else
{
c = pf_int & 1;
pf_int >>= 1;
pf_int &= (1<<(sizeof(pf_int)-1));
c = c + ((pf_int%(pf_base>>1)) << 1);
pf_int /= (pf_base>>1);
buf[100-(++bufcnt)] = bintodig( c );
while( pf_int != 0 )
{
buf[100-(++bufcnt)]
= bintodig( abs(pf_int%pf_base) );
pf_int /= pf_base;
}
cp = buf;
cp += (100 - bufcnt);
}
break;
case 'l': pf_char = ( pf_long < 0 );
if( pf_long >= 0 || !pf_unsigned )
then
{
do {
buf[100-(++bufcnt)] = bintodig(
abs((int)(pf_long%pf_base)) );
pf_long /= pf_base;
} while( pf_long != 0 );
if(pf_char) then buf[100-(++bufcnt)]='-';
cp = buf;
cp += (100 - bufcnt);
}
else
{
c = pf_long & 1;
pf_long >>= 1;
pf_long &= (1<<(sizeof(pf_long)-1));
c = c + ((pf_long%(pf_base>>1)) << 1);
pf_long /= (pf_base>>1);
buf[100-(++bufcnt)] = bintodig( c );
while( pf_long != 0 )
{
buf[100-(++bufcnt)] = bintodig(
abs((int)(pf_long%pf_base)) );
pf_long /= pf_base;
}
cp = buf;
cp += (100 - bufcnt);
}
break;
case 'f': if( pf_double < 0 )
then
{
buf[bufcnt++] = '-';
pf_double = -pf_double;
}
ind = 0;
for(pnum=1.0; pnum<=pf_double; pnum*=pf_base)
ind--;
pnum /= pf_base;
do {
if( ind++ == 0 ) then buf[bufcnt++]='.';
c = (int)(pf_double/pnum);
buf[bufcnt++] = bintodig( c );
pf_double -= (pnum*c);
pnum /= pf_base;
} while( ind < pf_dec );
cp = buf;
break;
}
if( bufcnt > pf_max && pf_max > 0 ) then bufcnt = pf_max;
if( pf_center > 0 )
then
{
pf_left = ( pf_center - bufcnt ) / 2;
pf_right = pf_center - pf_left - bufcnt;
}
else
{
pf_left -= bufcnt;
pf_right -= bufcnt;
}
while( pf_iter-- > 0 )
{
for( ind=0; ind<pf_right; ind++ )
switch( pf_func )
{
case PF_COUNT: (*pf_count)++; break;
case PF_ARRAY: *pf_addr++ = pf_pad; break;
case PF_PUTC: if( putc(pf_pad,pf_file) == EOF )
then return EOF;
else break;
}
for( ind=0; ind<bufcnt; ind++ )
switch( pf_func )
{
case PF_COUNT: (*pf_count)++; break;
case PF_ARRAY: *pf_addr++ = cp[ind]; break;
case PF_PUTC: if( putc(cp[ind],pf_file) == EOF )
then return EOF;
else break;
}
for( ind=0; ind<pf_left; ind++ )
switch( pf_func )
{
case PF_COUNT: (*pf_count)++; break;
case PF_ARRAY: *pf_addr++ = pf_pad; break;
case PF_PUTC: if( putc(pf_pad,pf_file) == EOF )
then return EOF;
else break;
}
}
if( t == 'S' ) then free( cp );
}
if( pf_func == PF_ARRAY ) then *pf_addr = 0;
return 0;
}