anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

gettext.h (10854B)


      1 /* Convenience header for conditional use of GNU <libintl.h>.
      2    Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software
      3    Foundation, Inc.
      4 
      5    This program is free software: you can redistribute it and/or modify
      6    it under the terms of the GNU Lesser General Public License as published by
      7    the Free Software Foundation; either version 2.1 of the License, or
      8    (at your option) any later version.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU Lesser General Public License for more details.
     14 
     15    You should have received a copy of the GNU Lesser General Public License
     16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
     17 #ifndef _LIBGETTEXT_H
     18 #define _LIBGETTEXT_H 1
     19 
     20 /* NLS can be disabled through the configure --disable-nls option
     21    or through "#define ENABLE NLS 0" before including this file.  */
     22 #if defined ENABLE_NLS && ENABLE_NLS
     23 
     24 /* Get declarations of GNU message catalog functions.  */
     25 # include <libintl.h>
     26 
     27 /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
     28    the gettext() and ngettext() macros.  This is an alternative to calling
     29    textdomain(), and is useful for libraries.  */
     30 # ifdef DEFAULT_TEXT_DOMAIN
     31 #  undef gettext
     32 #  define gettext(Msgid) \
     33   dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
     34 #  undef ngettext
     35 #  define ngettext(Msgid1, Msgid2, N) \
     36   dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
     37 # endif
     38 
     39 #else
     40 
     41 /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
     42    chokes if dcgettext is defined as a macro.  So include it now, to make
     43    later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
     44    as well because people using "gettext.h" will not include <libintl.h>,
     45    and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
     46    is OK.  */
     47 #if defined(__sun)
     48 # include <locale.h>
     49 #endif
     50 
     51 /* Many header files from the libstdc++ coming with g++ 3.3 or newer include
     52    <libintl.h>, which chokes if dcgettext is defined as a macro.  So include
     53    it now, to make later inclusions of <libintl.h> a NOP.  */
     54 #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
     55 # include <cstdlib>
     56 # if (__GLIBC__ >= 2 && ! defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
     57 #  include <libintl.h>
     58 # endif
     59 #endif
     60 
     61 /* Disabled NLS.
     62    The casts to 'const char *' serve the purpose of producing warnings
     63    for invalid uses of the value returned from these functions.
     64    On pre-ANSI systems without 'const', the config.h file is supposed to
     65    contain "#define const".  */
     66 # undef gettext
     67 # define gettext(Msgid) ((const char *) (Msgid))
     68 # undef dgettext
     69 # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
     70 # undef dcgettext
     71 # define dcgettext(Domainname, Msgid, Category) \
     72   ((void) (Category), dgettext (Domainname, Msgid))
     73 # undef ngettext
     74 # define ngettext(Msgid1, Msgid2, N) \
     75   ((N) == 1 \
     76    ? ((void) (Msgid2), (const char *) (Msgid1)) \
     77    : ((void) (Msgid1), (const char *) (Msgid2)))
     78 # undef dngettext
     79 # define dngettext(Domainname, Msgid1, Msgid2, N) \
     80   ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
     81 # undef dcngettext
     82 # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
     83   ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
     84 # undef textdomain
     85 # define textdomain(Domainname) ((const char *) (Domainname))
     86 # undef bindtextdomain
     87 # define bindtextdomain(Domainname, Dirname) \
     88   ((void) (Domainname), (const char *) (Dirname))
     89 # undef bind_textdomain_codeset
     90 # define bind_textdomain_codeset(Domainname, Codeset) \
     91   ((void) (Domainname), (const char *) (Codeset))
     92 
     93 #endif
     94 
     95 /* Prefer gnulib's setlocale override over libintl's setlocale override.  */
     96 #ifdef GNULIB_defined_setlocale
     97 # undef setlocale
     98 # define setlocale rpl_setlocale
     99 #endif
    100 
    101 /* A pseudo function call that serves as a marker for the automated
    102    extraction of messages, but does not call gettext().  The run-time
    103    translation is done at a different place in the code.
    104    The argument, String, should be a literal string.  Concatenated strings
    105    and other string expressions won't work.
    106    The macro's expansion is not parenthesized, so that it is suitable as
    107    initializer for static 'char[]' or 'const char[]' variables.  */
    108 #define gettext_noop(String) String
    109 
    110 /* The separator between msgctxt and msgid in a .mo file.  */
    111 #define GETTEXT_CONTEXT_GLUE "\004"
    112 
    113 /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
    114    MSGID.  MSGCTXT and MSGID must be string literals.  MSGCTXT should be
    115    short and rarely need to change.
    116    The letter 'p' stands for 'particular' or 'special'.  */
    117 #ifdef DEFAULT_TEXT_DOMAIN
    118 # define pgettext(Msgctxt, Msgid) \
    119   pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, \
    120                 LC_MESSAGES)
    121 #else
    122 # define pgettext(Msgctxt, Msgid) \
    123   pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
    124 #endif
    125 #define dpgettext(Domainname, Msgctxt, Msgid) \
    126   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, \
    127                 LC_MESSAGES)
    128 #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
    129   pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
    130 #ifdef DEFAULT_TEXT_DOMAIN
    131 # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    132   npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, \
    133                  MsgidPlural, N, LC_MESSAGES)
    134 #else
    135 # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
    136   npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, \
    137                  N, LC_MESSAGES)
    138 #endif
    139 #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    140   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, \
    141                  MsgidPlural, N, LC_MESSAGES)
    142 #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
    143   npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, \
    144                  MsgidPlural, N, Category)
    145 
    146 #ifdef __GNUC__
    147 __inline
    148 #else
    149 #ifdef __cplusplus
    150 inline
    151 #endif
    152 #endif
    153 static const char *
    154 pgettext_aux (const char *domain,
    155               const char *msg_ctxt_id, const char *msgid,
    156               int category)
    157 {
    158   const char *translation = dcgettext (domain, msg_ctxt_id, category);
    159   if (translation == msg_ctxt_id)
    160     return msgid;
    161   else
    162     return translation;
    163 }
    164 
    165 
    166 #ifdef __GNUC__
    167 __inline
    168 #else
    169 #ifdef __cplusplus
    170 inline
    171 #endif
    172 #endif
    173 static const char *
    174 npgettext_aux (const char *domain,
    175                const char *msg_ctxt_id, const char *msgid,
    176                const char *msgid_plural, unsigned long int n,
    177                int category)
    178 {
    179   const char *translation =
    180     dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    181   if ((translation == msg_ctxt_id) || (translation == msgid_plural))
    182     return (n == 1 ? msgid : msgid_plural);
    183   else
    184     return translation;
    185 }
    186 
    187 
    188 /* The same thing extended for non-constant arguments.  Here MSGCTXT and MSGID
    189    can be arbitrary expressions.  But for string literals these macros are
    190    less efficient than those above.  */
    191 
    192 #include <string.h>
    193 
    194 /* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
    195    This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
    196    the default GCC many warnings set.  This allows programs to disable use
    197    of VLAs, which may be unintended, or may be awkward to support portably,
    198    or may have security implications due to non-deterministic stack usage.  */
    199 
    200 #if (! defined GNULIB_NO_VLA \
    201      && (((__GNUC__ >= 3 || __GNUG__ >= 2) && ! defined __STRICT_ANSI__) \
    202   /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
    203           || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */))
    204 # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
    205 #else
    206 # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
    207 #endif
    208 
    209 #if ! _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    210 #include <stdlib.h>
    211 #endif
    212 
    213 #define pgettext_expr(Msgctxt, Msgid) \
    214   dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
    215 #define dpgettext_expr(Domainname, Msgctxt, Msgid) \
    216   dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
    217 
    218 #ifdef __GNUC__
    219 __inline
    220 #else
    221 #ifdef __cplusplus
    222 inline
    223 #endif
    224 #endif
    225 static const char *
    226 dcpgettext_expr (const char *domain,
    227                  const char *msgctxt, const char *msgid,
    228                  int category)
    229 {
    230   size_t msgctxt_len = strlen (msgctxt) + 1;
    231   size_t msgid_len = strlen (msgid) + 1;
    232   const char *translation;
    233 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    234   char msg_ctxt_id[msgctxt_len + msgid_len];
    235 #else
    236   char buf[1024];
    237   char *msg_ctxt_id =
    238     (msgctxt_len + msgid_len <= sizeof (buf)
    239      ? buf
    240      : (char *) malloc (msgctxt_len + msgid_len));
    241   if (msg_ctxt_id != NULL)
    242 #endif
    243   {
    244     int found_translation;
    245     memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    246     msg_ctxt_id[msgctxt_len - 1] = '\004';
    247     memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    248     translation = dcgettext (domain, msg_ctxt_id, category);
    249     found_translation = (translation != msg_ctxt_id);
    250 #if ! _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    251     if (msg_ctxt_id != buf)
    252       free (msg_ctxt_id);
    253 #endif
    254     if (found_translation)
    255       return translation;
    256   }
    257   return msgid;
    258 }
    259 
    260 
    261 #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
    262   dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    263 #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
    264   dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
    265 
    266 #ifdef __GNUC__
    267 __inline
    268 #else
    269 #ifdef __cplusplus
    270 inline
    271 #endif
    272 #endif
    273 static const char *
    274 dcnpgettext_expr (const char *domain,
    275                   const char *msgctxt, const char *msgid,
    276                   const char *msgid_plural, unsigned long int n,
    277                   int category)
    278 {
    279   size_t msgctxt_len = strlen (msgctxt) + 1;
    280   size_t msgid_len = strlen (msgid) + 1;
    281   const char *translation;
    282 #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    283   char msg_ctxt_id[msgctxt_len + msgid_len];
    284 #else
    285   char buf[1024];
    286   char *msg_ctxt_id =
    287     (msgctxt_len + msgid_len <= sizeof (buf)
    288      ? buf
    289      : (char *) malloc (msgctxt_len + msgid_len));
    290   if (msg_ctxt_id != NULL)
    291 #endif
    292   {
    293     int found_translation;
    294     memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
    295     msg_ctxt_id[msgctxt_len - 1] = '\004';
    296     memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
    297     translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
    298     found_translation = ! (translation == msg_ctxt_id || translation ==
    299                            msgid_plural);
    300 #if ! _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
    301     if (msg_ctxt_id != buf)
    302       free (msg_ctxt_id);
    303 #endif
    304     if (found_translation)
    305       return translation;
    306   }
    307   return (n == 1 ? msgid : msgid_plural);
    308 }
    309 
    310 
    311 #endif /* _LIBGETTEXT_H */