1 /*BEGIN_LEGAL
2
3 Copyright (c) 2018 Intel Corporation
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16
17 END_LEGAL */
18 /// @file xed-util.c
19 ///
20
21
22 ////////////////////////////////////////////////////////////////////////////
23
24 #include "xed-types.h"
25 #include "xed-util.h"
26 #include "xed-util-private.h"
27 #include "xed-portability.h"
28 #include "xed-portability-private.h"
29 #include "xed-common-defs.h"
30 #include "xed-common-hdrs.h"
31
32 #if defined(__linux__) && defined(__STDC_HOSTED__) && __STDC_HOSTED__ == 0
33 extern void abort (void) __attribute__ ((__noreturn__));
34 #else
35 # include <stdlib.h>
36 #endif
37
38 #include <ctype.h>
39
40
41 ////////////////////////////////////////////////////////////////////////////
42 int xed_verbose = 2;
43
44 #include <stdio.h> //required for fprintf,stderr in xed_abort()
45 #if defined(XED_MESSAGES)
46 FILE* xed_log_file;
47 #endif
48
49 ////////////////////////////////////////////////////////////////////////////
xed_set_verbosity(int v)50 void xed_set_verbosity(int v) {
51 xed_verbose = v;
52 }
53
xed_set_log_file(void * o)54 void xed_set_log_file(void* o) {
55 #if defined(XED_MESSAGES)
56 xed_log_file = (FILE*)o;
57 #else
58 (void)o;
59 #endif
60
61 }
62
63
64
65
66
67 #if !defined(XED_64B)
get_bit63(xed_uint64_t x)68 static XED_INLINE xed_uint64_t get_bit63(xed_uint64_t x) {
69 const xed_uint64_t s = 63;
70 return (x >> s) & 1;
71 }
72
xed_divide_by_10_64by32(xed_uint64_t numerator)73 static XED_INLINE xed_uint64_t xed_divide_by_10_64by32(xed_uint64_t numerator) {
74 /* ONLY WORKS FOR DIVIDE BY 10 because 2*9+1=19 and that is < 20, so I can use subtract */
75 int i=0;
76 const xed_uint32_t denominator = 10;
77 xed_uint64_t tn=numerator;
78 xed_uint64_t tqlo=0;
79 xed_uint32_t ir=0,b=0;
80 xed_uint32_t num=0;
81 xed_uint32_t qbit=0;
82
83 /* binary long division */
84 for(i=0;i<64;i++) {
85 b = get_bit63(tn); // next bit of the numerator
86 num = (ir << 1) | b; // intermediate remainder from last step + new numerator bit
87 if (num >= denominator) {
88 ir = num - denominator;
89 qbit = 1;
90 }
91 else {
92 ir = num;
93 qbit = 0;
94 }
95 tqlo = (tqlo <<1) | qbit;
96 tn = tn << 1;
97 }
98
99 // ignore quotient overflow;
100 return tqlo;
101 }
102 #endif
103
xed_itoa(char * buf,xed_uint64_t f,int buflen)104 int xed_itoa(char* buf, xed_uint64_t f, int buflen) {
105 char tbuf[100];
106 char* p = tbuf;
107 char* fp;
108 xed_uint64_t t = f;
109 xed_uint64_t x,v;
110
111 if (f == 0) {
112 *p++ = '0';
113 *p = 0;
114 return xed_strncpy(buf,tbuf,buflen);
115 }
116
117 while(t) {
118 #if defined(XED_64B)
119 x = t / 10;
120 #else
121 x = xed_divide_by_10_64by32(t);
122 #endif
123 v = t - (x*10);
124 *p++ = '0' + v;
125 t = x;
126 }
127 /* reverse string */
128 *p=0;
129 p--;
130 fp = tbuf;
131 while(fp < p) {
132 char ec = *p;
133 char fc = *fp;
134 *fp = ec;
135 *p = fc;
136 fp++;
137 p--;
138 }
139
140 return xed_strncpy(buf,tbuf,buflen);
141 }
142
add_leading_zeros(char * buf,char * tbuf,int buflen,xed_uint_t bits_to_print)143 static int add_leading_zeros(char* buf,
144 char* tbuf,
145 int buflen,
146 xed_uint_t bits_to_print)
147 {
148 char* p = buf;
149 xed_uint_t ilen = xed_strlen(tbuf);
150 if (ilen < bits_to_print) {
151 xed_uint_t i;
152 xed_uint_t zeros = bits_to_print - ilen;
153 for(i=0 ; i < zeros && buflen>0 ; i++) {
154 buflen--;
155 *p++ = '0';
156 }
157 }
158 return xed_strncpy(p,tbuf,buflen);
159 }
160
161
xed_itoa_hex_ul(char * buf,xed_uint64_t f,xed_uint_t bits_to_print,xed_bool_t leading_zeros,int buflen,xed_bool_t lowercase)162 int xed_itoa_hex_ul(char* buf,
163 xed_uint64_t f,
164 xed_uint_t bits_to_print,
165 xed_bool_t leading_zeros,
166 int buflen,
167 xed_bool_t lowercase)
168 {
169 const xed_uint64_t one = 1;
170 xed_uint_t nibbles_to_print = (bits_to_print+3)/4;
171 xed_uint64_t mul,rdiv;
172 xed_uint64_t n;
173 char tbuf[100];
174 char* p = tbuf;
175 // mask the value to the bits we care about. makes everything else easier.
176 xed_uint64_t ff,t;
177 xed_uint_t div = 0;
178 char base_letter;
179
180 if (bits_to_print == 64) // no masking required
181 ff = f;
182 else
183 ff = f & ((one<<bits_to_print)-1);
184
185 if (ff == 0) {
186 *p++ = '0';
187 *p = 0;
188 if (leading_zeros)
189 return add_leading_zeros(buf,tbuf,buflen,bits_to_print);
190 else
191 return xed_strncpy(buf,tbuf,buflen);
192 }
193
194 t = ff;
195 while(t) {
196 t = t >> 4;
197 div++;
198 }
199
200 n = ff;
201
202 if (lowercase)
203 base_letter = 'a';
204 else
205 base_letter = 'A';
206
207 while(div > 0) {
208
209 div--;
210 rdiv = one<<(4*div);
211 //mul = xed_divide(n,rdiv);
212 mul = (n >> (4*div)) & 0xF;
213 if (div <= nibbles_to_print) {
214 if (mul<10)
215 *p++ = XED_STATIC_CAST(char,mul + '0');
216 else
217 *p++ = XED_STATIC_CAST(char,mul - 10 + base_letter);
218 }
219 n = n - (mul*rdiv);
220 }
221
222 // tack on a null
223 *p = 0;
224 if (leading_zeros)
225 return add_leading_zeros(buf,tbuf,buflen,bits_to_print);
226 return xed_strncpy(buf,tbuf,buflen);
227 }
228
xed_itoa_hex_zeros(char * buf,xed_uint64_t f,xed_uint_t bits_to_print,xed_bool_t leading_zeros,int buflen)229 int xed_itoa_hex_zeros(char* buf,
230 xed_uint64_t f,
231 xed_uint_t bits_to_print,
232 xed_bool_t leading_zeros,
233 int buflen) {
234 const xed_bool_t lowercase=1;
235 return xed_itoa_hex_ul(buf,f,bits_to_print, leading_zeros, buflen, lowercase);
236 (void) leading_zeros;
237 }
238
xed_itoa_hex(char * buf,xed_uint64_t f,xed_uint_t bits_to_print,int buflen)239 int xed_itoa_hex(char* buf,
240 xed_uint64_t f,
241 xed_uint_t bits_to_print,
242 int buflen)
243 {
244 const xed_bool_t lowercase = 1;
245 const xed_bool_t leading_zeros = 0;
246 return xed_itoa_hex_ul(buf, f, bits_to_print, leading_zeros, buflen, lowercase);
247 }
248
xed_itoa_signed(char * buf,xed_int64_t f,int buflen)249 int xed_itoa_signed(char* buf, xed_int64_t f, int buflen) {
250 xed_uint64_t x;
251 int blen = buflen;
252 if (f<0) {
253 blen = xed_strncpy(buf,"-",blen);
254 x = -f;
255 }
256 else
257 x = f;
258 return xed_itoa(buf+xed_strlen(buf), x, blen);
259 }
260
xed_sprintf_uint8_hex(char * buf,xed_uint8_t x,int buflen)261 int xed_sprintf_uint8_hex(char* buf, xed_uint8_t x, int buflen) {
262 return xed_itoa_hex(buf,x,8,buflen);
263 }
xed_sprintf_uint16_hex(char * buf,xed_uint16_t x,int buflen)264 int xed_sprintf_uint16_hex(char* buf, xed_uint16_t x, int buflen) {
265 return xed_itoa_hex(buf,x,16,buflen);
266 }
xed_sprintf_uint32_hex(char * buf,xed_uint32_t x,int buflen)267 int xed_sprintf_uint32_hex(char* buf, xed_uint32_t x, int buflen) {
268 return xed_itoa_hex(buf,x,32,buflen);
269 }
xed_sprintf_uint64_hex(char * buf,xed_uint64_t x,int buflen)270 int xed_sprintf_uint64_hex(char* buf, xed_uint64_t x, int buflen) {
271 return xed_itoa_hex(buf,x,64,buflen);
272 }
xed_sprintf_uint8(char * buf,xed_uint8_t x,int buflen)273 int xed_sprintf_uint8(char* buf, xed_uint8_t x, int buflen) {
274 return xed_itoa(buf, x, buflen);
275 }
xed_sprintf_uint16(char * buf,xed_uint16_t x,int buflen)276 int xed_sprintf_uint16(char* buf, xed_uint16_t x, int buflen) {
277 return xed_itoa(buf, x, buflen);
278 }
xed_sprintf_uint32(char * buf,xed_uint32_t x,int buflen)279 int xed_sprintf_uint32(char* buf, xed_uint32_t x, int buflen) {
280 return xed_itoa(buf, x, buflen);
281 }
xed_sprintf_uint64(char * buf,xed_uint64_t x,int buflen)282 int xed_sprintf_uint64(char* buf, xed_uint64_t x, int buflen) {
283 return xed_itoa(buf, x, buflen);
284 }
xed_sprintf_int8(char * buf,xed_int8_t x,int buflen)285 int xed_sprintf_int8(char* buf, xed_int8_t x, int buflen) {
286 return xed_itoa_signed(buf,x,buflen);
287 }
xed_sprintf_int16(char * buf,xed_int16_t x,int buflen)288 int xed_sprintf_int16(char* buf, xed_int16_t x, int buflen) {
289 return xed_itoa_signed(buf,x,buflen);
290 }
xed_sprintf_int32(char * buf,xed_int32_t x,int buflen)291 int xed_sprintf_int32(char* buf, xed_int32_t x, int buflen) {
292 return xed_itoa_signed(buf,x,buflen);
293 }
xed_sprintf_int64(char * buf,xed_int64_t x,int buflen)294 int xed_sprintf_int64(char* buf, xed_int64_t x, int buflen) {
295 return xed_itoa_signed(buf,x,buflen);
296 }
297
xed_to_ascii_hex_nibble(xed_uint_t x,xed_bool_t lowercase)298 char xed_to_ascii_hex_nibble(xed_uint_t x, xed_bool_t lowercase) {
299 if (x<=9)
300 return XED_STATIC_CAST(char,x+'0');
301 if (x<=15) {
302 if (lowercase)
303 return XED_STATIC_CAST(char,x-10+'a');
304 else
305 return XED_STATIC_CAST(char,x-10+'A');
306 }
307 return '?';
308 }
xed_tolower(char c)309 static char xed_tolower(char c) {
310 if (c >= 'A' && c <= 'Z')
311 return c-'A'+'a';
312 return c;
313 }
314
315
xed_strncat_lower(char * dst,const char * src,int len)316 int xed_strncat_lower(char* dst, const char* src, int len) {
317 unsigned int dst_len = xed_strlen(dst) ;
318 unsigned int orig_max = dst_len + len;
319 unsigned int i;
320 unsigned int src_len = xed_strlen(src);
321 unsigned int copy_max = src_len;
322 unsigned int ulen = (unsigned int)len-1;
323 if (len <= 0)
324 return 0;
325
326 /* do not copy more bytes than fit in the buffer including the null */
327
328 if (src_len > ulen)
329 copy_max = ulen;
330
331 for(i=0;i<copy_max;i++)
332 dst[dst_len+i]=xed_tolower(src[i]);
333
334 dst[dst_len+copy_max]=0;
335 return orig_max - xed_strlen(dst);
336 }
337
338
339
340 ////////////////////////////////////////////////////////////////////////////
341
342 /* arbitrary sign extension from a qty of "bits" length to 64b */
xed_sign_extend_arbitrary_to_64(xed_uint64_t x,unsigned int bits)343 xed_int64_t xed_sign_extend_arbitrary_to_64(xed_uint64_t x, unsigned int bits) {
344 xed_uint64_t one = 1;
345 xed_int64_t mask = one<<(bits-1);
346 xed_int64_t vmask, o=0;
347 if (bits < 64) {
348 vmask = (one<<bits)-1;
349 o = ((x&vmask) ^ mask)- mask;
350 }
351 else if (bits == 64)
352 o=x;
353 else
354 xed_assert(0);
355 return o;
356 }
357
358 /* arbitrary sign extension from a qty of "bits" length to 32b */
xed_sign_extend_arbitrary_to_32(xed_uint32_t x,unsigned int bits)359 xed_int32_t xed_sign_extend_arbitrary_to_32(xed_uint32_t x, unsigned int bits) {
360 xed_int32_t mask = 1<<(bits-1);
361 xed_int32_t vmask, o=0;
362 if (bits < 32) {
363 vmask = (1<<bits)-1;
364 o = ((x&vmask) ^ mask)- mask;
365 }
366 else if (bits == 32)
367 o=x;
368 else
369 xed_assert(0);
370 return o;
371 }
372
373
xed_sign_extend32_64(xed_int32_t x)374 xed_int64_t xed_sign_extend32_64(xed_int32_t x) {
375 return x;
376 }
xed_sign_extend16_64(xed_int16_t x)377 xed_int64_t xed_sign_extend16_64(xed_int16_t x) {
378 return x;
379 }
xed_sign_extend8_64(xed_int8_t x)380 xed_int64_t xed_sign_extend8_64(xed_int8_t x) {
381 return x;
382 }
xed_sign_extend16_32(xed_int16_t x)383 xed_int32_t xed_sign_extend16_32(xed_int16_t x) {
384 return x;
385 }
xed_sign_extend8_32(xed_int8_t x)386 xed_int32_t xed_sign_extend8_32(xed_int8_t x) {
387 return x;
388 }
xed_sign_extend8_16(xed_int8_t x)389 xed_int16_t xed_sign_extend8_16(xed_int8_t x) {
390 return x;
391 }
392
393
xed_zero_extend32_64(xed_uint32_t x)394 xed_uint64_t xed_zero_extend32_64(xed_uint32_t x) {
395 return x;
396 }
xed_zero_extend16_64(xed_uint16_t x)397 xed_uint64_t xed_zero_extend16_64(xed_uint16_t x) {
398 return x;
399 }
xed_zero_extend8_64(xed_uint8_t x)400 xed_uint64_t xed_zero_extend8_64(xed_uint8_t x) {
401 return x;
402 }
xed_zero_extend16_32(xed_uint16_t x)403 xed_uint32_t xed_zero_extend16_32(xed_uint16_t x) {
404 return x;
405 }
xed_zero_extend8_32(xed_uint8_t x)406 xed_uint32_t xed_zero_extend8_32(xed_uint8_t x) {
407 return x;
408 }
xed_zero_extend8_16(xed_uint8_t x)409 xed_uint16_t xed_zero_extend8_16(xed_uint8_t x) {
410 return x;
411 }
412
413 #if defined(XED_LITTLE_ENDIAN_SWAPPING)
xed_sign_extend4_64(xed_int8_t x)414 static XED_INLINE xed_int64_t xed_sign_extend4_64(xed_int8_t x) {
415 const xed_int64_t eight = 8;
416 xed_int64_t o = (x ^ eight)- eight;
417 return o;
418 }
xed_sign_extend4_32(xed_int8_t x)419 static XED_INLINE xed_int32_t xed_sign_extend4_32(xed_int8_t x) {
420 xed_int32_t o = (x ^ 0x00000008)- 0x00000008;
421 return o;
422 }
423
xed_little_endian_hilo_to_int64(xed_uint32_t hi_le,xed_uint32_t lo_le,unsigned int len)424 xed_int64_t xed_little_endian_hilo_to_int64(xed_uint32_t hi_le, xed_uint32_t lo_le, unsigned int len) {
425 switch(len) {
426 case 4:
427 return xed_sign_extend4_64(XED_STATIC_CAST(xed_int8_t,lo_le&0xF));
428 case 8:
429 return xed_sign_extend8_64(XED_STATIC_CAST(xed_int8_t,lo_le));
430 case 16:
431 return xed_sign_extend16_64(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,lo_le)));
432 case 32: {
433 xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,lo_le));
434 xed_int64_t z;
435 //printf("BSWAPING %lx -> %x\n", x,y);
436 z= xed_sign_extend32_64(y);
437 //printf("SEXT -> %lx\n", z);
438 return z;
439 }
440 case 64: {
441 xed_uint64_t z = xed_make_uint64(xed_bswap32(hi_le),xed_bswap32(lo_le));
442 return XED_STATIC_CAST(xed_int64_t,z);
443 }
444 default:
445 xed_assert(0);
446 return 0;
447 }
448 }
xed_little_endian_hilo_to_uint64(xed_uint32_t hi_le,xed_uint32_t lo_le,unsigned int len)449 xed_uint64_t xed_little_endian_hilo_to_uint64(xed_uint32_t hi_le, xed_uint32_t lo_le, unsigned int len) {
450 switch(len) {
451 case 4:
452 return XED_STATIC_CAST(xed_uint8_t,lo_le&0xF);
453 case 8:
454 return XED_STATIC_CAST(xed_uint8_t,lo_le);
455 case 16:
456 return xed_bswap16(XED_STATIC_CAST(xed_uint16_t,lo_le));
457 case 32:
458 return xed_bswap32(XED_STATIC_CAST(xed_uint32_t,lo_le));
459 case 64:
460 return xed_make_uint64(xed_bswap32(hi_le),xed_bswap32(lo_le));
461 default:
462 xed_assert(0);
463 return 0;
464 }
465 }
466
xed_little_endian_to_uint64(xed_uint64_t x,unsigned int len)467 xed_uint64_t xed_little_endian_to_uint64(xed_uint64_t x, unsigned int len) {
468 switch(len) {
469 case 4:
470 return XED_STATIC_CAST(xed_uint8_t,x&0xF);
471 case 8:
472 return XED_STATIC_CAST(xed_uint8_t,x);
473 case 16:
474 return xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x));
475 case 32:
476 return xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
477 case 64:
478 return xed_bswap64(x);
479 default:
480 xed_assert(0);
481 return 0;
482 }
483 }
484
xed_little_endian_to_int64(xed_uint64_t x,unsigned int len)485 xed_int64_t xed_little_endian_to_int64(xed_uint64_t x, unsigned int len){
486 switch(len) {
487 case 4:
488 return xed_sign_extend4_64(XED_STATIC_CAST(xed_int8_t,x&0xF));
489 case 8:
490 return xed_sign_extend8_64(XED_STATIC_CAST(xed_int8_t,x));
491 case 16:
492 return xed_sign_extend16_64(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x)));
493 case 32: {
494 xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
495 xed_int64_t z;
496 //printf("BSWAPING %lx -> %x\n", x,y);
497 z= xed_sign_extend32_64(y);
498 //printf("SEXT -> %lx\n", z);
499 return z;
500 }
501 case 64:
502 return XED_STATIC_CAST(xed_int64_t,xed_bswap64(x));
503 default:
504 xed_assert(0);
505 return 0;
506 }
507 }
508
xed_little_endian_to_int32(xed_uint64_t x,unsigned int len)509 xed_int32_t xed_little_endian_to_int32(xed_uint64_t x, unsigned int len){
510 // heavily reliant on the type system
511 switch(len) {
512 case 4:
513 return xed_sign_extend4_32(XED_STATIC_CAST(xed_int8_t,x&0xF));
514 case 8:
515 return xed_sign_extend8_32(XED_STATIC_CAST(xed_int8_t,x));
516 case 16:
517 return xed_sign_extend16_32(xed_bswap16(XED_STATIC_CAST(xed_uint16_t,x)));
518 case 32: {
519 xed_int32_t y = xed_bswap32(XED_STATIC_CAST(xed_uint32_t,x));
520 return y;
521 }
522 default:
523 xed_assert(0);
524 return 0;
525 }
526 }
527 #endif
528
xed_get_byte(xed_uint64_t x,unsigned int i,unsigned int len)529 xed_uint8_t xed_get_byte(xed_uint64_t x, unsigned int i, unsigned int len) {
530 // THIS IS THE "IN REGISTER" VIEW!
531 // 1B .. .. .. .. .. .. .. 00
532 // 2B .. .. .. .. .. .. 11 00
533 // 4B .. .. .. .. 33 22 11 00
534 // 8B 77 66 55 44 33 22 11 00
535 // (The least significant byte is 00)
536
537 xed_assert (i < len);
538 return XED_BYTE_CAST(x >> (i*8));
539 (void)len; //pacify compiler
540 }
541
542
543
544 xed_uint_t
xed_shortest_width_signed(xed_int64_t x,xed_uint8_t legal_widths)545 xed_shortest_width_signed(xed_int64_t x, xed_uint8_t legal_widths) {
546 static const xed_int64_t max1[] = { 0x7f, 0x7fff, 0x7fffffff };
547 static const xed_int64_t min1[] = { -128,
548 0xffffffffffff8000LL,
549 0xffffffff80000000LL };
550 /*historical note: I experimented with different ways of computing the
551 * constants without making memory references, by shifting, etc. The
552 * thing is that any way I coded it, Gcc's optimizer unrolled the loop,
553 * removed the shifts or memops and did the right thing! I was
554 * astounded. This version of the code was the simplest to maintain
555 * and understand so I'm sticking with it.
556 */
557 unsigned int i,j;
558 for(i=0;i<3;i++)
559 {
560 j = 1 << i;
561 if ((j & legal_widths)==j)
562 if (x <= max1[i] && x >= min1[i])
563 break;
564 }
565 /* returns 1,2,4 or 8 */
566 return 1<<i;
567 }
568
569 xed_uint_t
xed_shortest_width_unsigned(xed_uint64_t x,xed_uint8_t legal_widths)570 xed_shortest_width_unsigned(xed_uint64_t x, xed_uint8_t legal_widths) {
571
572 unsigned int i,j;
573 const xed_uint64_t one = 1;
574 for(i=0;i<3; i++)
575 {
576 j = 1 << i;
577 if ((j & legal_widths)==j)
578 if (x < (one<<(j*8)))
579 break;
580 }
581 /* returns 1,2,4 or 8 */
582 return 1<<i;
583 }
584
585
586
xed_derror(const char * s)587 void xed_derror(const char* s) {
588 XED2DIE((xed_log_file,"%s\n", s));
589 (void)s; // needed for when msgs are disabled and compiler warnings are errors
590 }
591
592 //////////////////////////////////////////
593
594 static xed_user_abort_function_t xed_user_abort_function = 0;
595
596
597 static void* xed_user_abort_other = 0;
598
xed_register_abort_function(xed_user_abort_function_t fn,void * other)599 void xed_register_abort_function(xed_user_abort_function_t fn,
600 void* other) {
601 xed_user_abort_function = fn;
602 xed_user_abort_other = other;
603 }
604
xed_internal_assert(const char * msg,const char * file,int line)605 void xed_internal_assert( const char* msg, const char* file, int line) {
606 if (xed_user_abort_function) {
607 (*xed_user_abort_function)(msg, file, line, xed_user_abort_other);
608 }
609 else {
610 fprintf(stderr,"ASSERTION FAILURE %s at %s:%d\n", msg, file, line);
611 }
612 abort();
613 }
614
615
616