]> git.draconx.ca Git - dxcommon.git/commitdiff
help_print_optstring: Don't depend on snprintf.
authorNick Bowler <nbowler@draconx.ca>
Thu, 16 Nov 2023 01:33:31 +0000 (20:33 -0500)
committerNick Bowler <nbowler@draconx.ca>
Thu, 16 Nov 2023 01:33:31 +0000 (20:33 -0500)
The current code calls snprintf unconditionally, even if NLS is disabled
(although the function is not called, the code is still compiled), so it
won't build in environments which lack this function.

For the NLS-enabled case we can rely on the GNU libintl fallback being
available as required.

Otherwise we can just provide a stub to ensure the dead code compiles,
and for the NLS test programs hack in sprintf as a replacement which
should work just fine.

src/help.c
t/nls/gettext.h

index f96025f1298fdcad10c29953d64cd92aef0da7bb..4b77b2ce2e78587df19e0548ee2dea49bb4b9d1b 100644 (file)
@@ -68,9 +68,23 @@ enum {
        OPT_LONG_WITHOUT_ARG         = 0,
 };
 
+/*
+ * When NLS is enabled, we assume snprintf is available.  The GNU libintl
+ * library should provide a suitable fallback if necessary.
+ */
+#if ENABLE_NLS && !defined(help_do_snprintf)
+#define help_do_snprintf snprintf
+#elif !ENABLE_NLS
+#define help_do_snprintf fake_snprintf
+static inline int fake_snprintf(char *buf, size_t n, const char *fmt, ...)
+{
+       return -1;
+}
+#endif
+
 int help_print_optstring(const struct option *opt, const char *argname, int l)
 {
-       char optstring[100];
+       char optstring[256];
        int w;
 
        if (!ENABLE_NLS)
@@ -80,56 +94,56 @@ int help_print_optstring(const struct option *opt, const char *argname, int l)
 #if HELP_GETOPT_LONG_ONLY
        case OPT_SHORT_WITH_OPTIONAL_ARG:
        case OPT_LONG_WITH_OPTIONAL_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%s [%s]"), opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%s [%s]"), opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_SHORT_WITH_MANDATORY_ARG:
        case OPT_LONG_WITH_MANDATORY_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%s %s"), opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%s %s"), opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_SHORT_WITHOUT_ARG:
        case OPT_LONG_WITHOUT_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%s"), opt->name);
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%s"), opt->name);
                break;
 #else
        case OPT_SHORT_WITH_OPTIONAL_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%c, --%s[=%s]"), opt->val, opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%c, --%s[=%s]"), opt->val, opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_LONG_WITH_OPTIONAL_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  --%s[=%s]"), opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  --%s[=%s]"), opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_SHORT_WITH_MANDATORY_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%c, --%s=%s"), opt->val, opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%c, --%s=%s"), opt->val, opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_LONG_WITH_MANDATORY_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  --%s=%s"), opt->name,
-                            pgettext_expr(opt->name, argname));
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  --%s=%s"), opt->name,
+                                    pgettext_expr(opt->name, argname));
                break;
        case OPT_SHORT_WITHOUT_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  -%c, --%s"), opt->val, opt->name);
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  -%c, --%s"), opt->val, opt->name);
                break;
        case OPT_LONG_WITHOUT_ARG:
-               w = snprintf(optstring, sizeof optstring,
-                            _("  --%s"), opt->name);
+               w = help_do_snprintf(optstring, sizeof optstring,
+                                    _("  --%s"), opt->name);
                break;
 #endif
        default:
                assert(0);
        }
 
-       if (w < 0)
+       if (w < 0 || w >= sizeof optstring)
                goto no_translate;
 
        w = mbsnwidth(optstring, w, 0);
index b8a8060bc4bfc4760662ed097a0f2c6e52762745..83929924f718ccde6bcb58fb095618f218b085bc 100644 (file)
 #ifndef TEST_NLS_GETTEXT_H_
 #define TEST_NLS_GETTEXT_H_
 
+#include <stdio.h>
+#include <stdarg.h>
+
 #define gettext(s) (s)
 #define pgettext_expr(a, s) (s)
 
+/*
+ * We don't need a real snprintf for testing help functionality; substitute
+ * using vsprintf to ease testing on C89 implementations.
+ */
+#define help_do_snprintf help_do_snprintf
+static inline int help_do_snprintf(char *buf, size_t n, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, fmt);
+       ret = vsprintf(buf, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
+
 #endif