~ubuntu-branches/ubuntu/breezy/gettext/breezy

« back to all changes in this revision

Viewing changes to gettext-tools/src/format-qt.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2004-03-14 17:40:02 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040314174002-p1ad5ldve1hqzhye
Tags: 0.14.1-2
* Added libexpat1-dev to Build-Depends, for glade support.
* Added libc0.1-dev to Build-Depends, for GNU/kFreeBSD.
* Removed special-casing of knetbsd-gnu in debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Qt format strings.
 
2
   Copyright (C) 2003-2004 Free Software Foundation, Inc.
 
3
   Written by Bruno Haible <bruno@clisp.org>, 2003.
 
4
 
 
5
   This program is free software; you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; either version 2, or (at your option)
 
8
   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 General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program; if not, write to the Free Software Foundation,
 
17
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
18
 
 
19
#ifdef HAVE_CONFIG_H
 
20
# include <config.h>
 
21
#endif
 
22
 
 
23
#include <stdbool.h>
 
24
#include <stdlib.h>
 
25
 
 
26
#include "format.h"
 
27
#include "xalloc.h"
 
28
#include "xerror.h"
 
29
#include "error.h"
 
30
#include "error-progname.h"
 
31
#include "gettext.h"
 
32
 
 
33
#define _(str) gettext (str)
 
34
 
 
35
/* Qt format strings are processed by QString::arg and are documented in
 
36
   qt-3.0.5/doc/html/qstring.html.
 
37
   A directive starts with '%' and is followed by a digit ('0' to '9').
 
38
   Each %n must occur only once in the given string.
 
39
   The first .arg() invocation replaces the %n with the lowest numbered n,
 
40
   the next .arg() invocation then replaces the %n with the second-lowest
 
41
   numbered n, and so on.
 
42
   (This is inherently buggy because a '%' in the first replacement confuses
 
43
   the second .arg() invocation.)
 
44
   Although %0 is supported, usually %1 denotes the first argument, %2 the
 
45
   second argument etc.  */
 
46
 
 
47
struct spec
 
48
{
 
49
  unsigned int directives;
 
50
  unsigned int arg_count;
 
51
  bool args_used[10];
 
52
};
 
53
 
 
54
 
 
55
static void *
 
56
format_parse (const char *format, bool translated, char **invalid_reason)
 
57
{
 
58
  struct spec spec;
 
59
  struct spec *result;
 
60
 
 
61
  spec.directives = 0;
 
62
  spec.arg_count = 0;
 
63
 
 
64
  for (; *format != '\0';)
 
65
    if (*format++ == '%')
 
66
      if (*format >= '0' && *format <= '9')
 
67
        {
 
68
          /* A directive.  */
 
69
          unsigned int number;
 
70
 
 
71
          spec.directives++;
 
72
 
 
73
          number = *format - '0';
 
74
 
 
75
          while (spec.arg_count <= number)
 
76
            spec.args_used[spec.arg_count++] = false;
 
77
          if (spec.args_used[number])
 
78
            {
 
79
              *invalid_reason =
 
80
                xasprintf (_("Multiple references to %%%c."), *format);
 
81
              goto bad_format;
 
82
            }
 
83
          spec.args_used[number] = true;
 
84
 
 
85
          format++;
 
86
        }
 
87
 
 
88
  result = (struct spec *) xmalloc (sizeof (struct spec));
 
89
  *result = spec;
 
90
  return result;
 
91
 
 
92
 bad_format:
 
93
  return NULL;
 
94
}
 
95
 
 
96
static void
 
97
format_free (void *descr)
 
98
{
 
99
  struct spec *spec = (struct spec *) descr;
 
100
 
 
101
  free (spec);
 
102
}
 
103
 
 
104
static int
 
105
format_get_number_of_directives (void *descr)
 
106
{
 
107
  struct spec *spec = (struct spec *) descr;
 
108
 
 
109
  return spec->directives;
 
110
}
 
111
 
 
112
static bool
 
113
format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
 
114
              bool equality, bool noisy, const char *pretty_msgstr)
 
