예제 #1
0
파일: xprintf.c 프로젝트: AhmadTux/freebsd
int
__printf_out(struct __printf_io *io, const struct printf_info *pi, const void *ptr, int len)
{
	int ret = 0;

	if ((!pi->left) && pi->width > len)
		ret += __printf_pad(io, pi->width - len, pi->pad == '0');
	ret += __printf_puts(io, ptr, len);
	if (pi->left && pi->width > len)
		ret += __printf_pad(io, pi->width - len, pi->pad == '0');
	return (ret);
}
예제 #2
0
파일: xprintf.c 프로젝트: AhmadTux/freebsd
int
__printf_pad(struct __printf_io *io, int howmany, int zero)
{
	int n;
	const char *with;
	int ret = 0;

	if (zero)
		with = zeroes;
	else
		with = blanks;

	if ((n = (howmany)) > 0) {
		while (n > PADSIZE) { 
			ret += __printf_puts(io, with, PADSIZE);
			n -= PADSIZE;
		}
		ret += __printf_puts(io, with, n);
	}
	return (ret);
}
예제 #3
0
__private_extern__ int
__printf_render_hexdump(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{
	unsigned char *p;
	unsigned u, l, j, a;
	char buf[100], *q;
	int ret;

	if (pi->width > 0 && pi->width < 16)
		l = pi->width;
	else
		l = 16;
	p = *((unsigned char **)arg[0]);
	u = *((unsigned *)arg[1]);

	ret = 0;
	a = 0;
	while (u > 0) {
		q = buf;
		if (pi->showsign)
			q += sprintf(q, " %04x", a);
		for (j = 0; j < l && j < u; j++)
			q += sprintf(q, " %02x", p[j]);
		if (pi->alt) {
			for (; j < l; j++)
				q += sprintf(q, "   ");
			q += sprintf(q, "  |");
			for (j = 0; j < l && j < u; j++) {
				if (p[j] < ' ' || p[j] > '~')
					*q++ = '.';
				else
					*q++ = p[j];
			}
			for (; j < l; j++)
				*q++ = ' ';
			*q++ = '|';
		}
		if (l < u)
			j = l;
		else
			j = u;
		p += j;
		u -= j;
		a += j;
		if (u > 0)
			*q++ = '\n';
		ret += __printf_puts(io, buf + 1, q - (buf + 1));
		__printf_flush(io);
	}
	return (ret);
}
예제 #4
0
int
__printf_render_float(struct __printf_io* io, const struct printf_info* pi, const void* const* arg) {
    int prec;       /* precision from format; <0 for N/A */
    char* dtoaresult;   /* buffer allocated by dtoa */
    char expchar;       /* exponent character: [eEpP\0] */
    char* cp;
    int expt;       /* integer value of exponent */
    int signflag;       /* true if float is negative */
    char* dtoaend;      /* pointer to end of converted digits */
    char sign;      /* sign prefix (' ', '+', '-', or \0) */
    int size;       /* size of converted field or string */
    int ndig;       /* actual number of digits returned by dtoa */
    int expsize;        /* character count for expstr */
    char expstr[MAXEXPDIG + 2]; /* buffer for exponent string: e+ZZZ */
    int nseps;      /* number of group separators with ' */
    int nrepeats;       /* number of repeats of the last group */
    const char* grouping;   /* locale specific numeric grouping rules */
    int lead;       /* sig figs before decimal or group sep */
    long double ld;
    double d;
    int realsz;     /* field size expanded by dprec, sign, etc */
    int dprec;      /* a copy of prec if [diouxX], 0 otherwise */
    char ox[2];     /* space for 0x; ox[1] is either x, X, or \0 */
    int prsize;             /* max size of printed field */
    int ret;        /* return value accumulator */
    char* decimal_point;    /* locale specific decimal point */
    int n2;         /* XXX: for PRINTANDPAD */
    char thousands_sep; /* locale specific thousands separator */
    char buf[BUF];      /* buffer with space for digits of uintmax_t */
    const char* xdigs;
    int flag;
    prec = pi->prec;
    ox[1] = '\0';
    sign = pi->showsign;
    flag = 0;
    ret = 0;
    thousands_sep = *(localeconv()->thousands_sep);
    grouping = NULL;

    if (pi->alt) {
        grouping = localeconv()->grouping;
    }

    decimal_point = localeconv()->decimal_point;
    dprec = -1;

    switch (pi->spec) {
    case 'a':
    case 'A':
        if (pi->spec == 'a') {
            ox[1] = 'x';
            xdigs = __lowercase_hex;
            expchar = 'p';
        } else {
            ox[1] = 'X';
            xdigs = __uppercase_hex;
            expchar = 'P';
        }

        if (prec >= 0) {
            prec++;
        }

        if (pi->is_long_double) {
            ld = *((long double*)arg[0]);
            dtoaresult = cp =
                             __hldtoa(ld, xdigs, prec,
                                      &expt, &signflag, &dtoaend);
        } else {
            d = *((double*)arg[0]);
            dtoaresult = cp =
                             __hdtoa(d, xdigs, prec,
                                     &expt, &signflag, &dtoaend);
        }

        if (prec < 0) {
            prec = dtoaend - cp;
        }

        if (expt == INT_MAX) {
            ox[1] = '\0';
        }

        goto fp_common;

    case 'e':
    case 'E':
        expchar = pi->spec;

        if (prec < 0) { /* account for digit before decpt */
            prec = DEFPREC + 1;
        } else {
            prec++;
        }

        break;

    case 'f':
    case 'F':
        expchar = '\0';
        break;

    case 'g':
    case 'G':
        expchar = pi->spec - ('g' - 'e');

        if (prec == 0) {
            prec = 1;
        }

        break;

    default:
        assert(pi->spec == 'f');
    }

    if (prec < 0) {
        prec = DEFPREC;
    }

    if (pi->is_long_double) {
        ld = *((long double*)arg[0]);
        dtoaresult = cp =
                         __ldtoa(&ld, expchar ? 2 : 3, prec,
                                 &expt, &signflag, &dtoaend);
    } else {
        d = *((double*)arg[0]);
        dtoaresult = cp =
                         dtoa(d, expchar ? 2 : 3, prec,
                              &expt, &signflag, &dtoaend);

        if (expt == 9999) {
            expt = INT_MAX;
        }
    }

fp_common:

    if (signflag) {
        sign = '-';
    }

    if (expt == INT_MAX) {  /* inf or nan */
        if (*cp == 'N') {
            cp = (pi->spec >= 'a') ? "nan" : "NAN";
            sign = '\0';
        } else {
            cp = (pi->spec >= 'a') ? "inf" : "INF";
        }

        size = 3;
        flag = 1;
        goto here;
    }

    ndig = dtoaend - cp;

    if (pi->spec == 'g' || pi->spec == 'G') {
        if (expt > -4 && expt <= prec) {
            /* Make %[gG] smell like %[fF] */
            expchar = '\0';

            if (pi->alt) {
                prec -= expt;
            } else {
                prec = ndig - expt;
            }

            if (prec < 0) {
                prec = 0;
            }
        } else {
            /*
             * Make %[gG] smell like %[eE], but
             * trim trailing zeroes if no # flag.
             */
            if (!pi->alt) {
                prec = ndig;
            }
        }
    }

    if (expchar) {
        expsize = exponent(expstr, expt - 1, expchar);
        size = expsize + prec;

        if (prec > 1 || pi->alt) {
            ++size;
        }
    } else {
        /* space for digits before decimal point */
        if (expt > 0) {
            size = expt;
        } else { /* "0" */
            size = 1;
        }

        /* space for decimal pt and following digits */
        if (prec || pi->alt) {
            size += prec + 1;
        }

        if (grouping && expt > 0) {
            /* space for thousands' grouping */
            nseps = nrepeats = 0;
            lead = expt;

            while (*grouping != CHAR_MAX) {
                if (lead <= *grouping) {
                    break;
                }

                lead -= *grouping;

                if (*(grouping + 1)) {
                    nseps++;
                    grouping++;
                } else {
                    nrepeats++;
                }
            }

            size += nseps + nrepeats;
        } else {
            lead = expt;
        }
    }

here:
    /*
     * All reasonable formats wind up here.  At this point, `cp'
     * points to a string which (if not flags&LADJUST) should be
     * padded out to `width' places.  If flags&ZEROPAD, it should
     * first be prefixed by any sign or other prefix; otherwise,
     * it should be blank padded before the prefix is emitted.
     * After any left-hand padding and prefixing, emit zeroes
     * required by a decimal [diouxX] precision, then print the
     * string proper, then emit zeroes required by any leftover
     * floating precision; finally, if LADJUST, pad with blanks.
     *
     * Compute actual size, so we know how much to pad.
     * size excludes decimal prec; realsz includes it.
     */
    realsz = dprec > size ? dprec : size;

    if (sign) {
        realsz++;
    }

    if (ox[1]) {
        realsz += 2;
    }

    prsize = pi->width > realsz ? pi->width : realsz;

    /* right-adjusting blank padding */
    if (pi->pad != '0' && pi->left == 0) {
        ret += __printf_pad(io, pi->width - realsz, 0);
    }

    /* prefix */
    if (sign) {
        ret += __printf_puts(io, &sign, 1);
    }

    if (ox[1]) {    /* ox[1] is either x, X, or \0 */
        ox[0] = '0';
        ret += __printf_puts(io, ox, 2);
    }

    /* right-adjusting zero padding */
    if (pi->pad == '0' && pi->left == 0) {
        ret += __printf_pad(io, pi->width - realsz, 1);
    }

    /* leading zeroes from decimal precision */
    ret += __printf_pad(io, dprec - size, 1);

    if (flag) {
        ret += __printf_puts(io, cp, size);
    } else {
        /* glue together f_p fragments */
        if (!expchar) { /* %[fF] or sufficiently short %[gG] */
            if (expt <= 0) {
                ret += __printf_puts(io, "0", 1);

                if (prec || pi->alt) {
                    ret += __printf_puts(io, decimal_point, 1);
                }

                ret += __printf_pad(io, -expt, 1);
                /* already handled initial 0's */
                prec += expt;
            } else {
                PRINTANDPAD(cp, dtoaend, lead, 1);
                cp += lead;

                if (grouping) {
                    while (nseps > 0 || nrepeats > 0) {
                        if (nrepeats > 0) {
                            nrepeats--;
                        } else {
                            grouping--;
                            nseps--;
                        }

                        ret += __printf_puts(io, &thousands_sep, 1);
                        PRINTANDPAD(cp, dtoaend,
                                    *grouping, 1);
                        cp += *grouping;
                    }

                    if (cp > dtoaend) {
                        cp = dtoaend;
                    }
                }

                if (prec || pi->alt) {
                    ret += __printf_puts(io, decimal_point, 1);
                }
            }

            PRINTANDPAD(cp, dtoaend, prec, 1);
        } else {    /* %[eE] or sufficiently long %[gG] */
            if (prec > 1 || pi->alt) {
                buf[0] = *cp++;
                buf[1] = *decimal_point;
                ret += __printf_puts(io, buf, 2);
                ret += __printf_puts(io, cp, ndig - 1);
                ret += __printf_pad(io, prec - ndig, 1);
            } else { /* XeYYY */
                ret += __printf_puts(io, cp, 1);
            }

            ret += __printf_puts(io, expstr, expsize);
        }
    }

    /* left-adjusting padding (always blank) */
    if (pi->left) {
        ret += __printf_pad(io, pi->width - realsz, 0);
    }

    __printf_flush(io);

    if (dtoaresult != NULL) {
        freedtoa(dtoaresult);
    }

    return (ret);
}
예제 #5
0
static int
__v2printf(struct __printf_io *io, const char *fmt0, unsigned pct, va_list ap)
{
	struct printf_info	*pi, *pil;
	const char		*fmt;
	int			ch;
	struct printf_info	pia[pct + 10];
	int			argt[pct + 10];
	union arg		args[pct + 10];
	int			nextarg;
	int			maxarg;
	int			ret = 0;
	int			n;

	fmt = fmt0;
	maxarg = 0;
	nextarg = 1;
	memset(argt, 0, sizeof argt);
	for (pi = pia; ; pi++) {
		memset(pi, 0, sizeof *pi);
		pil = pi;
		if (*fmt == '\0')
			break;
		pil = pi + 1;
		pi->prec = -1;
		pi->pad = ' ';
		pi->begin = pi->end = fmt;
		while (*fmt != '\0' && *fmt != '%')
			pi->end = ++fmt;
		if (*fmt == '\0') 
			break;
		fmt++;
		for (;;) {
			pi->spec = *fmt;
			switch (pi->spec) {
			case ' ':
				/*-
				 * ``If the space and + flags both appear, the space
				 * flag will be ignored.''
				 *      -- ANSI X3J11
				 */
				if (pi->showsign == 0)
					pi->showsign = ' ';
				fmt++;
				continue;
			case '#':
				pi->alt = 1;
				fmt++;
				continue;
			case '.':
				pi->prec = 0;
				fmt++;
				if (*fmt == '*') {
					fmt++;
					pi->get_prec = nextarg;
					argt[nextarg++] = PA_INT;
					continue;
				}
				while (*fmt != '\0' && is_digit(*fmt)) {
					pi->prec *= 10;
					pi->prec += to_digit(*fmt);
					fmt++;
				}
				continue;
			case '-':
				pi->left = 1;
				fmt++;
				continue;
			case '+':
				pi->showsign = '+';
				fmt++;
				continue;
			case '*':
				fmt++;
				pi->get_width = nextarg;
				argt[nextarg++] = PA_INT;
				continue;
			case '%':
				fmt++;
				break;
			case '\'':
				pi->group = 1;
				fmt++;
				continue;
			case '0':
				/*-
				 * ``Note that 0 is taken as a flag, not as the
				 * beginning of a field width.''
				 *      -- ANSI X3J11
				 */
				pi->pad = '0';
				fmt++;
				continue;
			case '1': case '2': case '3':
			case '4': case '5': case '6':
			case '7': case '8': case '9':
				n = 0;
				while (*fmt != '\0' && is_digit(*fmt)) {
					n *= 10;
					n += to_digit(*fmt);
					fmt++;
				}
				if (*fmt == '$') {
					if (nextarg > maxarg)
						maxarg = nextarg;
					nextarg = n;
					fmt++;
				} else 
					pi->width = n;
				continue;
			case 'D':
			case 'O':
			case 'U':
				pi->spec += ('a' - 'A');
				pi->is_intmax = 0;
				if (pi->is_long_double || pi->is_quad) {
					pi->is_long = 0;
					pi->is_long_double = 1;
				} else {
					pi->is_long = 1;
					pi->is_long_double = 0;
				}
				fmt++;
				break;
			case 'j':
				pi->is_intmax = 1;
				fmt++;
				continue;
			case 'q':
				pi->is_long = 0;
				pi->is_quad = 1;
				fmt++;
				continue;
			case 'L':
				pi->is_long_double = 1;
				fmt++;
				continue;
			case 'h':
				fmt++;
				if (*fmt == 'h') {
					fmt++;
					pi->is_char = 1;
				} else {
					pi->is_short = 1;
				}
				continue;
			case 'l':
				fmt++;
				if (*fmt == 'l') {
					fmt++;
					pi->is_long_double = 1;
					pi->is_quad = 0;
				} else {
					pi->is_quad = 0;
					pi->is_long = 1;
				}
				continue;
			case 't':
				pi->is_ptrdiff = 1;
				fmt++;
				continue;
			case 'z':
				pi->is_size = 1;
				fmt++;
				continue;
			default:
				fmt++;
				break;
			}
			if (printf_tbl[pi->spec].arginfo == NULL)
				errx(1, "arginfo[%c] = NULL", pi->spec);
			ch = printf_tbl[pi->spec].arginfo(
			    pi, __PRINTFMAXARG, &argt[nextarg]);
			if (ch > 0)
				pi->arg[0] = &args[nextarg];
			if (ch > 1)
				pi->arg[1] = &args[nextarg + 1];
			nextarg += ch;
			break;
		}
	}
	if (nextarg > maxarg)
		maxarg = nextarg;
#if 0
	fprintf(stderr, "fmt0 <%s>\n", fmt0);
	fprintf(stderr, "pil %p\n", pil);
#endif
	for (ch = 1; ch < maxarg; ch++) {
#if 0
		fprintf(stderr, "arg %d %x\n", ch, argt[ch]);
#endif
		switch(argt[ch]) {
		case PA_CHAR:
			args[ch].intarg = (char)va_arg (ap, int);
			break;
		case PA_INT:
			args[ch].intarg = va_arg (ap, int);
			break;
		case PA_INT | PA_FLAG_SHORT:
			args[ch].intarg = (short)va_arg (ap, int);
			break;
		case PA_INT | PA_FLAG_LONG:
			args[ch].longarg = va_arg (ap, long);
			break;
		case PA_INT | PA_FLAG_INTMAX:
			args[ch].intmaxarg = va_arg (ap, intmax_t);
			break;
		case PA_INT | PA_FLAG_QUAD:
			args[ch].intmaxarg = va_arg (ap, long long);
			break;
		case PA_INT | PA_FLAG_LONG_LONG:
			args[ch].intmaxarg = va_arg (ap, long long);
			break;
		case PA_INT | PA_FLAG_SIZE:
			args[ch].intmaxarg = va_arg (ap, size_t);
			break;
		case PA_INT | PA_FLAG_PTRDIFF:
			args[ch].intmaxarg = va_arg (ap, ptrdiff_t);
			break;
		case PA_WCHAR:
#ifdef HAVE_WCHAR
			args[ch].wintarg = va_arg (ap, wint_t);
#endif
			break;
		case PA_POINTER:
			args[ch].pvoidarg = va_arg (ap, void *);
			break;
		case PA_STRING:
			args[ch].pchararg = va_arg (ap, char *);
			break;
		case PA_WSTRING:
#ifdef HAVE_WCHAR
			args[ch].pwchararg = va_arg (ap, wchar_t *);
#endif
			break;
		case PA_DOUBLE:
#ifndef NO_FLOATING_POINT
			args[ch].doublearg = va_arg (ap, double);
#endif
			break;
		case PA_DOUBLE | PA_FLAG_LONG_DOUBLE:
#ifndef NO_FLOATING_POINT
			args[ch].longdoublearg = va_arg (ap, long double);
#endif
			break;
		default:
			errx(1, "argtype = %x (fmt = \"%s\")\n",
			    argt[ch], fmt0);
		}
	}
	for (pi = pia; pi < pil; pi++) {
#if 0
		fprintf(stderr, "pi %p", pi);
		fprintf(stderr, " spec '%c'", pi->spec);
		fprintf(stderr, " args %d",
		    ((uintptr_t)pi->arg[0] - (uintptr_t)args) / sizeof args[0]);
		if (pi->width) fprintf(stderr, " width %d", pi->width);
		if (pi->pad) fprintf(stderr, " pad 0x%x", pi->pad);
		if (pi->left) fprintf(stderr, " left");
		if (pi->showsign) fprintf(stderr, " showsign");
		if (pi->prec != -1) fprintf(stderr, " prec %d", pi->prec);
		if (pi->is_char) fprintf(stderr, " char");
		if (pi->is_short) fprintf(stderr, " short");
		if (pi->is_long) fprintf(stderr, " long");
		if (pi->is_long_double) fprintf(stderr, " long_double");
		fprintf(stderr, "\n");
		fprintf(stderr, "\t\"%.*s\"\n", pi->end - pi->begin, pi->begin);
#endif
		if (pi->get_width) {
			pi->width = args[pi->get_width].intarg;
			/*-
			 * ``A negative field width argument is taken as a
			 * - flag followed by a positive field width.''
			 *      -- ANSI X3J11
			 * They don't exclude field widths read from args.
			 */
			if (pi->width < 0) {
				pi->left = 1;
				pi->width = -pi->width;
			}
		}
		if (pi->get_prec) 
			pi->prec = args[pi->get_prec].intarg;
		ret += __printf_puts(io, pi->begin, pi->end - pi->begin);
		if (printf_tbl[pi->spec].gnurender != NULL) {
			__printf_flush(io);
			pi->sofar = ret;
			ret += printf_tbl[pi->spec].gnurender(
			    io->u.fp, pi, (const void *)pi->arg);
		} else if (printf_tbl[pi->spec].render != NULL) {
			pi->sofar = ret;
			n = printf_tbl[pi->spec].render(
			    io, pi, (const void *)pi->arg);
			if (n < 0)
				; // io.fp->_flags |= __SERR;
			else
				ret += n;
		} else if (pi->begin == pi->end)
			errx(1, "render[%c] = NULL", *fmt);
	}
	__printf_flush(io);
	return (ret);
}
예제 #6
0
static int
__printf_render_pct(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{

	return (__printf_puts(io, "%", 1));
}