cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

printf.c (6028B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* -*- linux-c -*- ------------------------------------------------------- *
      3 *
      4 *   Copyright (C) 1991, 1992 Linus Torvalds
      5 *   Copyright 2007 rPath, Inc. - All Rights Reserved
      6 *
      7 * ----------------------------------------------------------------------- */
      8
      9/*
     10 * Oh, it's a waste of space, but oh-so-yummy for debugging.  This
     11 * version of printf() does not include 64-bit support.  "Live with
     12 * it."
     13 *
     14 */
     15
     16#include "boot.h"
     17
     18static int skip_atoi(const char **s)
     19{
     20	int i = 0;
     21
     22	while (isdigit(**s))
     23		i = i * 10 + *((*s)++) - '0';
     24	return i;
     25}
     26
     27#define ZEROPAD	1		/* pad with zero */
     28#define SIGN	2		/* unsigned/signed long */
     29#define PLUS	4		/* show plus */
     30#define SPACE	8		/* space if plus */
     31#define LEFT	16		/* left justified */
     32#define SMALL	32		/* Must be 32 == 0x20 */
     33#define SPECIAL	64		/* 0x */
     34
     35#define __do_div(n, base) ({ \
     36int __res; \
     37__res = ((unsigned long) n) % (unsigned) base; \
     38n = ((unsigned long) n) / (unsigned) base; \
     39__res; })
     40
     41static char *number(char *str, long num, int base, int size, int precision,
     42		    int type)
     43{
     44	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
     45	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
     46
     47	char tmp[66];
     48	char c, sign, locase;
     49	int i;
     50
     51	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
     52	 * produces same digits or (maybe lowercased) letters */
     53	locase = (type & SMALL);
     54	if (type & LEFT)
     55		type &= ~ZEROPAD;
     56	if (base < 2 || base > 16)
     57		return NULL;
     58	c = (type & ZEROPAD) ? '0' : ' ';
     59	sign = 0;
     60	if (type & SIGN) {
     61		if (num < 0) {
     62			sign = '-';
     63			num = -num;
     64			size--;
     65		} else if (type & PLUS) {
     66			sign = '+';
     67			size--;
     68		} else if (type & SPACE) {
     69			sign = ' ';
     70			size--;
     71		}
     72	}
     73	if (type & SPECIAL) {
     74		if (base == 16)
     75			size -= 2;
     76		else if (base == 8)
     77			size--;
     78	}
     79	i = 0;
     80	if (num == 0)
     81		tmp[i++] = '0';
     82	else
     83		while (num != 0)
     84			tmp[i++] = (digits[__do_div(num, base)] | locase);
     85	if (i > precision)
     86		precision = i;
     87	size -= precision;
     88	if (!(type & (ZEROPAD + LEFT)))
     89		while (size-- > 0)
     90			*str++ = ' ';
     91	if (sign)
     92		*str++ = sign;
     93	if (type & SPECIAL) {
     94		if (base == 8)
     95			*str++ = '0';
     96		else if (base == 16) {
     97			*str++ = '0';
     98			*str++ = ('X' | locase);
     99		}
    100	}
    101	if (!(type & LEFT))
    102		while (size-- > 0)
    103			*str++ = c;
    104	while (i < precision--)
    105		*str++ = '0';
    106	while (i-- > 0)
    107		*str++ = tmp[i];
    108	while (size-- > 0)
    109		*str++ = ' ';
    110	return str;
    111}
    112
    113int vsprintf(char *buf, const char *fmt, va_list args)
    114{
    115	int len;
    116	unsigned long num;
    117	int i, base;
    118	char *str;
    119	const char *s;
    120
    121	int flags;		/* flags to number() */
    122
    123	int field_width;	/* width of output field */
    124	int precision;		/* min. # of digits for integers; max
    125				   number of chars for from string */
    126	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
    127
    128	for (str = buf; *fmt; ++fmt) {
    129		if (*fmt != '%') {
    130			*str++ = *fmt;
    131			continue;
    132		}
    133
    134		/* process flags */
    135		flags = 0;
    136	      repeat:
    137		++fmt;		/* this also skips first '%' */
    138		switch (*fmt) {
    139		case '-':
    140			flags |= LEFT;
    141			goto repeat;
    142		case '+':
    143			flags |= PLUS;
    144			goto repeat;
    145		case ' ':
    146			flags |= SPACE;
    147			goto repeat;
    148		case '#':
    149			flags |= SPECIAL;
    150			goto repeat;
    151		case '0':
    152			flags |= ZEROPAD;
    153			goto repeat;
    154		}
    155
    156		/* get field width */
    157		field_width = -1;
    158		if (isdigit(*fmt))
    159			field_width = skip_atoi(&fmt);
    160		else if (*fmt == '*') {
    161			++fmt;
    162			/* it's the next argument */
    163			field_width = va_arg(args, int);
    164			if (field_width < 0) {
    165				field_width = -field_width;
    166				flags |= LEFT;
    167			}
    168		}
    169
    170		/* get the precision */
    171		precision = -1;
    172		if (*fmt == '.') {
    173			++fmt;
    174			if (isdigit(*fmt))
    175				precision = skip_atoi(&fmt);
    176			else if (*fmt == '*') {
    177				++fmt;
    178				/* it's the next argument */
    179				precision = va_arg(args, int);
    180			}
    181			if (precision < 0)
    182				precision = 0;
    183		}
    184
    185		/* get the conversion qualifier */
    186		qualifier = -1;
    187		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
    188			qualifier = *fmt;
    189			++fmt;
    190		}
    191
    192		/* default base */
    193		base = 10;
    194
    195		switch (*fmt) {
    196		case 'c':
    197			if (!(flags & LEFT))
    198				while (--field_width > 0)
    199					*str++ = ' ';
    200			*str++ = (unsigned char)va_arg(args, int);
    201			while (--field_width > 0)
    202				*str++ = ' ';
    203			continue;
    204
    205		case 's':
    206			s = va_arg(args, char *);
    207			len = strnlen(s, precision);
    208
    209			if (!(flags & LEFT))
    210				while (len < field_width--)
    211					*str++ = ' ';
    212			for (i = 0; i < len; ++i)
    213				*str++ = *s++;
    214			while (len < field_width--)
    215				*str++ = ' ';
    216			continue;
    217
    218		case 'p':
    219			if (field_width == -1) {
    220				field_width = 2 * sizeof(void *);
    221				flags |= ZEROPAD;
    222			}
    223			str = number(str,
    224				     (unsigned long)va_arg(args, void *), 16,
    225				     field_width, precision, flags);
    226			continue;
    227
    228		case 'n':
    229			if (qualifier == 'l') {
    230				long *ip = va_arg(args, long *);
    231				*ip = (str - buf);
    232			} else {
    233				int *ip = va_arg(args, int *);
    234				*ip = (str - buf);
    235			}
    236			continue;
    237
    238		case '%':
    239			*str++ = '%';
    240			continue;
    241
    242			/* integer number formats - set up the flags and "break" */
    243		case 'o':
    244			base = 8;
    245			break;
    246
    247		case 'x':
    248			flags |= SMALL;
    249		case 'X':
    250			base = 16;
    251			break;
    252
    253		case 'd':
    254		case 'i':
    255			flags |= SIGN;
    256		case 'u':
    257			break;
    258
    259		default:
    260			*str++ = '%';
    261			if (*fmt)
    262				*str++ = *fmt;
    263			else
    264				--fmt;
    265			continue;
    266		}
    267		if (qualifier == 'l')
    268			num = va_arg(args, unsigned long);
    269		else if (qualifier == 'h') {
    270			num = (unsigned short)va_arg(args, int);
    271			if (flags & SIGN)
    272				num = (short)num;
    273		} else if (flags & SIGN)
    274			num = va_arg(args, int);
    275		else
    276			num = va_arg(args, unsigned int);
    277		str = number(str, num, base, field_width, precision, flags);
    278	}
    279	*str = '\0';
    280	return str - buf;
    281}
    282
    283int sprintf(char *buf, const char *fmt, ...)
    284{
    285	va_list args;
    286	int i;
    287
    288	va_start(args, fmt);
    289	i = vsprintf(buf, fmt, args);
    290	va_end(args);
    291	return i;
    292}
    293
    294int printf(const char *fmt, ...)
    295{
    296	char printf_buf[1024];
    297	va_list args;
    298	int printed;
    299
    300	va_start(args, fmt);
    301	printed = vsprintf(printf_buf, fmt, args);
    302	va_end(args);
    303
    304	puts(printf_buf);
    305
    306	return printed;
    307}