4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "gnu_msgfmt.h"
40 extract_format(char *norm
, const char *sfmt
, size_t sz
)
42 const unsigned char *fmt
= (const unsigned char *)sfmt
;
62 while (*fmt
&& isdigit(*fmt
))
63 t
= t
* 10 + *fmt
++ - '0';
66 lastarg
= arg
= t
- 1;
78 while ((c
= *fmt
) != '\0') {
79 if (c
== '\'' || c
== '+' || c
== '-' ||
80 c
== ' ' || c
== '#' || c
== '0') {
87 while (*fmt
&& isdigit(*fmt
))
91 if (isdigit(*(fmt
+ 1))) {
94 while (*fmt
&& isdigit(*fmt
))
95 t
= t
* 10 + *fmt
++ - '0';
102 if ((ap
* 2 + 1 >= sz
) ||
104 norm
[ap
* 2] != '*')) {
105 /* error in format */
114 * If digits follow a '*', it is
115 * not loaded as an argument, the
116 * digits are used instead.
122 if (*(fmt
+ 1) == '$') {
128 if ((ap
* 2 + 1 >= sz
) ||
130 norm
[ap
* 2] != '*')) {
131 /* error in format */
143 if ((*fmt
== '.') || (*fmt
== '*')) {
157 if (!(flag
& OPT_ll
)) {
174 if (flag
& (OPT_h
|OPT_hh
))
184 if (!(flag
& OPT_ll
)) {
208 if ((c
= *fmt
) == 'C') {
211 } else if (c
== 'd') {
213 } else if (c
== 'S') {
216 } else if (c
== 's') {
218 } else if (c
== 'i') {
220 } else if (c
== 'o') {
222 } else if (c
== 'u') {
224 } else if (c
== 'c') {
226 } else if (c
== 'x') {
228 } else if (c
== 'X') {
230 } else if (c
== 'e') {
232 } else if (c
== 'E') {
234 } else if (c
== 'f') {
236 } else if (c
== 'F') {
238 } else if (c
== 'a') {
240 } else if (c
== 'A') {
242 } else if (c
== 'g') {
244 } else if (c
== 'G') {
246 } else if (c
== 'p') {
248 } else if (c
== 'n') {
255 if ((arg
* 2 + 1 >= sz
) ||
257 (norm
[arg
* 2] != conv
))) {
262 norm
[arg
* 2] = conv
;
264 norm
[arg
* 2 + 1] = flag
;
269 for (arg
= 0; arg
< max
; arg
++) {
270 if (norm
[arg
* 2] == '\0')
279 check_format(struct entry
*id
, struct entry
*str
, int is_c_format
)
282 int id_b_newline
, id_e_newline
;
283 int plural_b_newline
, plural_e_newline
;
284 int str_b_newline
, str_e_newline
;
285 int id_fmt
, plural_fmt
, str_fmt
;
287 char *msgid
, *plural
, *msgstr
;
288 char *id_norm
, *plural_norm
, *str_norm
;
290 size_t id_len
, id_num
;
291 size_t plural_off
, plural_len
, plural_num
;
292 size_t str_len
, str_num
;
298 * null string: header entry
299 * no check is performed
309 id_len
= id
->pos
[0].len
;
310 plural_off
= id
->pos
[1].off
;
311 plural_len
= id
->pos
[1].len
;
312 plural_num
= id
->pos
[1].num
;
313 plural
= msgid
+ plural_off
;
323 * First checking the newline
328 id_b_newline
= (msgid
[0] == '\n');
329 id_e_newline
= (msgid
[id_len
- 1 - 1] == '\n');
331 str_b_newline
= (msgstr
[0] == '\n');
332 str_e_newline
= (msgstr
[str_len
- 1 - 1] == '\n');
333 if (id_b_newline
&& !str_b_newline
) {
334 diag(gettext(ERR_BEGIN_NEWLINE_1
),
335 id_num
, str_num
, cur_po
);
337 } else if (!id_b_newline
&& str_b_newline
) {
338 diag(gettext(ERR_BEGIN_NEWLINE_2
),
339 id_num
, str_num
, cur_po
);
342 if (id_e_newline
&& !str_e_newline
) {
343 diag(gettext(ERR_END_NEWLINE_1
),
344 id_num
, str_num
, cur_po
);
346 } else if (!id_e_newline
&& str_e_newline
) {
347 diag(gettext(ERR_END_NEWLINE_2
),
348 id_num
, str_num
, cur_po
);
353 id_b_newline
= (msgid
[0] == '\n');
354 id_e_newline
= (msgid
[id_len
- 1 - 1] == '\n');
356 plural_b_newline
= (plural
[0] == '\n');
357 plural_e_newline
= (plural
[plural_len
- 1 -1 ] == '\n');
359 /* between msgid and msgid_plural */
360 if (id_b_newline
&& !plural_b_newline
) {
361 diag(gettext(ERR_BEGIN_NEWLINE_3
),
362 id_num
, plural_num
, cur_po
);
364 } else if (!id_b_newline
&& plural_b_newline
) {
365 diag(gettext(ERR_BEGIN_NEWLINE_4
),
366 id_num
, plural_num
, cur_po
);
369 if (id_e_newline
&& !plural_e_newline
) {
370 diag(gettext(ERR_END_NEWLINE_3
),
371 id_num
, plural_num
, cur_po
);
373 } else if (!id_e_newline
&& plural_e_newline
) {
374 diag(gettext(ERR_END_NEWLINE_4
),
375 id_num
, plural_num
, cur_po
);
379 for (i
= 0; i
< str
->no
; i
++) {
381 str_b_newline
= (msgstr
[p
->off
] == '\n');
383 (msgstr
[p
->off
+ p
->len
- 1 - 1] == '\n');
385 if (id_b_newline
&& !str_b_newline
) {
386 diag(gettext(ERR_BEGIN_NEWLINE_5
),
387 id_num
, p
->num
, cur_po
, i
);
389 } else if (!id_b_newline
&& str_b_newline
) {
390 diag(gettext(ERR_BEGIN_NEWLINE_6
),
391 id_num
, p
->num
, cur_po
, i
);
395 if (id_e_newline
&& !str_e_newline
) {
396 diag(gettext(ERR_END_NEWLINE_5
),
397 id_num
, p
->num
, cur_po
, i
);
399 } else if (!id_e_newline
&& str_e_newline
) {
400 diag(gettext(ERR_END_NEWLINE_6
),
401 id_num
, p
->num
, cur_po
, i
);
408 * if c-format is not specified, no printf-format check
416 id_norm
= (char *)Xcalloc(1, osz
);
417 id_fmt
= extract_format(id_norm
, msgid
, osz
);
419 diag(gettext(ERR_INVALID_FMT
), id_num
, cur_po
);
427 str_norm
= (char *)Xcalloc(1, nsz
);
428 str_fmt
= extract_format(str_norm
, msgstr
, nsz
);
430 diag(gettext(ERR_INVALID_FMT
), str_num
, cur_po
);
434 if (id_fmt
!= str_fmt
) {
435 diag(gettext(ERR_INCMP_FMT
),
436 id_num
, str_num
, cur_po
);
437 diag(gettext(ERR_INCMP_FMT_DIFF_1
),
441 for (n
= 0; n
< id_fmt
; n
++) {
442 if ((id_norm
[n
* 2] !=
444 (id_norm
[n
* 2 + 1] !=
445 str_norm
[n
* 2 + 1])) {
446 diag(gettext(ERR_INCMP_FMT
),
447 id_num
, str_num
, cur_po
);
448 diag(gettext(ERR_INCMP_FMT_DIFF_2
),
461 nsz
= plural_len
* 2;
462 plural_norm
= (char *)Xcalloc(1, nsz
);
463 plural_fmt
= extract_format(plural_norm
, plural
, nsz
);
464 if (plural_fmt
== -1) {
465 diag(gettext(ERR_INVALID_FMT
), plural_num
, cur_po
);
469 pstr_norm
= (char **)Xcalloc(str
->no
, sizeof (char *));
470 pstr_fmt
= (int *)Xcalloc(str
->no
, sizeof (int));
471 for (i
= 0; i
< str
->no
; i
++) {
474 pstr_norm
[i
] = (char *)Xcalloc(1, nsz
);
475 pstr_fmt
[i
] = extract_format(pstr_norm
[i
],
476 msgstr
+ p
->off
, nsz
);
477 if (pstr_fmt
[i
] == -1) {
478 diag(gettext(ERR_INVALID_FMT
),
484 /* between msgid and msgid_plural */
485 if (id_fmt
!= plural_fmt
) {
486 diag(gettext(ERR_INCMP_FMT
),
487 id_num
, plural_num
, cur_po
);
488 diag(gettext(ERR_INCMP_FMT_DIFF_1
),
492 for (n
= 0; n
< id_fmt
; n
++) {
493 if ((id_norm
[n
* 2] !=
494 plural_norm
[n
* 2]) ||
495 (id_norm
[n
* 2 + 1] !=
496 plural_norm
[n
* 2 + 1])) {
497 diag(gettext(ERR_INCMP_FMT
),
498 id_num
, plural_num
, cur_po
);
499 diag(gettext(ERR_INCMP_FMT_DIFF_2
),
507 /* between msgid and msgstr */
508 for (i
= 0; i
< str
->no
; i
++) {
510 if (id_fmt
!= pstr_fmt
[i
]) {
511 diag(gettext(ERR_INCMP_FMT
),
512 id_num
, p
->num
, cur_po
);
513 diag(gettext(ERR_INCMP_FMT_DIFF_1
),
514 id_fmt
, pstr_fmt
[i
]);
517 for (n
= 0; n
< id_fmt
; n
++) {
518 if ((id_norm
[n
* 2] !=
519 pstr_norm
[i
][n
* 2]) ||
520 (id_norm
[n
* 2 + 1] !=
521 pstr_norm
[i
][n
* 2 + 1])) {
522 diag(gettext(ERR_INCMP_FMT
),
523 id_num
, p
->num
, cur_po
);
524 diag(gettext(ERR_INCMP_FMT_DIFF_2
),