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

stdio.c (7190B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) Paul Mackerras 1997.
      4 */
      5#include <stdarg.h>
      6#include <stddef.h>
      7#include "string.h"
      8#include "stdio.h"
      9#include "ops.h"
     10
     11size_t strnlen(const char * s, size_t count)
     12{
     13	const char *sc;
     14
     15	for (sc = s; count-- && *sc != '\0'; ++sc)
     16		/* nothing */;
     17	return sc - s;
     18}
     19
     20char *strrchr(const char *s, int c)
     21{
     22	const char *last = NULL;
     23	do {
     24		if (*s == (char)c)
     25			last = s;
     26	} while (*s++);
     27	return (char *)last;
     28}
     29
     30#ifdef __powerpc64__
     31
     32# define do_div(n, base) ({						\
     33	unsigned int __base = (base);					\
     34	unsigned int __rem;						\
     35	__rem = ((unsigned long long)(n)) % __base;			\
     36	(n) = ((unsigned long long)(n)) / __base;			\
     37	__rem;								\
     38})
     39
     40#else
     41
     42extern unsigned int __div64_32(unsigned long long *dividend,
     43			       unsigned int divisor);
     44
     45/* The unnecessary pointer compare is there
     46 * to check for type safety (n must be 64bit)
     47 */
     48# define do_div(n,base) ({						\
     49	unsigned int __base = (base);					\
     50	unsigned int __rem;						\
     51	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
     52	if (((n) >> 32) == 0) {						\
     53		__rem = (unsigned int)(n) % __base;			\
     54		(n) = (unsigned int)(n) / __base;			\
     55	} else								\
     56		__rem = __div64_32(&(n), __base);			\
     57	__rem;								\
     58 })
     59
     60#endif /* __powerpc64__ */
     61
     62static int skip_atoi(const char **s)
     63{
     64	int i, c;
     65
     66	for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
     67		i = i*10 + c - '0';
     68	return i;
     69}
     70
     71#define ZEROPAD	1		/* pad with zero */
     72#define SIGN	2		/* unsigned/signed long */
     73#define PLUS	4		/* show plus */
     74#define SPACE	8		/* space if plus */
     75#define LEFT	16		/* left justified */
     76#define SPECIAL	32		/* 0x */
     77#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
     78
     79static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
     80{
     81	char c,sign,tmp[66];
     82	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
     83	int i;
     84
     85	if (type & LARGE)
     86		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     87	if (type & LEFT)
     88		type &= ~ZEROPAD;
     89	if (base < 2 || base > 36)
     90		return 0;
     91	c = (type & ZEROPAD) ? '0' : ' ';
     92	sign = 0;
     93	if (type & SIGN) {
     94		if ((signed long long)num < 0) {
     95			sign = '-';
     96			num = - (signed long long)num;
     97			size--;
     98		} else if (type & PLUS) {
     99			sign = '+';
    100			size--;
    101		} else if (type & SPACE) {
    102			sign = ' ';
    103			size--;
    104		}
    105	}
    106	if (type & SPECIAL) {
    107		if (base == 16)
    108			size -= 2;
    109		else if (base == 8)
    110			size--;
    111	}
    112	i = 0;
    113	if (num == 0)
    114		tmp[i++]='0';
    115	else while (num != 0) {
    116		tmp[i++] = digits[do_div(num, base)];
    117	}
    118	if (i > precision)
    119		precision = i;
    120	size -= precision;
    121	if (!(type&(ZEROPAD+LEFT)))
    122		while(size-->0)
    123			*str++ = ' ';
    124	if (sign)
    125		*str++ = sign;
    126	if (type & SPECIAL) {
    127		if (base==8)
    128			*str++ = '0';
    129		else if (base==16) {
    130			*str++ = '0';
    131			*str++ = digits[33];
    132		}
    133	}
    134	if (!(type & LEFT))
    135		while (size-- > 0)
    136			*str++ = c;
    137	while (i < precision--)
    138		*str++ = '0';
    139	while (i-- > 0)
    140		*str++ = tmp[i];
    141	while (size-- > 0)
    142		*str++ = ' ';
    143	return str;
    144}
    145
    146int vsprintf(char *buf, const char *fmt, va_list args)
    147{
    148	int len;
    149	unsigned long long num;
    150	int i, base;
    151	char * str;
    152	const char *s;
    153
    154	int flags;		/* flags to number() */
    155
    156	int field_width;	/* width of output field */
    157	int precision;		/* min. # of digits for integers; max
    158				   number of chars for from string */
    159	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
    160	                        /* 'z' support added 23/7/1999 S.H.    */
    161				/* 'z' changed to 'Z' --davidm 1/25/99 */
    162
    163	
    164	for (str=buf ; *fmt ; ++fmt) {
    165		if (*fmt != '%') {
    166			*str++ = *fmt;
    167			continue;
    168		}
    169			
    170		/* process flags */
    171		flags = 0;
    172		repeat:
    173			++fmt;		/* this also skips first '%' */
    174			switch (*fmt) {
    175				case '-': flags |= LEFT; goto repeat;
    176				case '+': flags |= PLUS; goto repeat;
    177				case ' ': flags |= SPACE; goto repeat;
    178				case '#': flags |= SPECIAL; goto repeat;
    179				case '0': flags |= ZEROPAD; goto repeat;
    180				}
    181		
    182		/* get field width */
    183		field_width = -1;
    184		if ('0' <= *fmt && *fmt <= '9')
    185			field_width = skip_atoi(&fmt);
    186		else if (*fmt == '*') {
    187			++fmt;
    188			/* it's the next argument */
    189			field_width = va_arg(args, int);
    190			if (field_width < 0) {
    191				field_width = -field_width;
    192				flags |= LEFT;
    193			}
    194		}
    195
    196		/* get the precision */
    197		precision = -1;
    198		if (*fmt == '.') {
    199			++fmt;	
    200			if ('0' <= *fmt && *fmt <= '9')
    201				precision = skip_atoi(&fmt);
    202			else if (*fmt == '*') {
    203				++fmt;
    204				/* it's the next argument */
    205				precision = va_arg(args, int);
    206			}
    207			if (precision < 0)
    208				precision = 0;
    209		}
    210
    211		/* get the conversion qualifier */
    212		qualifier = -1;
    213		if (*fmt == 'l' && *(fmt + 1) == 'l') {
    214			qualifier = 'q';
    215			fmt += 2;
    216		} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
    217			|| *fmt == 'Z') {
    218			qualifier = *fmt;
    219			++fmt;
    220		}
    221
    222		/* default base */
    223		base = 10;
    224
    225		switch (*fmt) {
    226		case 'c':
    227			if (!(flags & LEFT))
    228				while (--field_width > 0)
    229					*str++ = ' ';
    230			*str++ = (unsigned char) va_arg(args, int);
    231			while (--field_width > 0)
    232				*str++ = ' ';
    233			continue;
    234
    235		case 's':
    236			s = va_arg(args, char *);
    237			if (!s)
    238				s = "<NULL>";
    239
    240			len = strnlen(s, precision);
    241
    242			if (!(flags & LEFT))
    243				while (len < field_width--)
    244					*str++ = ' ';
    245			for (i = 0; i < len; ++i)
    246				*str++ = *s++;
    247			while (len < field_width--)
    248				*str++ = ' ';
    249			continue;
    250
    251		case 'p':
    252			if (field_width == -1) {
    253				field_width = 2*sizeof(void *);
    254				flags |= ZEROPAD;
    255			}
    256			str = number(str,
    257				(unsigned long) va_arg(args, void *), 16,
    258				field_width, precision, flags);
    259			continue;
    260
    261
    262		case 'n':
    263			if (qualifier == 'l') {
    264				long * ip = va_arg(args, long *);
    265				*ip = (str - buf);
    266			} else if (qualifier == 'Z') {
    267				size_t * ip = va_arg(args, size_t *);
    268				*ip = (str - buf);
    269			} else {
    270				int * ip = va_arg(args, int *);
    271				*ip = (str - buf);
    272			}
    273			continue;
    274
    275		case '%':
    276			*str++ = '%';
    277			continue;
    278
    279		/* integer number formats - set up the flags and "break" */
    280		case 'o':
    281			base = 8;
    282			break;
    283
    284		case 'X':
    285			flags |= LARGE;
    286		case 'x':
    287			base = 16;
    288			break;
    289
    290		case 'd':
    291		case 'i':
    292			flags |= SIGN;
    293		case 'u':
    294			break;
    295
    296		default:
    297			*str++ = '%';
    298			if (*fmt)
    299				*str++ = *fmt;
    300			else
    301				--fmt;
    302			continue;
    303		}
    304		if (qualifier == 'l') {
    305			num = va_arg(args, unsigned long);
    306			if (flags & SIGN)
    307				num = (signed long) num;
    308		} else if (qualifier == 'q') {
    309			num = va_arg(args, unsigned long long);
    310			if (flags & SIGN)
    311				num = (signed long long) num;
    312		} else if (qualifier == 'Z') {
    313			num = va_arg(args, size_t);
    314		} else if (qualifier == 'h') {
    315			num = (unsigned short) va_arg(args, int);
    316			if (flags & SIGN)
    317				num = (signed short) num;
    318		} else {
    319			num = va_arg(args, unsigned int);
    320			if (flags & SIGN)
    321				num = (signed int) num;
    322		}
    323		str = number(str, num, base, field_width, precision, flags);
    324	}
    325	*str = '\0';
    326	return str-buf;
    327}
    328
    329int sprintf(char * buf, const char *fmt, ...)
    330{
    331	va_list args;
    332	int i;
    333
    334	va_start(args, fmt);
    335	i=vsprintf(buf,fmt,args);
    336	va_end(args);
    337	return i;
    338}
    339
    340static char sprint_buf[1024];
    341
    342int
    343printf(const char *fmt, ...)
    344{
    345	va_list args;
    346	int n;
    347
    348	va_start(args, fmt);
    349	n = vsprintf(sprint_buf, fmt, args);
    350	va_end(args);
    351	if (console_ops.write)
    352		console_ops.write(sprint_buf, n);
    353	return n;
    354}