crt: Deduplicate mingw-w64 stat code into __MINGW_FIXED_STAT macro Create new function-like macro __MINGW_FIXED_STAT with same pattern as existing __MINGW_FIXED_FSTAT macro, and extract repeated stat and wstat code into that new __MINGW_FIXED_STAT macro. Use gcc compound statement extension to create function-like macro and __builtin_choose_expr to choose correct narrow or wide function based on the passed type (char* or wchar_t*). With this patterns, the whole stat and wstat code is deduplicated to macro functions. This allows to extend the __MINGW_FIXED_STAT code by followup changes without duplicating the functionality again. Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/stdio/__mingw_fix_stat.h b/mingw-w64-crt/stdio/__mingw_fix_stat.h index 1317dbf..13e4bf6 100644 --- a/mingw-w64-crt/stdio/__mingw_fix_stat.h +++ b/mingw-w64-crt/stdio/__mingw_fix_stat.h
@@ -19,4 +19,27 @@ _fstat_ret; \ }) +#define __MINGW_CHOOSE_CHAR_WCHART_EXPR(var, char_expr, wchart_expr, other_expr) \ + __builtin_choose_expr(__builtin_types_compatible_p(typeof(var), char), char_expr, \ + __builtin_choose_expr(__builtin_types_compatible_p(typeof(var), wchar_t), wchart_expr, \ + other_expr)) + +#define __MINGW_PATH_PTR_TYPE(path) \ + typeof(__MINGW_CHOOSE_CHAR_WCHART_EXPR((path)[0], (char*)0, (wchar_t*)0, (void)0)) + +#define __MINGW_FIX_STAT_PATH(path) \ + __MINGW_CHOOSE_CHAR_WCHART_EXPR((path)[0], __mingw_fix_stat_path, __mingw_fix_wstat_path, NULL)(path) + +#define __MINGW_FIXED_STAT(stat_func, filename, obj) ({ \ + int _stat_ret; \ + __MINGW_PATH_PTR_TYPE(filename) path = __MINGW_FIX_STAT_PATH(filename); \ + if (path == NULL && (filename) != NULL) { \ + _stat_ret = -1; \ + } else { \ + _stat_ret = (stat_func)(path, (obj)); \ + _stat_ret = __mingw_fix_stat_finish(_stat_ret, (filename), path, (obj)->st_mode); \ + } \ + _stat_ret; \ +}) + #endif
diff --git a/mingw-w64-crt/stdio/msvcr110plus_stat32.c b/mingw-w64-crt/stdio/msvcr110plus_stat32.c index f936ef9..400ac1f 100644 --- a/mingw-w64-crt/stdio/msvcr110plus_stat32.c +++ b/mingw-w64-crt/stdio/msvcr110plus_stat32.c
@@ -11,11 +11,7 @@ int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat); int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat) { - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat32(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_stat32, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(stat32))(const char *, struct _stat32 *) = stat32;
diff --git a/mingw-w64-crt/stdio/msvcr110plus_stat64i32.c b/mingw-w64-crt/stdio/msvcr110plus_stat64i32.c index 89c3e05..299abd8 100644 --- a/mingw-w64-crt/stdio/msvcr110plus_stat64i32.c +++ b/mingw-w64-crt/stdio/msvcr110plus_stat64i32.c
@@ -11,11 +11,7 @@ int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat); int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat) { - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat64i32(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_stat64i32, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(stat64i32))(const char *, struct _stat64i32 *) = stat64i32;
diff --git a/mingw-w64-crt/stdio/msvcr110plus_wstat32.c b/mingw-w64-crt/stdio/msvcr110plus_wstat32.c index 50e183c..85291d9 100644 --- a/mingw-w64-crt/stdio/msvcr110plus_wstat32.c +++ b/mingw-w64-crt/stdio/msvcr110plus_wstat32.c
@@ -11,11 +11,7 @@ int __cdecl wstat32(const wchar_t *_Filename, struct _stat32 *_Stat); int __cdecl wstat32(const wchar_t *_Filename, struct _stat32 *_Stat) { - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat32(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_wstat32, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(wstat32))(const wchar_t *, struct _stat32 *) = wstat32;
diff --git a/mingw-w64-crt/stdio/msvcr110plus_wstat64i32.c b/mingw-w64-crt/stdio/msvcr110plus_wstat64i32.c index caf5ca7..baff6a0 100644 --- a/mingw-w64-crt/stdio/msvcr110plus_wstat64i32.c +++ b/mingw-w64-crt/stdio/msvcr110plus_wstat64i32.c
@@ -11,11 +11,7 @@ int __cdecl wstat64i32(const wchar_t *_Filename, struct _stat64i32 *_Stat); int __cdecl wstat64i32(const wchar_t *_Filename, struct _stat64i32 *_Stat) { - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat64i32(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_wstat64i32, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(wstat64i32))(const wchar_t *, struct _stat64i32 *) = wstat64i32;
diff --git a/mingw-w64-crt/stdio/msvcr110pre_stat32.c b/mingw-w64-crt/stdio/msvcr110pre_stat32.c index 196c2de..8650db2 100644 --- a/mingw-w64-crt/stdio/msvcr110pre_stat32.c +++ b/mingw-w64-crt/stdio/msvcr110pre_stat32.c
@@ -19,11 +19,7 @@ int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat) { struct _stat32i64 st; - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat32i64(_path, &st); - ret = __mingw_fix_stat_finish(ret, _Filename, _path, st.st_mode); + int ret = __MINGW_FIXED_STAT(_stat32i64, _Filename, &st); if (ret != 0) return ret; if (st.st_size > INT32_MAX) {
diff --git a/mingw-w64-crt/stdio/msvcr110pre_stat64i32.c b/mingw-w64-crt/stdio/msvcr110pre_stat64i32.c index 2a6cc9a..d929a4f 100644 --- a/mingw-w64-crt/stdio/msvcr110pre_stat64i32.c +++ b/mingw-w64-crt/stdio/msvcr110pre_stat64i32.c
@@ -19,11 +19,7 @@ int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat) { struct _stat64 st; - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat64(_path, &st); - ret = __mingw_fix_stat_finish(ret, _Filename, _path, st.st_mode); + int ret = __MINGW_FIXED_STAT(_stat64, _Filename, &st); if (ret != 0) return ret; if (st.st_size > INT32_MAX) {
diff --git a/mingw-w64-crt/stdio/msvcr110pre_wstat32.c b/mingw-w64-crt/stdio/msvcr110pre_wstat32.c index b9848ff..308c7f6 100644 --- a/mingw-w64-crt/stdio/msvcr110pre_wstat32.c +++ b/mingw-w64-crt/stdio/msvcr110pre_wstat32.c
@@ -19,11 +19,7 @@ int __cdecl wstat32(const wchar_t *_Filename, struct _stat32 *_Stat) { struct _stat32i64 st; - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat32i64(_path, &st); - ret = __mingw_fix_stat_finish(ret, _Filename, _path, st.st_mode); + int ret = __MINGW_FIXED_STAT(_wstat32i64, _Filename, &st); if (ret != 0) return ret; if (st.st_size > INT32_MAX) {
diff --git a/mingw-w64-crt/stdio/msvcr110pre_wstat64i32.c b/mingw-w64-crt/stdio/msvcr110pre_wstat64i32.c index a7611bf..f8ed493 100644 --- a/mingw-w64-crt/stdio/msvcr110pre_wstat64i32.c +++ b/mingw-w64-crt/stdio/msvcr110pre_wstat64i32.c
@@ -19,11 +19,7 @@ int __cdecl wstat64i32(const wchar_t *_Filename, struct _stat64i32 *_Stat) { struct _stat64 st; - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat64(_path, &st); - ret = __mingw_fix_stat_finish(ret, _Filename, _path, st.st_mode); + int ret = __MINGW_FIXED_STAT(_wstat64, _Filename, &st); if (ret != 0) return ret; if (st.st_size > INT32_MAX) {
diff --git a/mingw-w64-crt/stdio/stat32i64.c b/mingw-w64-crt/stdio/stat32i64.c index 0b0c5cd..f8e84bf 100644 --- a/mingw-w64-crt/stdio/stat32i64.c +++ b/mingw-w64-crt/stdio/stat32i64.c
@@ -11,10 +11,6 @@ int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat); int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat) { - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat32i64(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_stat32i64, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(stat32i64))(const char *, struct _stat32i64 *) = stat32i64;
diff --git a/mingw-w64-crt/stdio/stat64.c b/mingw-w64-crt/stdio/stat64.c index b1f5b43..0cef610 100644 --- a/mingw-w64-crt/stdio/stat64.c +++ b/mingw-w64-crt/stdio/stat64.c
@@ -10,10 +10,6 @@ int __cdecl stat64(const char *_Filename, struct stat64 *_Stat) { - char *_path = __mingw_fix_stat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _stat64(_path, (struct _stat64 *)_Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_stat64, _Filename, (struct _stat64 *)_Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(stat64))(const char *, struct stat64 *) = stat64;
diff --git a/mingw-w64-crt/stdio/wstat32i64.c b/mingw-w64-crt/stdio/wstat32i64.c index 98dcaf1..d4bb87e 100644 --- a/mingw-w64-crt/stdio/wstat32i64.c +++ b/mingw-w64-crt/stdio/wstat32i64.c
@@ -11,10 +11,6 @@ int __cdecl wstat32i64(const wchar_t *_Filename, struct _stat32i64 *_Stat); int __cdecl wstat32i64(const wchar_t *_Filename, struct _stat32i64 *_Stat) { - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat32i64(_path, _Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_wstat32i64, _Filename, _Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(wstat32i64))(const wchar_t *, struct _stat32i64 *) = wstat32i64;
diff --git a/mingw-w64-crt/stdio/wstat64.c b/mingw-w64-crt/stdio/wstat64.c index 76d5474..0f00a4e 100644 --- a/mingw-w64-crt/stdio/wstat64.c +++ b/mingw-w64-crt/stdio/wstat64.c
@@ -10,10 +10,6 @@ int __cdecl wstat64(const wchar_t *_Filename, struct stat64 *_Stat) { - wchar_t *_path = __mingw_fix_wstat_path(_Filename); - if (_path == NULL && _Filename != NULL) - return -1; - int ret = _wstat64(_path, (struct _stat64 *)_Stat); - return __mingw_fix_stat_finish(ret, _Filename, _path, _Stat->st_mode); + return __MINGW_FIXED_STAT(_wstat64, _Filename, (struct _stat64 *)_Stat); } int (__cdecl *__MINGW_IMP_SYMBOL(wstat64))(const wchar_t *, struct stat64 *) = wstat64;