Example #1
0
char*
translate(const char* loc, const char* cmd, const char* cat, const char* msg)
{
	register char*	r;
	char*		t;
	int		p;
	int		oerrno;
	Catalog_t*	cp;
	Message_t*	mp;

	oerrno = errno;
	r = (char*)msg;

	/*
	 * quick out
	 */

	if (!cmd && !cat)
		goto done;
	if (cmd && (t = strrchr(cmd, '/')))
		cmd = (const char*)(t + 1);

	/*
	 * initialize the catalogs dictionary
	 */

	if (!state.catalogs)
	{
		if (state.error)
			goto done;
		if (!(state.tmp = sfstropen()))
		{
			state.error = 1;
			goto done;
		}
		if (!(state.catalogs = dtopen(&state.catalog_disc, Dtset)))
		{
			sfclose(state.tmp);
			state.error = 1;
			goto done;
		}
		if (streq(loc, "debug"))
			state.debug = loc;
	}

	/*
	 * get the message
	 * or do we have to spell it out for you
	 */

	if ((!cmd || !(mp = match(cmd, msg))) &&
	    (!cat || !(mp = match(cat, msg))) &&
	    (!error_info.catalog || !(mp = match(error_info.catalog, msg))) &&
	    (!ast.id || !(mp = match(ast.id, msg))) ||
	     !(cp = mp->cat))
	{
#if DEBUG_trace > 1
sfprintf(sfstderr, "AHA#%d:%s cmd %s cat %s:%s id %s msg `%s'\n", __LINE__, __FILE__, cmd, cat, error_info.catalog, ast.id, msg);
#endif
		goto done;
	}

	/*
	 * adjust for the current locale
	 */

#if DEBUG_trace
sfprintf(sfstderr, "AHA#%d:%s cp->locale `%s' %p loc `%s' %p\n", __LINE__, __FILE__, cp->locale, cp->locale, loc, loc);
#endif
	if (cp->locale != loc)
	{
		cp->locale = loc;
		if (cp->cat != NOCAT)
			catclose(cp->cat);
		if ((cp->cat = find(cp->locale, cp->name)) == NOCAT)
			cp->debug = streq(cp->locale, "debug");
		else
			cp->debug = 0;
#if DEBUG_trace
sfprintf(sfstderr, "AHA#%d:%s cp->cat %p cp->debug %d NOCAT %p\n", __LINE__, __FILE__, cp->cat, cp->debug, NOCAT);
#endif
	}
	if (cp->cat == NOCAT)
	{
		if (cp->debug)
		{
			p = tempget(state.tmp);
			sfprintf(state.tmp, "(%s,%d,%d)", cp->name, mp->set, mp->seq);
			r = tempuse(state.tmp, p);
		}
		else if (ast.locale.set & AST_LC_debug)
		{
			p = tempget(state.tmp);
			sfprintf(state.tmp, "(%s,%d,%d)%s", cp->name, mp->set, mp->seq, r);
			r = tempuse(state.tmp, p);
		}
		goto done;
	}

	/*
	 * get the translated message
	 */

	r = catgets(cp->cat, mp->set, mp->seq, msg);
	if (ast.locale.set & AST_LC_translate)
		sfprintf(sfstderr, "translate locale=%s catalog=%s set=%d seq=%d \"%s\" => \"%s\"\n", cp->locale, cp->name, mp->set, mp->seq, msg, r == (char*)msg ? "NOPE" : r);
	if (r != (char*)msg)
	{
		if (streq(r, (char*)msg))
			r = (char*)msg;
		else if (strcmp(fmtfmt(r), fmtfmt(msg)))
		{
			sfprintf(sfstderr, "locale %s catalog %s message %d.%d \"%s\" does not match \"%s\"\n", cp->locale, cp->name, mp->set, mp->seq, r, msg);
			r = (char*)msg;
		}
	}
	if (ast.locale.set & AST_LC_debug)
	{
		p = tempget(state.tmp);
		sfprintf(state.tmp, "(%s,%d,%d)%s", cp->name, mp->set, mp->seq, r);
		r = tempuse(state.tmp, p);
	}
 done:
	if (r == (char*)msg && loc == state.debug)
	{
		p = tempget(state.tmp);
		sfprintf(state.tmp, "(%s,%s,%s,\"%s\")", loc, cmd, cat, r);
		r = tempuse(state.tmp, p);
	}
	errno = oerrno;
	return r;
}
Example #2
0
File: fmt.c Project: aahud/harvey
void*
_fmtdispatch(Fmt *f, const void *fmt, int isrunes)
{
	Rune rune, r;
	int i, n, w, p;
	uint32_t fl;
	const void *ret;

	w = f->width;
	p = f->prec;
	fl = f->flags;

	f->flags = 0;
	f->width = f->prec = 0;

	for(;;){
		if(isrunes){
			r = *(Rune*)fmt;
			fmt = (Rune*)fmt + 1;
		}else{
			fmt = (char*)fmt + chartorune(&rune, fmt);
			r = rune;
		}
		f->r = r;
		switch(r){
		case '\0':
			ret = nil;
			goto end;
		case '.':
			f->flags |= FmtWidth|FmtPrec;
			continue;
		case '0':
			if(!(f->flags & FmtWidth)){
				f->flags |= FmtZero;
				continue;
			}
			/* fall through */
		case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			i = 0;
			while(r >= '0' && r <= '9'){
				i = i * 10 + r - '0';
				if(isrunes){
					r = *(Rune*)fmt;
					fmt = (Rune*)fmt + 1;
				}else{
					r = *(char*)fmt;
					fmt = (char*)fmt + 1;
				}
			}
			if(isrunes)
				fmt = (Rune*)fmt - 1;
			else
				fmt = (char*)fmt - 1;
		numflag:
			if(f->flags & FmtWidth){
				f->flags |= FmtPrec;
				f->prec = i;
			}else{
				f->flags |= FmtWidth;
				f->width = i;
			}
			continue;
		case '*':
			i = va_arg(f->args, int);
			if(i < 0){
				/*
				 * negative precision =>
				 * ignore the precision.
				 */
				if(f->flags & FmtPrec){
					f->flags &= ~FmtPrec;
					f->prec = 0;
					continue;
				}
				i = -i;
				f->flags |= FmtLeft;
			}
			goto numflag;
		}
		n = (*fmtfmt(r))(f);
		if(n < 0){
			ret = nil;
			break;
		}
		if(n == 0){
			ret = fmt;
			break;
		}
	}
end:
	f->width = w;
	f->prec = p;
	f->flags = fl;
	return (void*)ret;
}
Example #3
0
int
main(int argc, char** argv)
{
	register Mc_t*	mc;
	register char*	s;
	register char*	t;
	register int	c;
	register int	q;
	register int	i;
	int		num;
	char*		b;
	char*		e;
	char*		catfile;
	char*		msgfile;
	Sfio_t*		sp;
	Sfio_t*		mp;
	Sfio_t*		tp;
	Xl_t*		px;
	Xl_t*		bp;

	Xl_t*		xp = 0;
	int		format = 0;
	int		list = 0;
	int		set = 0;

	NoP(argc);
	error_info.id = "msggen";
	for (;;)
	{
		switch (optget(argv, usage))
		{
		case 'f':
			format = list = 1;
			continue;
		case 'l':
			list = 1;
			continue;
		case 's':
			set = 1;
			continue;
		case '?':
			error(ERROR_USAGE|4, "%s", opt_info.arg);
			continue;
		case ':':
			error(2, "%s", opt_info.arg);
			continue;
		}
		break;
	}
	argv += opt_info.index;
	if (error_info.errors || !(catfile = *argv++))
		error(ERROR_USAGE|4, "%s", optusage(NiL));

	/*
	 * set and list only need catfile
	 */

	if (set)
	{
		sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL));
		return error_info.errors != 0;
	}
	else if (list)
	{
		if (!(sp = sfopen(NiL, catfile, "r")))
			error(ERROR_SYSTEM|3, "%s: cannot read catalog", catfile);
		if (!(mc = mcopen(sp)))
			error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
		sfclose(sp);
		if (format)
		{
			for (set = 1; set <= mc->num; set++)
				if (mc->set[set].num)
				{
					sfprintf(sfstdout, "$set %d\n", set);
					for (num = 1; num <= mc->set[set].num; num++)
						if (s = mc->set[set].msg[num])
							sfprintf(sfstdout, "%d \"%s\"\n", num, fmtfmt(s));
				}
		}
		else
		{
			if (*mc->translation)
			{
				ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$translation ");
				sfprintf(sfstdout, "%s", mc->translation);
				ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n");
			}
			ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote \"\n");
			for (set = 1; set <= mc->num; set++)
				if (mc->set[set].num)
				{
					ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$set %d\n", set);
					for (num = 1; num <= mc->set[set].num; num++)
						if (s = mc->set[set].msg[num])
						{
							ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "%d \"", num);
							while (c = *s++)
							{
								/*INDENT...*/

			switch (c)
			{
			case 0x22: /* " */
			case 0x5C: /* \ */
				sfputc(sfstdout, 0x5C);
				break;
			case 0x07: /* \a */
				c = 0x61;
				sfputc(sfstdout, 0x5C);
				break;
			case 0x08: /* \b */
				c = 0x62;
				sfputc(sfstdout, 0x5C);
				break;
			case 0x0A: /* \n */
				c = 0x6E;
				sfputc(sfstdout, 0x5C);
				break;
			case 0x0B: /* \v */
				c = 0x76;
				sfputc(sfstdout, 0x5C);
				break;
			case 0x0C: /* \f */
				c = 0x66;
				sfputc(sfstdout, 0x5C);
				break;
			case 0x0D: /* \r */
				c = 0x72;
				sfputc(sfstdout, 0x5C);
				break;
			}

								/*...UNDENT*/
								sfputc(sfstdout, c);
							}
							ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\"\n");
						}
				}
		}
		mcclose(mc);
		return error_info.errors != 0;
	}
	else if (!(msgfile = *argv++) || *argv)
		error(3, "exactly one message file must be specified");

	/*
	 * open the files and handles
	 */

	if (!(tp = sfstropen()))
		error(ERROR_SYSTEM|3, "out of space [string stream]");
	if (!(mp = sfopen(NiL, msgfile, "r")))
		error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile);
	sp = sfopen(NiL, catfile, "r");
	if (!(mc = mcopen(sp)))
		error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
	if (sp)
		sfclose(sp);
	xp = translation(xp, mc->translation);

	/*
	 * read the message file
	 */

	q = 0;
	set = 1;
	error_info.file = msgfile;
	while (s = sfgetr(mp, '\n', 1))
	{
		error_info.line++;
		if (!*s)
			continue;
		if (*s == '$')
		{
			if (!*++s || isspace(*s))
				continue;
			for (t = s; *s && !isspace(*s); s++);
			if (*s)
				*s++ = 0;
			if (streq(t, "delset"))
			{
				while (isspace(*s))
					s++;
				num = (int)strtol(s, NiL, 0);
				if (num < mc->num && mc->set[num].num)
					for (i = 1; i <= mc->set[num].num; i++)
						mcput(mc, num, i, NiL);
			}
			else if (streq(t, "quote"))
				q = *s ? *s : 0;
			else if (streq(t, "set"))
			{
				while (isspace(*s))
					s++;
				num = (int)strtol(s, &e, 0);
				if (e != s)
					set = num;
				else
					error(2, "set number expected");
			}
			else if (streq(t, "translation"))
				xp = translation(xp, s);
		}
		else
		{
			t = s + sfvalue(mp);
			num = (int)strtol(s, &e, 0);
			if (e != s)
			{
				s = e;
				if (!*s)
				{
					if (mcput(mc, set, num, NiL))
						error(2, "(%d,%d): cannot delete message", set, num);
				}
				else if (isspace(*s++))
				{
					if (t > (s + 1) && *(t -= 2) == '\\')
					{
						sfwrite(tp, s, t - s);
						while (s = sfgetr(mp, '\n', 0))
						{
							error_info.line++;
							t = s + sfvalue(mp);
							if (t <= (s + 1) || *(t -= 2) != '\\')
								break;
							sfwrite(tp, s, t - s);
						}
						if (!(s = sfstruse(tp)))
							error(ERROR_SYSTEM|3, "out of space");
					}
					if (q)
					{
						if (*s++ != q)
						{
							error(2, "(%d,%d): %c quote expected", set, num, q);
							continue;
						}
						b = t = s;
						while (c = *s++)
						{
							if (c == '\\')
							{
								c = chresc(s - 1, &e);
								s = e;
								if (c)
									*t++ = c;
								else
									error(1, "nul character ignored");
							}
							else if (c == q)
								break;
							else
								*t++ = c;
						}
						if (*s)
						{
							error(2, "(%d,%d): characters after quote not expected", set, num);
							continue;
						}
						*t = 0;
						s = b;
					}
					if (mcput(mc, set, num, s))
						error(2, "(%d,%d): cannot add message", set, num);
				}
				else
					error(2, "message text expected");
			}
			else
				error(2, "message number expected");
		}
	}
	error_info.file = 0;
	error_info.line = 0;

	/*
	 * fix up the translation record
	 */

	if (xp)
	{
		t = "";
		for (;;)
		{
			for (bp = 0, px = xp; px; px = px->next)
				if (px->date && (!bp || strcoll(bp->date, px->date) < 0))
					bp = px;
			if (!bp)
				break;
			sfprintf(tp, "%s%s %s", t, bp->name, bp->date);
			t = ", ";
			bp->date = 0;
		}
		if (!(mc->translation = sfstruse(tp)))
			error(ERROR_SYSTEM|3, "out of space");
	}

	/*
	 * dump the catalog to a local temporary
	 * rename if no errors
	 */

	if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = sfopen(NiL, s, "w")))
		error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile);
	if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp))
	{
		remove(s);
		error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", s);
	}
	remove(catfile);
	if (rename(s, catfile))
		error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog file %s", catfile, s);
	return error_info.errors != 0;
}