1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
/*
* This file is part of the sn package.
* Distribution of sn is covered by the GNU GPL. See file COPYING.
* Copyright 1998-2000 Harold Tay.
* Copyright 2000- Patrik Rdman.
*/
#include <string.h>
#include <errno.h>
#include <stdarg.h>
static const char rcsid[] = "$Id$";
static char *ichars = "0123456789abcdefghijklmnopqrstuvwxyz";
char *istr (int i, int base, char tmp[40])
{
int n;
int negative = 0;
tmp[n = 39] = '\0';
if (i < 0)
{
negative = 1;
i = 0 - i;
}
do
tmp[--n] = ichars[i % base];
while (i /= base);
if (negative)
tmp[--n] = '-';
return (tmp + n);
}
char *uistr (unsigned int u, int base, char tmp[40])
{
int n;
tmp[n = 39] = '\0';
do
tmp[--n] = ichars[u % base];
while (u /= base);
return (tmp + n);
}
char *vachar (int c, va_list * app, char tmp[40], int *len)
{
int e;
int i;
unsigned u;
char *p;
e = errno;
switch (c)
{
case 'S': *len = va_arg(*app, int); return (va_arg(*app, char *));
case 's': p = va_arg(*app, char *); break;
case 'i': /* Fall Through */
case 'd': i = va_arg(*app, int); p = istr(i, 10, tmp); break;
case 'u': u = va_arg(*app, unsigned); p = uistr(u, 10, tmp); break;
case 'o': u = va_arg(*app, unsigned); p = uistr(u, 8, tmp); break;
case 'x': u = va_arg(*app, unsigned); p = uistr(u, 16, tmp); break;
case 'm': p = strerror(e); break;
case '%': *len = 1; return ("%");
default: *len = 0; return ("");
}
if (!p)
{
*len = 6;
return ("(null)");
}
*len = strlen(p);
return (p);
}
int formatv (char *buf, int size, char *fmt, va_list ap)
{
char *p;
int len;
char tmp[40];
char *lim;
char *start;
lim = buf + size;
start = buf;
for (; *fmt; fmt++)
if ('%' == *fmt)
{
fmt++;
p = vachar(*fmt, &ap, tmp, &len);
for (; len; len--)
{
*buf++ = *p++;
if (buf >= lim)
goto done;
}
}
else
{
*buf++ = *fmt;
if (buf >= lim)
break;
}
done:
*buf = '\0';
return (buf - start);
}
int formats(char *buf, int size, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
return (formatv(buf, size, fmt, ap));
}
|