| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #ifndef LIBINTL_H
- #define LIBINTL_H
- /* BBS: __attribute__((format_arg(N))) tells GCC that this function
- returns a format-string equivalent to argument N. -Wformat-security
- uses this to see through gettext/dgettext/... calls and detect that
- the msgid argument was a string literal. glibc's libintl.h ships the
- same annotation; without it, programs that build with
- -Werror=format-security (e.g. distro-style hardening flags) would
- fail on every printf(_("fmt %d"), n). */
- #if defined __GNUC__ && __GNUC__ >= 3
- # define __libintl_format_arg(N) __attribute__ ((__format_arg__ (N)))
- #else
- # define __libintl_format_arg(N)
- #endif
- char *gettext(const char *msgid)
- __libintl_format_arg(1);
- char *dgettext(const char *domainname, const char *msgid)
- __libintl_format_arg(2);
- char *dcgettext(const char *domainname, const char *msgid, int category)
- __libintl_format_arg(2);
- char *ngettext(const char *msgid1, const char *msgid2, unsigned long n)
- __libintl_format_arg(1) __libintl_format_arg(2);
- char *dngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long n)
- __libintl_format_arg(2) __libintl_format_arg(3);
- char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long n, int category)
- __libintl_format_arg(2) __libintl_format_arg(3);
- char *textdomain(const char *domainname);
- char *bind_textdomain_codeset(const char *domainname, const char *codeset);
- char *bindtextdomain(const char *domainname, const char *dirname);
- /* BBS: gettext_noop is just compile-time identity; many GNU programs
- (e.g. elfutils' lib/system.h line 157) ship
- #define gettext_noop(Str) Str
- verbatim. Use the same token form so a redefinition is recognised
- as identical by the preprocessor and does not trigger
- -Werror=macro-redefined. Also gate with #ifndef so a consumer that
- defines it first keeps its definition (which the previous
- "#undef gettext_noop" would have wiped). */
- #ifndef gettext_noop
- #define gettext_noop(Str) Str
- #endif
- #ifndef LIBINTL_NO_MACROS
- /* if these macros are defined, configure checks will detect libintl as
- * built into the libc because test programs will work without -lintl.
- * for example:
- * checking for ngettext in libc ... yes
- * the consequence is that -lintl will not be added to the LDFLAGS.
- * so if for some reason you want that libintl.a gets linked,
- * add -DLIBINTL_NO_MACROS=1 to your CPPFLAGS.
- *
- * BBS: the previous implementation expanded to comma expressions like
- * #define dgettext(dom, X) ((void)(dom), (char*) (X))
- * which silenced -Wunused-value on the unused dom argument but defeated
- * -Wformat-security: GCC cannot see through a comma expression to
- * decide that the result is still a string literal. Route through
- * static-inline stubs decorated with __attribute__((format_arg))
- * instead:
- * - function-call semantics evaluate every argument, so side effects
- * in callers like dgettext(read_dom(), "fmt") are preserved;
- * - the inline body collapses to (char*) msgid at -O1+ for literal
- * msgid, so there is zero runtime overhead in the common case;
- * - format_arg tells -Wformat-security how to follow the call back
- * to the original literal.
- * The static-inline stub names match the convention __libintl_stub_*.
- * The user-visible macros shadow the extern declarations only at call
- * sites (foo(...)), so taking &gettext still resolves to the extern
- * function declared above. */
- static inline __libintl_format_arg(1)
- char *__libintl_stub_gettext(const char *__msgid)
- {
- return (char *) __msgid;
- }
- #define gettext(X) __libintl_stub_gettext(X)
- static inline __libintl_format_arg(2)
- char *__libintl_stub_dgettext(const char *__dom, const char *__msgid)
- {
- (void) __dom;
- return (char *) __msgid;
- }
- #define dgettext(dom, X) __libintl_stub_dgettext((dom), (X))
- static inline __libintl_format_arg(2)
- char *__libintl_stub_dcgettext(const char *__dom, const char *__msgid, int __cat)
- {
- (void) __dom; (void) __cat;
- return (char *) __msgid;
- }
- #define dcgettext(dom, X, cat) __libintl_stub_dcgettext((dom), (X), (cat))
- static inline __libintl_format_arg(1) __libintl_format_arg(2)
- char *__libintl_stub_ngettext(const char *__s1, const char *__s2, unsigned long __n)
- {
- return (char *) ((__n == 1) ? __s1 : __s2);
- }
- #define ngettext(X, Y, N) __libintl_stub_ngettext((X), (Y), (N))
- static inline __libintl_format_arg(2) __libintl_format_arg(3)
- char *__libintl_stub_dngettext(const char *__dom, const char *__s1, const char *__s2, unsigned long __n)
- {
- (void) __dom;
- return (char *) ((__n == 1) ? __s1 : __s2);
- }
- #define dngettext(dom, X, Y, N) __libintl_stub_dngettext((dom), (X), (Y), (N))
- static inline __libintl_format_arg(2) __libintl_format_arg(3)
- char *__libintl_stub_dcngettext(const char *__dom, const char *__s1, const char *__s2, unsigned long __n, int __cat)
- {
- (void) __dom; (void) __cat;
- return (char *) ((__n == 1) ? __s1 : __s2);
- }
- #define dcngettext(dom, X, Y, N, cat) __libintl_stub_dcngettext((dom), (X), (Y), (N), (cat))
- static inline char *__libintl_stub_bindtextdomain(const char *__dom, const char *__dir)
- {
- (void) __dom; (void) __dir;
- return (char *) "/";
- }
- #define bindtextdomain(X, Y) __libintl_stub_bindtextdomain((X), (Y))
- static inline char *__libintl_stub_bind_textdomain_codeset(const char *__dom, const char *__codeset)
- {
- (void) __dom; (void) __codeset;
- return (char *) 0;
- }
- #define bind_textdomain_codeset(dom, codeset) __libintl_stub_bind_textdomain_codeset((dom), (codeset))
- static inline char *__libintl_stub_textdomain(const char *__dom)
- {
- (void) __dom;
- return (char *) "messages";
- }
- #define textdomain(X) __libintl_stub_textdomain(X)
- #undef ENABLE_NLS
- #undef DISABLE_NLS
- #define DISABLE_NLS 1
- /* BBS: the previous version had
- * #pragma GCC diagnostic ignored "-Wunused-value"
- * here because the comma-expression macros produced a (char*)"..."
- * trailing rvalue that callers discarded as a statement. With
- * function-call semantics (static-inline stubs) the discarded return
- * value is a regular function call statement, not an unused expression
- * value, so -Wunused-value never fires and the pragma is no longer
- * needed. */
- #endif
- /* to supply LC_MESSAGES and other stuff GNU expects to be exported when
- including libintl.h */
- #include <locale.h>
- #endif
|