115
{
 
116
  struct spec *spec1 = (struct spec *) msgid_descr;
 
117
  struct spec *spec2 = (struct spec *) msgstr_descr;
 
118
  bool err = false;
 
119
  unsigned int i;
 
120
 
 
121
  for (i = 0; i < spec1->arg_count || i < spec2->arg_count; i++)
 
122
    {
 
123
      bool arg_used1 = (i < spec1->arg_count && spec1->args_used[i]);
 
124
      bool arg_used2 = (i < spec2->arg_count && spec2->args_used[i]);
 
125
 
 
126
      /* The translator cannot omit a %n from the msgstr because that would
 
127
         yield a "Argument missing" warning at runtime.  */
 
128
      if (arg_used1 != arg_used2)
 
129
        {
 
130
          if (noisy)
 
131
            {
 
132
              error_with_progname = false;
 
133
              error_at_line (0, 0, pos->file_name, pos->line_number,
 
134
                             arg_used1
 
135
                             ? _("a format specification for argument %u doesn't exist in '%s'")
 
136
                             : _("a format specification for argument %u, as in '%s', doesn't exist in 'msgid'"),
 
137
                             i, pretty_msgstr);
 
138
              error_with_progname = true;
 
139
            }
 
140
          err = true;
 
141
          break;
 
142
        }
 
143
    }
 
144
 
 
145
  return err;
 
146
}
 
147
 
 
148
 
 
149
struct formatstring_parser formatstring_qt =
 
150
{
 
151
  format_parse,
 
152
  format_free,
 
153
  format_get_number_of_directives,
 
154
  format_check
 
155
};
 
156
 
 
157
 
 
158
#ifdef TEST
 
159
 
 
160
/* Test program: Print the argument list specification returned by
 
161
   format_parse for strings read from standard input.  */
 
162
 
 
163
#include <stdio.h>
 
164
#include "getline.h"
 
165
 
 
166
static void
 
167
format_print (void *descr)
 
168
{
 
169
  struct spec *spec = (struct spec *) descr;
 
170
  unsigned int i;
 
171
 
 
172
  if (spec == NULL)
 
173
    {
 
174
      printf ("INVALID");
 
175
      return;
 
176
    }
 
177
 
 
178
  printf ("(");
 
179
  for (i = 0; i < spec->arg_count; i++)
 
180
    {
 
181
      if (i > 0)
 
182
        printf (" ");
 
183
      if (spec->args_used[i])
 
184
        printf ("*");
 
185
      else
 
186
        printf ("_");
 
187
    }
 
188
  printf (")");
 
189
}
 
190
 
 
191
int
 
192
main ()
 
193
{
 
194
  for (;;)
 
195
    {
 
196
      char *line = NULL;
 
197
      size_t line_size = 0;
 
198
      int line_len;
 
199
      char *invalid_reason;
 
200
      void *descr;
 
201
 
 
202
      line_len = getline (&line, &line_size, stdin);
 
203
      if (line_len < 0)
 
204
        break;
 
205
      if (line_len > 0 && line[line_len - 1] == '\n')
 
206
        line[--line_len] = '\0';
 
207
 
 
208
      invalid_reason = NULL;
 
209
      descr = format_parse (line, false, &invalid_reason);
 
210
 
 
211
      format_print (descr);
 
212
      printf ("\n");
 
213
      if (descr == NULL)
 
214
        printf ("%s\n", invalid_reason);
 
215
 
 
216
      free (invalid_reason);
 
217
      free (line);
 
218
    }
 
219
 
 
220
  return 0;
 
221
}
 
222
 
 
223
/*
 
224
 * For Emacs M-x compile
 
225
 * Local Variables:
 
226
 * compile-command: "/bin/sh ../libtool --mode=link gcc -o a.out -static -O -g -Wall -I.. -I../lib -I../intl -DHAVE_CONFIG_H -DTEST format-qt.c ../lib/libgettextlib.la"
 
227
 * End:
 
228
 */
 
229
 
 
230
#endif /* TEST */