1/* Printing operations with very long integers.
2 Copyright (C) 2012-2023 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3, or (at your option) any
10later version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "pretty-print.h"
25
26/*
27 * public printing routines.
28 */
29
30#define BLOCKS_NEEDED(PREC) \
31 (((PREC) + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT)
32
33void
34print_dec (const wide_int_ref &wi, char *buf, signop sgn)
35{
36 if (sgn == SIGNED)
37 print_decs (wi, buf);
38 else
39 print_decu (wi, buf);
40}
41
42void
43print_dec (const wide_int_ref &wi, FILE *file, signop sgn)
44{
45 if (sgn == SIGNED)
46 print_decs (wi, file);
47 else
48 print_decu (wi, file);
49}
50
51
52/* Try to print the signed self in decimal to BUF. */
53
54void
55print_decs (const wide_int_ref &wi, char *buf)
56{
57 if (wi.get_precision () <= HOST_BITS_PER_WIDE_INT || wi.get_len () == 1)
58 {
59 if (wi::neg_p (x: wi))
60 sprintf (s: buf, format: "-" HOST_WIDE_INT_PRINT_UNSIGNED,
61 -(unsigned HOST_WIDE_INT) wi.to_shwi ());
62 else
63 sprintf (s: buf, HOST_WIDE_INT_PRINT_DEC, wi.to_shwi ());
64 }
65 else if (wi::neg_p (x: wi))
66 {
67 widest2_int w = widest2_int::from (x: wi, sgn: SIGNED);
68 *buf = '-';
69 print_decu (wi: -w, buf: buf + 1);
70 }
71 else
72 print_decu (wi, buf);
73}
74
75/* Try to print the signed self in decimal to FILE. */
76
77void
78print_decs (const wide_int_ref &wi, FILE *file)
79{
80 char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
81 unsigned len;
82 if (print_decs_buf_size (wi, len: &len))
83 p = XALLOCAVEC (char, len);
84 print_decs (wi, buf: p);
85 fputs (s: p, stream: file);
86}
87
88/* Try to print the unsigned self in decimal to BUF. */
89
90void
91print_decu (const wide_int_ref &wi, char *buf)
92{
93 if ((wi.get_precision () <= HOST_BITS_PER_WIDE_INT)
94 || (wi.get_len () == 1 && !wi::neg_p (x: wi)))
95 sprintf (s: buf, HOST_WIDE_INT_PRINT_UNSIGNED, wi.to_uhwi ());
96 else
97 {
98 widest2_int w = widest2_int::from (x: wi, sgn: UNSIGNED), r;
99 widest2_int ten19 = HOST_WIDE_INT_UC (10000000000000000000);
100 char buf2[20], next1[19], next2[19];
101 size_t l, c = 0, i;
102 /* In order to avoid dividing this twice, print the 19 decimal
103 digit chunks in reverse order into buffer and then reorder
104 them in-place. */
105 while (wi::gtu_p (x: w, y: ten19))
106 {
107 w = wi::divmod_trunc (x: w, y: ten19, sgn: UNSIGNED, remainder_ptr: &r);
108 sprintf (s: buf + c * 19, format: "%019" PRIu64, r.to_uhwi ());
109 ++c;
110 }
111 l = sprintf (s: buf2, HOST_WIDE_INT_PRINT_UNSIGNED, w.to_uhwi ());
112 buf[c * 19 + l] = '\0';
113 memcpy (dest: next1, src: buf, n: 19);
114 memcpy (dest: buf, src: buf2, n: l);
115 for (i = 0; i < c / 2; ++i)
116 {
117 memcpy (dest: next2, src: buf + (c - i - 1) * 19, n: 19);
118 memcpy (dest: buf + l + (c - i - 1) * 19, src: next1, n: 19);
119 memcpy (dest: next1, src: buf + (i + 1) * 19, n: 19);
120 memcpy (dest: buf + l + i * 19, src: next2, n: 19);
121 }
122 if (c & 1)
123 memcpy (dest: buf + l + i * 19, src: next1, n: 19);
124 }
125}
126
127/* Try to print the signed self in decimal to FILE. */
128
129void
130print_decu (const wide_int_ref &wi, FILE *file)
131{
132 char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
133 unsigned len;
134 if (print_decu_buf_size (wi, len: &len))
135 p = XALLOCAVEC (char, len);
136 print_decu (wi, buf: p);
137 fputs (s: p, stream: file);
138}
139
140void
141print_hex (const wide_int_ref &val, char *buf)
142{
143 if (val == 0)
144 buf += sprintf (s: buf, format: "0x0");
145 else
146 {
147 buf += sprintf (s: buf, format: "0x");
148 int start = ROUND_DOWN (val.get_precision (), HOST_BITS_PER_WIDE_INT);
149 int width = val.get_precision () - start;
150 bool first_p = true;
151 for (int i = start; i >= 0; i -= HOST_BITS_PER_WIDE_INT)
152 {
153 unsigned HOST_WIDE_INT uhwi = wi::extract_uhwi (x: val, bitpos: i, width);
154 if (!first_p)
155 buf += sprintf (s: buf, HOST_WIDE_INT_PRINT_PADDED_HEX, uhwi);
156 else if (uhwi != 0)
157 {
158 buf += sprintf (s: buf, HOST_WIDE_INT_PRINT_HEX_PURE, uhwi);
159 first_p = false;
160 }
161 width = HOST_BITS_PER_WIDE_INT;
162 }
163 }
164}
165
166/* Print one big hex number to FILE. Note that some assemblers may not
167 accept this for large modes. */
168void
169print_hex (const wide_int_ref &wi, FILE *file)
170{
171 char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
172 unsigned len;
173 if (print_hex_buf_size (wi, len: &len))
174 p = XALLOCAVEC (char, len);
175 print_hex (val: wi, buf: p);
176 fputs (s: p, stream: file);
177}
178
179/* Print larger precision wide_int. Not defined as inline in a header
180 together with pp_wide_int because XALLOCAVEC will make it uninlinable. */
181
182void
183pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn)
184{
185 unsigned int len;
186 print_dec_buf_size (wi: w, sgn, len: &len);
187 char *buf = XALLOCAVEC (char, len);
188 print_dec (wi: w, buf, sgn);
189 pp_string (pp, buf);
190}
191

source code of gcc/wide-int-print.cc