summaryrefslogtreecommitdiffhomepage
path: root/src/etc.c
diff options
context:
space:
mode:
authorcremno <[email protected]>2014-08-03 21:15:48 +0200
committercremno <[email protected]>2014-08-03 21:15:48 +0200
commitb6e27218ad1ffdba6d2103b85d5d9231b6380008 (patch)
tree6b84ad30e85f50fa4eab6c7373306e741d194508 /src/etc.c
parent206f89e2090524f009fc5a87f42c15a453ebdbee (diff)
downloadmruby-b6e27218ad1ffdba6d2103b85d5d9231b6380008.tar.gz
mruby-b6e27218ad1ffdba6d2103b85d5d9231b6380008.zip
MSVC: add simple (v)snprintf implementation
_snprintf is not C99's snprintf! This simple implementation, unlike _snprintf, always null-terminates and returns the expected return value (in most cases). Other C99 behaviors (like format specifiers) require adding a complete snprintf implementation. Do we want or need that? The same applies to vsnprintf (aka _vsnprintf).
Diffstat (limited to 'src/etc.c')
-rw-r--r--src/etc.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/etc.c b/src/etc.c
index 4aee04ec0..9125aa16a 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -183,3 +183,40 @@ mrb_regexp_p(mrb_state *mrb, mrb_value v)
{
return mrb_class_defined(mrb, REGEXP_CLASS) && mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS));
}
+
+#if defined _MSC_VER && _MSC_VER < 1900
+
+#ifndef va_copy
+static void
+mrb_msvc_va_copy(va_list *dest, va_list src)
+{
+ *dest = src;
+}
+#define va_copy(dest, src) msvc_va_copy(&(dest), src)
+#endif
+
+MRB_API int
+mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg)
+{
+ int cnt;
+ va_list argcp;
+ va_copy(argcp, arg);
+ if (n == 0 || (cnt = _vsnprintf_s(s, n, _TRUNCATE, format, argcp)) < 0) {
+ cnt = _vscprintf(format, arg);
+ }
+ va_end(argcp);
+ return cnt;
+}
+
+MRB_API int
+mrb_msvc_snprintf(char *s, size_t n, const char *format, ...)
+{
+ va_list arg;
+ int ret;
+ va_start(arg, format);
+ ret = mrb_msvc_vsnprintf(s, n, format, arg);
+ va_end(arg);
+ return ret;
+}
+
+#endif /* defined _MSC_VER && _MSC_VER < 1900 */