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