2 Copyright (C) 2003-2004 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
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)
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.
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. */
32 #define _(str) gettext (str)
34 /* C# format strings are described in the description of the .NET System.String
35 class and implemented in
36 pnetlib-0.5.6/runtime/System/String.cs
38 mcs-0.28/class/corlib/System/String.cs
39 A format string consists of literal text (that is output verbatim), doubled
40 braces ('{{' and '}}', that lead to a single brace when output), and
44 - is followed by a nonnegative integer m,
45 - is optionally followed by ',' and an integer denoting a width,
46 - is optionally followed by ':' and a sequence of format specifiers.
47 (But the interpretation of the format specifiers is up to the IFormattable
48 implementation, depending on the argument's runtime value. New classes
49 implementing IFormattable can be defined by the user.)
50 - is finished with '}'.
55 unsigned int directives
;
56 unsigned int numbered_arg_count
;
60 format_parse (const char *format
, bool translated
, char **invalid_reason
)
66 spec
.numbered_arg_count
= 0;
68 for (; *format
!= '\0';)
83 if (!c_isdigit (*format
))
86 xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec
.directives
);
92 number
= 10 * number
+ (*format
- '0');
95 while (c_isdigit (*format
));
103 if (!c_isdigit (*format
))
106 xasprintf (_("In the directive number %u, ',' is not followed by a number."), spec
.directives
);
111 while (c_isdigit (*format
));
116 /* Parse format specifiers. */
119 while (*format
!= '\0' && *format
!= '}');
125 xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'."));
133 ? xasprintf (_("The directive number %u ends with an invalid character '%c' instead of '}'."), spec
.directives
, *format
)
134 : xasprintf (_("The directive number %u ends with an invalid character instead of '}'."), spec
.directives
));
140 if (spec
.numbered_arg_count
<= number
)
141 spec
.numbered_arg_count
= number
+ 1;
151 (spec
.directives
== 0
152 ? xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'."))
153 : xasprintf (_("The string contains a lone '}' after directive number %u."), spec
.directives
));
159 result
= (struct spec
*) xmalloc (sizeof (struct spec
));
165 format_free (void *descr
)
167 struct spec
*spec
= (struct spec
*) descr
;
173 format_get_number_of_directives (void *descr
)
175 struct spec
*spec
= (struct spec
*) descr
;
177 return spec
->directives
;
181 format_check (void *msgid_descr
, void *msgstr_descr
, bool equality
,
182 formatstring_error_logger_t error_logger
,
183 const char *pretty_msgstr
)
185 struct spec
*spec1
= (struct spec
*) msgid_descr
;
186 struct spec
*spec2
= (struct spec
*) msgstr_descr
;
189 /* Check that the argument counts are the same. */
191 ? spec1
->numbered_arg_count
!= spec2
->numbered_arg_count
192 : spec1
->numbered_arg_count
< spec2
->numbered_arg_count
)
195 error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
204 struct formatstring_parser formatstring_csharp
=
208 format_get_number_of_directives
,
215 /* Test program: Print the argument list specification returned by
216 format_parse for strings read from standard input. */
222 format_print (void *descr
)
224 struct spec
*spec
= (struct spec
*) descr
;
234 for (i
= 0; i
< spec
->numbered_arg_count
; i
++)
249 size_t line_size
= 0;
251 char *invalid_reason
;
254 line_len
= getline (&line
, &line_size
, stdin
);
257 if (line_len
> 0 && line
[line_len
- 1] == '\n')
258 line
[--line_len
] = '\0';
260 invalid_reason
= NULL
;
261 descr
= format_parse (line
, false, &invalid_reason
);
263 format_print (descr
);
266 printf ("%s\n", invalid_reason
);
268 free (invalid_reason
);
276 * For Emacs M-x compile
278 * 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-csharp.c ../lib/libgettextlib.la"