Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /* -*- linux-c -*- ------------------------------------------------------- *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *   Copyright (C) 1991, 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *   Copyright 2007 rPath, Inc. - All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * ----------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Oh, it's a waste of space, but oh-so-yummy for debugging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) int skip_atoi(const char **s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	while (isdigit(**s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 		i = i * 10 + *((*s)++) - '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * put_dec_full4 handles numbers in the range 0 <= r < 10000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * The multiplier 0xccd is round(2^15/10), and the approximation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) void put_dec_full4(char *end, unsigned int r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		unsigned int q = (r * 0xccd) >> 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		*--end = '0' + (r - q * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		r = q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	*--end = '0' + r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) /* put_dec is copied from lib/vsprintf.c with small modifications */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Call put_dec_full4 on x % 10000, return x / 10000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * The approximation x/10000 == (x * 0x346DC5D7) >> 43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * holds for all x < 1,128,869,999.  The largest value this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * helper will ever be asked to convert is 1,125,520,955.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * (second call in the put_dec code, assuming n is all-ones).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) unsigned int put_dec_helper4(char *end, unsigned int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	unsigned int q = (x * 0x346DC5D7ULL) >> 43;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	put_dec_full4(end, x - q * 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	return q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) /* Based on code by Douglas W. Jones found at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * (with permission from the author).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * Performs no 64-bit division and hence should be fast on 32-bit machines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) char *put_dec(char *end, unsigned long long n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned int d3, d2, d1, q, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	char *p = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	d1  = ((unsigned int)n >> 16); /* implicit "& 0xffff" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	h   = (n >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	d2  = (h      ) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	d3  = (h >> 16); /* implicit "& 0xffff" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	/* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	q = put_dec_helper4(p, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	p -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	q += 7671 * d3 + 9496 * d2 + 6 * d1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	q = put_dec_helper4(p, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	p -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	q += 4749 * d3 + 42 * d2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	q = put_dec_helper4(p, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	p -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	q += 281 * d3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	q = put_dec_helper4(p, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	p -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	put_dec_full4(p, q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	p -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	/* strip off the extra 0's we printed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	while (p < end && *p == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		++p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) char *number(char *end, unsigned long long num, int base, char locase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	 * locase = 0 or 0x20. ORing digits or letters with 'locase'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	 * produces same digits or (maybe lowercased) letters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	switch (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (num != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			end = put_dec(end, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		for (; num != 0; num >>= 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			*--end = '0' + (num & 07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		for (; num != 0; num >>= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			*--end = digits[num & 0xf] | locase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		unreachable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	return end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define ZEROPAD	1		/* pad with zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define SIGN	2		/* unsigned/signed long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define PLUS	4		/* show plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SPACE	8		/* space if plus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define LEFT	16		/* left justified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #define SMALL	32		/* Must be 32 == 0x20 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define SPECIAL	64		/* 0x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define WIDE	128		/* UTF-16 string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int get_flags(const char **fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	int flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		switch (**fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		case '-':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			flags |= LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		case '+':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			flags |= PLUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		case ' ':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			flags |= SPACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		case '#':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			flags |= SPECIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		case '0':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			flags |= ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			return flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		++(*fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	} while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int get_int(const char **fmt, va_list *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if (isdigit(**fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		return skip_atoi(fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	if (**fmt == '*') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		++(*fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		/* it's the next argument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		return va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned long long get_number(int sign, int qualifier, va_list *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (sign) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		switch (qualifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			return va_arg(*ap, long long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			return va_arg(*ap, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			return (short)va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		case 'H':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			return (signed char)va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			return va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		switch (qualifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			return va_arg(*ap, unsigned long long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			return va_arg(*ap, unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		case 'h':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 			return (unsigned short)va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		case 'H':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			return (unsigned char)va_arg(*ap, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			return va_arg(*ap, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) char get_sign(long long *num, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	if (!(flags & SIGN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (*num < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		*num = -(*num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		return '-';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	if (flags & PLUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		return '+';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (flags & SPACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		return ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) size_t utf16s_utf8nlen(const u16 *s16, size_t maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	size_t len, clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	for (len = 0; len < maxlen && *s16; len += clen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		u16 c0 = *s16++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		/* First, get the length for a BMP character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		clen = 1 + (c0 >= 0x80) + (c0 >= 0x800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		if (len + clen > maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		 * If this is a high surrogate, and we're already at maxlen, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		 * can't include the character if it's a valid surrogate pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		 * Avoid accessing one extra word just to check if it's valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		 * or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if ((c0 & 0xfc00) == 0xd800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			if (len + clen == maxlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			if ((*s16 & 0xfc00) == 0xdc00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				++s16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 				++clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u32 utf16_to_utf32(const u16 **s16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	u16 c0, c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	c0 = *(*s16)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	/* not a surrogate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	if ((c0 & 0xf800) != 0xd800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		return c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	/* invalid: low surrogate instead of high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (c0 & 0x0400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		return 0xfffd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	c1 = **s16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	/* invalid: missing low surrogate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if ((c1 & 0xfc00) != 0xdc00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		return 0xfffd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	/* valid surrogate pair */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	++(*s16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	return (0x10000 - (0xd800 << 10) - 0xdc00) + (c0 << 10) + c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define PUTC(c) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) do {				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	if (pos < size)		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		buf[pos] = (c);	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	++pos;			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	/* The maximum space required is to print a 64-bit number in octal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	long long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	const char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	size_t len, pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	char sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	int flags;		/* flags to number() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	int field_width;	/* width of output field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	int precision;		/* min. # of digits for integers; max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				   number of chars for from string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	int qualifier;		/* 'h', 'hh', 'l' or 'll' for integer fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	 * We want to pass our input va_list to helper functions by reference,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	 * but there's an annoying edge case. If va_list was originally passed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	 * to us by value, we could just pass &ap down to the helpers. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	 * the case on, for example, X86_32.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	 * However, on X86_64 (and possibly others), va_list is actually a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	 * size-1 array containing a structure. Our function parameter ap has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	 * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	 * which is what will be expected by a function taking a va_list *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	 * parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	 * One standard way to solve this mess is by creating a copy in a local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	 * variable of type va_list and then passing a pointer to that local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	 * copy instead, which is what we do here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	va_copy(args, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	for (pos = 0; *fmt; ++fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		if (*fmt != '%' || *++fmt == '%') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			PUTC(*fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		/* process flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		flags = get_flags(&fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		/* get field width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		field_width = get_int(&fmt, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (field_width < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			field_width = -field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			flags |= LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		if (flags & LEFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			flags &= ~ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		/* get the precision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		precision = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		if (*fmt == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 			precision = get_int(&fmt, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			if (precision >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 				flags &= ~ZEROPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		/* get the conversion qualifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		qualifier = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		if (*fmt == 'h' || *fmt == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			qualifier = *fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			if (qualifier == *fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 				qualifier -= 'a'-'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 				++fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		sign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		switch (*fmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			flags &= LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			s = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			if (qualifier == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 				((u16 *)tmp)[0] = (u16)va_arg(args, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 				((u16 *)tmp)[1] = L'\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 				precision = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 				goto wstring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 				tmp[0] = (unsigned char)va_arg(args, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 				precision = len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 			goto output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 			flags &= LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			if (precision < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 				precision = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			s = va_arg(args, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 				s = precision < 6 ? "" : "(null)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 			else if (qualifier == 'l') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		wstring:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 				flags |= WIDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 				precision = len = utf16s_utf8nlen((const u16 *)s, precision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 				goto output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 			precision = len = strnlen(s, precision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 			goto output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			/* integer number formats - set up the flags and "break" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			if (precision < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				precision = 2 * sizeof(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			flags |= SMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		case 'X':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 			base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 			flags |= SIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			flags &= ~SPECIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			base = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 			 * Bail out if the conversion specifier is invalid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			 * There's probably a typo in the format string and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 			 * remaining specifiers are unlikely to match up with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 			 * the arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 			goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		if (*fmt == 'p') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 			num = (unsigned long)va_arg(args, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			num = get_number(flags & SIGN, qualifier, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		sign = get_sign(&num, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		if (sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 			--field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		s = number(tmp_end, num, base, flags & SMALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		len = tmp_end - s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		/* default precision is 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		if (precision < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 			precision = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		/* precision is minimum number of digits to print */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		if (precision < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			precision = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		if (flags & SPECIAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			 * For octal, a leading 0 is printed only if necessary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			 * i.e. if it's not already there because of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			 * precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 			if (base == 8 && precision == len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 				++precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			 * For hexadecimal, the leading 0x is skipped if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			 * output is empty, i.e. both the number and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 			 * precision are 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			if (base == 16 && precision > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				field_width -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 				flags &= ~SPECIAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		 * For zero padding, increase the precision to fill the field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		 * width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		if ((flags & ZEROPAD) && field_width > precision)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			precision = field_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		/* Calculate the padding necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		field_width -= precision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		/* Leading padding with ' ' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		if (!(flags & LEFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 			while (field_width-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 				PUTC(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		/* sign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		if (sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 			PUTC(sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		/* 0x/0X for hexadecimal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		if (flags & SPECIAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			PUTC('0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			PUTC( 'X' | (flags & SMALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		/* Zero padding and excess precision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		while (precision-- > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			PUTC('0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		/* Actual output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		if (flags & WIDE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			const u16 *ws = (const u16 *)s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 			while (len-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 				u32 c32 = utf16_to_utf32(&ws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 				u8 *s8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 				size_t clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 				if (c32 < 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 					PUTC(c32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 				/* Number of trailing octets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 				clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 				len -= clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 				s8 = (u8 *)&buf[pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 				/* Avoid writing partial character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 				PUTC('\0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 				pos += clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 				if (pos >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 				/* Set high bits of leading octet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 				*s8 = (0xf00 >> 1) >> clen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 				/* Write trailing octets in reverse order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 				for (s8 += clen; clen; --clen, c32 >>= 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 					*s8-- = 0x80 | (c32 & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 				/* Set low bits of leading octet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 				*s8 |= c32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 			while (len-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 				PUTC(*s++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		/* Trailing padding with ' ' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		while (field_width-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 			PUTC(' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		buf[min(pos, size-1)] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int snprintf(char *buf, size_t size, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	i = vsnprintf(buf, size, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }