Home | History | Annotate | Line # | Download | only in src
      1 /* xgettext common functions.
      2    Copyright (C) 2001-2003, 2005-2006 Free Software Foundation, Inc.
      3    Written by Peter Miller <millerp (at) canb.auug.org.au>
      4    and Bruno Haible <haible (at) clisp.cons.org>, 2001.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 2, or (at your option)
      9    any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software Foundation,
     18    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     19 
     20 #ifndef _XGETTEXT_H
     21 #define _XGETTEXT_H
     22 
     23 #include <stdbool.h>
     24 #include <stddef.h>
     25 #include <stdlib.h>
     26 
     27 #if HAVE_ICONV
     28 #include <iconv.h>
     29 #endif
     30 
     31 #include "message.h"
     32 #include "pos.h"
     33 #include "str-list.h"
     34 
     35 /* Declare 'line_comment' and 'input_syntax'.  */
     36 #include "read-catalog.h"
     37 
     38 
     39 #ifdef __cplusplus
     40 extern "C" {
     41 #endif
     42 
     43 
     44 /* If true, omit the header entry.
     45    If false, keep the header entry present in the input.  */
     46 extern int xgettext_omit_header;
     47 
     48 extern bool substring_match;
     49 
     50 
     51 /* Calling convention for a given keyword.  */
     52 struct callshape
     53 {
     54   int argnum1; /* argument number to use for msgid */
     55   int argnum2; /* argument number to use for msgid_plural */
     56   int argnumc; /* argument number to use for msgctxt */
     57   bool argnum1_glib_context; /* argument argnum1 has the syntax "ctxt|msgid" */
     58   bool argnum2_glib_context; /* argument argnum2 has the syntax "ctxt|msgid" */
     59   int argtotal; /* total number of arguments */
     60   string_list_ty xcomments; /* auto-extracted comments */
     61 };
     62 
     63 /* Split keyword spec into keyword, argnum1, argnum2, argnumc.  */
     64 extern void split_keywordspec (const char *spec, const char **endp,
     65 			       struct callshape *shapep);
     66 
     67 /* Set of alternative calling conventions for a given keyword.  */
     68 struct callshapes
     69 {
     70   const char *keyword;          /* the keyword, not NUL terminated */
     71   size_t keyword_len;           /* the keyword's length */
     72   size_t nshapes;
     73   struct callshape shapes[1];   /* actually nshapes elements */
     74 };
     75 
     76 /* Insert a (keyword, callshape) pair into a hash table mapping keyword to
     77    'struct callshapes *'.  */
     78 extern void insert_keyword_callshape (hash_table *table,
     79 				      const char *keyword, size_t keyword_len,
     80 				      const struct callshape *shape);
     81 
     82 
     83 /* Context representing some flags.  */
     84 typedef struct flag_context_ty flag_context_ty;
     85 struct flag_context_ty
     86 {
     87   /* Regarding the primary formatstring type.  */
     88   /*enum is_format*/ unsigned int is_format1    : 3;
     89   /*bool*/           unsigned int pass_format1  : 1;
     90   /* Regarding the secondary formatstring type.  */
     91   /*enum is_format*/ unsigned int is_format2    : 3;
     92   /*bool*/           unsigned int pass_format2  : 1;
     93 };
     94 /* Null context.  */
     95 extern flag_context_ty null_context;
     96 /* Transparent context.  */
     97 extern flag_context_ty passthrough_context;
     98 /* Compute an inherited context.
     99    The outer_context is assumed to have all pass_format* flags = false.
    100    The result will then also have all pass_format* flags = false.  */
    101 extern flag_context_ty
    102        inherited_context (flag_context_ty outer_context,
    103 			  flag_context_ty modifier_context);
    104 
    105 /* Context representing some flags, for each possible argument number.
    106    This is a linked list, sorted according to the argument number.  */
    107 typedef struct flag_context_list_ty flag_context_list_ty;
    108 struct flag_context_list_ty
    109 {
    110   int argnum;			/* current argument number, > 0 */
    111   flag_context_ty flags;	/* flags for current argument */
    112   flag_context_list_ty *next;
    113 };
    114 
    115 /* Iterator through a flag_context_list_ty.  */
    116 typedef struct flag_context_list_iterator_ty flag_context_list_iterator_ty;
    117 struct flag_context_list_iterator_ty
    118 {
    119   int argnum;				/* current argument number, > 0 */
    120   const flag_context_list_ty* head;	/* tail of list */
    121 };
    122 extern flag_context_list_iterator_ty null_context_list_iterator;
    123 extern flag_context_list_iterator_ty passthrough_context_list_iterator;
    124 extern flag_context_list_iterator_ty
    125        flag_context_list_iterator (flag_context_list_ty *list);
    126 extern flag_context_ty
    127        flag_context_list_iterator_advance (flag_context_list_iterator_ty *iter);
    128 
    129 /* For nearly each backend, we have a separate table mapping a keyword to
    130    a flag_context_list_ty *.  */
    131 typedef hash_table /* char[] -> flag_context_list_ty * */
    132         flag_context_list_table_ty;
    133 extern flag_context_list_ty *
    134        flag_context_list_table_lookup (flag_context_list_table_ty *flag_table,
    135 				       const void *key, size_t keylen);
    136 /* Record a flag in the appropriate backend's table.  */
    137 extern void xgettext_record_flag (const char *optionstring);
    138 
    139 
    140 /* Canonicalized encoding name for all input files.  */
    141 extern const char *xgettext_global_source_encoding;
    142 
    143 #if HAVE_ICONV
    144 /* Converter from xgettext_global_source_encoding to UTF-8 (except from
    145    ASCII or UTF-8, when this conversion is a no-op).  */
    146 extern iconv_t xgettext_global_source_iconv;
    147 #endif
    148 
    149 /* Canonicalized encoding name for the current input file.  */
    150 extern const char *xgettext_current_source_encoding;
    151 
    152 #if HAVE_ICONV
    153 /* Converter from xgettext_current_source_encoding to UTF-8 (except from
    154    ASCII or UTF-8, when this conversion is a no-op).  */
    155 extern iconv_t xgettext_current_source_iconv;
    156 #endif
    157 
    158 /* Convert the given string from xgettext_current_source_encoding to
    159    the output file encoding (i.e. ASCII or UTF-8).
    160    The resulting string is either the argument string, or freshly allocated.
    161    The file_name and line_number are only used for error message purposes.  */
    162 extern char *from_current_source_encoding (const char *string,
    163 					   const char *file_name,
    164 					   size_t line_number);
    165 
    166 
    167 /* List of messages whose msgids must not be extracted, or NULL.
    168    Used by remember_a_message().  */
    169 extern message_list_ty *exclude;
    170 
    171 
    172 /* Comment handling for backends which support combining adjacent strings
    173    even across lines.
    174    In these backends we cannot use the xgettext_comment* functions directly,
    175    because in multiline string expressions like
    176            "string1" +
    177            "string2"
    178    the newline between "string1" and "string2" would cause a call to
    179    xgettext_comment_reset(), thus destroying the accumulated comments
    180    that we need a little later, when we have concatenated the two strings
    181    and pass them to remember_a_message().
    182    Instead, we do the bookkeeping of the accumulated comments directly,
    183    and save a pointer to the accumulated comments when we read "string1".
    184    In order to avoid excessive copying of strings, we use reference
    185    counting.  */
    186 
    187 typedef struct refcounted_string_list_ty refcounted_string_list_ty;
    188 struct refcounted_string_list_ty
    189 {
    190   unsigned int refcount;
    191   struct string_list_ty contents;
    192 };
    193 
    194 static inline refcounted_string_list_ty *
    195 add_reference (refcounted_string_list_ty *rslp)
    196 {
    197   if (rslp != NULL)
    198     rslp->refcount++;
    199   return rslp;
    200 }
    201 
    202 static inline void
    203 drop_reference (refcounted_string_list_ty *rslp)
    204 {
    205   if (rslp != NULL)
    206     {
    207       if (rslp->refcount > 1)
    208 	rslp->refcount--;
    209       else
    210 	{
    211 	  string_list_destroy (&rslp->contents);
    212 	  free (rslp);
    213 	}
    214     }
    215 }
    216 
    217 extern refcounted_string_list_ty *savable_comment;
    218 extern void savable_comment_add (const char *str);
    219 extern void savable_comment_reset (void);
    220 
    221 
    222 /* Add a message to the list of extracted messages.
    223    msgctxt must be either NULL or a malloc()ed string; its ownership is passed
    224    to the callee.
    225    MSGID must be a malloc()ed string; its ownership is passed to the callee.
    226    POS->file_name must be allocated with indefinite extent.
    227    COMMENT may be savable_comment, or it may be a saved copy of savable_comment
    228    (then add_reference must be used when saving it, and drop_reference while
    229    dropping it).  Clear savable_comment.  */
    230 extern message_ty *remember_a_message (message_list_ty *mlp,
    231 				       char *msgctxt,
    232 				       char *msgid,
    233 				       flag_context_ty context,
    234 				       lex_pos_ty *pos,
    235 				       refcounted_string_list_ty *comment);
    236 /* Add an msgid_plural to a message previously returned by
    237    remember_a_message.
    238    STRING must be a malloc()ed string; its ownership is passed to the callee.
    239    POS->file_name must be allocated with indefinite extent.
    240    COMMENT may be savable_comment, or it may be a saved copy of savable_comment
    241    (then add_reference must be used when saving it, and drop_reference while
    242    dropping it).  Clear savable_comment.  */
    243 extern void remember_a_message_plural (message_ty *mp,
    244 				       char *string,
    245 				       flag_context_ty context,
    246 				       lex_pos_ty *pos,
    247 				       refcounted_string_list_ty *comment);
    248 
    249 
    250 /* Represents the progressive parsing of an argument list w.r.t. a single
    251    'struct callshape'.  */
    252 struct partial_call
    253 {
    254   int argnumc;                  /* number of context argument, 0 when seen */
    255   int argnum1;                  /* number of singular argument, 0 when seen */
    256   int argnum2;                  /* number of plural argument, 0 when seen */
    257   bool argnum1_glib_context;    /* argument argnum1 has the syntax "ctxt|msgid" */
    258   bool argnum2_glib_context;    /* argument argnum2 has the syntax "ctxt|msgid" */
    259   int argtotal;                 /* total number of arguments, 0 if unspecified */
    260   string_list_ty xcomments;     /* auto-extracted comments */
    261   char *msgctxt;                /* context - owned string, or NULL */
    262   lex_pos_ty msgctxt_pos;
    263   char *msgid;                  /* msgid - owned string, or NULL */
    264   flag_context_ty msgid_context;
    265   lex_pos_ty msgid_pos;
    266   refcounted_string_list_ty *msgid_comment;
    267   char *msgid_plural;           /* msgid_plural - owned string, or NULL */
    268   flag_context_ty msgid_plural_context;
    269   lex_pos_ty msgid_plural_pos;
    270 };
    271 
    272 /* Represents the progressive parsing of an argument list w.r.t. an entire
    273    'struct callshapes'.  */
    274 struct arglist_parser
    275 {
    276   message_list_ty *mlp;         /* list where the message shall be added */
    277   const char *keyword;          /* the keyword, not NUL terminated */
    278   size_t keyword_len;           /* the keyword's length */
    279   size_t nalternatives;         /* number of partial_call alternatives */
    280   struct partial_call alternative[1]; /* partial_call alternatives */
    281 };
    282 
    283 /* Creates a fresh arglist_parser recognizing calls.
    284    You can pass shapes = NULL for a parser not recognizing any calls.  */
    285 extern struct arglist_parser * arglist_parser_alloc (message_list_ty *mlp,
    286 						     const struct callshapes *shapes);
    287 /* Clones an arglist_parser.  */
    288 extern struct arglist_parser * arglist_parser_clone (struct arglist_parser *ap);
    289 /* Adds a string argument to an arglist_parser.  ARGNUM must be > 0.
    290    STRING must be malloc()ed string; its ownership is passed to the callee.
    291    FILE_NAME must be allocated with indefinite extent.
    292    COMMENT may be savable_comment, or it may be a saved copy of savable_comment
    293    (then add_reference must be used when saving it, and drop_reference while
    294    dropping it).  Clear savable_comment.  */
    295 extern void arglist_parser_remember (struct arglist_parser *ap,
    296 				     int argnum, char *string,
    297 				     flag_context_ty context,
    298 				     char *file_name, size_t line_number,
    299 				     refcounted_string_list_ty *comment);
    300 /* Tests whether an arglist_parser has is not waiting for more arguments after
    301    argument ARGNUM.  */
    302 extern bool arglist_parser_decidedp (struct arglist_parser *ap, int argnum);
    303 /* Terminates the processing of an arglist_parser after argument ARGNUM and
    304    deletes it.  */
    305 extern void arglist_parser_done (struct arglist_parser *ap, int argnum);
    306 
    307 
    308 #ifdef __cplusplus
    309 }
    310 #endif
    311 
    312 
    313 #endif /* _XGETTEXT_H */
    314