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 2001, 2002 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"
35 static char backbuf
[MB_LEN_MAX
];
36 static int backlen
= 0;
39 * get_mb() returns one multibyte character.
41 * This function uses the iconv() function to find out one
42 * multibyte character from a sequence of bytes in the file stream.
43 * The conversion from the codeset specified in the PO file to UTF-8
44 * is performed. The funcition reads another byte and calls iconv(),
45 * until iconv() successfully returns as a valid UTF-8 character has
46 * been converted or returns EILSEQ. If iconv() successfully returned,
47 * the function returns the read bytes as one character. Otherwise,
48 * returns error. The string converted to UTF-8 in outbuf won't be
52 get_mb(unsigned char *tmpbuf
, unsigned char fc
)
55 char outbuf
[8]; /* max size of a UTF-8 char */
58 size_t insize
= 0, inlen
, outlen
, ret
;
60 tmpbuf
[insize
++] = fc
; /* size of tmpbuf is MB_LEN_MAX+1 */
62 if (cd
== (iconv_t
)-1) {
64 tmpbuf
[insize
] = '\0';
69 inptr
= (const char *)tmpbuf
;
72 outlen
= sizeof (outbuf
);
75 ret
= iconv(cd
, &inptr
, &inlen
, &outptr
, &outlen
);
76 if (ret
== (size_t)-1) {
80 /* invalid character found */
81 error(gettext(ERR_INVALID_CHAR
),
85 /* not enough input */
86 if (insize
== MB_LEN_MAX
) {
87 /* invalid character found */
88 error(gettext(ERR_INVALID_CHAR
),
94 error(gettext(ERR_UNEXP_EOF
),
98 tmpbuf
[insize
++] = (unsigned char)c
;
100 /* initialize the conversion */
102 outlen
= sizeof (outbuf
);
103 (void) iconv(cd
, NULL
, NULL
, &outptr
, &outlen
);
108 /* should never happen */
115 tmpbuf
[insize
] = '\0';
124 (void) ungetc(c
, fp
);
130 po_ungetc(struct ch
*pch
)
133 error(gettext(ERR_INTERNAL
), cur_line
, cur_po
);
138 (void) memcpy(backbuf
, pch
->buf
, backlen
);
145 static struct ch och
;
150 (void) memcpy(och
.buf
, backbuf
, backlen
);
160 error(gettext(ERR_READ_FAILED
), cur_po
);
170 /* this newline should be escaped */
189 if (isascii((unsigned char)c
)) {
190 /* single byte ascii */
193 och
.buf
[0] = (unsigned char)c
;
197 och
.len
= get_mb(&och
.buf
[0], (unsigned char)c
);
205 extend_buf(char **buf
, size_t *size
, size_t add
)
210 tmp
= (char *)Xrealloc(*buf
, *size
);
218 static struct ch och
;
223 error(gettext(ERR_UNEXP_EOF
),
228 /* not a valid escape sequence */
234 switch (pch
->buf
[0]) {
237 och
.buf
[0] = pch
->buf
[0];
270 for (n
= 0, loop
= 0; ; ) {
277 error(gettext(ERR_UNEXP_EOF
),
281 if ((pch
->len
> 1) || (pch
->buf
[0] < '0') ||
287 och
.buf
[0] = (unsigned char)n
;
293 error(gettext(ERR_UNEXP_EOF
),
303 if (!isxdigit((unsigned char)c
)) {
308 if (isdigit((unsigned char)c
)) {
310 } else if (isupper((unsigned char)c
)) {
318 error(gettext(ERR_UNEXP_EOF
),
324 och
.buf
[0] = (unsigned char)n
;
328 if (!isxdigit((unsigned char)c
)) {
330 och
.buf
[0] = (unsigned char)n
;
334 if (isdigit((unsigned char)c
)) {
336 } else if (isupper((unsigned char)c
)) {
341 och
.buf
[0] = (unsigned char)n
;
345 och
.buf
[0] = pch
->buf
[0];
357 size_t buf_size
, buf_pos
;
369 yylval
.c
.len
= pch
->len
;
370 (void) memcpy(yylval
.c
.buf
, pch
->buf
, pch
->len
);
374 switch (pch
->buf
[0]) {
383 buf
= (char *)Xmalloc(buf_size
);
387 ((pch
->len
!= 1) || (pch
->buf
[0] != '\n'))) {
388 if (buf_pos
+ pch
->len
+ 1 > buf_size
)
389 extend_buf(&buf
, &buf_size
, CBUFSIZE
);
390 (void) memcpy(buf
+ buf_pos
,
402 return (pch
->buf
[0]);
407 buf
= (char *)Xmalloc(buf_size
);
414 error(gettext(ERR_UNEXP_EOF
),
423 error(gettext(ERR_UNEXP_EOL
),
432 if (buf_pos
+ pch
->len
+ 1 > buf_size
)
433 extend_buf(&buf
, &buf_size
,
435 (void) memcpy(buf
+ buf_pos
,
448 if (isalpha(uc
) || (uc
== '_')) {
450 buf
= (char *)Xmalloc(buf_size
);
452 buf
[buf_pos
++] = (char)uc
;
456 (isalpha(uc
= pch
->buf
[0]) ||
457 isdigit(uc
) || (uc
== '_'))) {
458 if (buf_pos
+ 1 + 1 > buf_size
)
459 extend_buf(&buf
, &buf_size
,
461 buf
[buf_pos
++] = (char)uc
;
464 /* push back the last char */
468 if (buf_pos
> MAX_KW_LEN
) {
469 /* kbuf is longer than any keywords */
472 yylval
.num
= cur_line
;
473 if (strcmp(buf
, KW_DOMAIN
) == 0) {
476 } else if (strcmp(buf
, KW_MSGID
) == 0) {
479 } else if (strcmp(buf
, KW_MSGID_PLURAL
) == 0) {
481 return (MSGID_PLURAL
);
482 } else if (strcmp(buf
, KW_MSGSTR
) == 0) {
493 buf
= (char *)Xmalloc(buf_size
);
495 buf
[buf_pos
++] = (char)uc
;
499 isdigit(uc
= pch
->buf
[0])) {
500 if (buf_pos
+ 1 + 1 > buf_size
)
501 extend_buf(&buf
, &buf_size
,
503 buf
[buf_pos
++] = (char)uc
;
506 /* push back the last char */
509 yylval
.num
= atoi(buf
);
515 yylval
.c
.buf
[0] = uc
;