Exemple #1
0
/*
 * gnu_key_2_text
 *
 * Extracts msgstr from the GNU MO file
 */
char *
gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
	struct msg_pack *mp)
{
	char	*result, *msgstr;
	size_t	msgstr_len;
	unsigned int	midx;
	int	ret;
	char	*conv_msgstr, *conv_dst;
	size_t	*p;
	size_t	conv_msgstr_len, buflen;
	iconv_t	fd;
	int	conversion, new_encoding;
	unsigned int	num_of_str;

#ifdef GETTEXT_DEBUG
	(void) printf("*************** gnu_key_2_text("
		"0x%p, \"%s\", 0x%p)\n",
		(void *)gmnp, codeset ? codeset : "(null)", (void *)mp);
	printgnumsg(gmnp, 0);
	printmp(mp, 0);
#endif

	/* first checks if header entry has been processed */
	if (!(gmnp->flag & ST_CHK)) {
		char	*msg_header;

		msg_header = gnu_msgsearch(gmnp, "", NULL, NULL);
		ret = parse_header((const char *)msg_header, gmnp);
		if (ret == -1) {
			/* fatal error */
			DFLTMSG(result, mp->msgid1, mp->msgid2,
				mp->n, mp->plural);
			return (result);
		}
		gmnp->flag |= ST_CHK;
	}
	msgstr = gnu_msgsearch(gmnp, mp->msgid1, &msgstr_len, &midx);
	if (msgstr == mp->msgid1) {
		/* not found */
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}

#ifdef GETTEXT_DEBUG
	printgnumsg(gmnp, 0);
#endif
	if (!gmnp->dst_encoding) {
		/*
		 * destination encoding has not been set.
		 */
		char	*dupcodeset = strdup(codeset);
		if (!dupcodeset) {
			/* strdup failed */
			result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
			return (result);
		}
		gmnp->dst_encoding = dupcodeset;

		if (strcmp(gmnp->dst_encoding, gmnp->src_encoding) == 0) {
			/*
			 * target encoding and src encoding
			 * are the same.
			 * No conversion required.
			 */
			conversion = 0;
		} else {
			/*
			 * target encoding is different from
			 * src encoding.
			 * New conversion required.
			 */
			/* sanity check */
			if (gmnp->fd && (gmnp->fd != (iconv_t)-1)) {
				(void) iconv_close(gmnp->fd);
				gmnp->fd = (iconv_t)-1;
			}
			if (gmnp->conv_msgstr)
				free_conv_msgstr(gmnp);
			conversion = 1;
			new_encoding = 1;
		}
	} else {
		/*
		 * dst encoding has been already set.
		 */
		if (strcmp(gmnp->dst_encoding, codeset) == 0) {
			/*
			 * dst encoding and target encoding are the same.
			 */
			if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
				== 0) {
				/*
				 * dst encoding and src encoding are the same.
				 * No conversion required.
				 */
				conversion = 0;
			} else {
				/*
				 * dst encoding is different from src encoding.
				 * current conversion is valid.
				 */
				conversion = 1;
				new_encoding = 0;
				/* checks if iconv_open has succeeded before */
				if (gmnp->fd == (iconv_t)-1) {
					/*
					 * iconv_open should have failed before
					 * Assume this conversion is invalid
					 */
					conversion = 0;
				} else {
					if (!gmnp->conv_msgstr) {
						/*
						 * memory allocation for
						 * conv_msgstr should
						 * have failed before.
						 */
						new_encoding = 1;
						if (gmnp->fd)
							(void) iconv_close(
								gmnp->fd);
						gmnp->fd = (iconv_t)-1;
					}
				}
			}
		} else {
			/*
			 * dst encoding is different from target encoding.
			 * It has changed since before.
			 */
			char	*dupcodeset = strdup(codeset);
			if (!dupcodeset) {
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			free(gmnp->dst_encoding);
			gmnp->dst_encoding = dupcodeset;
			if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
				== 0) {
				/*
				 * dst encoding and src encoding are the same.
				 * now, no conversion required.
				 */
				conversion = 0;
			} else {
				/*
				 * dst encoding is different from src encoding.
				 * new conversion required.
				 */
				conversion = 1;
				new_encoding = 1;
			}

			if (gmnp->fd && (gmnp->fd != (iconv_t)-1)) {
				(void) iconv_close(gmnp->fd);
			}
			if (gmnp->fd != (iconv_t)-1) {
				gmnp->fd = (iconv_t)-1;
			}
			if (gmnp->conv_msgstr)
				free_conv_msgstr(gmnp);
		}
	}

	if (conversion == 0) {
		/* no conversion */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	/* conversion required */

	if (new_encoding == 0) {
		/* dst codeset hasn't been changed since before */
		if (!gmnp->conv_msgstr[midx]) {
			/* this msgstr hasn't been converted yet */
			conv_msgstr_len = do_conv(gmnp->fd,
				&conv_dst, (const char *)msgstr, msgstr_len);
			if (conv_msgstr_len == (size_t)-1) {
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			buflen = (conv_msgstr_len + sizeof (size_t));
			/* allign to sizeof (size_t) */
			if (buflen % sizeof (size_t))
				buflen += (sizeof (size_t) -
					(buflen % sizeof (size_t)));
			p = (size_t *)malloc(buflen);
			if (!p) {
				free(conv_dst);
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			*p = conv_msgstr_len;
			(void) memcpy(p + 1, conv_dst, conv_msgstr_len);
			free(conv_dst);
			gmnp->conv_msgstr[midx] = (char *)p;
			conv_msgstr = (char *)(p + 1);
		} else {
			/* this msgstr is in the conversion cache */
			/* LINTED */
			size_t	*cmsg = (size_t *)gmnp->conv_msgstr[midx];
			conv_msgstr_len = *cmsg;
			conv_msgstr = (char *)(cmsg + 1);
		}
		result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
		return (result);
	}
	/* new conversion */
#ifdef GETTEXT_DEBUG
	(void) printf("******* calling iconv_open()\n");
	(void) printf("      dst: \"%s\", src: \"%s\"\n",
		gmnp->dst_encoding, gmnp->src_encoding);
#endif
	fd = iconv_open(gmnp->dst_encoding, gmnp->src_encoding);
	gmnp->fd = fd;
	if (fd == (iconv_t)-1) {
		/*
		 * iconv_open() failed.
		 * no conversion
		 */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	num_of_str = SWAP(gmnp, gmnp->msg_file_info->num_of_str);
	gmnp->conv_msgstr = (char **)calloc((size_t)num_of_str,
		sizeof (char *));
	if (!gmnp->conv_msgstr) {
		/* malloc failed */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	conv_msgstr_len = do_conv(gmnp->fd, &conv_dst,
		(const char *)msgstr, msgstr_len);
	if (conv_msgstr_len == (size_t)-1) {
		free_conv_msgstr(gmnp);
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	buflen = (conv_msgstr_len + sizeof (size_t));
	/* allign to sizeof (size_t) */
	if (buflen % sizeof (size_t))
		buflen += (sizeof (size_t) - (buflen % sizeof (size_t)));
	p = (size_t *)malloc(buflen);
	if (!p) {
		free(conv_dst);
		free_conv_msgstr(gmnp);
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	*p = conv_msgstr_len;
	(void) memcpy(p + 1, conv_dst, conv_msgstr_len);
	free(conv_dst);
	gmnp->conv_msgstr[midx] = (char *)p;
	conv_msgstr = (char *)(p + 1);
	result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
	return (result);
}
Exemple #2
0
int
main(int argc, char **argv)
{
	int ch, i;
	int opt_l = 0, opt_s = 0, opt_c = 0;
	char *opt_f = NULL, *opt_t = NULL;
	FILE *fp;

	while ((ch=getopt(argc, argv, "cslf:t:")) != -1) {
		switch (ch) {
		case 'c':
			opt_c = 1;
			break;
		case 's':
			opt_s = 1;
			break;
		case 'l':
			/* list */
			opt_l = 1;
			break;
		case 'f':
			/* from */
			opt_f = strdup(optarg);
			break;
		case 't':
			/* to */
			opt_t = strdup(optarg);
			break;
		default:
			usage();
		}
	}
	argc-=optind;
	argv+=optind;
	if (opt_l) {
		if (argc>0 || opt_s || opt_f != NULL || opt_t != NULL) {
			warnx("%s: -l should be specified solely.",
			      getprogname());
			usage();
		}
		show_codesets();
	} else {
		if (opt_f == NULL || opt_t == NULL)
			usage();

		if (argc == 0)
			do_conv(stdin, opt_f, opt_t, opt_s, opt_c);
		else {
			for (i=0; i<argc; i++) {
				fp = fopen(argv[i], "r");
				if (fp == NULL)
					errx(EXIT_FAILURE, "%s: %s:%s",
					     getprogname(), argv[i],
					     strerror(errno));
				do_conv(fp, opt_f, opt_t, opt_s, opt_c);
				fclose(fp);
			}
		}
	}

	return(EXIT_SUCCESS);
}