Join messages with existing file.
@item -k @var{word}
-@itemx --keyword[=@var{word}]
-Additonal keyword to be looked for (without @var{word} means not to
+@itemx --keyword[=@var{keywordspec}]
+Additional keyword to be looked for (without @var{keywordspec} means not to
use default keywords).
-The default keywords, which are always looked for if not explicitly
-disabled, are @code{gettext}, @code{dgettext}, @code{dcgettext} and
-@code{gettext_noop}.
+If @var{keywordspec} is a C identifer @var{id}, @code{xgettext} looks
+for strings in the first argument of each call to the function or macro
+@var{id}. If @var{keywordspec} is of the form
+@samp{@var{id}:@var{argnum}}, @code{xgettext} looks for strings in the
+@var{argnum}th argument of the call.
+
+The default keyword specifications, which are always looked for if not
+explicitly disabled, are @code{gettext}, @code{dgettext:2},
+@code{dcgettext:2} and @code{gettext_noop}.
@item -m [@var{string}]
@itemx --msgstr-prefix[=@var{string}]
+2000-07-28 Bruno Haible <haible@clisp.cons.org>
+
+ * xget-lex.h (enum xgettext_token_type_ty): Rename
+ xgettext_token_type_lp/rp to xgettext_token_type_lparen/rparen.
+ * xget-lex.c (enum token_type_ty): Rename token_type_lp/rp to
+ token_type_lparen/rparen.
+ (xgettext_any_keywords): `keywords' is now a hash table.
+ * xgettext.c (construct_header): Change two printf directives %02d
+ to %02ld.
+
+1998-07-17 Paul Eggert <eggert@twinsun.com>
+
+ Add support for user-specified argument numbers for keywords.
+ Extract all strings from a keyword arg, not just the first one.
+ Handle parenthesized commas inside keyword args correctly.
+ Warn about nested keywords.
+
+ * xgettext.c (scan_c_file):
+ Warn about nested keywords, e.g. _(_("xxx")).
+ Warn also about not-yet-implemented but allowed nesting, e.g.
+ dcgettext(..._("xxx")..., "yyy").
+ Get all strings in a keyword arg, not just the first one.
+ Handle parenthesized commas inside keyword args correctly.
+
+ * xget-lex.h (enum xgettext_token_type_ty):
+ Replace xgettext_token_type_keyword1 and
+ xgettext_token_type_keyword2 with just plain
+ xgettext_token_type_keyword; it now has argnum value.
+ Add xgettext_token_type_rp.
+ (struct xgettext_token_ty): Add argnum member.
+ line_number and file_name are now also set for
+ xgettext_token_type_keyword.
+ (xgettext_lex_keyword): Arg is const char *.
+
+ * xget-lex.c: Include "hash.h".
+ (enum token_type_ty): Add token_type_rp.
+ (keywords): Now a hash table.
+ (phase5_get): Return token_type_rp for ')'.
+ (xgettext_lex, xgettext_lex_keyword): Add support for keyword argnums.
+ (xgettext_lex): Return xgettext_token_type_rp for ')'.
+ Report keyword argnum, line number, and file name back to caller.
+
2000-05-06 Ulrich Drepper <drepper@redhat.com>
* Makefile.am (EXTRA_DIST): Replace po-gram.gen.h and po-hash.gen.h
/* GNU gettext - internationalization aids
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
#include "error.h"
#include "system.h"
#include "libgettext.h"
+#include "hash.h"
#include "str-list.h"
#include "xget-lex.h"
token_type_eof,
token_type_eoln,
token_type_hash,
- token_type_lp,
+ token_type_lparen,
+ token_type_rparen,
token_type_comma,
token_type_name,
token_type_number,
static int trigraphs;
static int cplusplus_comments;
static string_list_ty *comment;
-static string_list_ty *keywords;
+static hash_table keywords;
static int default_keywords = 1;
/* These are for tracking whether comments count as immediately before
return;
case '(':
- tp->type = token_type_lp;
+ tp->type = token_type_lparen;
+ return;
+
+ case ')':
+ tp->type = token_type_rparen;
return;
case ',':
while (1)
{
token_ty token;
+ void *keyword_value;
phase8_get (&token);
switch (token.type)
if (default_keywords)
{
xgettext_lex_keyword ("gettext");
- xgettext_lex_keyword ("dgettext");
- xgettext_lex_keyword ("dcgettext");
+ xgettext_lex_keyword ("dgettext:2");
+ xgettext_lex_keyword ("dcgettext:2");
xgettext_lex_keyword ("gettext_noop");
default_keywords = 0;
}
- if (string_list_member (keywords, token.string))
+ if (find_entry (&keywords, token.string, strlen (token.string),
+ &keyword_value)
+ == 0)
{
- tp->type = (strcmp (token.string, "dgettext") == 0
- || strcmp (token.string, "dcgettext") == 0)
- ? xgettext_token_type_keyword2 : xgettext_token_type_keyword1;
+ tp->type = xgettext_token_type_keyword;
+ tp->argnum = (int) (long) keyword_value;
+ tp->line_number = token.line_number;
+ tp->file_name = logical_file_name;
}
else
tp->type = xgettext_token_type_symbol;
free (token.string);
return;
- case token_type_lp:
+ case token_type_lparen:
+ last_non_comment_line = newline_count;
+
+ tp->type = xgettext_token_type_lparen;
+ return;
+
+ case token_type_rparen:
last_non_comment_line = newline_count;
- tp->type = xgettext_token_type_lp;
+ tp->type = xgettext_token_type_rparen;
return;
case token_type_comma:
void
xgettext_lex_keyword (name)
- char *name;
+ const char *name;
{
if (name == NULL)
default_keywords = 0;
else
{
- if (keywords == NULL)
- keywords = string_list_alloc ();
+ int argnum;
+ size_t len;
+ const char *sp;
+
+ if (keywords.table == NULL)
+ init_hash (&keywords, 100);
+
+ sp = strchr (name, ':');
+ if (sp)
+ {
+ len = sp - name;
+ argnum = atoi (sp + 1);
+ }
+ else
+ {
+ len = strlen (name);
+ argnum = 1;
+ }
- string_list_append_unique (keywords, name);
+ insert_entry (&keywords, name, len, (void *) (long) argnum);
}
}
int
xgettext_any_keywords ()
{
- return keywords != NULL || default_keywords;
+ return (keywords.filled > 0) || default_keywords;
}
/* GNU gettext - internationalization aids
- Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1998, 2000 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
enum xgettext_token_type_ty
{
xgettext_token_type_eof,
- xgettext_token_type_keyword1,
- xgettext_token_type_keyword2,
- xgettext_token_type_lp,
+ xgettext_token_type_keyword,
+ xgettext_token_type_lparen,
+ xgettext_token_type_rparen,
xgettext_token_type_comma,
xgettext_token_type_string_literal,
xgettext_token_type_symbol
{
xgettext_token_type_ty type;
- /* These 3 are only set for xgettext_token_type_string_literal. */
+ /* This field is used only for xgettext_token_type_keyword. */
+ int argnum;
+
+ /* This field is used only for xgettext_token_type_string_literal. */
char *string;
+
+ /* These fields are only for
+ xgettext_token_type_keyword,
+ xgettext_token_type_string_literal. */
int line_number;
char *file_name;
};
const char *xgettext_lex_comment PARAMS ((size_t __n));
void xgettext_lex_comment_reset PARAMS ((void));
/* void xgettext_lex_filepos PARAMS ((char **, int *)); FIXME needed? */
-void xgettext_lex_keyword PARAMS ((char *__name));
+void xgettext_lex_keyword PARAMS ((const char *__name));
int xgettext_any_keywords PARAMS ((void));
void xgettext_lex_cplusplus PARAMS ((void));
void xgettext_lex_trigraphs PARAMS ((void));
/* Extracts strings from C source file to Uniforum style .po file.
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software; you can redistribute it and/or modify
int is_cpp_file;
{
int state;
+ int commas_to_skip = 0; /* defined only when in states 1 and 2 */
+ int paren_nesting = 0; /* defined only when in state 2 */
/* Inform scanner whether we have C++ files or not. */
if (is_cpp_file)
{
xgettext_token_ty token;
- /* A simple state machine is used to do the recognising:
+ /* A state machine is used to do the recognising:
State 0 = waiting for something to happen
- State 1 = seen one of our keywords with string in first parameter
- State 2 = was in state 1 and now saw a left paren
- State 3 = seen one of our keywords with string in second parameter
- State 4 = was in state 3 and now saw a left paren
- State 5 = waiting for comma after being in state 4
- State 6 = saw comma after being in state 5 */
+ State 1 = seen one of our keywords
+ State 2 = waiting for part of an argument */
xgettext_lex (&token);
switch (token.type)
{
- case xgettext_token_type_keyword1:
+ case xgettext_token_type_keyword:
+ if (!extract_all && state == 2)
+ {
+ if (commas_to_skip == 0)
+ {
+ error (0, 0,
+ _("%s:%d: warning: keyword nested in keyword arg"),
+ token.file_name, token.line_number);
+ continue;
+ }
+
+ /* Here we should nest properly, but this would require a
+ potentially unbounded stack. We haven't run across an
+ example that needs this functionality yet. For now,
+ we punt and forget the outer keyword. */
+ error (0, 0,
+ _("%s:%d: warning: keyword between outer keyword and its arg"),
+ token.file_name, token.line_number);
+ }
+ commas_to_skip = token.argnum - 1;
state = 1;
continue;
- case xgettext_token_type_keyword2:
- state = 3;
- continue;
-
- case xgettext_token_type_lp:
+ case xgettext_token_type_lparen:
switch (state)
{
case 1:
+ paren_nesting = 0;
state = 2;
break;
- case 3:
- state = 4;
+ case 2:
+ paren_nesting++;
break;
- default:
- state = 0;
}
continue;
- case xgettext_token_type_comma:
- state = state == 5 ? 6 : 0;
+ case xgettext_token_type_rparen:
+ if (state == 2 && paren_nesting != 0)
+ paren_nesting--;
+ else
+ state = 0;
continue;
- case xgettext_token_type_string_literal:
- if (extract_all || state == 2 || state == 6)
+ case xgettext_token_type_comma:
+ if (state == 2 && commas_to_skip != 0)
{
- remember_a_message (mlp, &token);
- state = 0;
+ if (paren_nesting == 0)
+ commas_to_skip--;
}
+ else
+ state = 0;
+ continue;
+
+ case xgettext_token_type_string_literal:
+ if (extract_all || (state == 2 && commas_to_skip == 0))
+ remember_a_message (mlp, &token);
else
{
free (token.string);
- state = (state == 4 || state == 5) ? 5 : 0;
+ if (state == 1)
+ state = 0;
}
continue;
case xgettext_token_type_symbol:
- state = (state == 4 || state == 5) ? 5 : 0;
- continue;
-
- default:
- state = 0;
+ if (state == 1)
+ state = 0;
continue;
case xgettext_token_type_eof:
break;
+
+ default:
+ abort ();
}
break;
}
asprintf (&msgstr, "\
Project-Id-Version: PACKAGE VERSION\n\
-POT-Creation-Date: %d-%02d-%02d %02d:%02d%c%02d%02d\n\
+POT-Creation-Date: %d-%02d-%02d %02d:%02d%c%02ld%02ld\n\
PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n\
Last-Translator: FULL NAME <EMAIL@ADDRESS>\n\
Language-Team: LANGUAGE <LL@li.org>\n\