//
// aegis - project change supervisor
// Copyright (C) 2002-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
static char *header_begin;
static char *header_pos;
static int
header_getc(void)
{
if (!header_pos || !*header_pos)
return 0;
return *header_pos++;
}
static void
header_ungetc(int c)
{
if (!c)
return;
if (header_pos > header_begin && header_pos[-1] == c)
--header_pos;
}
static nstring
header_get_line(void)
{
static nstring_accumulator sa;
sa.clear();
for (;;)
{
int c = header_getc();
if (!c)
{
if (sa.empty())
return "";
break;
}
if (c == '\n')
{
c = header_getc();
if (c != ' ' && c != '\t')
{
header_ungetc(c);
break;
}
}
sa.push_back(c);
}
return sa.mkstr();
}
static nstring
find_plural_forms(void)
{
//
// Find the relevant transaltion information.
//
language_human();
header_pos = gettext("");
language_C();
header_begin = header_pos;
//
// Now parse out the relevant header information.
//
for (;;)
{
nstring s = header_get_line();
if (!s)
break;
if (0 == strncasecmp(s.c_str(), "plural-forms:", 13))
{
return nstring(s.c_str() + 13, s.size() - 13);
}
}
//
// No relevant information. Use the default, which is suitable for
// the Germanic family (Danish, Dutch, English, German, Norwegian
// and Swedish), the Finno-Urgic family (Estonian and Finnish),
// the Latin/Greek family (Greek), the Semitic family (Hebrew),
// the Romanic family (Italian, Portugese and Spanish) and Esperanto.
//
return "nplurals=2; plural=n!=1";
}
static nstring plural_forms;
wstring
sub_plural_forms(sub_context_ty *scp, const wstring_list &arg)
{
trace(("sub_plural()\n{\n"));
wstring result;
if (arg.size() < 2)
{
oh_dear:
scp->error_set(i18n("requires two or three arguments"));
trace(("}\n"));
return result;
}
//
// This is undocumented: if the first argument starts with '@'
// then use it instead of the Plural-Forms: header in the po/mo file.
// It is used for testing via aesub(1).
//
size_t argpos = 1;
if (arg[argpos][0] == '@')
{
nstring s = arg[1].to_nstring();
plural_forms = s.substring(1, s.size());
++argpos;
}
else
{
if (!plural_forms)
plural_forms = find_plural_forms();
}
//
// Get the number of items that the plural form is for.
//
if (argpos >= arg.size())
goto oh_dear;
nstring s = arg[argpos++].to_nstring();
unsigned n = s.to_long();
//
// Run the expression tree extracted from the PO file header,
// to determine which of the following arguments should be used.
//
n = sub_plural_gram(plural_forms, n);
//
// If the appropriately numbered argument is not present,
// return the singular form.
//
if (argpos >= arg.size())
goto oh_dear;
if (argpos + n > arg.size())
n = 0;
result = arg[argpos + n];
trace(("return %8.8lX;\n", (long)result.get_ref()));
trace(("}\n"));
return result;
}