Files
Rhialto The M aa5e36aac2 Fix remaining warnings (#574)
* Work around nonportable printing of pthread_t values.

Consider these warnings:
```
  CC       hthreads.lo
In file included from msgenu.h:19,
                 from hercules.h:104,
                 from hthreads.c:19:
hthreads.c: In function 'locks_cmd':
printfmt.h:120:33: warning: format '%lx' expects argument of type 'long unsigned int *', but argument 3 has type 'struct __pthread_st **' [-Wformat=]
  120 |   #define SCN_TIDPAT            "%"PRIx64       // complete format spec
      |                                 ^~~
hthreads.c:1295:31: note: in expansion of macro 'SCN_TIDPAT'
 1295 |     else if (sscanf( argv[1], SCN_TIDPAT "%c", &tid, &c ) != 1)
      |                               ^~~~~~~~~~
In file included from /usr/include/sys/inttypes.h:43,
                 from /usr/include/sys/mutex.h:144,
                 from /usr/include/net/if.h:87,
                 from /usr/include/net/route.h:40,
                 from hstdinc.h:154,
                 from hthreads.c:14:
/usr/include/amd64/int_fmtio.h:112:19: note: format string is defined here
  112 | #define PRIx64  "lx" /* uint64_t  */

In file included from msgenu.h:19,
                 from hercules.h:104,
                 from hthreads.c:19:
hthreads.c: In function 'threads_cmd':
printfmt.h:120:33: warning: format '%lx' expects argument of type 'long unsigned int *', but argument 3 has type 'struct __pthread_st **' [-Wformat=]
  120 |   #define SCN_TIDPAT            "%"PRIx64       // complete format spec
      |                                 ^~~
hthreads.c:1563:31: note: in expansion of macro 'SCN_TIDPAT'
 1563 |     else if (sscanf( argv[1], SCN_TIDPAT "%c", &tid, &c ) != 1)
      |                               ^~~~~~~~~~
In file included from /usr/include/sys/inttypes.h:43,
                 from /usr/include/sys/mutex.h:144,
                 from /usr/include/net/if.h:87,
                 from /usr/include/net/route.h:40,
                 from hstdinc.h:154,
                 from hthreads.c:14:
/usr/include/amd64/int_fmtio.h:112:19: note: format string is defined here
  112 | #define PRIx64  "lx" /* uint64_t  */

tcpnje.c: In function 'tcpnje_thread':
tcpnje.c:1458:15: warning: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'pthread_t' {aka 'struct __pthread_st *'} [-Wformat=]
 1458 |     DBGMSG(1, "HHCTN002I %4.4X:TCPNJE - networking thread "TIDPAT" started for link %s - %s\n",
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tcpnje.c:98:109: note: in definition of macro 'DBGMSG'
   98 | #define DBGMSG(_level, ...) if ((tn->dev->ccwtrace && (_level & tn->trace)) || (_level & tn->debug)) logmsg(__VA_ARGS__)
      |                                                                                                             ^~~~~~~~~~~
```
Apparently, values of type TID, which expands to pthread_t, are scanned in
with sscanf(). Unfortunately this is quite difficult since it is unknown
if these values are integers (and what size), pointers, or even
strucures. In the last case they can't be printed or scanned at all.
This follows from
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html

The workaround is to define an integral type which is (hopefully) long
enough to contain the pthread_t value; it's the same type that is used
when printing it, so hopefully that's ok. Then we use this type for
sscanf() to store its scanned value in, so that it matches with the
pattern given in SCN_TIDPAT. Then the value is copied to the TID
variable.

If a pthread_t is a structure, we're out of luck and this won't work at
all.

* Fix a simple format string argument mismatch.

  CC       cckddasd.lo
In file included from hercules.h:104,
                 from cckddasd.c:21:
cckddasd.c: In function 'cckd_trace':
cckddasd.c:6715:13: warning: format '%ld' expects argument of type 'long int', but argument 5 has type 'suseconds_t' {aka 'int'} [-Wformat=]
 6715 |             "%s.%6.6ld %1d:%04X ",          // "hh:mm:ss.uuuuuu n:CCUU "
      |             ^~~~~~~~~~~~~~~~~~~~~
 6716 |             todwrk + 11,                    // "hh:mm:ss" (%s)
 6717 |             timeval.tv_usec,                // "uuuuuu"   (%6.6ld
      |             ~~~~~~~~~~~~~~~
      |                    |
      |                    suseconds_t {aka int}
msgenu.h:208:70: note: in definition of macro 'MSGBUF'
  208 | #define MSGBUF( _buf, ... )     snprintf(_buf, sizeof(_buf),      ## __VA_ARGS__ )
      |                                                                      ^~~~~~~~~~~
cckddasd.c:6715:22: note: format string is defined here
 6715 |             "%s.%6.6ld %1d:%04X ",          // "hh:mm:ss.uuuuuu n:CCUU "
      |                 ~~~~~^
      |                      |
      |                      long int
      |                 %6.6d

  CC       tcpnje.o
tcpnje.c: In function 'tcpnje_thread':
tcpnje.c:1848:25: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'suseconds_t' {aka 'int'} [-Wformat=]
 1848 |             DBGMSG(512, "HHCTN127D %4.4X:TCPNJE - select() timeout after %ld seconds %ld microseconds\n",
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1849 |                         devnum, tvcopy.tv_sec, tvcopy.tv_usec);
      |                                                ~~~~~~~~~~~~~~
      |                                                      |
      |                                                      suseconds_t {aka int}
tcpnje.c:98:109: note: in definition of macro 'DBGMSG'
   98 | #define DBGMSG(_level, ...) if ((tn->dev->ccwtrace && (_level & tn->trace)) || (_level & tn->debug)) logmsg(__VA_ARGS__)
      |                                                                                                             ^~~~~~~~~~~
tcpnje.c:1848:88: note: format string is defined here
 1848 |             DBGMSG(512, "HHCTN127D %4.4X:TCPNJE - select() timeout after %ld seconds %ld microseconds\n",
      |                                                                                      ~~^
      |                                                                                        |
      |                                                                                        long int
      |                                                                                      %d

Since the argument is apparently too short, it is easy to convert it to
a longer type. On some systems it may already be long int, so changing
the format string to %d is likely to be incorrect in such cases.

* Fix incorrect format string.

  CC       config.lo
In file included from hercules.h:104,
                 from config.c:20:
config.c: In function 'configure_cpu':
config.c:1079:57: warning: format '%d' expects argument of type 'int', but argument 8 has type 'long int' [-Wformat=]
 1079 |             WRMSG( HHC00111, "I", _POSIX_THREAD_CPUTIME );
      |                                                         ^
msgenu.h:99:98: note: in definition of macro 'PFWRITEMSG'
   99 | #define PFWRITEMSG( pan, f, fmt, ... ) fwritemsg( __FILE__, __LINE__, __FUNCTION__, pan,   f,    fmt, ## __VA_ARGS__ )
      |                                                                                                  ^~~
msgenu.h:108:36: note: in expansion of macro 'PWRITEMSG'
  108 | #define  LOGMSG(      fmt,   ... ) PWRITEMSG(  WRMSG_NORMAL,       fmt,                 ## __VA_ARGS__ )
      |                                    ^~~~~~~~~
msgenu.h:110:36: note: in expansion of macro 'LOGMSG'
  110 | #define  WRMSG(     id, sev, ... ) LOGMSG(                      #id "%s " id "\n", sev, ## __VA_ARGS__ )
      |                                    ^~~~~~
config.c:1079:13: note: in expansion of macro 'WRMSG'
 1079 |             WRMSG( HHC00111, "I", _POSIX_THREAD_CPUTIME );
      |             ^~~~~

The `%d` comes from the definition of `HHC00111`:

`#define HHC00111 "Thread CPU Time IS available (_POSIX_THREAD_CPUTIME=%d)"`

and `_POSIX_THREAD_CPUTIME` comes from `<unistd.h>`:

`#define       _POSIX_THREAD_CPUTIME           200112L`

https://pubs.opengroup.org/onlinepubs/9699919799/ defines it as "shall either be -1 or 200809L"
So NetBSD is a bit behind with the value, but it is correct that it is a long int.

* Fix incorrect SCANDIR_CONST_STRUCT_DIRENT for *BSD.

  CC       fillfnam.lo
fillfnam.c: In function 'tab_pressed':
fillfnam.c:146:32: warning: passing argument 3 of 'scandir' from incompatible pointer type [-Wincompatible-pointer-types]
  146 |   n = scandir(path, &namelist, filter, alphasort);
      |                                ^~~~~~
      |                                |
      |                                int (*)(struct dirent *)
In file included from hstdinc.h:215,
                 from fillfnam.c:8:
/usr/include/dirent.h:112:5: note: expected 'int (*)(const struct dirent *)' but argument is of type 'int (*)(struct dirent *)'
  112 |     int (*)(const struct dirent *), int (*)(const struct dirent **,
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

NetBSD defines `scandir` as

`int
scandir(const char *dirname, struct dirent ***namelist,
        int (*select)(const struct dirent *),
        int (*compar)(const struct dirent **, const struct dirent **)); `

The filter function is defined as
```
int filter(const struct dirent *ent)
int filter(      struct dirent *ent)
```
SCANDIR_CONST_STRUCT_DIRENT in hostopts.h is set wrong.

Of course it would be better if this were checked by configure.

I also inspected the <dirent.h> from FreeBSD and OpenBSD and they also
have const.

* Undefined functions can't be inlined.

  CC       impl.lo
impl.c:798:20: warning: inline function 'z900_get_storage_key' declared but never defined
  798 | extern inline BYTE z900_get_storage_key( U64 abs );
      |                    ^~~~~~~~~~~~~~~~~~~~
impl.c:797:20: warning: inline function 's390_get_storage_key' declared but never defined
  797 | extern inline BYTE s390_get_storage_key( U64 abs );
      |                    ^~~~~~~~~~~~~~~~~~~~
impl.c:796:20: warning: inline function 's370_get_storage_key' declared but never defined
  796 | extern inline BYTE s370_get_storage_key( U64 abs );
      |                    ^~~~~~~~~~~~~~~~~~~~

* Fix multi-line comment.

  CC       dasdload.o
In file included from dasdload.c:31:
dasdload2.h: In function 'process_iebcopy_file':
dasdload2.h:2849:13: warning: multi-line comment [-Wcomment]
 2849 |             // "Input record:   CCHHR[%04X%04X%02X] (TTR[%04X%02X]) kl[%d] dl[%d]\n" \
      |             ^

  CC       dasdload64.o
In file included from dasdload64.c:31:
dasdload2.h: In function 'process_iebcopy_file':
dasdload2.h:2849:13: warning: multi-line comment [-Wcomment]
 2849 |             // "Input record:   CCHHR[%04X%04X%02X] (TTR[%04X%02X]) kl[%d] dl[%d]\n" \
      |             ^

* Simplify format strings and avoid warnings.

  CC       tfprint.o
In file included from hercules.h:104,
                 from tfprint.c:14:
tfprint.c: In function 'print_op_stor':
tfprint.c:1732:26: warning: '0' flag ignored with precision and '%X' gnu_printf format [-Wformat=]
 1732 |         FLOGMSG( stdout, "%sTranslation exception %04.4"PRIX16" (%s)\n",
      |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
msgenu.h:99:98: note: in definition of macro 'PFWRITEMSG'
   99 | #define PFWRITEMSG( pan, f, fmt, ... ) fwritemsg( __FILE__, __LINE__, __FUNCTION__, pan,   f,    fmt, ## __VA_ARGS__ )
      |
                                    ^~~
tfprint.c:1732:9: note: in expansion of macro 'FLOGMSG'
 1732 |         FLOGMSG( stdout, "%sTranslation exception %04.4"PRIX16" (%s)\n",
      |         ^~~~~~~

tfprint.c:1753:13: warning: '0' flag ignored with precision and '%X' gnu_printf
format [-Wformat=]
 1753 |             "%02.2X%02.2X%02.2X%02.2X "
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
msgenu.h:208:70: note: in definition of macro 'MSGBUF'
  208 | #define MSGBUF( _buf, ... )     snprintf(_buf, sizeof(_buf),      ## __VA_ARGS__ )
      |                                                                      ^~~~~~~~~~~

and more similar warnings.

This seems to say that in the format string "%04.4X", the 0 is ignored
because it's filling with 0s already anyway due to the precision (.4).
Format string %045X prints the same as %4.45X and seems more reliable in
case older standards are used (which don't define a precision for the X
format). So I changed all the warned cases to the form %04X.

* Use TID_INT to scan for TID values.

Suggested by comment https://github.com/SDL-Hercules-390/hyperion/pull/574#issuecomment-1595924831 .
2023-06-19 10:21:04 -07:00

141 lines
7.0 KiB
C

/* PRINTFMT.H (C) Copyright "Fish" (David B. Trout), 2013 */
/* printf/sscanf format specifier strings */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
#ifndef _PRINTFMT_H_
#define _PRINTFMT_H_
/*-------------------------------------------------------------------*/
/* Length modifiers only */
/*-------------------------------------------------------------------*/
#if defined( _MSVC_ )
#define I16_FMT "h" // length modifier only
#define I32_FMT "I32" // length modifier only
#define I64_FMT "I64" // length modifier only
#elif defined( __PRI_64_LENGTH_MODIFIER__ ) // (MAC)
#define I16_FMT "h" // length modifier only
#define I32_FMT "" // length modifier only
#define I64_FMT __PRI_64_LENGTH_MODIFIER__
#elif defined( SIZEOF_LONG ) && SIZEOF_LONG >= 8
#define I16_FMT "h" // length modifier only
#define I32_FMT "" // length modifier only
#define I64_FMT "l" // length modifier only
#else
#define I16_FMT "h" // length modifier only
#define I32_FMT "" // length modifier only
#define I64_FMT "ll" // length modifier only
#endif
/*-------------------------------------------------------------------*/
/* C99 ISO Standard Names (most of them but not all) */
/*-------------------------------------------------------------------*/
#if !defined( PRId64 )
#define PRId16 I16_FMT "d" // without leading "%"
#define PRId32 I32_FMT "d" // without leading "%"
#define PRId64 I64_FMT "d" // without leading "%"
#define PRIi16 I16_FMT "i" // without leading "%"
#define PRIi32 I32_FMT "i" // without leading "%"
#define PRIi64 I64_FMT "i" // without leading "%"
#define PRIu16 I16_FMT "u" // without leading "%"
#define PRIu32 I32_FMT "u" // without leading "%"
#define PRIu64 I64_FMT "u" // without leading "%"
#define PRIx16 I16_FMT "x" // without leading "%"
#define PRIx32 I32_FMT "x" // without leading "%"
#define PRIx64 I64_FMT "x" // without leading "%"
#define PRIX16 I16_FMT "X" // without leading "%"
#define PRIX32 I32_FMT "X" // without leading "%"
#define PRIX64 I64_FMT "X" // without leading "%"
#if defined( SIZEOF_INT_P ) && SIZEOF_INT_P >= 8
#define PRIdPTR I64_FMT "d" // without leading "%"
#define PRIiPTR I64_FMT "i" // without leading "%"
#define PRIuPTR I64_FMT "u" // without leading "%"
#define PRIxPTR I64_FMT "x" // without leading "%"
#define PRIXPTR I64_FMT "X" // without leading "%"
#else
#define PRIdPTR I32_FMT "d" // without leading "%"
#define PRIiPTR I32_FMT "i" // without leading "%"
#define PRIuPTR I32_FMT "u" // without leading "%"
#define PRIxPTR I32_FMT "x" // without leading "%"
#define PRIXPTR I32_FMT "X" // without leading "%"
#endif
#define SCNd16 PRId16 // without leading "%"
#define SCNd32 PRId32 // without leading "%"
#define SCNd64 PRId64 // without leading "%"
#define SCNi16 PRIi16 // without leading "%"
#define SCNi32 PRIi32 // without leading "%"
#define SCNi64 PRIi64 // without leading "%"
#define SCNu16 PRIu16 // without leading "%"
#define SCNu32 PRIu32 // without leading "%"
#define SCNu64 PRIu64 // without leading "%"
#define SCNx16 PRIx16 // without leading "%"
#define SCNx32 PRIx32 // without leading "%"
#define SCNx64 PRIx64 // without leading "%"
#define SCNdPTR PRIdPTR // without leading "%"
#define SCNiPTR PRIiPTR // without leading "%"
#define SCNuPTR PRIuPTR // without leading "%"
#define SCNxPTR PRIxPTR // without leading "%"
#endif // !defined( PRId64 )
/*-------------------------------------------------------------------*/
/* Hercules pointer/address formats */
/*-------------------------------------------------------------------*/
#if defined( SIZEOF_INT_P ) && SIZEOF_INT_P >= 8
#define PTR_FMTx "%16.16"PRIx64 // complete format spec
#define PTR_FMTX "%16.16"PRIX64 // complete format spec
#define PTR_CAST( p ) ((U64)(p)) // cast to printable
#else
#define PTR_FMTx "%8.8" PRIx32 // complete format spec
#define PTR_FMTX "%8.8" PRIX32 // complete format spec
#define PTR_CAST( p ) ((U32)(p)) // cast to printable
#endif
/*-------------------------------------------------------------------*/
/* Hercules thread-id format */
/*-------------------------------------------------------------------*/
#if defined( _MSVC_ )
#define TIDPAT "%8.8"PRIx32 // complete format spec
#define SCN_TIDPAT "%"PRIx32 // complete format spec
#define TID_INT U32 // integer most like a TID
#elif defined( SIZEOF_PTHREAD_T ) && SIZEOF_PTHREAD_T >= 8
#define TIDPAT "%16.16"PRIx64 // complete format spec
#define SCN_TIDPAT "%"PRIx64 // complete format spec
#define TID_INT U64 // integer most like a TID
#else
#define TIDPAT "%8.8"PRIx32 // complete format spec
#define SCN_TIDPAT "%"PRIx32 // complete format spec
#define TID_INT U32 // integer most like a TID
#endif
#define TID_CAST( _tid ) ((TID_INT)(_tid)) // cast to printable
#define LOG_TID_BEGIN( _tid, _name ) \
WRMSG( HHC00100, "I", \
TID_CAST( _tid ), get_thread_priority_id( _tid ), _name );
#define LOG_TID_END( _tid, _name ) \
WRMSG( HHC00101, "I", \
TID_CAST( _tid ), get_thread_priority_id( _tid ), _name );
#define LOG_THREAD_BEGIN( _name ) LOG_TID_BEGIN( thread_id(), _name )
#define LOG_THREAD_END( _name ) LOG_TID_END ( thread_id(), _name )
#endif // _PRINTFMT_H_