utils: Reimplement ver2str() for sanity

The dense mix of print_version_field(), snprintf() with its tricky
return semantics, and the tricky POINTER_MOVE() macro are replaced by an
implementation where each statement directly inserts one character into
the buffer while preventing buffer overflow.

While we're reworking ver2str(), change the return type to avoid
clang-tidy's bugprone-narrowing-conversion diagnostic. This is an
API/ABI break, but it's one with low impact: The test suite declares the
variable holding the return type as `auto`, while the one ver2str() call
in the entire openbmc github org, in pldmd, immediately discards the
return value (it is never assigned).

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I11708a32019a36ea0d31229f6c91c8a75f7f22d0
diff --git a/include/libpldm/utils.h b/include/libpldm/utils.h
index 35b039b..9b7bd9f 100644
--- a/include/libpldm/utils.h
+++ b/include/libpldm/utils.h
@@ -9,6 +9,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <sys/types.h>
 
 /** @struct variable_field
  *
@@ -38,11 +39,14 @@
 /** @brief Convert ver32_t to string
  *  @param[in] version - Pointer to ver32_t
  *  @param[out] buffer - Pointer to the buffer
- *  @param[in] buffer_size - Size of the buffer
- *  @return The number of characters(excluding the null byte) or negative if
- * error is encountered
+ *  @param[in] buffer_size - Size of the buffer, up to SSIZE_MAX
+ *  @return The number of characters written to the buffer (excluding the null
+ * byte). The converted string may be truncated, and truncation is not
+ * considered an error. The result is negative if invalid arguments are supplied
+ * (NULL values for required pointers or the buffer size is beyond a
+ *  representable range).
  */
-int ver2str(const ver32_t *version, char *buffer, size_t buffer_size);
+ssize_t ver2str(const ver32_t *version, char *buffer, size_t buffer_size);
 
 /** @brief Convert bcd number(uint8_t) to decimal
  *  @param[in] bcd - bcd number