From: Bruno Haible Date: Fri, 28 Jul 2000 21:11:32 +0000 (+0000) Subject: Support for user-specified argument numbers for keywords. From Paul Eggert. X-Git-Tag: v0.10.36~246 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=047ad57d649e73d09778ba9a6d9ec7831bc5f9b9;p=thirdparty%2Fgettext.git Support for user-specified argument numbers for keywords. From Paul Eggert. --- diff --git a/doc/gettext.texi b/doc/gettext.texi index 343ffb41a..870db5bc4 100644 --- a/doc/gettext.texi +++ b/doc/gettext.texi @@ -1859,13 +1859,19 @@ List of directories searched for input files. 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}] diff --git a/src/ChangeLog b/src/ChangeLog index 4c08e959b..8ef5a6aff 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,45 @@ +2000-07-28 Bruno Haible + + * 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 + + 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 * Makefile.am (EXTRA_DIST): Replace po-gram.gen.h and po-hash.gen.h diff --git a/src/xget-lex.c b/src/xget-lex.c index a838e4cae..3fa5cf6d2 100644 --- a/src/xget-lex.c +++ b/src/xget-lex.c @@ -1,5 +1,5 @@ /* 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 @@ -33,6 +33,7 @@ #include "error.h" #include "system.h" #include "libgettext.h" +#include "hash.h" #include "str-list.h" #include "xget-lex.h" @@ -82,7 +83,8 @@ enum token_type_ty 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, @@ -109,7 +111,7 @@ static FILE *fp; 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 @@ -938,7 +940,11 @@ phase5_get (tp) return; case '(': - tp->type = token_type_lp; + tp->type = token_type_lparen; + return; + + case ')': + tp->type = token_type_rparen; return; case ',': @@ -1179,6 +1185,7 @@ xgettext_lex (tp) while (1) { token_ty token; + void *keyword_value; phase8_get (&token); switch (token.type) @@ -1213,27 +1220,36 @@ xgettext_lex (tp) 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: @@ -1263,16 +1279,32 @@ xgettext_lex (tp) 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); } } @@ -1280,7 +1312,7 @@ xgettext_lex_keyword (name) int xgettext_any_keywords () { - return keywords != NULL || default_keywords; + return (keywords.filled > 0) || default_keywords; } diff --git a/src/xget-lex.h b/src/xget-lex.h index 18491ca73..ccdaf3425 100644 --- a/src/xget-lex.h +++ b/src/xget-lex.h @@ -1,5 +1,5 @@ /* 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 @@ -23,9 +23,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 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 @@ -37,8 +37,15 @@ struct xgettext_token_ty { 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; }; @@ -50,7 +57,7 @@ void xgettext_lex PARAMS ((xgettext_token_ty *__tp)); 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)); diff --git a/src/xgettext.c b/src/xgettext.c index 552a25867..db8113f40 100644 --- a/src/xgettext.c +++ b/src/xgettext.c @@ -1,5 +1,5 @@ /* 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 , April 1995. This program is free software; you can redistribute it and/or modify @@ -842,6 +842,8 @@ scan_c_file(filename, mlp, is_cpp_file) 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) @@ -861,66 +863,87 @@ scan_c_file(filename, mlp, 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; } @@ -1247,7 +1270,7 @@ FIRST AUTHOR , YEAR.\n"); 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 \n\ Language-Team: LANGUAGE \n\