|
Packit |
9741aa |
/* xfprintf.c -
|
|
Packit |
9741aa |
X/Open extended v?fprintf implemented in terms of v?fprintf.
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
Written by James Clark (jjc@jclark.com).
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* Compile with:
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
-DVARARGS to use varargs.h instead of stdarg.h
|
|
Packit |
9741aa |
-DLONG_DOUBLE_MISSING if your compiler doesn't like `long double'
|
|
Packit |
9741aa |
-DFP_SUPPORT to include floating point stuff
|
|
Packit |
9741aa |
*/
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#include "config.h"
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifndef HAVE_EXTENDED_PRINTF
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#include "std.h"
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef lint
|
|
Packit |
9741aa |
/* avoid stupid lint warnings */
|
|
Packit |
9741aa |
#undef va_arg
|
|
Packit |
9741aa |
#define va_arg(ap, type) (ap, (type)0)
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
#ifdef LONG_DOUBLE_MISSING
|
|
Packit |
9741aa |
typedef double long_double;
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
typedef long double long_double;
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifndef __STDC__
|
|
Packit |
9741aa |
#define const /* as nothing */
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef USE_PROTOTYPES
|
|
Packit |
9741aa |
#define P(parms) parms
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
#define P(parms) ()
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
typedef int (*printer)();
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
typedef int (*printer)(UNIV, const char *, ...);
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
enum arg_type {
|
|
Packit |
9741aa |
NONE,
|
|
Packit |
9741aa |
INT,
|
|
Packit |
9741aa |
UNSIGNED,
|
|
Packit |
9741aa |
LONG,
|
|
Packit |
9741aa |
UNSIGNED_LONG,
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
DOUBLE,
|
|
Packit |
9741aa |
LONG_DOUBLE,
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
PCHAR,
|
|
Packit |
9741aa |
PINT,
|
|
Packit |
9741aa |
PLONG,
|
|
Packit |
9741aa |
PSHORT
|
|
Packit |
9741aa |
};
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
union arg {
|
|
Packit |
9741aa |
int i;
|
|
Packit |
9741aa |
unsigned u;
|
|
Packit |
9741aa |
long l;
|
|
Packit |
9741aa |
unsigned long ul;
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
double d;
|
|
Packit |
9741aa |
long_double ld;
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
char *pc;
|
|
Packit |
9741aa |
UNIV pv;
|
|
Packit |
9741aa |
int *pi;
|
|
Packit |
9741aa |
short *ps;
|
|
Packit |
9741aa |
long *pl;
|
|
Packit |
9741aa |
};
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#define NEXT 0
|
|
Packit |
9741aa |
#define MISSING 10
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
struct spec {
|
|
Packit |
9741aa |
enum arg_type type;
|
|
Packit |
9741aa |
char pos;
|
|
Packit |
9741aa |
char field_width;
|
|
Packit |
9741aa |
char precision;
|
|
Packit |
9741aa |
};
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#define FLAG_CHARS "-+ #0"
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int parse_spec P((const char **, struct spec *));
|
|
Packit |
9741aa |
static int find_arg_types P((const char *, enum arg_type *));
|
|
Packit |
9741aa |
static void get_arg P((enum arg_type, va_list *, union arg *));
|
|
Packit |
9741aa |
static int do_arg P((UNIV, printer, const char *, enum arg_type, union arg *));
|
|
Packit |
9741aa |
static int xdoprt P((UNIV, printer, const char *, va_list));
|
|
Packit |
9741aa |
static int printit P((UNIV, printer, const char *, va_list, int, union arg *));
|
|
Packit |
9741aa |
static int maybe_positional P((const char *));
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* Return 1 if sucessful, 0 otherwise. **pp points to character after % */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int parse_spec(pp, sp)
|
|
Packit |
9741aa |
const char **pp;
|
|
Packit |
9741aa |
struct spec *sp;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
char modifier = 0;
|
|
Packit |
9741aa |
sp->pos = NEXT;
|
|
Packit |
9741aa |
if (isdigit((unsigned char)(**pp)) && (*pp)[1] == '$') {
|
|
Packit |
9741aa |
if (**pp == '0')
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
sp->pos = **pp - '0';
|
|
Packit |
9741aa |
*pp += 2;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
while (**pp != '\0' && strchr(FLAG_CHARS, **pp))
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* handle the field width */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
sp->field_width = MISSING;
|
|
Packit |
9741aa |
if (**pp == '*') {
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
if (isdigit((unsigned char)**pp) && (*pp)[1] == '$') {
|
|
Packit |
9741aa |
if (**pp == '0')
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
sp->field_width = **pp - '0';
|
|
Packit |
9741aa |
*pp += 2;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
sp->field_width = NEXT;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else {
|
|
Packit |
9741aa |
while (isdigit((unsigned char)**pp))
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* handle the precision */
|
|
Packit |
9741aa |
sp->precision = MISSING;
|
|
Packit |
9741aa |
if (**pp == '.') {
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
if (**pp == '*') {
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
if (isdigit((unsigned char)**pp) && (*pp)[1] == '$') {
|
|
Packit |
9741aa |
if (**pp == '0')
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
sp->precision = **pp - '0';
|
|
Packit |
9741aa |
*pp += 2;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
sp->precision = NEXT;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else {
|
|
Packit |
9741aa |
while (isdigit((unsigned char)**pp))
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* handle h l or L */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if (**pp == 'h' || **pp == 'l' || **pp == 'L') {
|
|
Packit |
9741aa |
modifier = **pp;
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
switch (**pp) {
|
|
Packit |
9741aa |
case 'd':
|
|
Packit |
9741aa |
case 'i':
|
|
Packit |
9741aa |
sp->type = modifier == 'l' ? LONG : INT;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case 'o':
|
|
Packit |
9741aa |
case 'u':
|
|
Packit |
9741aa |
case 'x':
|
|
Packit |
9741aa |
case 'X':
|
|
Packit |
9741aa |
sp->type = modifier == 'l' ? UNSIGNED_LONG : UNSIGNED;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
case 'e':
|
|
Packit |
9741aa |
case 'E':
|
|
Packit |
9741aa |
case 'f':
|
|
Packit |
9741aa |
case 'g':
|
|
Packit |
9741aa |
case 'G':
|
|
Packit |
9741aa |
sp->type = modifier == 'L' ? LONG_DOUBLE : DOUBLE;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
case 'c':
|
|
Packit |
9741aa |
sp->type = INT;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case 's':
|
|
Packit |
9741aa |
sp->type = PCHAR;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case 'p':
|
|
Packit |
9741aa |
/* a pointer to void has the same representation as a pointer to char */
|
|
Packit |
9741aa |
sp->type = PCHAR;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case 'n':
|
|
Packit |
9741aa |
if (modifier == 'h')
|
|
Packit |
9741aa |
sp->type = PSHORT;
|
|
Packit |
9741aa |
else if (modifier == 'l')
|
|
Packit |
9741aa |
sp->type = PLONG;
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
sp->type = PINT;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case '%':
|
|
Packit |
9741aa |
sp->type = NONE;
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
default:
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
*pp += 1;
|
|
Packit |
9741aa |
return 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int find_arg_types(format, arg_type)
|
|
Packit |
9741aa |
const char *format;
|
|
Packit |
9741aa |
enum arg_type *arg_type;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
int i, pos;
|
|
Packit |
9741aa |
const char *p;
|
|
Packit |
9741aa |
struct spec spec;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (i = 0; i < 9; i++)
|
|
Packit |
9741aa |
arg_type[i] = NONE;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
pos = 0;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
p = format;
|
|
Packit |
9741aa |
while (*p)
|
|
Packit |
9741aa |
if (*p == '%') {
|
|
Packit |
9741aa |
p++;
|
|
Packit |
9741aa |
if (!parse_spec(&p, &spec))
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
if (spec.type != NONE) {
|
|
Packit |
9741aa |
int n;
|
|
Packit |
9741aa |
if (spec.pos == NEXT)
|
|
Packit |
9741aa |
n = pos++;
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
n = spec.pos - 1;
|
|
Packit |
9741aa |
if (n < 9) {
|
|
Packit |
9741aa |
enum arg_type t = arg_type[n];
|
|
Packit |
9741aa |
if (t != NONE && t != spec.type)
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
arg_type[n] = spec.type;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
if (spec.field_width != MISSING) {
|
|
Packit |
9741aa |
int n;
|
|
Packit |
9741aa |
if (spec.field_width == NEXT)
|
|
Packit |
9741aa |
n = pos++;
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
n = spec.field_width - 1;
|
|
Packit |
9741aa |
if (n < 9) {
|
|
Packit |
9741aa |
enum arg_type t = arg_type[n];
|
|
Packit |
9741aa |
if (t != NONE && t != INT)
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
arg_type[n] = INT;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
if (spec.precision != MISSING) {
|
|
Packit |
9741aa |
int n;
|
|
Packit |
9741aa |
if (spec.precision == NEXT)
|
|
Packit |
9741aa |
n = pos++;
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
n = spec.precision - 1;
|
|
Packit |
9741aa |
if (n < 9) {
|
|
Packit |
9741aa |
enum arg_type t = arg_type[n];
|
|
Packit |
9741aa |
if (t != NONE && t != INT)
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
arg_type[n] = INT;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
p++;
|
|
Packit |
9741aa |
return 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static void get_arg(arg_type, app, argp)
|
|
Packit |
9741aa |
enum arg_type arg_type;
|
|
Packit |
9741aa |
va_list *app;
|
|
Packit |
9741aa |
union arg *argp;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
switch (arg_type) {
|
|
Packit |
9741aa |
case NONE:
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case INT:
|
|
Packit |
9741aa |
argp->i = va_arg(*app, int);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case UNSIGNED:
|
|
Packit |
9741aa |
argp->u = va_arg(*app, unsigned);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case LONG:
|
|
Packit |
9741aa |
argp->l = va_arg(*app, long);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case UNSIGNED_LONG:
|
|
Packit |
9741aa |
argp->ul = va_arg(*app, unsigned long);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
case DOUBLE:
|
|
Packit |
9741aa |
argp->d = va_arg(*app, double);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case LONG_DOUBLE:
|
|
Packit |
9741aa |
argp->ld = va_arg(*app, long_double);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
case PCHAR:
|
|
Packit |
9741aa |
argp->pc = va_arg(*app, char *);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case PINT:
|
|
Packit |
9741aa |
argp->pi = va_arg(*app, int *);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case PSHORT:
|
|
Packit |
9741aa |
argp->ps = va_arg(*app, short *);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
case PLONG:
|
|
Packit |
9741aa |
argp->pl = va_arg(*app, long *);
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
default:
|
|
Packit |
9741aa |
abort();
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int do_arg(handle, func, buf, arg_type, argp)
|
|
Packit |
9741aa |
UNIV handle;
|
|
Packit |
9741aa |
printer func;
|
|
Packit |
9741aa |
const char *buf;
|
|
Packit |
9741aa |
enum arg_type arg_type;
|
|
Packit |
9741aa |
union arg *argp;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
switch (arg_type) {
|
|
Packit |
9741aa |
case NONE:
|
|
Packit |
9741aa |
return (*func)(handle, buf);
|
|
Packit |
9741aa |
case INT:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->i);
|
|
Packit |
9741aa |
case UNSIGNED:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->u);
|
|
Packit |
9741aa |
case LONG:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->l);
|
|
Packit |
9741aa |
case UNSIGNED_LONG:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->ul);
|
|
Packit |
9741aa |
#ifdef FP_SUPPORT
|
|
Packit |
9741aa |
case DOUBLE:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->d);
|
|
Packit |
9741aa |
case LONG_DOUBLE:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->ld);
|
|
Packit |
9741aa |
#endif /* FP_SUPPORT */
|
|
Packit |
9741aa |
case PCHAR:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->pc);
|
|
Packit |
9741aa |
case PINT:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->pi);
|
|
Packit |
9741aa |
case PSHORT:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->ps);
|
|
Packit |
9741aa |
case PLONG:
|
|
Packit |
9741aa |
return (*func)(handle, buf, argp->pl);
|
|
Packit |
9741aa |
default:
|
|
Packit |
9741aa |
abort();
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
/* NOTREACHED */
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int printit(handle, func, p, ap, nargs, arg)
|
|
Packit |
9741aa |
UNIV handle;
|
|
Packit |
9741aa |
printer func;
|
|
Packit |
9741aa |
const char *p;
|
|
Packit |
9741aa |
va_list ap;
|
|
Packit |
9741aa |
int nargs;
|
|
Packit |
9741aa |
union arg *arg;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
char buf[512]; /* enough for a spec */
|
|
Packit |
9741aa |
int count = 0;
|
|
Packit |
9741aa |
int pos = 0;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
while (*p)
|
|
Packit |
9741aa |
if (*p == '%') {
|
|
Packit |
9741aa |
char *q;
|
|
Packit |
9741aa |
struct spec spec;
|
|
Packit |
9741aa |
const char *start;
|
|
Packit |
9741aa |
int had_field_width;
|
|
Packit |
9741aa |
union arg *argp;
|
|
Packit |
9741aa |
union arg a;
|
|
Packit |
9741aa |
int res;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
start = ++p;
|
|
Packit |
9741aa |
if (!parse_spec(&p, &spec))
|
|
Packit |
9741aa |
abort(); /* should have caught it in find_arg_types */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
buf[0] = '%';
|
|
Packit |
9741aa |
q = buf + 1;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if (spec.pos != NEXT)
|
|
Packit |
9741aa |
start += 2;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* substitute in precision and field width if necessary */
|
|
Packit |
9741aa |
had_field_width = 0;
|
|
Packit |
9741aa |
while (start < p) {
|
|
Packit |
9741aa |
if (*start == '*') {
|
|
Packit |
9741aa |
char c;
|
|
Packit |
9741aa |
int n, val;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
start++;
|
|
Packit |
9741aa |
if (!had_field_width && spec.field_width != MISSING) {
|
|
Packit |
9741aa |
c = spec.field_width;
|
|
Packit |
9741aa |
had_field_width = 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
c = spec.precision;
|
|
Packit |
9741aa |
if (c == NEXT)
|
|
Packit |
9741aa |
n = pos++;
|
|
Packit |
9741aa |
else {
|
|
Packit |
9741aa |
start += 2;
|
|
Packit |
9741aa |
n = c - 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
if (n >= nargs)
|
|
Packit |
9741aa |
val = va_arg(ap, int);
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
val = arg[n].i;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* ignore negative precision */
|
|
Packit |
9741aa |
if (val >= 0 || q[-1] != '.') {
|
|
Packit |
9741aa |
(void)sprintf(q, "%d", val);
|
|
Packit |
9741aa |
q = strchr(q, '\0');
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
*q++ = *start++;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
*q++ = '\0';
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
argp = 0;
|
|
Packit |
9741aa |
if (spec.type != NONE) {
|
|
Packit |
9741aa |
int n = spec.pos == NEXT ? pos++ : spec.pos - 1;
|
|
Packit |
9741aa |
if (n >= nargs) {
|
|
Packit |
9741aa |
get_arg(spec.type, &ap, &a);
|
|
Packit |
9741aa |
argp = &a;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
argp = arg + n;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
res = do_arg(handle, func, buf, spec.type, argp);
|
|
Packit |
9741aa |
if (res < 0)
|
|
Packit |
9741aa |
return -1;
|
|
Packit |
9741aa |
count += res;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
else {
|
|
Packit |
9741aa |
if ((*func)(handle, "%c", *p++) < 0)
|
|
Packit |
9741aa |
return -1;
|
|
Packit |
9741aa |
count++;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return count;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
/* Do a quick check to see if it may contains any positional thingies. */
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int maybe_positional(format)
|
|
Packit |
9741aa |
const char *format;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
const char *p;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
p = format;
|
|
Packit |
9741aa |
for (;;) {
|
|
Packit |
9741aa |
p = strchr(p, '$');
|
|
Packit |
9741aa |
if (!p)
|
|
Packit |
9741aa |
return 0;
|
|
Packit |
9741aa |
if (p - format >= 2
|
|
Packit |
9741aa |
&& isdigit((unsigned char)p[-1])
|
|
Packit |
9741aa |
&& (p[-2] == '%' || p[-2] == '*'))
|
|
Packit |
9741aa |
break; /* might be a positional thingy */
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
return 1;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
static int xdoprt(handle, func, format, ap)
|
|
Packit |
9741aa |
UNIV handle;
|
|
Packit |
9741aa |
printer func;
|
|
Packit |
9741aa |
const char *format;
|
|
Packit |
9741aa |
va_list ap;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
enum arg_type arg_type[9];
|
|
Packit |
9741aa |
union arg arg[9];
|
|
Packit |
9741aa |
int nargs, i;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
if (!find_arg_types(format, arg_type))
|
|
Packit |
9741aa |
return -1;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (nargs = 0; nargs < 9; nargs++)
|
|
Packit |
9741aa |
if (arg_type[nargs] == NONE)
|
|
Packit |
9741aa |
break;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (i = nargs; i < 9; i++)
|
|
Packit |
9741aa |
if (arg_type[i] != NONE)
|
|
Packit |
9741aa |
return -1;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
for (i = 0; i < nargs; i++)
|
|
Packit |
9741aa |
get_arg(arg_type[i], &ap, arg + i);
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
return printit(handle, func, format, ap, nargs, arg);
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
static int do_fprintf(va_alist) va_dcl
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
static int do_fprintf(UNIV p, const char *format,...)
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
UNIV p;
|
|
Packit |
9741aa |
const char *format;
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
va_list ap;
|
|
Packit |
9741aa |
int res;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
va_start(ap);
|
|
Packit |
9741aa |
p = va_arg(ap, UNIV);
|
|
Packit |
9741aa |
format = va_arg(ap, char *);
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
va_start(ap, format);
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
res = vfprintf((FILE *)p, format, ap);
|
|
Packit |
9741aa |
va_end(ap);
|
|
Packit |
9741aa |
return res;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
int xfprintf(va_alist) va_dcl
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
int xfprintf(FILE *fp, const char *format, ...)
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
FILE *fp;
|
|
Packit |
9741aa |
char *format;
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
va_list ap;
|
|
Packit |
9741aa |
int res;
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#ifdef VARARGS
|
|
Packit |
9741aa |
va_start(ap);
|
|
Packit |
9741aa |
fp = va_arg(ap, FILE *);
|
|
Packit |
9741aa |
format = va_arg(ap, char *);
|
|
Packit |
9741aa |
#else
|
|
Packit |
9741aa |
va_start(ap, format);
|
|
Packit |
9741aa |
#endif
|
|
Packit |
9741aa |
if (maybe_positional(format))
|
|
Packit |
9741aa |
res = xdoprt((UNIV)fp, do_fprintf, format, ap);
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
res = vfprintf(fp, format, ap);
|
|
Packit |
9741aa |
va_end(ap);
|
|
Packit |
9741aa |
return res;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
int xvfprintf(fp, format, ap)
|
|
Packit |
9741aa |
FILE *fp;
|
|
Packit |
9741aa |
const char *format;
|
|
Packit |
9741aa |
va_list ap;
|
|
Packit |
9741aa |
{
|
|
Packit |
9741aa |
int res;
|
|
Packit |
9741aa |
if (maybe_positional(format))
|
|
Packit |
9741aa |
res = xdoprt((UNIV)fp, do_fprintf, format, ap);
|
|
Packit |
9741aa |
else
|
|
Packit |
9741aa |
res = vfprintf(fp, format, ap);
|
|
Packit |
9741aa |
return res;
|
|
Packit |
9741aa |
}
|
|
Packit |
9741aa |
|
|
Packit |
9741aa |
#endif /* not HAVE_EXTENDED_PRINTF */
|