1 
2 /*
3  * Copyright (c) 2018-2019, NVIDIA CORPORATION.  All rights reserved.
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  */
18 
19 
20 #if !defined __DEBUG_PRN_H_INCLUDED__
21 #define __DEBUG_PRN_H_INCLUDED__ 1
22 
23 // self-debug
24 #if defined DO_PRINT
25     #include <stdio.h>
26     #include <fenv.h>
27     #include <string.h>
28     #define PRINT(x)    do_printing(&(x), #x, __LINE__, __FILE__, sizeof(x))
29 #else
30     #define PRINT(x)
31 #endif
32 
33 #if defined DO_PRINT
print_status_flags(char * dst)34 static void print_status_flags(char * dst)
35 {
36     if ( fetestexcept(FE_INEXACT) )
37     {
38         strncat(dst, "P", 1);
39     }
40     else
41     {
42         strncat(dst, "p", 1);
43     }
44 
45     if ( fetestexcept(FE_UNDERFLOW) )
46     {
47         strncat(dst, "U", 1);
48     }
49     else
50     {
51         strncat(dst, "u", 1);
52     }
53 
54     if ( fetestexcept(FE_OVERFLOW) )
55     {
56         strncat(dst, "O", 1);
57     }
58     else
59     {
60         strncat(dst, "o", 1);
61     }
62 
63     if ( fetestexcept(FE_DIVBYZERO) )
64     {
65         strncat(dst, "Z", 1);
66     }
67     else
68     {
69         strncat(dst, "z", 1);
70     }
71 //TODO: add non-Intel compiler support for denormal flag
72     {
73         strncat(dst, "d", 1);
74     }
75     if ( fetestexcept(FE_INVALID) )
76     {
77         strncat(dst, "I", 1);
78     }
79     else
80     {
81         strncat(dst, "i", 1);
82     }
83 
84     return;
85 }
86 
do_printing(void * pvar,const char * varname,int linenum,const char * filename,int varsize)87 static void do_printing(void * pvar, const char * varname, int linenum, const char * filename, int varsize)
88 {
89     char buffer[100];
90     char buffer1[150] = "";
91     char tmp[16];
92 
93     // copy last 15 chars from the file name, pad with spaces, right-justified
94     #define THIS_MAX(a, b) ((a) > (b) ? (a) : (b))
95     snprintf(buffer, 15+1+1, "%15s:", filename + THIS_MAX((int)strlen(filename) - 15, 0));
96     #undef THIS_MAX
97     // print line number
98     snprintf(tmp, 5+1+1+1, "%5d: ", linenum);
99     strncat(buffer, tmp, 5+1+1);
100     // print status flags
101     print_status_flags(buffer);
102     strncat(buffer, ": ", 2);
103     // print variable name
104     snprintf(tmp, sizeof(tmp), "%14s:", varname);
105     strncat(buffer, tmp, sizeof(tmp));
106     // print variable value
107     switch(varsize)
108     {
109         case sizeof(float):
110         {
111             float    fval = *((float*)pvar);
112             double   dval = (double)fval;
113             unsigned uval = *((unsigned*)pvar);
114             snprintf(buffer1, 150, "%s:         %08X == %-20g == %-25a == %d",
115                     buffer, uval, dval, fval, uval);
116         }
117             break;
118 default:
119         case sizeof(double):
120         {
121             double   dval = *((double*)pvar);
122             unsigned long long u64val = *((unsigned long long*)pvar);
123             snprintf(buffer1, 150,      "%s: %016llX == %-20g == %-25a == %lld",
124                     buffer, u64val, dval, dval, u64val);
125         }
126             break;
127     }
128 
129     fprintf(stdout, "%s\n", buffer1);
130     return;
131 }
132 #endif
133 
134 #endif //#if !defined __DEBUG_PRN_H_INCLUDED__
135