If this is VS prior to 2015 or MinGW, we can't trust snprintf(); we have
to use _snprintf_s(), but that requires us to insert _TRUNCATE as an
argument after the buffer and buffer length and before the format string
and arguments, if any, to the format string.
That means we need to use a vararg macro; however, if we make the format
string a regular argument to the macro, that means that, if there are no
arguments *after* the format string, you end up with an argument list to
_snprintf_s() that ends with "fmt, ", and that's not valid C.
*If* we knew this was GCC or Clang, we could use a GNU C-specific hack,
wherein, if __VA_ARGS__ is preceded by ## and there's a comma before
that, the comma is removed if __VA_ARGS__ is empty, but this might be
Microsoft's C compiler in a version of Visual Studio prior to VS 2015,
which might not support that.
So we have to just have the macro take, as the ... arguments, the format
string and its arguments.
Addresses GitHub issue #713.
ndo_nflag has not this function. We don't currently have an appropriate
flag for this use. Not sure printing the header in hex is currently useful.
Update the output of a test accordingly.
Cast pointer differences, widen some variables, make some function
returns unsigned as they never return a negative number.
Fix a format while we're at it.
Get rid of the global nfserr variable and, instead, have it be local to
interp_reply(). That means one less global variable, which may be good
if any multi-threaded program tries to use libnetdissect in more than
one thread (there are still global variables that would have to be
removed), and gets rid of some cases where we didn't need to set it.
Don't bundle multiple operations inside an if clause. This squelches
some warnings from MSVC, and makes the code a bit more uniform and a bit
easier to understand (and, in the process of doing that, found a bug
that was fixed in 596aca3d93).
This eliminates a warning from MSVC, and makes the flow a little
clearer.
(Yes, it duplicates some code, but compilers have been pretty good at
merging common code sequences, so it might just turn it into the
equivalent of
if (optopt == (int)':')
goto label;
oli = strchr(ostr, optopt);
if (!oli) {
label:
/*
* Unknown option character.
*/
if (!*place)
++optind;
...
}
although it does mean that the same C code exists in two places.)
Some of the narrowing warnings are false positives; newer versions of
Clang do a better job than older ones of determining the range of values
of expressions, and don't warn if the range is such that it can be
safely narrowed, so maybe the same is true of MSVC.