diff options
author | jbj <devnull@localhost> | 1998-09-20 18:27:03 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 1998-09-20 18:27:03 +0000 |
commit | 32ffb6b77c138989f89bedb97b8ceaf982a9cc2e (patch) | |
tree | 9b6fe6629f7971bfafde9db4c4411b96ae192b83 /tools | |
parent | 33e58c54f53e14e4f214153a40fa59f9b0ae07aa (diff) | |
download | rpm-32ffb6b77c138989f89bedb97b8ceaf982a9cc2e.tar.gz rpm-32ffb6b77c138989f89bedb97b8ceaf982a9cc2e.tar.bz2 rpm-32ffb6b77c138989f89bedb97b8ceaf982a9cc2e.zip |
Rearrange gettext sources to taste.
CVS patchset: 2332
CVS date: 1998/09/20 18:27:03
Diffstat (limited to 'tools')
-rw-r--r-- | tools/fstrcmp.h | 25 | ||||
-rw-r--r-- | tools/message.c | 1404 | ||||
-rw-r--r-- | tools/rpmgettext.c | 421 | ||||
-rw-r--r-- | tools/rpmpo.h | 78 | ||||
-rw-r--r-- | tools/str-list.h | 50 |
5 files changed, 1504 insertions, 474 deletions
diff --git a/tools/fstrcmp.h b/tools/fstrcmp.h deleted file mode 100644 index 04047171f..000000000 --- a/tools/fstrcmp.h +++ /dev/null @@ -1,25 +0,0 @@ -/* GNU gettext - internationalization aids - Copyright (C) 1995 Free Software Foundation, Inc. - - This file was written by Peter Miller <pmiller@agso.gov.au> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#ifndef _FSTRCMP_H -#define _FSTRCMP_H - -double fstrcmp PARAMS ((const char *__s1, const char *__s2)); - -#endif diff --git a/tools/message.c b/tools/message.c new file mode 100644 index 000000000..e381a291e --- /dev/null +++ b/tools/message.c @@ -0,0 +1,1404 @@ +/* GNU gettext - internationalization aids + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + This file was written by Peter Miller <millerp@canb.auug.org.au> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <ctype.h> +#include <stdio.h> + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif + +#include "fstrcmp.h" +#include "message.h" +#include "system.h" +#include "error.h" +#include "libgettext.h" + + +/* Our regular abbreviation. */ +#define _(str) gettext (str) + + +/* These two variables control the output style of the message_print + function. Interface functions for them are to be used. */ +static int indent; +static int uniforum; +static int escape; + +/* This variable controls the page width when printing messages. + Defaults to PAGE_WIDTH if not set. Zero (0) given to message_page_- + width_set will result in no wrapping being performed. */ +static size_t page_width = PAGE_WIDTH; + + +/* Prototypes for local functions. */ +static void wrap PARAMS ((FILE *__fp, const char *__line_prefix, + const char *__name, const char *__value, + int do_wrap)); +static void print_blank_line PARAMS ((FILE *__fp)); +static void message_print PARAMS ((const message_ty *__mp, FILE *__fp, + const char *__domain, int blank_line, + int __debug)); +static void message_print_obsolete PARAMS ((const message_ty *__mp, FILE *__fp, + const char *__domain, + int blank_line)); +static int msgid_cmp PARAMS ((const void *__va, const void *__vb)); +static int filepos_cmp PARAMS ((const void *__va, const void *__vb)); +static const char *make_c_format_description_string PARAMS ((enum is_c_format, + int debug)); +static const char *make_c_width_description_string PARAMS ((enum is_c_format)); +static int significant_c_format_p PARAMS ((enum is_c_format __is_c_format)); + + + +message_ty * +message_alloc (msgid) + char *msgid; +{ + message_ty *mp; + + mp = xmalloc (sizeof (message_ty)); + mp->msgid = msgid; + mp->comment = NULL; + mp->comment_dot = NULL; + mp->filepos_count = 0; + mp->filepos = NULL; + mp->variant_count = 0; + mp->variant = NULL; + mp->used = 0; + mp->obsolete = 0; + mp->is_fuzzy = 0; + mp->is_c_format = undecided; + mp->do_wrap = undecided; + return mp; +} + + +void +message_free (mp) + message_ty *mp; +{ + size_t j; + + if (mp->comment != NULL) + string_list_free (mp->comment); + if (mp->comment_dot != NULL) + string_list_free (mp->comment_dot); + free ((char *) mp->msgid); + for (j = 0; j < mp->variant_count; ++j) + free ((char *) mp->variant[j].msgstr); + if (mp->variant != NULL) + free (mp->variant); + for (j = 0; j < mp->filepos_count; ++j) + free ((char *) mp->filepos[j].file_name); + if (mp->filepos != NULL) + free (mp->filepos); + free (mp); +} + + +message_variant_ty * +message_variant_search (mp, domain) + message_ty *mp; + const char *domain; +{ + size_t j; + message_variant_ty *mvp; + + for (j = 0; j < mp->variant_count; ++j) + { + mvp = &mp->variant[j]; + if (0 == strcmp (domain, mvp->domain)) + return mvp; + } + return 0; +} + + +void +message_variant_append (mp, domain, msgstr, pp) + message_ty *mp; + const char *domain; + const char *msgstr; + const lex_pos_ty *pp; +{ + size_t nbytes; + message_variant_ty *mvp; + + nbytes = (mp->variant_count + 1) * sizeof (mp->variant[0]); + mp->variant = xrealloc (mp->variant, nbytes); + mvp = &mp->variant[mp->variant_count++]; + mvp->domain = domain; + mvp->msgstr = msgstr; + mvp->pos = *pp; +} + + +void +message_comment_append (mp, s) + message_ty *mp; + const char *s; +{ + if (mp->comment == NULL) + mp->comment = string_list_alloc (); + string_list_append (mp->comment, s); +} + + +void +message_comment_dot_append (mp, s) + message_ty *mp; + const char *s; +{ + if (mp->comment_dot == NULL) + mp->comment_dot = string_list_alloc (); + string_list_append (mp->comment_dot, s); +} + + +message_ty * +message_copy (mp) + message_ty *mp; +{ + message_ty *result; + size_t j; + + result = message_alloc (xstrdup (mp->msgid)); + + for (j = 0; j < mp->variant_count; ++j) + { + message_variant_ty *mvp = &mp->variant[j]; + message_variant_append (result, mvp->domain, mvp->msgstr, &mvp->pos); + } + if (mp->comment) + { + for (j = 0; j < mp->comment->nitems; ++j) + message_comment_append (result, mp->comment->item[j]); + } + if (mp->comment_dot) + { + for (j = 0; j < mp->comment_dot->nitems; ++j) + message_comment_dot_append (result, mp->comment_dot->item[j]); + } + result->is_fuzzy = mp->is_fuzzy; + result->is_c_format = mp->is_c_format; + result->do_wrap = mp->do_wrap; + for (j = 0; j < mp->filepos_count; ++j) + { + lex_pos_ty *pp = &mp->filepos[j]; + message_comment_filepos (result, pp->file_name, pp->line_number); + } + return result; +} + + +message_ty * +message_merge (def, ref) + message_ty *def; + message_ty *ref; +{ + message_ty *result; + const char *pot_date_ptr = NULL; + size_t pot_date_len = 0; + size_t j; + + /* Take the msgid from the reference. When fuzzy matches are made, + the definition will not be unique, but the reference will be - + usually because it has a typo. */ + result = message_alloc (xstrdup (ref->msgid)); + + /* If msgid is the header entry (i.e., "") we find the + POT-Creation-Date line in the reference. */ + if (ref->msgid[0] == '\0') + { + pot_date_ptr = strstr (ref->variant[0].msgstr, "POT-Creation-Date:"); + if (pot_date_ptr != NULL) + { + const char *endp; + + pot_date_ptr += sizeof ("POT-Creation-Date:") - 1; + + endp = strchr (pot_date_ptr, '\n'); + if (endp == NULL) + { + char *extended; + endp = strchr (pot_date_ptr, '\0'); + pot_date_len = (endp - pot_date_ptr) + 1; + extended = (char *) alloca (pot_date_len + 1); + stpcpy (stpcpy (extended, pot_date_ptr), "\n"); + pot_date_ptr = extended; + } + else + pot_date_len = (endp - pot_date_ptr) + 1; + + if (pot_date_len == 0) + pot_date_ptr = NULL; + } + } + + /* Take the variant list from the definition. The msgstr of the + refences will be empty, as they were generated by xgettext. If + we currently process the header entry we have to merge the msgstr + by using the POT-Creation-Date field from the .pot file. */ + for (j = 0; j < def->variant_count; ++j) + { + message_variant_ty *mvp = &def->variant[j]; + + if (ref->msgid[0] == '\0') + { + /* Oh, oh. The header entry and we have something to fill in. */ + static const struct + { + const char *name; + size_t len; + } known_fields[] = + { + { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 }, +#define PROJECT_ID 0 + { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 }, +#define POT_CREATION 1 + { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 }, +#define PO_REVISION 2 + { "Last-Translator:", sizeof ("Last-Translator:") - 1 }, +#define LAST_TRANSLATOR 3 + { "Language-Team:", sizeof ("Language-Team:") - 1 }, +#define LANGUAGE_TEAM 4 + { "MIME-Version:", sizeof ("MIME-Version:") - 1 }, +#define MIME_VERSION 5 + { "Content-Type:", sizeof ("Content-Type:") - 1 }, +#define CONTENT_TYPE 6 + { "Content-Transfer-Encoding:", + sizeof ("Content-Transfer-Encoding:") - 1 } +#define CONTENT_TRANSFER 7 + }; +#define UNKNOWN 8 + struct + { + const char *string; + size_t len; + } header_fields[UNKNOWN + 1]; + const char *cp; + char *newp; + size_t len, cnt; + + /* Clear all fields. */ + memset (header_fields, '\0', sizeof (header_fields)); + + cp = mvp->msgstr; + while (*cp != '\0') + { + const char *endp = strchr (cp, '\n'); + int terminated = endp != NULL; + + if (!terminated) + { + char *copy; + endp = strchr (cp, '\0'); + + len = endp - cp + 1; + + copy = (char *) alloca (len + 1); + stpcpy (stpcpy (copy, cp), "\n"); + cp = copy; + } + else + { + len = (endp - cp) + 1; + ++endp; + } + + /* Compare with any of the known fields. */ + for (cnt = 0; + cnt < sizeof (known_fields) / sizeof (known_fields[0]); + ++cnt) + if (strncasecmp (cp, known_fields[cnt].name, + known_fields[cnt].len) == 0) + break; + + if (cnt < sizeof (known_fields) / sizeof (known_fields[0])) + { + header_fields[cnt].string = &cp[known_fields[cnt].len]; + header_fields[cnt].len = len - known_fields[cnt].len; + } + else + { + /* It's an unknown field. Append content to what is + already known. */ + char *extended = (char *) alloca (header_fields[UNKNOWN].len + + len + 1); + memcpy (extended, header_fields[UNKNOWN].string, + header_fields[UNKNOWN].len); + memcpy (&extended[header_fields[UNKNOWN].len], cp, len); + extended[header_fields[UNKNOWN].len + len] = '\0'; + header_fields[UNKNOWN].string = extended; + header_fields[UNKNOWN].len += len; + } + + cp = endp; + } + + if (pot_date_ptr != NULL) + { + header_fields[POT_CREATION].string = pot_date_ptr; + header_fields[POT_CREATION].len = pot_date_len; + } + + /* Concatenate all the various fields. */ + len = 0; + for (cnt = 0; cnt < UNKNOWN; ++cnt) + if (header_fields[cnt].string != NULL) + len += known_fields[cnt].len + header_fields[cnt].len; + len += header_fields[UNKNOWN].len; + + cp = newp = (char *) xmalloc (len + 1); + newp[len] = '\0'; + +#define IF_FILLED(idx) \ + if (header_fields[idx].string) \ + newp = stpncpy (stpcpy (newp, known_fields[idx].name), \ + header_fields[idx].string, header_fields[idx].len) + + IF_FILLED (PROJECT_ID); + IF_FILLED (POT_CREATION); + IF_FILLED (PO_REVISION); + IF_FILLED (LAST_TRANSLATOR); + IF_FILLED (LANGUAGE_TEAM); + IF_FILLED (MIME_VERSION); + IF_FILLED (CONTENT_TYPE); + IF_FILLED (CONTENT_TRANSFER); + if (header_fields[UNKNOWN].string != NULL) + stpcpy (newp, header_fields[UNKNOWN].string); + + message_variant_append (result, mvp->domain, cp, &mvp->pos); + } + else + message_variant_append (result, mvp->domain, mvp->msgstr, &mvp->pos); + } + + /* Take the comments from the definition file. There will be none at + all in the reference file, as it was generated by xgettext. */ + if (def->comment) + for (j = 0; j < def->comment->nitems; ++j) + message_comment_append (result, def->comment->item[j]); + + /* Take the dot comments from the reference file, as they are + generated by xgettext. Any in the definition file are old ones + collected by previous runs of xgettext and msgmerge. */ + if (ref->comment_dot) + for (j = 0; j < ref->comment_dot->nitems; ++j) + message_comment_dot_append (result, ref->comment_dot->item[j]); + + /* The flags are mixed in a special way. Some informations come + from the reference message (such as format/no-format), others + come from the definition file (fuzzy or not). */ + result->is_fuzzy = def->is_fuzzy; + result->is_c_format = ref->is_c_format; + result->do_wrap = ref->do_wrap; + + /* Take the file position comments from the reference file, as they + are generated by xgettext. Any in the definition file are old ones + collected by previous runs of xgettext and msgmerge. */ + for (j = 0; j < ref->filepos_count; ++j) + { + lex_pos_ty *pp = &ref->filepos[j]; + message_comment_filepos (result, pp->file_name, pp->line_number); + } + + /* All done, return the merged message to the caller. */ + return result; +} + + +void +message_comment_filepos (mp, name, line) + message_ty *mp; + const char *name; + size_t line; +{ + size_t nbytes; + lex_pos_ty *pp; + int min, max; + int j; + + /* See if we have this position already. They are kept in sorted + order, so use a binary chop. */ + /* FIXME: use bsearch */ + min = 0; + max = (int) mp->filepos_count - 1; + while (min <= max) + { + int mid; + int cmp; + + mid = (min + max) / 2; + pp = &mp->filepos[mid]; + cmp = strcmp (pp->file_name, name); + if (cmp == 0) + cmp = (int) pp->line_number - line; + if (cmp == 0) + return; + if (cmp < 0) + min = mid + 1; + else + max = mid - 1; + } + + /* Extend the list so that we can add an position to it. */ + nbytes = (mp->filepos_count + 1) * sizeof (mp->filepos[0]); + mp->filepos = xrealloc (mp->filepos, nbytes); + + /* Shuffle the rest of the list up one, so that we can insert the + position at ``min''. */ + /* FIXME: use memmove */ + for (j = mp->filepos_count; j > min; --j) + mp->filepos[j] = mp->filepos[j - 1]; + mp->filepos_count++; + + /* Insert the postion into the empty slot. */ + pp = &mp->filepos[min]; + pp->file_name = xstrdup (name); + pp->line_number = line; +} + + +void +message_print_style_indent () +{ + indent = 1; +} + + +void +message_print_style_uniforum () +{ + uniforum = 1; +} + + +void +message_print_style_escape (flag) + int flag; +{ + escape = (flag != 0); +} + + +message_list_ty * +message_list_alloc () +{ + message_list_ty *mlp; + + mlp = xmalloc (sizeof (message_list_ty)); + mlp->nitems = 0; + mlp->nitems_max = 0; + mlp->item = 0; + return mlp; +} + + +void +message_list_append (mlp, mp) + message_list_ty *mlp; + message_ty *mp; +{ + if (mlp->nitems >= mlp->nitems_max) + { + size_t nbytes; + + mlp->nitems_max = mlp->nitems_max * 2 + 4; + nbytes = mlp->nitems_max * sizeof (message_ty *); + mlp->item = xrealloc (mlp->item, nbytes); + } + mlp->item[mlp->nitems++] = mp; +} + + +void +message_list_delete_nth (mlp, n) + message_list_ty *mlp; + size_t n; +{ + size_t j; + + if (n >= mlp->nitems) + return; + message_free (mlp->item[n]); + for (j = n + 1; j < mlp->nitems; ++j) + mlp->item[j - 1] = mlp->item[j]; + mlp->nitems--; +} + + +message_ty * +message_list_search (mlp, msgid) + message_list_ty *mlp; + const char *msgid; +{ + size_t j; + + for (j = 0; j < mlp->nitems; ++j) + { + message_ty *mp; + + mp = mlp->item[j]; + if (0 == strcmp (msgid, mp->msgid)) + return mp; + } + return 0; +} + + +message_ty * +message_list_search_fuzzy (mlp, msgid) + message_list_ty *mlp; + const char *msgid; +{ + size_t j; + double best_weight; + message_ty *best_mp; + + best_weight = 0.6; + best_mp = NULL; + for (j = 0; j < mlp->nitems; ++j) + { + size_t k; + double weight; + message_ty *mp; + + mp = mlp->item[j]; + + for (k = 0; k < mp->variant_count; ++k) + if (mp->variant[k].msgstr != NULL && mp->variant[k].msgstr[0] != '\0') + break; + if (k >= mp->variant_count) + continue; + + weight = fstrcmp (msgid, mp->msgid); + if (weight > best_weight) + { + best_weight = weight; + best_mp = mp; + } + } + return best_mp; +} + + +void +message_list_free (mlp) + message_list_ty *mlp; +{ + size_t j; + + for (j = 0; j < mlp->nitems; ++j) + message_free (mlp->item[j]); + if (mlp->item) + free (mlp->item); + free (mlp); +} + + +/* Local functions. */ + +static void +wrap (fp, line_prefix, name, value, do_wrap) + FILE *fp; + const char *line_prefix; + const char *name; + const char *value; + int do_wrap; +{ + const char *s; + int first_line; + /* The \a and \v escapes were added by the ANSI C Standard. Prior + to the Standard, most compilers did not have them. Because we + need the same program on all platforms we don't provide support + for them here. */ + static const char escapes[] = "\b\f\n\r\t"; + static const char escape_names[] = "bfnrt"; + + /* The empty string is a special case. */ + if (*value == '\0') + { + if (line_prefix != NULL) + fputs (line_prefix, fp); + fputs (name, fp); + putc (indent ? '\t' : ' ', fp); + fputs ("\"\"\n", fp); + return; + } + + s = value; + first_line = 1; + while (*s) + { + const char *ep; + int ocol; + + /* The line starts with different things depending on whether it + is the first line, and if we are using the indented style. */ + if (first_line) + { + ocol = strlen (name) + (line_prefix ? strlen (line_prefix) : 0); + if (indent && ocol < 8) + ocol = 8; + else + ++ocol; + } + else + ocol = (indent ? 8 : 0); + + /* Allow room for the opening quote character. */ + ++ocol; + + /* Work out how many characters from the string will fit on a + line. Natural breaks occur at embedded newline characters. */ + for (ep = s; *ep; ++ep) + { + const char *esc; + int cw; + int c; + + c = (unsigned char) *ep; + /* FIXME This is the wrong locale. While message_list_print + set the "C" locale for LC_CTYPE, the need is to use the + correct locale for the file's contents. */ + esc = strchr (escapes, c); + if (esc == NULL && (!escape || isprint (c))) + cw = 1 + (c == '\\' || c == '"'); + else + cw = esc != NULL ? 2 : 4; + /* Allow 1 character for the closing quote. */ + if (ocol + cw >= (do_wrap == no ? INT_MAX : page_width)) + break; + ocol += cw; + if (c == '\n') + { + ++ep; + break; + } + } + + /* The above loop detects if a line is too long. If it is too + long, see if there is a better place to break the line. */ + if (*ep) + { + const char *bp; + + for (bp = ep; bp > s; --bp) + if (bp[-1] == ' ' || bp[-1] == '\n') + { + ep = bp; + break; + } + } + + /* If this is the first line, and we are not using the indented + style, and the line would wrap, then use an empty first line + and restart. */ + if (first_line && !indent && *ep != '\0') + { + fprintf (fp, "%s%s \"\"\n", line_prefix ? line_prefix : "", name); + s = value; + first_line = 0; + continue; + } + + /* Print the beginning of the line. This will depend on whether + this is the first line, and if the indented style is being + used. */ + if (first_line) + { + first_line = 0; + if (line_prefix != NULL) + fputs (line_prefix, fp); + fputs (name, fp); + putc (indent ? '\t' : ' ', fp); + } + else + { + if (line_prefix != NULL) + fputs (line_prefix, fp); + if (indent) + putc ('\t', fp); + } + + /* Print the body of the line. C escapes are used for + unprintable characters. */ + putc ('"', fp); + while (s < ep) + { + const char *esc; + int c; + + c = (unsigned char) *s++; + /* FIXME This is the wrong locale. While message_list_print + set the "C" locale for LC_CTYPE, the need is to use the + correct locale for the file's contents. */ + esc = strchr (escapes, c); + if (esc == NULL && (!escape || isprint (c))) + { + if (c == '\\' || c == '"') + putc ('\\', fp); + putc (c, fp); + } + else if (esc != NULL) + { + c = escape_names[esc - escapes]; + + putc ('\\', fp); + putc (c, fp); + + /* We warn about any use of escape sequences beside + '\n' and '\t'. */ + if (c != 'n' && c != 't') + error (0, 0, _("\ +internationalized messages should not contain the `\\%c' escape sequence"), + c); + } + else + fprintf (fp, "\\%3.3o", c); + } + fputs ("\"\n", fp); + } +} + + +static void +print_blank_line (fp) + FILE *fp; +{ + if (uniforum) + fputs ("#\n", fp); + else + putc ('\n', fp); +} + + +static void +message_print (mp, fp, domain, blank_line, debug) + const message_ty *mp; + FILE *fp; + const char *domain; + int blank_line; + int debug; +{ + message_variant_ty *mvp; + int first; + size_t j; + + /* Find the relevant message variant. If there isn't one, remember + this using a NULL pointer. */ + mvp = NULL; + first = 0; + + for (j = 0; j < mp->variant_count; ++j) + { + if (strcmp (domain, mp->variant[j].domain) == 0) + { + mvp = &mp->variant[j]; + first = (j == 0); + break; + } + } + + /* Separate messages with a blank line. Uniforum doesn't like blank + lines, so use an empty comment (unless there already is one). */ + if (blank_line && (!uniforum + || mp->comment == NULL + || mp->comment->nitems == 0 + || mp->comment->item[0][0] != '\0')) + print_blank_line (fp); + + /* The first variant of a message will have the comments attached to + it. We can't attach them to all variants in case we are read in + again, multiplying the number of comment lines. Usually there is + only one variant. */ + if (first) + { + if (mp->comment != NULL) + for (j = 0; j < mp->comment->nitems; ++j) + { + const unsigned char *s = mp->comment->item[j]; + do + { + const unsigned char *e; + putc ('#', fp); + /* FIXME This is the wrong locale. While + message_list_print set the "C" locale for LC_CTYPE, + the need to use the correct locale for the file's + contents. */ + if (*s != '\0' && !isspace (*s)) + putc (' ', fp); + e = strchr (s, '\n'); + if (e == NULL) + { + fputs (s, fp); + s = NULL; + } + else + { + fwrite (s, 1, e - s, fp); + s = e + 1; + } + putc ('\n', fp); + } + while (s != NULL); + } + + if (mp->comment_dot != NULL) + for (j = 0; j < mp->comment_dot->nitems; ++j) + { + const unsigned char *s = mp->comment_dot->item[j]; + putc ('#', fp); + putc ('.', fp); + /* FIXME This is the wrong locale. While + message_list_print set the "C" locale for LC_CTYPE, the + need to use the correct locale for the file's contents. */ + if (*s && !isspace (*s)) + putc (' ', fp); + fputs (s, fp); + putc ('\n', fp); + } + } + + /* Print the file position comments for every domain. This will + help a human who is trying to navigate the sources. There is no + problem of getting repeat positions, because duplicates are + checked for. */ + if (mp->filepos_count != 0) + { + if (uniforum) + for (j = 0; j < mp->filepos_count; ++j) + { + lex_pos_ty *pp = &mp->filepos[j]; + char *cp = pp->file_name; + while (cp[0] == '.' && cp[1] == '/') + cp += 2; + /* There are two Sun formats to choose from: SunOS and + Solaris. Use the Solaris form here. */ + fprintf (fp, "# File: %s, line: %ld\n", + cp, (long) pp->line_number); + } + else + { + size_t column; + + fputs ("#:", fp); + column = 2; + for (j = 0; j < mp->filepos_count; ++j) + { + lex_pos_ty *pp; + char buffer[20]; + char *cp; + size_t len; + + pp = &mp->filepos[j]; + cp = pp->file_name; + while (cp[0] == '.' && cp[1] == '/') + cp += 2; + sprintf (buffer, "%ld", (long) pp->line_number); + len = strlen (cp) + strlen (buffer) + 2; + if (column > 2 && column + len >= page_width) + { + fputs ("\n#:", fp); + column = 2; + } + fprintf (fp, " %s:%s", cp, buffer); + column += len; + } + putc ('\n', fp); + } + } + + /* Print flag information in special comment. */ + if (first && ((mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0') + || significant_c_format_p (mp->is_c_format) + || mp->do_wrap == no)) + { + int first_flag = 1; + + putc ('#', fp); + putc (',', fp); + + /* We don't print the fuzzy flag if the msgstr is empty. This + might be introduced by the user but we want to normalize the + output. */ + if (mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0') + { + fputs (" fuzzy", fp); + first_flag = 0; + } + + if (significant_c_format_p (mp->is_c_format)) + { + if (!first_flag) + putc (',', fp); + + fputs (make_c_format_description_string (mp->is_c_format, debug), + fp); + first_flag = 0; + } + + if (mp->do_wrap == no) + { + if (!first_flag) + putc (',', fp); + + fputs (make_c_width_description_string (mp->do_wrap), fp); + first_flag = 0; + } + + putc ('\n', fp); + } + + /* Print each of the message components. Wrap them nicely so they + are as readable as possible. If there is no recorded msgstr for + this domain, emit an empty string. */ + wrap (fp, NULL, "msgid", mp->msgid, mp->do_wrap); + wrap (fp, NULL, "msgstr", mvp ? mvp->msgstr : "", mp->do_wrap); +} + + +static void +message_print_obsolete (mp, fp, domain, blank_line) + const message_ty *mp; + FILE *fp; + const char *domain; + int blank_line; +{ + message_variant_ty *mvp; + size_t j; + + /* Find the relevant message variant. If there isn't one, remember + this using a NULL pointer. */ + mvp = NULL; + + for (j = 0; j < mp->variant_count; ++j) + { + if (strcmp (domain, mp->variant[j].domain) == 0) + { + mvp = &mp->variant[j]; + break; + } + } + + /* If no msgstr is found or it is the empty string we print nothing. */ + if (mvp == NULL || mvp->msgstr[0] == '\0') + return; + + /* Separate messages with a blank line. Uniforum doesn't like blank + lines, so use an empty comment (unless there already is one). */ + if (blank_line) + print_blank_line (fp); + + /* Print translator comment if available. */ + if (mp->comment) + for (j = 0; j < mp->comment->nitems; ++j) + { + const unsigned char *s = mp->comment->item[j]; + do + { + const unsigned char *e; + putc ('#', fp); + /* FIXME This is the wrong locale. While + message_list_print set the "C" locale for LC_CTYPE, the + need to use the correct locale for the file's contents. */ + if (*s != '\0' && !isspace (*s)) + putc (' ', fp); + e = strchr (s, '\n'); + if (e == NULL) + { + fputs (s, fp); + s = NULL; + } + else + { + fwrite (s, 1, e - s, fp); + s = e + 1; + } + putc ('\n', fp); + } + while (s != NULL); + } + + /* Print flag information in special comment. */ + if (mp->is_fuzzy) + { + int first = 1; + + putc ('#', fp); + putc (',', fp); + + if (mp->is_fuzzy) + { + fputs (" fuzzy", fp); + first = 0; + } + + putc ('\n', fp); + } + + /* Print each of the message components. Wrap them nicely so they + are as readable as possible. */ + wrap (fp, "#~ ", "msgid", mp->msgid, mp->do_wrap); + wrap (fp, "#~ ", "msgstr", mvp->msgstr, mp->do_wrap); +} + + +void +message_list_print (mlp, filename, force, debug) + message_list_ty *mlp; + const char *filename; + int force; + int debug; +{ + FILE *fp; + size_t j, k; + string_list_ty *dl; + int blank_line; +#ifdef HAVE_SETLOCALE + char *old_locale; +#endif + + /* We will not write anything if we have no message or only the + header entry. */ + if (force == 0 + && (mlp->nitems == 0 + || (mlp->nitems == 1 && *mlp->item[0]->msgid == '\0'))) + return; + + /* Build the list of domains. */ + dl = string_list_alloc (); + for (j = 0; j < mlp->nitems; ++j) + { + message_ty *mp = mlp->item[j]; + for (k = 0; k < mp->variant_count; ++k) + string_list_append_unique (dl, mp->variant[k].domain); + } + + /* Open the output file. */ + if (filename != NULL && strcmp (filename, "-") != 0 + && strcmp (filename, "/dev/stdout") != 0) + { + fp = fopen (filename, "w"); + if (fp == NULL) + error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""), + filename); + } + else + { + fp = stdout; + /* xgettext:no-c-format */ + filename = _("standard output"); + } + +#ifdef HAVE_SETLOCALE + /* FIXME This is the wrong locale. The program is currently set for + the user's native language locale, for the error messages. This + code sets it to the "C" locale, but that isn't right either. The + need is to use the correct locale for the file's contents. */ + old_locale = setlocale (LC_CTYPE, "C"); + if (old_locale) + old_locale = xstrdup (old_locale); +#endif + + /* Write out the messages for each domain. */ + blank_line = 0; + for (k = 0; k < dl->nitems; ++k) + { + /* If there is only one domain, and that domain is the default, + don't bother emitting the domain name, because it is the + default. */ + if (dl->nitems != 1 || strcmp (dl->item[0], MESSAGE_DOMAIN_DEFAULT) != 0) + { + if (blank_line) + print_blank_line (fp); + fprintf (fp, "domain \"%s\"\n", dl->item[k]); + blank_line = 1; + } + + /* Write out each of the messages for this domain. */ + for (j = 0; j < mlp->nitems; ++j) + if (mlp->item[j]->obsolete == 0) + { + message_print (mlp->item[j], fp, dl->item[k], blank_line, debug); + blank_line = 1; + } + + /* Write out each of the obsolete messages for this domain. */ + for (j = 0; j < mlp->nitems; ++j) + if (mlp->item[j]->obsolete != 0) + { + message_print_obsolete (mlp->item[j], fp, dl->item[k], blank_line); + blank_line = 1; + } + } + string_list_free (dl); + + /* Restore the old locale. Do this before emitting error messages, + so that the correct locale is used for the error. (Ideally, + error should ensure this before calling gettext for the format + string.) */ +#ifdef HAVE_SETLOCALE + if (old_locale) + { + setlocale (LC_CTYPE, old_locale); + free (old_locale); + } +#endif + + /* Make sure nothing went wrong. */ + if (fflush (fp)) + error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"), + filename); + fclose (fp); +} + + +static int +msgid_cmp (va, vb) + const void *va; + const void *vb; +{ + const message_ty *a = *(const message_ty **) va; + const message_ty *b = *(const message_ty **) vb; +#ifdef HAVE_STRCOLL + return strcoll (a->msgid, b->msgid); +#else + return strcmp (a->msgid, b->msgid); +#endif +} + + +void +message_list_sort_by_msgid (mlp) + message_list_ty *mlp; +{ + /* FIXME This is the wrong locale. The program is currently set for + the user's native language locale, for the error messages. This + code sets it to the "C" locale, but that isn't right either. The + need is to use the correct locale for the file's contents. */ +#ifdef HAVE_SETLOCALE + char *tmp = setlocale (LC_COLLATE, "C"); + if (tmp) + tmp = xstrdup (tmp); +#endif + qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), msgid_cmp); +#ifdef HAVE_SETLOCALE + if (tmp) + { + setlocale (LC_COLLATE, tmp); + free (tmp); + } +#endif +} + + +static int +filepos_cmp (va, vb) + const void *va; + const void *vb; +{ + const message_ty *a = *(const message_ty **) va; + const message_ty *b = *(const message_ty **) vb; + int cmp; + + /* No filepos is smaller than any other filepos. */ + if (a->filepos_count == 0) + { + if (b->filepos_count != 0) + return -1; + } + if (b->filepos_count == 0) + return 1; + + /* Compare on the file names... */ + cmp = strcmp (a->filepos[0].file_name, b->filepos[0].file_name); + if (cmp != 0) + return cmp; + + /* If they are equal, compare on the line numbers... */ + cmp = a->filepos[0].line_number - b->filepos[0].line_number; + if (cmp != 0) + return cmp; + + /* If they are equal, compare on the msgid strings. */ +#ifdef HAVE_STRCOLL + return strcoll (a->msgid, b->msgid); +#else + return strcmp (a->msgid, b->msgid); +#endif +} + + +void +message_list_sort_by_filepos (mlp) + message_list_ty *mlp; +{ + /* FIXME This is the wrong locale. The program is currently set for + the user's native language locale, for the error messages. This + code sets it to the "C" locale, but that isn't right either. The + need is to use the correct locale for the file's contents. */ +#ifdef HAVE_SETLOCALE + char *tmp = setlocale (LC_COLLATE, "C"); + if (tmp) + tmp = xstrdup (tmp); +#endif + qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), filepos_cmp); +#ifdef HAVE_SETLOCALE + if (tmp) + { + setlocale (LC_COLLATE, tmp); + free (tmp); + } +#endif +} + + +enum is_c_format +parse_c_format_description_string (s) + const char *s; +{ + if (strstr (s, "no-c-format") != NULL) + return no; + else if (strstr (s, "impossible-c-format") != NULL) + return impossible; + else if (strstr (s, "possible-c-format") != NULL) + return possible; + else if (strstr (s, "c-format") != NULL) + return yes; + return undecided; +} + + +enum is_c_format +parse_c_width_description_string (s) + const char *s; +{ + if (strstr (s, "no-wrap") != NULL) + return no; + else if (strstr (s, "wrap") != NULL) + return yes; + return undecided; +} + + +static const char * +make_c_format_description_string (is_c_format, debug) + enum is_c_format is_c_format; + int debug; +{ + const char *result = NULL; + + switch (is_c_format) + { + case possible: + if (debug) + { + result = " possible-c-format"; + break; + } + /* FALLTHROUGH */ + case yes: + result = " c-format"; + break; + case impossible: + result = " impossible-c-format"; + break; + case no: + result = " no-c-format"; + break; + case undecided: + result = " undecided"; + break; + default: + abort (); + } + + return result; +} + + +static const char * +make_c_width_description_string (do_wrap) + enum is_c_format do_wrap; +{ + const char *result = NULL; + + switch (do_wrap) + { + case yes: + result = " wrap"; + break; + case no: + result = " no-wrap"; + break; + default: + abort (); + } + + return result; +} + + +int +possible_c_format_p (is_c_format) + enum is_c_format is_c_format; +{ + return is_c_format == possible || is_c_format == yes; +} + + +static int +significant_c_format_p (is_c_format) + enum is_c_format is_c_format; +{ + return is_c_format != undecided && is_c_format != impossible; +} + + +void +message_page_width_set (n) + size_t n; +{ + if (n == 0) + { + page_width = INT_MAX; + return; + } + + if (n < 20) + n = 20; + + page_width = n; +} diff --git a/tools/rpmgettext.c b/tools/rpmgettext.c index 805295ed1..b23439feb 100644 --- a/tools/rpmgettext.c +++ b/tools/rpmgettext.c @@ -1,5 +1,7 @@ /* rpmheader: spit out the header portion of a package */ +#define _GNU_SOURCE 1 + #include "system.h" #include "../build/rpmbuild.h" @@ -31,7 +33,6 @@ static void dpf(char *format, ...) const char *progname = NULL; int debug = MYDEBUG; int verbose = 0; -int escape = 1; /* use octal escape sequence for !isprint(c)? */ char *inputdir = "/mnt/redhat/comps/dist/5.2"; char *outputdir = "/tmp/OUT"; char *onlylang = NULL; @@ -122,6 +123,90 @@ headerGetLangs(Header h) return table; } +/* ================================================================== */ + +static const char * +genSrpmFileName(Header h) +{ + char *name, *version, *release, *sourcerpm; + char sfn[BUFSIZ], bfn[BUFSIZ]; + + headerGetEntry(h, RPMTAG_NAME, NULL, (void **)&name, NULL); + headerGetEntry(h, RPMTAG_VERSION, NULL, (void **)&version, NULL); + headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **)&release, NULL); + sprintf(sfn, "%s-%s-%s.src.rpm", name, version, release); + + headerGetEntry(h, RPMTAG_SOURCERPM, NULL, (void **)&sourcerpm, NULL); + +#if 0 + if (strcmp(sourcerpm, sfn)) + return strdup(sourcerpm); + + return NULL; +#else + return strdup(sourcerpm); +#endif + +} + +static const char * +hasLang(const char *onlylang, char **langs, char **s) +{ + const char *e = *s; + int i = 0; + + while(langs[i] && strcmp(langs[i], onlylang)) { + i++; + e += strlen(e) + 1; + } +#if 0 + if (langs[i] && *e) + return e; + return NULL; +#else + return onlylang; +#endif +} + +/* ================================================================== */ +/* XXX stripped down gettext environment */ + +#define HAVE_LOCALE_H 1 +#include <libintl.h> +#include <string.h> + +#define xstrdup strdup +#define xmalloc malloc +#define xrealloc realloc + +#define PARAMS(_x) _x +/* Length from which starting on warnings about too long strings are given. + Several systems have limits for strings itself, more have problems with + strings in their tools (important here: gencat). 1024 bytes is a + conservative limit. Because many translation let the message size grow + (German translations are always bigger) choose a length < 1024. */ +#if !defined(WARN_ID_LEN) +#define WARN_ID_LEN 900 +#endif + +/* This is the page width for the message_print function. It should + not be set to more than 79 characters (Emacs users will appreciate + it). It is used to wrap the msgid and msgstr strings, and also to + wrap the file position (#:) comments. */ +#if !defined(PAGE_WIDTH) +#define PAGE_WIDTH 79 +#endif + +#include "fstrcmp.c" + +#include "str-list.c" + +#define _LIBGETTEXT_H 1 /* XXX WTFO? _LIBINTL_H is undef? */ +#undef _ /* XXX WTFO? */ +#include "message.c" + +/* ================================================================== */ + /* XXX cribbed from gettext/src/message.c */ static const char escapes[] = "\b\f\n\r\t"; static const char escape_names[] = "bfnrt"; @@ -190,51 +275,6 @@ contractRpmPO(char *t, const char *s) *t = '\0'; } -/* ================================================================== */ - -static const char * -genSrpmFileName(Header h) -{ - char *name, *version, *release, *sourcerpm; - char sfn[BUFSIZ], bfn[BUFSIZ]; - - headerGetEntry(h, RPMTAG_NAME, NULL, (void **)&name, NULL); - headerGetEntry(h, RPMTAG_VERSION, NULL, (void **)&version, NULL); - headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **)&release, NULL); - sprintf(sfn, "%s-%s-%s.src.rpm", name, version, release); - - headerGetEntry(h, RPMTAG_SOURCERPM, NULL, (void **)&sourcerpm, NULL); - -#if 0 - if (strcmp(sourcerpm, sfn)) - return strdup(sourcerpm); - - return NULL; -#else - return strdup(sourcerpm); -#endif - -} - -static const char * -hasLang(const char *onlylang, char **langs, char **s) -{ - const char *e = *s; - int i = 0; - - while(langs[i] && strcmp(langs[i], onlylang)) { - i++; - e += strlen(e) + 1; - } -#if 0 - if (langs[i] && *e) - return e; - return NULL; -#else - return onlylang; -#endif -} - static int poTags[] = { RPMTAG_DESCRIPTION, RPMTAG_GROUP, @@ -334,277 +374,6 @@ gettextfile(int fd, const char *file, FILE *fp, int *poTags) } /* ================================================================== */ -#define xstrdup strdup -#define xmalloc malloc -#define xrealloc realloc -#define PARAMS(_x) _x - -#include "fstrcmp.c" - -#include "str-list.c" - -#include "rpmpo.h" - -message_ty * -message_alloc (msgid) - char *msgid; -{ - message_ty *mp; - - mp = xmalloc (sizeof (message_ty)); - mp->msgid = msgid; - mp->comment = NULL; - mp->comment_dot = NULL; - mp->filepos_count = 0; - mp->filepos = NULL; - mp->variant_count = 0; - mp->variant = NULL; - mp->used = 0; - mp->obsolete = 0; - mp->is_fuzzy = 0; - mp->is_c_format = undecided; - mp->do_wrap = undecided; - return mp; -} - -void -message_free (mp) - message_ty *mp; -{ - size_t j; - - if (mp->comment != NULL) - string_list_free (mp->comment); - if (mp->comment_dot != NULL) - string_list_free (mp->comment_dot); - free ((char *) mp->msgid); - for (j = 0; j < mp->variant_count; ++j) - free ((char *) mp->variant[j].msgstr); - if (mp->variant != NULL) - free (mp->variant); - for (j = 0; j < mp->filepos_count; ++j) - free ((char *) mp->filepos[j].file_name); - if (mp->filepos != NULL) - free (mp->filepos); - free (mp); -} - -message_variant_ty * -message_variant_search (mp, domain) - message_ty *mp; - const char *domain; -{ - size_t j; - message_variant_ty *mvp; - - for (j = 0; j < mp->variant_count; ++j) - { - mvp = &mp->variant[j]; - if (0 == strcmp (domain, mvp->domain)) - return mvp; - } - return 0; -} - -void -message_variant_append (mp, domain, msgstr, pp) - message_ty *mp; - const char *domain; - const char *msgstr; - const lex_pos_ty *pp; -{ - size_t nbytes; - message_variant_ty *mvp; - - nbytes = (mp->variant_count + 1) * sizeof (mp->variant[0]); - mp->variant = xrealloc (mp->variant, nbytes); - mvp = &mp->variant[mp->variant_count++]; - mvp->domain = domain; - mvp->msgstr = msgstr; - mvp->pos = *pp; -} - -void -message_comment_append (mp, s) - message_ty *mp; - const char *s; -{ - if (mp->comment == NULL) - mp->comment = string_list_alloc (); - string_list_append (mp->comment, s); -} - -void -message_comment_dot_append (mp, s) - message_ty *mp; - const char *s; -{ - if (mp->comment_dot == NULL) - mp->comment_dot = string_list_alloc (); - string_list_append (mp->comment_dot, s); -} - -void -message_comment_filepos (mp, name, line) - message_ty *mp; - const char *name; - size_t line; -{ - size_t nbytes; - lex_pos_ty *pp; - int min, max; - int j; - - /* See if we have this position already. They are kept in sorted - order, so use a binary chop. */ - /* FIXME: use bsearch */ - min = 0; - max = (int) mp->filepos_count - 1; - while (min <= max) - { - int mid; - int cmp; - - mid = (min + max) / 2; - pp = &mp->filepos[mid]; - cmp = strcmp (pp->file_name, name); - if (cmp == 0) - cmp = (int) pp->line_number - line; - if (cmp == 0) - return; - if (cmp < 0) - min = mid + 1; - else - max = mid - 1; - } - - /* Extend the list so that we can add an position to it. */ - nbytes = (mp->filepos_count + 1) * sizeof (mp->filepos[0]); - mp->filepos = xrealloc (mp->filepos, nbytes); - - /* Shuffle the rest of the list up one, so that we can insert the - position at ``min''. */ - /* FIXME: use memmove */ - for (j = mp->filepos_count; j > min; --j) - mp->filepos[j] = mp->filepos[j - 1]; - mp->filepos_count++; - - /* Insert the postion into the empty slot. */ - pp = &mp->filepos[min]; - pp->file_name = xstrdup (name); - pp->line_number = line; -} - -message_list_ty * -message_list_alloc () -{ - message_list_ty *mlp; - - mlp = xmalloc (sizeof (message_list_ty)); - mlp->nitems = 0; - mlp->nitems_max = 0; - mlp->item = 0; - return mlp; -} - -void -message_list_append (mlp, mp) - message_list_ty *mlp; - message_ty *mp; -{ - if (mlp->nitems >= mlp->nitems_max) - { - size_t nbytes; - - mlp->nitems_max = mlp->nitems_max * 2 + 4; - nbytes = mlp->nitems_max * sizeof (message_ty *); - mlp->item = xrealloc (mlp->item, nbytes); - } - mlp->item[mlp->nitems++] = mp; -} - -void -message_list_delete_nth (mlp, n) - message_list_ty *mlp; - size_t n; -{ - size_t j; - - if (n >= mlp->nitems) - return; - message_free (mlp->item[n]); - for (j = n + 1; j < mlp->nitems; ++j) - mlp->item[j - 1] = mlp->item[j]; - mlp->nitems--; -} - -message_ty * -message_list_search (mlp, msgid) - message_list_ty *mlp; - const char *msgid; -{ - size_t j; - - for (j = 0; j < mlp->nitems; ++j) - { - message_ty *mp; - - mp = mlp->item[j]; - if (0 == strcmp (msgid, mp->msgid)) - return mp; - } - return 0; -} - -message_ty * -message_list_search_fuzzy (mlp, msgid) - message_list_ty *mlp; - const char *msgid; -{ - size_t j; - double best_weight; - message_ty *best_mp; - - best_weight = 0.6; - best_mp = NULL; - for (j = 0; j < mlp->nitems; ++j) - { - size_t k; - double weight; - message_ty *mp; - - mp = mlp->item[j]; - - for (k = 0; k < mp->variant_count; ++k) - if (mp->variant[k].msgstr != NULL && mp->variant[k].msgstr[0] != '\0') - break; - if (k >= mp->variant_count) - continue; - - weight = fstrcmp (msgid, mp->msgid); - if (weight > best_weight) - { - best_weight = weight; - best_mp = mp; - } - } - return best_mp; -} - -void -message_list_free (mlp) - message_list_ty *mlp; -{ - size_t j; - - for (j = 0; j < mlp->nitems; ++j) - message_free (mlp->item[j]); - if (mlp->item) - free (mlp->item); - free (mlp); -} - -/* ================================================================== */ static int slurp(const char *file, char **ibufp, size_t *nbp) @@ -742,7 +511,9 @@ DPRINTF(100, ("%.*s\n", (int)(se-s), s)); if (c) *se = '\0'; /* zap \n */ switch (s[1]) { - case ':': + case '~': /* archival translations */ + break; + case ':': /* file cross reference */ f = s+2; while (*f && strchr(" \t", *f)) f++; fe = f; @@ -755,10 +526,15 @@ DPRINTF(100, ("%.*s\n", (int)(se-s), s)); string_list_append_unique(flp, f); message_comment_filepos(mp, f, getTagVal(fe)); break; - case '.': + case '.': /* automatic comments */ message_comment_dot_append(mp, xstrdup(s)); break; + case ',': /* flag... */ + mp->is_c_format = parse_c_format_description_string(f); + break; default: + /* XXX might want to fix and/or warn here */ + case ' ': /* flag... */ message_comment_append(mp, xstrdup(s)); break; } @@ -1194,13 +970,16 @@ main(int argc, char **argv) progname = basename(argv[0]); - while((c = getopt(argc, argv, "del:I:O:Tv")) != EOF) + while((c = getopt(argc, argv, "deEl:I:O:Tv")) != EOF) switch (c) { case 'd': debug++; break; case 'e': - escape = 0; + message_print_style_escape(0); + break; + case 'E': + message_print_style_escape(1); break; case 'l': onlylang = optarg; diff --git a/tools/rpmpo.h b/tools/rpmpo.h deleted file mode 100644 index 0411d71f4..000000000 --- a/tools/rpmpo.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _H_RPMPO_ -#define _H_RPMPO_ - -/* XXX lifted from gettext/src/po-lex.h */ -typedef struct lex_pos_ty lex_pos_ty; -struct lex_pos_ty -{ - char *file_name; - size_t line_number; -}; - -/* XXX lifted from gettext/src/message.h */ - -/* Is current msgid a format string? */ -enum is_c_format -{ - undecided, - yes, - no, - possible, - impossible -}; - -typedef struct message_variant_ty message_variant_ty; -struct message_variant_ty -{ - const char *domain; - lex_pos_ty pos; - const char *msgstr; -}; - -typedef struct message_ty message_ty; -struct message_ty -{ - /* Plain comments (#) appearing before the message. */ - string_list_ty *comment; - - /* Extracted comments (#.) appearing before the message. */ - string_list_ty *comment_dot; - - /* File position comments (#:) appearing before the message, one for - each unique file position instance, sorted by file name and then - by line. */ - size_t filepos_count; - lex_pos_ty *filepos; - - /* Informations from special comments (e.g. generated by msgmerge). */ - int is_fuzzy; - enum is_c_format is_c_format; - - /* Do we want the string to be wrapped in the emitted PO file? */ - enum is_c_format do_wrap; - - /* The msgid string. */ - const char *msgid; - - /* The msgstr strings, one for each observed domain in the file. */ - size_t variant_count; - message_variant_ty *variant; - - /* Used for checking that messages have been used, in the msgcmp and - msgmerge programs. */ - int used; - - /* If set the message is obsolete and while writing out it should be - commented out. */ - int obsolete; -}; - -typedef struct message_list_ty message_list_ty; -struct message_list_ty -{ - message_ty **item; - size_t nitems; - size_t nitems_max; -}; - -#endif /* _H_RPMPO_ */ diff --git a/tools/str-list.h b/tools/str-list.h deleted file mode 100644 index 9e2b99817..000000000 --- a/tools/str-list.h +++ /dev/null @@ -1,50 +0,0 @@ -/* GNU gettext - internationalization aids - Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. - - This file was written by Peter Miller <millerp@canb.auug.org.au> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#ifndef SRC_STR_LIST_H -#define SRC_STR_LIST_H 1 - -#ifdef STC_HEADERS -# define __need_size_t -# define __need_NULL -# include <stddef.h> -#else -# include <sys/types.h> -# include <stdio.h> -#endif - -/* Type describing list of strings implemented using a dynamic array. */ -typedef struct string_list_ty string_list_ty; -struct string_list_ty -{ - const char **item; - size_t nitems; - size_t nitems_max; -}; - - -string_list_ty *string_list_alloc PARAMS ((void)); -void string_list_append PARAMS ((string_list_ty *__slp, const char *__s)); -void string_list_append_unique PARAMS ((string_list_ty *__slp, - const char *__s)); -void string_list_free PARAMS ((string_list_ty *__slp)); -char *string_list_join PARAMS ((const string_list_ty *__slp)); -int string_list_member PARAMS ((const string_list_ty *__slp, const char *__s)); - -#endif |