+2024-12-30 Bruno Haible <bruno@clisp.org>
+
+ bcp47: Handle language variants.
+ Reported by Balló György <ballogyor@gmail.com> at
+ <https://savannah.gnu.org/bugs/?66620>.
+ * lib/bcp47.c (xpg_to_bcp47, bcp47_to_xpg): Handle variants.
+ * tests/test-bcp47.c (main): Test a regional variant.
+
2024-12-30 Bruno Haible <bruno@clisp.org>
doc: Revisit some index entries.
}
const char *script_subtag = NULL;
+ const char *variant_start = NULL;
+ size_t variant_len = 0;
/* Determine script from the modifier. */
if (modifier_len > 0)
if (strlen (scripts[i].name) == modifier_len
&& memcmp (scripts[i].name, modifier_start, modifier_len) == 0)
script_subtag = scripts[i].code;
+ if (script_subtag == NULL)
+ {
+ /* If the modifier does not designate a script, assume that it
+ designates a variant. */
+ variant_start = modifier_start;
+ variant_len = modifier_len;
+ }
}
/* Determine script from the language and possibly the territory. */
}
}
- /* Construct the result: language[-script][-territory]. */
+ /* Construct the result: language[-script][-territory][-variant]. */
if (language_len
+ (script_subtag != NULL ? 1 + 4 : 0)
+ (territory_len > 0 ? 1 + territory_len : 0)
+ + (variant_len > 0 ? 1 + variant_len : 0)
< BCP47_MAX)
{
char *q = bcp47;
memcpy (q, territory_start, territory_len);
q += territory_len;
}
+ if (variant_len > 0)
+ {
+ *q++ = '-';
+ memcpy (q, variant_start, variant_len);
+ q += variant_len;
+ }
*q = '\0';
return;
}
size_t script_len = 0;
const char *region_start = NULL;
size_t region_len = 0;
+ const char *variant_start = NULL;
+ size_t variant_len = 0;
{
bool past_script = false;
bool past_region = false;
+ bool past_variant = false;
const char *p;
p = bcp47;
/* It must be -variant or -extension. */
past_script = true;
past_region = true;
+ if (!past_variant)
+ {
+ variant_start = subtag_start;
+ variant_len = subtag_len;
+ past_variant = true;
+ }
}
}
}
}
}
- /* The modifier is the script. */
- const char *modifier = script;
-
/* Construct the result: language[_territory][.codeset][@modifier]. */
size_t codeset_len = (codeset != NULL ? strlen (codeset) : 0);
- size_t modifier_len = (modifier != NULL ? strlen (modifier) : 0);
+ /* The modifier is the script or, if the script is absent or already handled,
+ the variant. */
+ const char *modifier;
+ size_t modifier_len;
+ if (script != NULL)
+ {
+ modifier = script;
+ modifier_len = strlen (modifier);
+ }
+ else if (variant_len > 0)
+ {
+ modifier = variant_start;
+ modifier_len = variant_len;
+ }
+ else
+ {
+ modifier = NULL;
+ modifier_len = 0;
+ }
if (language_len
+ (territory_len > 0 ? 1 + territory_len : 0)
+ (codeset != NULL ? 1 + codeset_len : 0)