put_c(b, esc, *str++);
}
+#if __LP64__ || defined(__arm64__)
+static unsigned long long
+udiv10(unsigned long long a, unsigned long long *rem)
+{
+ *rem = a % 10;
+ return a / 10;
+}
+#else
+unsigned long long
+udiv10(unsigned long long a, unsigned long long *rem_out)
+{
+ if (a <= UINT_MAX) {
+ *rem_out = (unsigned long long)((unsigned int)a % 10);
+ return (unsigned long long)((unsigned int)a / 10);
+ }
+
+ // The biggest multiple of 10 that dividend might contain
+ unsigned long long divisor = 0xa000000000000000;
+ unsigned long long dividend = a;
+ unsigned long long quotient = 0;
+
+ while (divisor >= 0xa) {
+ quotient = quotient << 1;
+ if (dividend >= divisor) {
+ dividend -= divisor;
+ quotient += 1;
+ }
+ divisor = divisor >> 1;
+ }
+
+ *rem_out = dividend;
+ return quotient;
+}
+#endif
+
/*
* Output the signed decimal string representing the number in "in". "width" is
* the minimum field width, and "zero" is a boolean value, true for zero padding
ssize_t pad;
int neg = 0;
unsigned long long n = (unsigned long long)in;
+ unsigned long long rem;
if(in < 0) {
neg++;
*--cp = 0;
if(n) {
while(n) {
- *--cp = (n % 10) + '0';
- n /= 10;
+ n = udiv10(n, &rem);
+ *--cp = rem + '0';
}
} else
*--cp = '0';
put_s(b, esc, cp);
}
+/*
+ * Output the octal string representing the number in "n". "width" is
+ * the minimum field width, and "zero" is a boolean value, true for zero padding
+ * (otherwise blank padding).
+ */
+static void
+oct(BUF *b, _esc_func esc, unsigned long long n, int width, int zero)
+{
+ char buf[32];
+ char *cp = buf + sizeof(buf);
+ ssize_t pad;
+
+ *--cp = 0;
+ if (n) {
+ while (n) {
+ *--cp = (n % 8) + '0';
+ n /= 8;
+ }
+ } else {
+ *--cp = '0';
+ }
+ pad = width - strlen(cp);
+ zero = zero ? '0' : ' ';
+ while (pad-- > 0) {
+ put_c(b, esc, zero);
+ }
+ put_s(b, esc, cp);
+}
+
/*
* Output the hex string representing the number in "n". "width" is the
* minimum field width, and "zero" is a boolean value, true for zero padding
{
char buf[32];
char *cp = buf + sizeof(buf);
+ unsigned long long rem;
ssize_t pad;
*--cp = 0;
if(n) {
while(n) {
- *--cp = (n % 10) + '0';
- n /= 10;
+ n = udiv10(n, &rem);
+ *--cp = rem + '0';
}
} else
*--cp = '0';
lflag++;
fmt++;
continue;
+ case 'o':
+ switch (lflag) {
+ case 0:
+ oct(b, esc, va_arg(ap, int), width, zero);
+ break;
+ case 1:
+ oct(b, esc, va_arg(ap, long), width, zero);
+ break;
+ default:
+ oct(b, esc, va_arg(ap, long long), width, zero);
+ break;
+ }
+ break;
case 'p':
hex(b, esc, (unsigned long)va_arg(ap, void *), width, zero, 0, 1);
break;