libintl.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #ifndef LIBINTL_H
  2. #define LIBINTL_H
  3. /* BBS: __attribute__((format_arg(N))) tells GCC that this function
  4. returns a format-string equivalent to argument N. -Wformat-security
  5. uses this to see through gettext/dgettext/... calls and detect that
  6. the msgid argument was a string literal. glibc's libintl.h ships the
  7. same annotation; without it, programs that build with
  8. -Werror=format-security (e.g. distro-style hardening flags) would
  9. fail on every printf(_("fmt %d"), n). */
  10. #if defined __GNUC__ && __GNUC__ >= 3
  11. # define __libintl_format_arg(N) __attribute__ ((__format_arg__ (N)))
  12. #else
  13. # define __libintl_format_arg(N)
  14. #endif
  15. char *gettext(const char *msgid)
  16. __libintl_format_arg(1);
  17. char *dgettext(const char *domainname, const char *msgid)
  18. __libintl_format_arg(2);
  19. char *dcgettext(const char *domainname, const char *msgid, int category)
  20. __libintl_format_arg(2);
  21. char *ngettext(const char *msgid1, const char *msgid2, unsigned long n)
  22. __libintl_format_arg(1) __libintl_format_arg(2);
  23. char *dngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long n)
  24. __libintl_format_arg(2) __libintl_format_arg(3);
  25. char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, unsigned long n, int category)
  26. __libintl_format_arg(2) __libintl_format_arg(3);
  27. char *textdomain(const char *domainname);
  28. char *bind_textdomain_codeset(const char *domainname, const char *codeset);
  29. char *bindtextdomain(const char *domainname, const char *dirname);
  30. /* BBS: gettext_noop is just compile-time identity; many GNU programs
  31. (e.g. elfutils' lib/system.h line 157) ship
  32. #define gettext_noop(Str) Str
  33. verbatim. Use the same token form so a redefinition is recognised
  34. as identical by the preprocessor and does not trigger
  35. -Werror=macro-redefined. Also gate with #ifndef so a consumer that
  36. defines it first keeps its definition (which the previous
  37. "#undef gettext_noop" would have wiped). */
  38. #ifndef gettext_noop
  39. #define gettext_noop(Str) Str
  40. #endif
  41. #ifndef LIBINTL_NO_MACROS
  42. /* if these macros are defined, configure checks will detect libintl as
  43. * built into the libc because test programs will work without -lintl.
  44. * for example:
  45. * checking for ngettext in libc ... yes
  46. * the consequence is that -lintl will not be added to the LDFLAGS.
  47. * so if for some reason you want that libintl.a gets linked,
  48. * add -DLIBINTL_NO_MACROS=1 to your CPPFLAGS.
  49. *
  50. * BBS: the previous implementation expanded to comma expressions like
  51. * #define dgettext(dom, X) ((void)(dom), (char*) (X))
  52. * which silenced -Wunused-value on the unused dom argument but defeated
  53. * -Wformat-security: GCC cannot see through a comma expression to
  54. * decide that the result is still a string literal. Route through
  55. * static-inline stubs decorated with __attribute__((format_arg))
  56. * instead:
  57. * - function-call semantics evaluate every argument, so side effects
  58. * in callers like dgettext(read_dom(), "fmt") are preserved;
  59. * - the inline body collapses to (char*) msgid at -O1+ for literal
  60. * msgid, so there is zero runtime overhead in the common case;
  61. * - format_arg tells -Wformat-security how to follow the call back
  62. * to the original literal.
  63. * The static-inline stub names match the convention __libintl_stub_*.
  64. * The user-visible macros shadow the extern declarations only at call
  65. * sites (foo(...)), so taking &gettext still resolves to the extern
  66. * function declared above. */
  67. static inline __libintl_format_arg(1)
  68. char *__libintl_stub_gettext(const char *__msgid)
  69. {
  70. return (char *) __msgid;
  71. }
  72. #define gettext(X) __libintl_stub_gettext(X)
  73. static inline __libintl_format_arg(2)
  74. char *__libintl_stub_dgettext(const char *__dom, const char *__msgid)
  75. {
  76. (void) __dom;
  77. return (char *) __msgid;
  78. }
  79. #define dgettext(dom, X) __libintl_stub_dgettext((dom), (X))
  80. static inline __libintl_format_arg(2)
  81. char *__libintl_stub_dcgettext(const char *__dom, const char *__msgid, int __cat)
  82. {
  83. (void) __dom; (void) __cat;
  84. return (char *) __msgid;
  85. }
  86. #define dcgettext(dom, X, cat) __libintl_stub_dcgettext((dom), (X), (cat))
  87. static inline __libintl_format_arg(1) __libintl_format_arg(2)
  88. char *__libintl_stub_ngettext(const char *__s1, const char *__s2, unsigned long __n)
  89. {
  90. return (char *) ((__n == 1) ? __s1 : __s2);
  91. }
  92. #define ngettext(X, Y, N) __libintl_stub_ngettext((X), (Y), (N))
  93. static inline __libintl_format_arg(2) __libintl_format_arg(3)
  94. char *__libintl_stub_dngettext(const char *__dom, const char *__s1, const char *__s2, unsigned long __n)
  95. {
  96. (void) __dom;
  97. return (char *) ((__n == 1) ? __s1 : __s2);
  98. }
  99. #define dngettext(dom, X, Y, N) __libintl_stub_dngettext((dom), (X), (Y), (N))
  100. static inline __libintl_format_arg(2) __libintl_format_arg(3)
  101. char *__libintl_stub_dcngettext(const char *__dom, const char *__s1, const char *__s2, unsigned long __n, int __cat)
  102. {
  103. (void) __dom; (void) __cat;
  104. return (char *) ((__n == 1) ? __s1 : __s2);
  105. }
  106. #define dcngettext(dom, X, Y, N, cat) __libintl_stub_dcngettext((dom), (X), (Y), (N), (cat))
  107. static inline char *__libintl_stub_bindtextdomain(const char *__dom, const char *__dir)
  108. {
  109. (void) __dom; (void) __dir;
  110. return (char *) "/";
  111. }
  112. #define bindtextdomain(X, Y) __libintl_stub_bindtextdomain((X), (Y))
  113. static inline char *__libintl_stub_bind_textdomain_codeset(const char *__dom, const char *__codeset)
  114. {
  115. (void) __dom; (void) __codeset;
  116. return (char *) 0;
  117. }
  118. #define bind_textdomain_codeset(dom, codeset) __libintl_stub_bind_textdomain_codeset((dom), (codeset))
  119. static inline char *__libintl_stub_textdomain(const char *__dom)
  120. {
  121. (void) __dom;
  122. return (char *) "messages";
  123. }
  124. #define textdomain(X) __libintl_stub_textdomain(X)
  125. #undef ENABLE_NLS
  126. #undef DISABLE_NLS
  127. #define DISABLE_NLS 1
  128. /* BBS: the previous version had
  129. * #pragma GCC diagnostic ignored "-Wunused-value"
  130. * here because the comma-expression macros produced a (char*)"..."
  131. * trailing rvalue that callers discarded as a statement. With
  132. * function-call semantics (static-inline stubs) the discarded return
  133. * value is a regular function call statement, not an unused expression
  134. * value, so -Wunused-value never fires and the pragma is no longer
  135. * needed. */
  136. #endif
  137. /* to supply LC_MESSAGES and other stuff GNU expects to be exported when
  138. including libintl.h */
  139. #include <locale.h>
  140. #endif