Fossil SCM

Preserve the C89 compatibility of pikchr.c by using MSVC C89 implementations of rint() and snprintf() with older MSVC versions

developer 2021-06-16 20:26 test-msc89
Commit 6429a4bdc284dc03295a1d3d86dd061ca380e586ddb357eb986890b750c32a30
1 file changed +54
+54
--- src/pikchr.c
+++ src/pikchr.c
@@ -128,10 +128,64 @@
128128
#endif
129129
130130
/* Tag intentionally unused parameters with this macro to prevent
131131
** compiler warnings with -Wextra */
132132
#define UNUSED_PARAMETER(X) (void)(X)
133
+
134
+#if defined(_MSC_VER) && (_MSC_VER < 1900) /* before MSVC 2015 */
135
+#include <stdarg.h>
136
+
137
+/* NOTE: On truncation, this version of snprintf returns the input count, not
138
+** the expected number of chars to fully output the requested format (as
139
+** done in the C99 standard implementation). However the truncation test should
140
+** still be applicable (nret >= count).
141
+*/
142
+static __forceinline
143
+int c89_snprintf(char *buf, size_t count, const char *fmt, ...){
144
+ va_list argptr;
145
+ int n;
146
+ if( count==0 ) return 0;
147
+ va_start(argptr, fmt);
148
+ n = _vsprintf_p(buf, count, fmt, argptr);
149
+ va_end(argptr);
150
+
151
+ /* force zero-termination to avoid some known MSVC bugs */
152
+ if( count>0 ){
153
+ buf[count - 1] = '\0';
154
+ if( n<0 ) n = count;
155
+ }
156
+ return n;
157
+}
158
+
159
+#if defined(_WIN64)
160
+#include <emmintrin.h>
161
+#include <limits.h>
162
+
163
+static __forceinline
164
+double c89_rint(double v){
165
+ return ( v<0.0 && v>=-0.5 ? -0.0
166
+ : ( v!=0 && v>LLONG_MIN && v<LLONG_MAX
167
+ ? _mm_cvtsd_si64(_mm_load_sd(&v)) : v ) ); /* SSE2 */
168
+}
169
+#else
170
+static __forceinline
171
+double c89_rint(double v){
172
+ double rn;
173
+ __asm
174
+ {
175
+ FLD v
176
+ FRNDINT
177
+ FSTP rn
178
+ FWAIT
179
+ };
180
+ return rn;
181
+}
182
+#endif /* _WIN64 */
183
+
184
+#define snprintf c89_snprintf
185
+#define rint c89_rint
186
+#endif
133187
134188
typedef struct Pik Pik; /* Complete parsing context */
135189
typedef struct PToken PToken; /* A single token */
136190
typedef struct PObj PObj; /* A single diagram object */
137191
typedef struct PList PList; /* A list of diagram objects */
138192
--- src/pikchr.c
+++ src/pikchr.c
@@ -128,10 +128,64 @@
128 #endif
129
130 /* Tag intentionally unused parameters with this macro to prevent
131 ** compiler warnings with -Wextra */
132 #define UNUSED_PARAMETER(X) (void)(X)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
134 typedef struct Pik Pik; /* Complete parsing context */
135 typedef struct PToken PToken; /* A single token */
136 typedef struct PObj PObj; /* A single diagram object */
137 typedef struct PList PList; /* A list of diagram objects */
138
--- src/pikchr.c
+++ src/pikchr.c
@@ -128,10 +128,64 @@
128 #endif
129
130 /* Tag intentionally unused parameters with this macro to prevent
131 ** compiler warnings with -Wextra */
132 #define UNUSED_PARAMETER(X) (void)(X)
133
134 #if defined(_MSC_VER) && (_MSC_VER < 1900) /* before MSVC 2015 */
135 #include <stdarg.h>
136
137 /* NOTE: On truncation, this version of snprintf returns the input count, not
138 ** the expected number of chars to fully output the requested format (as
139 ** done in the C99 standard implementation). However the truncation test should
140 ** still be applicable (nret >= count).
141 */
142 static __forceinline
143 int c89_snprintf(char *buf, size_t count, const char *fmt, ...){
144 va_list argptr;
145 int n;
146 if( count==0 ) return 0;
147 va_start(argptr, fmt);
148 n = _vsprintf_p(buf, count, fmt, argptr);
149 va_end(argptr);
150
151 /* force zero-termination to avoid some known MSVC bugs */
152 if( count>0 ){
153 buf[count - 1] = '\0';
154 if( n<0 ) n = count;
155 }
156 return n;
157 }
158
159 #if defined(_WIN64)
160 #include <emmintrin.h>
161 #include <limits.h>
162
163 static __forceinline
164 double c89_rint(double v){
165 return ( v<0.0 && v>=-0.5 ? -0.0
166 : ( v!=0 && v>LLONG_MIN && v<LLONG_MAX
167 ? _mm_cvtsd_si64(_mm_load_sd(&v)) : v ) ); /* SSE2 */
168 }
169 #else
170 static __forceinline
171 double c89_rint(double v){
172 double rn;
173 __asm
174 {
175 FLD v
176 FRNDINT
177 FSTP rn
178 FWAIT
179 };
180 return rn;
181 }
182 #endif /* _WIN64 */
183
184 #define snprintf c89_snprintf
185 #define rint c89_rint
186 #endif
187
188 typedef struct Pik Pik; /* Complete parsing context */
189 typedef struct PToken PToken; /* A single token */
190 typedef struct PObj PObj; /* A single diagram object */
191 typedef struct PList PList; /* A list of diagram objects */
192

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button