- neg = FALSE;
-#endif
- GCC_DIAG_RESTORE;
- CLANG_DIAG_RESTORE;
- if (neg) {
- s.st_ino = (IV)PL_statcache.st_ino;
- if (LIKELY(s.st_ino == PL_statcache.st_ino)) {
- mPUSHi(s.st_ino);
- } else {
- char buf[sizeof(s.st_ino)*3+1], *p;
- s.st_ino = PL_statcache.st_ino;
- for (p = buf + sizeof(buf); p != buf+1; ) {
- Stat_t t;
- t.st_ino = s.st_ino / 10;
- *--p = '0' + (int)(t.st_ino*10 - s.st_ino);
- s.st_ino = t.st_ino;
- }
- while (*p == '0')
- p++;
- *--p = '-';
- mPUSHp(p, buf+sizeof(buf) - p);
- }
- } else {
- s.st_ino = (UV)PL_statcache.st_ino;
- if (LIKELY(s.st_ino == PL_statcache.st_ino)) {
- mPUSHu(s.st_ino);
- } else {
- char buf[sizeof(s.st_ino)*3], *p;
- s.st_ino = PL_statcache.st_ino;
- for (p = buf + sizeof(buf); p != buf; ) {
- Stat_t t;
- t.st_ino = s.st_ino / 10;
- *--p = '0' + (int)(s.st_ino - t.st_ino*10);
- s.st_ino = t.st_ino;
- }
- while (*p == '0')
- p++;
- mPUSHp(p, buf+sizeof(buf) - p);
- }
- }
- }
- mPUSHu(PL_statcache.st_mode);
- mPUSHu(PL_statcache.st_nlink);
-
+# if ST_DEV_SIGN < 0
+ if (LIKELY((IV)PL_statcache.st_dev == PL_statcache.st_dev)) {
+ mPUSHi((IV)PL_statcache.st_dev);
+ }
+# else
+ if (LIKELY((UV)PL_statcache.st_dev == PL_statcache.st_dev)) {
+ mPUSHu((UV)PL_statcache.st_dev);
+ }
+# endif
+ else {
+ char buf[sizeof(PL_statcache.st_dev)*3+1];
+ /* sv_catpvf() casts 'j' size values down to IV, so it
+ isn't suitable for use here.
+ */
+# if defined(I_INTTYPES) && defined(HAS_SNPRINTF)
+# if ST_DEV_SIGN < 0
+ int size = snprintf(buf, sizeof(buf), "%" PRIdMAX, (intmax_t)PL_statcache.st_dev);
+# else
+ int size = snprintf(buf, sizeof(buf), "%" PRIuMAX, (uintmax_t)PL_statcache.st_dev);
+# endif
+ STATIC_ASSERT_STMT(sizeof(intmax_t) >= sizeof(PL_statcache.st_dev));
+ mPUSHp(buf, size);
+# else
+# error extraordinarily large st_dev but no inttypes.h or no snprintf
+# endif
+ }
+#endif
+ {
+ /*
+ * We try to represent st_ino as a native IV or UV where
+ * possible, but fall back to a decimal string where
+ * necessary. The code to generate these decimal strings
+ * is quite obtuse, because (a) we're portable to non-POSIX
+ * platforms where st_ino might be signed; (b) we didn't
+ * necessarily detect at Configure time whether st_ino is
+ * signed; (c) we're portable to non-POSIX platforms where
+ * ino_t isn't defined, so have no name for the type of
+ * st_ino; and (d) sprintf() doesn't necessarily support
+ * integers as large as st_ino.
+ */
+ bool neg;
+ Stat_t s;
+ CLANG_DIAG_IGNORE_STMT(-Wtautological-compare);
+ GCC_DIAG_IGNORE_STMT(-Wtype-limits);
+ neg = PL_statcache.st_ino < 0;
+ GCC_DIAG_RESTORE_STMT;
+ CLANG_DIAG_RESTORE_STMT;
+ if (neg) {
+ s.st_ino = (IV)PL_statcache.st_ino;
+ if (LIKELY(s.st_ino == PL_statcache.st_ino)) {
+ mPUSHi(s.st_ino);
+ } else {
+ char buf[sizeof(s.st_ino)*3+1], *p;
+ s.st_ino = PL_statcache.st_ino;
+ for (p = buf + sizeof(buf); p != buf+1; ) {
+ Stat_t t;
+ t.st_ino = s.st_ino / 10;
+ *--p = '0' + (int)(t.st_ino*10 - s.st_ino);
+ s.st_ino = t.st_ino;
+ }
+ while (*p == '0')
+ p++;
+ *--p = '-';
+ mPUSHp(p, buf+sizeof(buf) - p);
+ }
+ } else {
+ s.st_ino = (UV)PL_statcache.st_ino;
+ if (LIKELY(s.st_ino == PL_statcache.st_ino)) {
+ mPUSHu(s.st_ino);
+ } else {
+ char buf[sizeof(s.st_ino)*3], *p;
+ s.st_ino = PL_statcache.st_ino;
+ for (p = buf + sizeof(buf); p != buf; ) {
+ Stat_t t;
+ t.st_ino = s.st_ino / 10;
+ *--p = '0' + (int)(s.st_ino - t.st_ino*10);
+ s.st_ino = t.st_ino;
+ }
+ while (*p == '0')
+ p++;
+ mPUSHp(p, buf+sizeof(buf) - p);
+ }
+ }
+ }
+ mPUSHu(PL_statcache.st_mode);
+ mPUSHu(PL_statcache.st_nlink);
+