1 | /* Support for diagnostic traces. |
---|
2 | |
---|
3 | Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
---|
4 | |
---|
5 | This file is part of the GNU MP Library. |
---|
6 | |
---|
7 | The GNU MP Library is free software; you can redistribute it and/or modify |
---|
8 | it under the terms of the GNU Lesser General Public License as published by |
---|
9 | the Free Software Foundation; either version 2.1 of the License, or (at your |
---|
10 | option) any later version. |
---|
11 | |
---|
12 | The GNU MP Library is distributed in the hope that it will be useful, but |
---|
13 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
---|
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
---|
15 | License for more details. |
---|
16 | |
---|
17 | You should have received a copy of the GNU Lesser General Public License |
---|
18 | along with the GNU MP Library; see the file COPYING.LIB. If not, write to |
---|
19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
---|
20 | MA 02111-1307, USA. */ |
---|
21 | |
---|
22 | |
---|
23 | /* Future: Would like commas printed between limbs in hex or binary, but |
---|
24 | perhaps not always since it might upset cutting and pasting into bc or |
---|
25 | whatever. */ |
---|
26 | |
---|
27 | |
---|
28 | #include <stdio.h> |
---|
29 | #include <stdlib.h> |
---|
30 | #include <string.h> /* for strlen */ |
---|
31 | |
---|
32 | #include "gmp.h" |
---|
33 | #include "gmp-impl.h" |
---|
34 | |
---|
35 | #include "tests.h" |
---|
36 | |
---|
37 | |
---|
38 | /* Number base for the various trace printing routines. |
---|
39 | Set this in main() or with the debugger. |
---|
40 | If hexadecimal is going to be fed into GNU bc, remember to use -16 |
---|
41 | because bc requires upper case. */ |
---|
42 | |
---|
43 | int mp_trace_base = 10; |
---|
44 | |
---|
45 | |
---|
46 | void |
---|
47 | mp_trace_start (const char *name) |
---|
48 | { |
---|
49 | if (name != NULL && name[0] != '\0') |
---|
50 | printf ("%s=", name); |
---|
51 | |
---|
52 | switch (ABS (mp_trace_base)) { |
---|
53 | case 2: printf ("bin:"); break; |
---|
54 | case 8: printf ("oct:"); break; |
---|
55 | case 10: break; |
---|
56 | case 16: printf ("0x"); break; |
---|
57 | default: printf ("base%d:", ABS (mp_trace_base)); break; |
---|
58 | } |
---|
59 | } |
---|
60 | |
---|
61 | /* Print "name=value\n" to stdout for an mpq_t value. */ |
---|
62 | void |
---|
63 | mpq_trace (const char *name, mpq_srcptr q) |
---|
64 | { |
---|
65 | mp_trace_start (name); |
---|
66 | if (q == NULL) |
---|
67 | { |
---|
68 | printf ("NULL\n"); |
---|
69 | return; |
---|
70 | } |
---|
71 | |
---|
72 | mpq_out_str (stdout, mp_trace_base, q); |
---|
73 | printf ("\n"); |
---|
74 | } |
---|
75 | |
---|
76 | |
---|
77 | /* Print "name=value\n" to stdout for an mpz_t value. */ |
---|
78 | void |
---|
79 | mpz_trace (const char *name, mpz_srcptr z) |
---|
80 | { |
---|
81 | mpq_t q; |
---|
82 | mp_limb_t one; |
---|
83 | |
---|
84 | if (z == NULL) |
---|
85 | { |
---|
86 | mpq_trace (name, NULL); |
---|
87 | return; |
---|
88 | } |
---|
89 | |
---|
90 | q->_mp_num._mp_alloc = ALLOC(z); |
---|
91 | q->_mp_num._mp_size = SIZ(z); |
---|
92 | q->_mp_num._mp_d = PTR(z); |
---|
93 | |
---|
94 | one = 1; |
---|
95 | q->_mp_den._mp_alloc = 1; |
---|
96 | q->_mp_den._mp_size = 1; |
---|
97 | q->_mp_den._mp_d = &one; |
---|
98 | |
---|
99 | mpq_trace(name, q); |
---|
100 | } |
---|
101 | |
---|
102 | |
---|
103 | /* Print "name=value\n" to stdout for an mpf_t value. */ |
---|
104 | void |
---|
105 | mpf_trace (const char *name, mpf_srcptr f) |
---|
106 | { |
---|
107 | mp_trace_start (name); |
---|
108 | if (f == NULL) |
---|
109 | { |
---|
110 | printf ("NULL\n"); |
---|
111 | return; |
---|
112 | } |
---|
113 | |
---|
114 | mpf_out_str (stdout, mp_trace_base, 0, f); |
---|
115 | printf ("\n"); |
---|
116 | } |
---|
117 | |
---|
118 | |
---|
119 | /* Print "namenum=value\n" to stdout for an mpz_t value. |
---|
120 | "name" should have a "%d" to get the number. */ |
---|
121 | void |
---|
122 | mpz_tracen (const char *name, int num, mpz_srcptr z) |
---|
123 | { |
---|
124 | if (name != NULL && name[0] != '\0') |
---|
125 | { |
---|
126 | printf (name, num); |
---|
127 | putchar ('='); |
---|
128 | } |
---|
129 | mpz_trace (NULL, z); |
---|
130 | } |
---|
131 | |
---|
132 | |
---|
133 | /* Print "name=value\n" to stdout for an mpn style ptr,size. */ |
---|
134 | void |
---|
135 | mpn_trace (const char *name, mp_srcptr ptr, mp_size_t size) |
---|
136 | { |
---|
137 | mpz_t z; |
---|
138 | if (ptr == NULL) |
---|
139 | { |
---|
140 | mpz_trace (name, NULL); |
---|
141 | return; |
---|
142 | } |
---|
143 | MPN_NORMALIZE (ptr, size); |
---|
144 | PTR(z) = (mp_ptr) ptr; |
---|
145 | SIZ(z) = size; |
---|
146 | ALLOC(z) = size; |
---|
147 | mpz_trace (name, z); |
---|
148 | } |
---|
149 | |
---|
150 | |
---|
151 | /* Print "namenum=value\n" to stdout for an mpn style ptr,size. |
---|
152 | "name" should have a "%d" to get the number. */ |
---|
153 | void |
---|
154 | mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size) |
---|
155 | { |
---|
156 | if (name != NULL && name[0] != '\0') |
---|
157 | { |
---|
158 | printf (name, num); |
---|
159 | putchar ('='); |
---|
160 | } |
---|
161 | mpn_trace (NULL, ptr, size); |
---|
162 | } |
---|
163 | |
---|
164 | |
---|
165 | /* Print "namenum=value\n" to stdout for an array of mpn style ptr,size. |
---|
166 | |
---|
167 | "a" is an array of pointers, each a[i] is a pointer to "size" many limbs. |
---|
168 | The formal parameter isn't mp_srcptr because that causes compiler |
---|
169 | warnings, but the values aren't modified. |
---|
170 | |
---|
171 | "name" should have a printf style "%d" to get the array index. */ |
---|
172 | |
---|
173 | void |
---|
174 | mpn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size) |
---|
175 | { |
---|
176 | int i; |
---|
177 | for (i = 0; i < count; i++) |
---|
178 | mpn_tracen (name, i, a[i], size); |
---|
179 | } |
---|
180 | |
---|
181 | |
---|
182 | /* Print "value\n" to a file for an mpz_t value. Any previous contents of |
---|
183 | the file are overwritten, so you need different file names each time this |
---|
184 | is called. |
---|
185 | |
---|
186 | Overwriting the file is a feature, it means you get old data replaced |
---|
187 | when you run a test program repeatedly. */ |
---|
188 | |
---|
189 | void |
---|
190 | mpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size) |
---|
191 | { |
---|
192 | FILE *fp; |
---|
193 | mpz_t z; |
---|
194 | |
---|
195 | fp = fopen (filename, "w"); |
---|
196 | if (fp == NULL) |
---|
197 | { |
---|
198 | perror ("fopen"); |
---|
199 | abort(); |
---|
200 | } |
---|
201 | |
---|
202 | MPN_NORMALIZE (ptr, size); |
---|
203 | PTR(z) = (mp_ptr) ptr; |
---|
204 | SIZ(z) = (int) size; |
---|
205 | |
---|
206 | mpz_out_str (fp, mp_trace_base, z); |
---|
207 | fprintf (fp, "\n"); |
---|
208 | |
---|
209 | if (ferror (fp) || fclose (fp) != 0) |
---|
210 | { |
---|
211 | printf ("error writing %s\n", filename); |
---|
212 | abort(); |
---|
213 | } |
---|
214 | } |
---|
215 | |
---|
216 | |
---|
217 | /* Print "value\n" to a set of files, one file for each element of the given |
---|
218 | array of mpn style ptr,size. Any previous contents of the files are |
---|
219 | overwritten, so you need different file names each time this is called. |
---|
220 | Each file is "filenameN" where N is 0 to count-1. |
---|
221 | |
---|
222 | "a" is an array of pointers, each a[i] is a pointer to "size" many limbs. |
---|
223 | The formal parameter isn't mp_srcptr because that causes compiler |
---|
224 | warnings, but the values aren't modified. |
---|
225 | |
---|
226 | Overwriting the files is a feature, it means you get old data replaced |
---|
227 | when you run a test program repeatedly. The output style isn't |
---|
228 | particularly pretty, but at least it gets something out, and you can cat |
---|
229 | the files into bc, or whatever. */ |
---|
230 | |
---|
231 | void |
---|
232 | mpn_tracea_file (const char *filename, |
---|
233 | const mp_ptr *a, int count, mp_size_t size) |
---|
234 | { |
---|
235 | char *s; |
---|
236 | int i; |
---|
237 | TMP_DECL (marker); |
---|
238 | |
---|
239 | TMP_MARK (marker); |
---|
240 | s = (char *) TMP_ALLOC (strlen (filename) + 50); |
---|
241 | |
---|
242 | for (i = 0; i < count; i++) |
---|
243 | { |
---|
244 | sprintf (s, "%s%d", filename, i); |
---|
245 | mpn_trace_file (s, a[i], size); |
---|
246 | } |
---|
247 | |
---|
248 | TMP_FREE (marker); |
---|
249 | } |
---|
250 | |
---|
251 | |
---|
252 | void |
---|
253 | byte_trace (const char *name, const void *ptr, mp_size_t size) |
---|
254 | { |
---|
255 | char *fmt; |
---|
256 | mp_size_t i; |
---|
257 | |
---|
258 | mp_trace_start (name); |
---|
259 | |
---|
260 | switch (mp_trace_base) { |
---|
261 | case 8: fmt = " %o"; break; |
---|
262 | case 10: fmt = " %d"; break; |
---|
263 | case 16: fmt = " %x"; break; |
---|
264 | case -16: fmt = " %X"; break; |
---|
265 | default: printf ("Oops, unsupported base in byte_trace\n"); abort (); break; |
---|
266 | } |
---|
267 | |
---|
268 | for (i = 0; i < size; i++) |
---|
269 | printf (fmt, (int) ((unsigned char *) ptr)[i]); |
---|
270 | printf ("\n"); |
---|
271 | } |
---|
272 | |
---|
273 | void |
---|
274 | byte_tracen (const char *name, int num, const void *ptr, mp_size_t size) |
---|
275 | { |
---|
276 | if (name != NULL && name[0] != '\0') |
---|
277 | { |
---|
278 | printf (name, num); |
---|
279 | putchar ('='); |
---|
280 | } |
---|
281 | byte_trace (NULL, ptr, size); |
---|
282 | } |
---|