Blame src/fclang.c

Packit 352660
/*
Packit 352660
 * fontconfig/src/fclang.c
Packit 352660
 *
Packit 352660
 * Copyright © 2002 Keith Packard
Packit 352660
 *
Packit 352660
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit 352660
 * documentation for any purpose is hereby granted without fee, provided that
Packit 352660
 * the above copyright notice appear in all copies and that both that
Packit 352660
 * copyright notice and this permission notice appear in supporting
Packit 352660
 * documentation, and that the name of the author(s) not be used in
Packit 352660
 * advertising or publicity pertaining to distribution of the software without
Packit 352660
 * specific, written prior permission.  The authors make no
Packit 352660
 * representations about the suitability of this software for any purpose.  It
Packit 352660
 * is provided "as is" without express or implied warranty.
Packit 352660
 *
Packit 352660
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit 352660
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit 352660
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit 352660
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit 352660
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit 352660
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit 352660
 * PERFORMANCE OF THIS SOFTWARE.
Packit 352660
 */
Packit 352660
Packit 352660
#include "fcint.h"
Packit 352660
#include "fcftint.h"
Packit 352660
Packit 352660
/* Objects MT-safe for readonly access. */
Packit 352660
Packit 352660
typedef struct {
Packit 352660
    const FcChar8    	lang[16];
Packit 352660
    const FcCharSet	charset;
Packit 352660
} FcLangCharSet;
Packit 352660
Packit 352660
typedef struct {
Packit 352660
    int begin;
Packit 352660
    int end;
Packit 352660
} FcLangCharSetRange;
Packit 352660
Packit 352660
#include "../fc-lang/fclang.h"
Packit 352660
Packit 352660
struct _FcLangSet {
Packit 352660
    FcStrSet	*extra;
Packit 352660
    FcChar32    map_size;
Packit 352660
    FcChar32	map[NUM_LANG_SET_MAP];
Packit 352660
};
Packit 352660
Packit 352660
static int FcLangSetIndex (const FcChar8 *lang);
Packit 352660
Packit 352660
Packit 352660
static void
Packit 352660
FcLangSetBitSet (FcLangSet    *ls,
Packit 352660
		 unsigned int  id)
Packit 352660
{
Packit 352660
  unsigned int bucket;
Packit 352660
Packit 352660
  id = fcLangCharSetIndices[id];
Packit 352660
  bucket = id >> 5;
Packit 352660
  if (bucket >= ls->map_size)
Packit 352660
    return; /* shouldn't happen really */
Packit 352660
Packit 352660
  ls->map[bucket] |= ((FcChar32) 1U << (id & 0x1f));
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcLangSetBitGet (const FcLangSet *ls,
Packit 352660
		 unsigned int     id)
Packit 352660
{
Packit 352660
  unsigned int bucket;
Packit 352660
Packit 352660
  id = fcLangCharSetIndices[id];
Packit 352660
  bucket = id >> 5;
Packit 352660
  if (bucket >= ls->map_size)
Packit 352660
    return FcFalse;
Packit 352660
Packit 352660
  return ((ls->map[bucket] >> (id & 0x1f)) & 1) ? FcTrue : FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcLangSetBitReset (FcLangSet    *ls,
Packit 352660
		   unsigned int  id)
Packit 352660
{
Packit 352660
  unsigned int bucket;
Packit 352660
Packit 352660
  id = fcLangCharSetIndices[id];
Packit 352660
  bucket = id >> 5;
Packit 352660
  if (bucket >= ls->map_size)
Packit 352660
    return; /* shouldn't happen really */
Packit 352660
Packit 352660
  ls->map[bucket] &= ~((FcChar32) 1U << (id & 0x1f));
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcFreeTypeLangSet (const FcCharSet  *charset,
Packit 352660
		   const FcChar8    *exclusiveLang)
Packit 352660
{
Packit 352660
    int		    i, j;
Packit 352660
    FcChar32	    missing;
Packit 352660
    const FcCharSet *exclusiveCharset = 0;
Packit 352660
    FcLangSet	    *ls;
Packit 352660
Packit 352660
    if (exclusiveLang)
Packit 352660
	exclusiveCharset = FcLangGetCharSet (exclusiveLang);
Packit 352660
    ls = FcLangSetCreate ();
Packit 352660
    if (!ls)
Packit 352660
	return 0;
Packit 352660
    if (FcDebug() & FC_DBG_LANGSET)
Packit 352660
    {
Packit 352660
	printf ("font charset");
Packit 352660
	FcCharSetPrint (charset);
Packit 352660
	printf ("\n");
Packit 352660
    }
Packit 352660
    for (i = 0; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
    {
Packit 352660
	if (FcDebug() & FC_DBG_LANGSET)
Packit 352660
	{
Packit 352660
	    printf ("%s charset", fcLangCharSets[i].lang);
Packit 352660
	    FcCharSetPrint (&fcLangCharSets[i].charset);
Packit 352660
	    printf ("\n");
Packit 352660
	}
Packit 352660
	
Packit 352660
	/*
Packit 352660
	 * Check for Han charsets to make fonts
Packit 352660
	 * which advertise support for a single language
Packit 352660
	 * not support other Han languages
Packit 352660
	 */
Packit 352660
	if (exclusiveCharset &&
Packit 352660
	    FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
Packit 352660
	{
Packit 352660
	    if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
Packit 352660
		continue;
Packit 352660
Packit 352660
	    for (j = 0; j < fcLangCharSets[i].charset.num; j++)
Packit 352660
		if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) !=
Packit 352660
		    FcCharSetLeaf(exclusiveCharset, j))
Packit 352660
		    continue;
Packit 352660
	}
Packit 352660
	missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
Packit 352660
        if (FcDebug() & FC_DBG_SCANV)
Packit 352660
	{
Packit 352660
	    if (missing && missing < 10)
Packit 352660
	    {
Packit 352660
		FcCharSet   *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
Packit 352660
							 charset);
Packit 352660
		FcChar32    ucs4;
Packit 352660
		FcChar32    map[FC_CHARSET_MAP_SIZE];
Packit 352660
		FcChar32    next;
Packit 352660
Packit 352660
		printf ("\n%s(%u) ", fcLangCharSets[i].lang, missing);
Packit 352660
		printf ("{");
Packit 352660
		for (ucs4 = FcCharSetFirstPage (missed, map, &next;;
Packit 352660
		     ucs4 != FC_CHARSET_DONE;
Packit 352660
		     ucs4 = FcCharSetNextPage (missed, map, &next))
Packit 352660
		{
Packit 352660
		    int	    i, j;
Packit 352660
		    for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
Packit 352660
			if (map[i])
Packit 352660
			{
Packit 352660
			    for (j = 0; j < 32; j++)
Packit 352660
				if (map[i] & (1U << j))
Packit 352660
				    printf (" %04x", ucs4 + i * 32 + j);
Packit 352660
			}
Packit 352660
		}
Packit 352660
		printf (" }\n\t");
Packit 352660
		FcCharSetDestroy (missed);
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
		printf ("%s(%u) ", fcLangCharSets[i].lang, missing);
Packit 352660
	}
Packit 352660
	if (!missing)
Packit 352660
	    FcLangSetBitSet (ls, i);
Packit 352660
    }
Packit 352660
Packit 352660
    if (FcDebug() & FC_DBG_SCANV)
Packit 352660
	printf ("\n");
Packit 352660
Packit 352660
Packit 352660
    return ls;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcLangNormalize (const FcChar8 *lang)
Packit 352660
{
Packit 352660
    FcChar8 *result = NULL, *s, *orig;
Packit 352660
    char *territory, *encoding, *modifier;
Packit 352660
    size_t llen, tlen = 0, mlen = 0;
Packit 352660
Packit 352660
    if (!lang || !*lang)
Packit 352660
	return NULL;
Packit 352660
Packit 352660
    /* might be called without initialization */
Packit 352660
    FcInitDebug ();
Packit 352660
Packit 352660
    if (FcStrCmpIgnoreCase (lang, (const FcChar8 *)"C") == 0 ||
Packit 352660
	FcStrCmpIgnoreCase (lang, (const FcChar8 *)"C.UTF-8") == 0 ||
Packit 352660
	FcStrCmpIgnoreCase (lang, (const FcChar8 *)"C.utf8") == 0 ||
Packit 352660
	FcStrCmpIgnoreCase (lang, (const FcChar8 *)"POSIX") == 0)
Packit 352660
    {
Packit 352660
	result = FcStrCopy ((const FcChar8 *)"en");
Packit 352660
	goto bail;
Packit 352660
    }
Packit 352660
Packit 352660
    s = FcStrCopy (lang);
Packit 352660
    if (!s)
Packit 352660
	goto bail;
Packit 352660
Packit 352660
    /* from the comments in glibc:
Packit 352660
     *
Packit 352660
     * LOCALE can consist of up to four recognized parts for the XPG syntax:
Packit 352660
     *
Packit 352660
     *            language[_territory[.codeset]][@modifier]
Packit 352660
     *
Packit 352660
     * Beside the first all of them are allowed to be missing.  If the
Packit 352660
     * full specified locale is not found, the less specific one are
Packit 352660
     * looked for.  The various part will be stripped off according to
Packit 352660
     * the following order:
Packit 352660
     *            (1) codeset
Packit 352660
     *            (2) normalized codeset
Packit 352660
     *            (3) territory
Packit 352660
     *            (4) modifier
Packit 352660
     *
Packit 352660
     * So since we don't take care of the codeset part here, what patterns
Packit 352660
     * we need to deal with is:
Packit 352660
     *
Packit 352660
     *   1. language_territory@modifier
Packit 352660
     *   2. language@modifier
Packit 352660
     *   3. language
Packit 352660
     *
Packit 352660
     * then. and maybe no need to try language_territory here.
Packit 352660
     */
Packit 352660
    modifier = strchr ((const char *) s, '@');
Packit 352660
    if (modifier)
Packit 352660
    {
Packit 352660
	*modifier = 0;
Packit 352660
	modifier++;
Packit 352660
	mlen = strlen (modifier);
Packit 352660
    }
Packit 352660
    encoding = strchr ((const char *) s, '.');
Packit 352660
    if (encoding)
Packit 352660
    {
Packit 352660
	*encoding = 0;
Packit 352660
	encoding++;
Packit 352660
	if (modifier)
Packit 352660
	{
Packit 352660
	    memmove (encoding, modifier, mlen + 1);
Packit 352660
	    modifier = encoding;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    territory = strchr ((const char *) s, '_');
Packit 352660
    if (!territory)
Packit 352660
	territory = strchr ((const char *) s, '-');
Packit 352660
    if (territory)
Packit 352660
    {
Packit 352660
	*territory = 0;
Packit 352660
	territory++;
Packit 352660
	tlen = strlen (territory);
Packit 352660
    }
Packit 352660
    llen = strlen ((const char *) s);
Packit 352660
    if (llen < 2 || llen > 3)
Packit 352660
    {
Packit 352660
	fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid language tag\n",
Packit 352660
		 lang);
Packit 352660
	goto bail0;
Packit 352660
    }
Packit 352660
    if (territory && (tlen < 2 || tlen > 3) &&
Packit 352660
	!(territory[0] == 'z' && tlen < 5))
Packit 352660
    {
Packit 352660
	fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid region tag\n",
Packit 352660
		 lang);
Packit 352660
	goto bail0;
Packit 352660
    }
Packit 352660
    if (territory)
Packit 352660
	territory[-1] = '-';
Packit 352660
    if (modifier)
Packit 352660
	modifier[-1] = '@';
Packit 352660
    orig = FcStrDowncase (s);
Packit 352660
    if (!orig)
Packit 352660
	goto bail0;
Packit 352660
    if (territory)
Packit 352660
    {
Packit 352660
	if (FcDebug () & FC_DBG_LANGSET)
Packit 352660
	    printf("Checking the existence of %s.orth\n", s);
Packit 352660
	if (FcLangSetIndex (s) < 0)
Packit 352660
	{
Packit 352660
	    memmove (territory - 1, territory + tlen, (mlen > 0 ? mlen + 1 : 0) + 1);
Packit 352660
	    if (modifier)
Packit 352660
		modifier = territory;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    result = s;
Packit 352660
	    /* we'll miss the opportunity to reduce the correct size
Packit 352660
	     * of the allocated memory for the string after that.
Packit 352660
	     */
Packit 352660
	    s = NULL;
Packit 352660
	    goto bail1;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (modifier)
Packit 352660
    {
Packit 352660
	if (FcDebug () & FC_DBG_LANGSET)
Packit 352660
	    printf("Checking the existence of %s.orth\n", s);
Packit 352660
	if (FcLangSetIndex (s) < 0)
Packit 352660
	    modifier[-1] = 0;
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    result = s;
Packit 352660
	    /* we'll miss the opportunity to reduce the correct size
Packit 352660
	     * of the allocated memory for the string after that.
Packit 352660
	     */
Packit 352660
	    s = NULL;
Packit 352660
	    goto bail1;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (FcDebug () & FC_DBG_LANGSET)
Packit 352660
	printf("Checking the existence of %s.orth\n", s);
Packit 352660
    if (FcLangSetIndex (s) < 0)
Packit 352660
    {
Packit 352660
	/* there seems no languages matched in orth.
Packit 352660
	 * add the language as is for fallback.
Packit 352660
	 */
Packit 352660
	result = orig;
Packit 352660
	orig = NULL;
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	result = s;
Packit 352660
	/* we'll miss the opportunity to reduce the correct size
Packit 352660
	 * of the allocated memory for the string after that.
Packit 352660
	 */
Packit 352660
	s = NULL;
Packit 352660
    }
Packit 352660
  bail1:
Packit 352660
    if (orig)
Packit 352660
	FcStrFree (orig);
Packit 352660
  bail0:
Packit 352660
    if (s)
Packit 352660
	free (s);
Packit 352660
  bail:
Packit 352660
    if (FcDebug () & FC_DBG_LANGSET)
Packit 352660
    {
Packit 352660
	if (result)
Packit 352660
	    printf ("normalized: %s -> %s\n", lang, result);
Packit 352660
	else
Packit 352660
	    printf ("Unable to normalize %s\n", lang);
Packit 352660
    }
Packit 352660
Packit 352660
    return result;
Packit 352660
}
Packit 352660
Packit 352660
#define FcLangEnd(c)	((c) == '-' || (c) == '\0')
Packit 352660
Packit 352660
FcLangResult
Packit 352660
FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
Packit 352660
{
Packit 352660
    FcChar8	    c1, c2;
Packit 352660
    FcLangResult    result = FcLangDifferentLang;
Packit 352660
    const FcChar8  *s1_orig = s1;
Packit 352660
    FcBool	    is_und;
Packit 352660
Packit 352660
    is_und = FcToLower (s1[0]) == 'u' &&
Packit 352660
	     FcToLower (s1[1]) == 'n' &&
Packit 352660
	     FcToLower (s1[2]) == 'd' &&
Packit 352660
	     FcLangEnd (s1[3]);
Packit 352660
Packit 352660
    for (;;)
Packit 352660
    {
Packit 352660
	c1 = *s1++;
Packit 352660
	c2 = *s2++;
Packit 352660
	
Packit 352660
	c1 = FcToLower (c1);
Packit 352660
	c2 = FcToLower (c2);
Packit 352660
	if (c1 != c2)
Packit 352660
	{
Packit 352660
	    if (!is_und && FcLangEnd (c1) && FcLangEnd (c2))
Packit 352660
		result = FcLangDifferentTerritory;
Packit 352660
	    return result;
Packit 352660
	}
Packit 352660
	else if (!c1)
Packit 352660
	{
Packit 352660
	    return is_und ? result : FcLangEqual;
Packit 352660
	}
Packit 352660
	else if (c1 == '-')
Packit 352660
	{
Packit 352660
	    if (!is_und)
Packit 352660
		result = FcLangDifferentTerritory;
Packit 352660
	}
Packit 352660
Packit 352660
	/* If we parsed past "und-", then do not consider it undefined anymore,
Packit 352660
	 * as there's *something* specified. */
Packit 352660
	if (is_und && s1 - s1_orig == 4)
Packit 352660
	    is_und = FcFalse;
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Return FcTrue when super contains sub.
Packit 352660
 *
Packit 352660
 * super contains sub if super and sub have the same
Packit 352660
 * language and either the same country or one
Packit 352660
 * is missing the country
Packit 352660
 */
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcLangContains (const FcChar8 *super, const FcChar8 *sub)
Packit 352660
{
Packit 352660
    FcChar8	    c1, c2;
Packit 352660
Packit 352660
    for (;;)
Packit 352660
    {
Packit 352660
	c1 = *super++;
Packit 352660
	c2 = *sub++;
Packit 352660
	
Packit 352660
	c1 = FcToLower (c1);
Packit 352660
	c2 = FcToLower (c2);
Packit 352660
	if (c1 != c2)
Packit 352660
	{
Packit 352660
	    /* see if super has a country while sub is mising one */
Packit 352660
	    if (c1 == '-' && c2 == '\0')
Packit 352660
		return FcTrue;
Packit 352660
	    /* see if sub has a country while super is mising one */
Packit 352660
	    if (c1 == '\0' && c2 == '-')
Packit 352660
		return FcTrue;
Packit 352660
	    return FcFalse;
Packit 352660
	}
Packit 352660
	else if (!c1)
Packit 352660
	    return FcTrue;
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
const FcCharSet *
Packit 352660
FcLangGetCharSet (const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int		i;
Packit 352660
    int		country = -1;
Packit 352660
Packit 352660
    for (i = 0; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
    {
Packit 352660
	switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
Packit 352660
	case FcLangEqual:
Packit 352660
	    return &fcLangCharSets[i].charset;
Packit 352660
	case FcLangDifferentTerritory:
Packit 352660
	    if (country == -1)
Packit 352660
		country = i;
Packit 352660
	case FcLangDifferentLang:
Packit 352660
	default:
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (country == -1)
Packit 352660
	return 0;
Packit 352660
    return &fcLangCharSets[country].charset;
Packit 352660
}
Packit 352660
Packit 352660
FcStrSet *
Packit 352660
FcGetLangs (void)
Packit 352660
{
Packit 352660
    FcStrSet *langs;
Packit 352660
    int	i;
Packit 352660
Packit 352660
    langs = FcStrSetCreate();
Packit 352660
    if (!langs)
Packit 352660
	return 0;
Packit 352660
Packit 352660
    for (i = 0; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
	FcStrSetAdd (langs, fcLangCharSets[i].lang);
Packit 352660
Packit 352660
    return langs;
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcLangSetCreate (void)
Packit 352660
{
Packit 352660
    FcLangSet	*ls;
Packit 352660
Packit 352660
    ls = malloc (sizeof (FcLangSet));
Packit 352660
    if (!ls)
Packit 352660
	return 0;
Packit 352660
    memset (ls->map, '\0', sizeof (ls->map));
Packit 352660
    ls->map_size = NUM_LANG_SET_MAP;
Packit 352660
    ls->extra = 0;
Packit 352660
    return ls;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcLangSetDestroy (FcLangSet *ls)
Packit 352660
{
Packit 352660
    if (!ls)
Packit 352660
	return;
Packit 352660
Packit 352660
    if (ls->extra)
Packit 352660
	FcStrSetDestroy (ls->extra);
Packit 352660
    free (ls);
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcLangSetCopy (const FcLangSet *ls)
Packit 352660
{
Packit 352660
    FcLangSet	*new;
Packit 352660
Packit 352660
    if (!ls)
Packit 352660
	return NULL;
Packit 352660
Packit 352660
    new = FcLangSetCreate ();
Packit 352660
    if (!new)
Packit 352660
	goto bail0;
Packit 352660
    memset (new->map, '\0', sizeof (new->map));
Packit 352660
    memcpy (new->map, ls->map, FC_MIN (sizeof (new->map), ls->map_size * sizeof (ls->map[0])));
Packit 352660
    if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrList	*list;
Packit 352660
	FcChar8		*extra;
Packit 352660
	
Packit 352660
	new->extra = FcStrSetCreate ();
Packit 352660
	if (!new->extra)
Packit 352660
	    goto bail1;
Packit 352660
Packit 352660
	list = FcStrListCreate (ls->extra);	
Packit 352660
	if (!list)
Packit 352660
	    goto bail1;
Packit 352660
	
Packit 352660
	while ((extra = FcStrListNext (list)))
Packit 352660
	    if (!FcStrSetAdd (new->extra, extra))
Packit 352660
	    {
Packit 352660
		FcStrListDone (list);
Packit 352660
		goto bail1;
Packit 352660
	    }
Packit 352660
	FcStrListDone (list);
Packit 352660
    }
Packit 352660
    return new;
Packit 352660
bail1:
Packit 352660
    FcLangSetDestroy (new);
Packit 352660
bail0:
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
/* When the language isn't found, the return value r is such that:
Packit 352660
 *  1) r < 0
Packit 352660
 *  2) -r -1 is the index of the first language in fcLangCharSets that comes
Packit 352660
 *     after the 'lang' argument in lexicographic order.
Packit 352660
 *
Packit 352660
 *  The -1 is necessary to avoid problems with language id 0 (otherwise, we
Packit 352660
 *  wouldn't be able to distinguish between “language found, id is 0” and
Packit 352660
 *  “language not found, sorts right before the language with id 0”).
Packit 352660
 */
Packit 352660
static int
Packit 352660
FcLangSetIndex (const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int	    low, high, mid = 0;
Packit 352660
    int	    cmp = 0;
Packit 352660
    FcChar8 firstChar = FcToLower(lang[0]);
Packit 352660
    FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
Packit 352660
Packit 352660
    if (firstChar < 'a')
Packit 352660
    {
Packit 352660
	low = 0;
Packit 352660
	high = fcLangCharSetRanges[0].begin;
Packit 352660
    }
Packit 352660
    else if(firstChar > 'z')
Packit 352660
    {
Packit 352660
	low = fcLangCharSetRanges[25].begin;
Packit 352660
	high = NUM_LANG_CHAR_SET - 1;
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	low = fcLangCharSetRanges[firstChar - 'a'].begin;
Packit 352660
	high = fcLangCharSetRanges[firstChar - 'a'].end;
Packit 352660
	/* no matches */
Packit 352660
	if (low > high)
Packit 352660
	    return -(low+1); /* one past next entry after where it would be */
Packit 352660
    }
Packit 352660
Packit 352660
    while (low <= high)
Packit 352660
    {
Packit 352660
	mid = (high + low) >> 1;
Packit 352660
	if(fcLangCharSets[mid].lang[0] != firstChar)
Packit 352660
	    cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang);
Packit 352660
	else
Packit 352660
	{   /* fast path for resolving 2-letter languages (by far the most common) after
Packit 352660
	     * finding the first char (probably already true because of the hash table) */
Packit 352660
	    cmp = fcLangCharSets[mid].lang[1] - secondChar;
Packit 352660
	    if (cmp == 0 &&
Packit 352660
		(fcLangCharSets[mid].lang[2] != '\0' ||
Packit 352660
		 lang[2] != '\0'))
Packit 352660
	    {
Packit 352660
		cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
Packit 352660
					 lang+2);
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	if (cmp == 0)
Packit 352660
	    return mid;
Packit 352660
	if (cmp < 0)
Packit 352660
	    low = mid + 1;
Packit 352660
	else
Packit 352660
	    high = mid - 1;
Packit 352660
    }
Packit 352660
    if (cmp < 0)
Packit 352660
	mid++;
Packit 352660
    return -(mid + 1);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int	    id;
Packit 352660
Packit 352660
    id = FcLangSetIndex (lang);
Packit 352660
    if (id >= 0)
Packit 352660
    {
Packit 352660
	FcLangSetBitSet (ls, id);
Packit 352660
	return FcTrue;
Packit 352660
    }
Packit 352660
    if (!ls->extra)
Packit 352660
    {
Packit 352660
	ls->extra = FcStrSetCreate ();
Packit 352660
	if (!ls->extra)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    return FcStrSetAdd (ls->extra, lang);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcLangSetDel (FcLangSet *ls, const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int	id;
Packit 352660
Packit 352660
    id = FcLangSetIndex (lang);
Packit 352660
    if (id >= 0)
Packit 352660
    {
Packit 352660
	FcLangSetBitReset (ls, id);
Packit 352660
    }
Packit 352660
    else if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrSetDel (ls->extra, lang);
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcLangResult
Packit 352660
FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int		    id;
Packit 352660
    FcLangResult    best, r;
Packit 352660
    int		    i;
Packit 352660
Packit 352660
    id = FcLangSetIndex (lang);
Packit 352660
    if (id < 0)
Packit 352660
	id = -id - 1;
Packit 352660
    else if (FcLangSetBitGet (ls, id))
Packit 352660
	return FcLangEqual;
Packit 352660
    best = FcLangDifferentLang;
Packit 352660
    for (i = id - 1; i >= 0; i--)
Packit 352660
    {
Packit 352660
	r = FcLangCompare (lang, fcLangCharSets[i].lang);
Packit 352660
	if (r == FcLangDifferentLang)
Packit 352660
	    break;
Packit 352660
	if (FcLangSetBitGet (ls, i) && r < best)
Packit 352660
	    best = r;
Packit 352660
    }
Packit 352660
    for (i = id; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
    {
Packit 352660
	r = FcLangCompare (lang, fcLangCharSets[i].lang);
Packit 352660
	if (r == FcLangDifferentLang)
Packit 352660
	    break;
Packit 352660
	if (FcLangSetBitGet (ls, i) && r < best)
Packit 352660
	    best = r;
Packit 352660
    }
Packit 352660
    if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrList	*list = FcStrListCreate (ls->extra);
Packit 352660
	FcChar8		*extra;
Packit 352660
	
Packit 352660
	if (list)
Packit 352660
	{
Packit 352660
	    while (best > FcLangEqual && (extra = FcStrListNext (list)))
Packit 352660
	    {
Packit 352660
		r = FcLangCompare (lang, extra);
Packit 352660
		if (r < best)
Packit 352660
		    best = r;
Packit 352660
	    }
Packit 352660
	    FcStrListDone (list);
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return best;
Packit 352660
}
Packit 352660
Packit 352660
static FcLangResult
Packit 352660
FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
Packit 352660
{
Packit 352660
    FcStrList	    *list = FcStrListCreate (set);
Packit 352660
    FcLangResult    r, best = FcLangDifferentLang;
Packit 352660
    FcChar8	    *extra;
Packit 352660
Packit 352660
    if (list)
Packit 352660
    {
Packit 352660
	while (best > FcLangEqual && (extra = FcStrListNext (list)))
Packit 352660
	{
Packit 352660
	    r = FcLangSetHasLang (ls, extra);
Packit 352660
	    if (r < best)
Packit 352660
		best = r;
Packit 352660
	}
Packit 352660
	FcStrListDone (list);
Packit 352660
    }
Packit 352660
    return best;
Packit 352660
}
Packit 352660
Packit 352660
FcLangResult
Packit 352660
FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
Packit 352660
{
Packit 352660
    int		    i, j, count;
Packit 352660
    FcLangResult    best, r;
Packit 352660
    FcChar32 aInCountrySet, bInCountrySet;
Packit 352660
Packit 352660
    count = FC_MIN (lsa->map_size, lsb->map_size);
Packit 352660
    count = FC_MIN (NUM_LANG_SET_MAP, count);
Packit 352660
    for (i = 0; i < count; i++)
Packit 352660
	if (lsa->map[i] & lsb->map[i])
Packit 352660
	    return FcLangEqual;
Packit 352660
    best = FcLangDifferentLang;
Packit 352660
    for (j = 0; j < NUM_COUNTRY_SET; j++)
Packit 352660
    {
Packit 352660
	aInCountrySet = 0;
Packit 352660
	bInCountrySet = 0;
Packit 352660
Packit 352660
	for (i = 0; i < count; i++)
Packit 352660
	{
Packit 352660
	    aInCountrySet |= lsa->map[i] & fcLangCountrySets[j][i];
Packit 352660
	    bInCountrySet |= lsb->map[i] & fcLangCountrySets[j][i];
Packit 352660
Packit 352660
	    if (aInCountrySet && bInCountrySet)
Packit 352660
	    {
Packit 352660
		best = FcLangDifferentTerritory;
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (lsa->extra)
Packit 352660
    {
Packit 352660
	r = FcLangSetCompareStrSet (lsb, lsa->extra);
Packit 352660
	if (r < best)
Packit 352660
	    best = r;
Packit 352660
    }
Packit 352660
    if (best > FcLangEqual && lsb->extra)
Packit 352660
    {
Packit 352660
	r = FcLangSetCompareStrSet (lsa, lsb->extra);
Packit 352660
	if (r < best)
Packit 352660
	    best = r;
Packit 352660
    }
Packit 352660
    return best;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Used in computing values -- mustn't allocate any storage
Packit 352660
 */
Packit 352660
FcLangSet *
Packit 352660
FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *vbuf)
Packit 352660
{
Packit 352660
    int		id;
Packit 352660
    typedef struct {
Packit 352660
	FcLangSet  ls;
Packit 352660
	FcStrSet   strs;
Packit 352660
	FcChar8   *str;
Packit 352660
    } FcLangSetPromotionBuffer;
Packit 352660
    FcLangSetPromotionBuffer *buf = (FcLangSetPromotionBuffer *) vbuf;
Packit 352660
Packit 352660
    FC_ASSERT_STATIC (sizeof (FcLangSetPromotionBuffer) <= sizeof (FcValuePromotionBuffer));
Packit 352660
Packit 352660
    memset (buf->ls.map, '\0', sizeof (buf->ls.map));
Packit 352660
    buf->ls.map_size = NUM_LANG_SET_MAP;
Packit 352660
    buf->ls.extra = 0;
Packit 352660
    if (lang)
Packit 352660
    {
Packit 352660
	id = FcLangSetIndex (lang);
Packit 352660
	if (id >= 0)
Packit 352660
	{
Packit 352660
	    FcLangSetBitSet (&buf->ls, id);
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    buf->ls.extra = &buf->strs;
Packit 352660
	    buf->strs.num = 1;
Packit 352660
	    buf->strs.size = 1;
Packit 352660
	    buf->strs.strs = &buf->str;
Packit 352660
	    FcRefInit (&buf->strs.ref, 1);
Packit 352660
	    buf->str = (FcChar8 *) lang;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return &buf->ls;
Packit 352660
}
Packit 352660
Packit 352660
FcChar32
Packit 352660
FcLangSetHash (const FcLangSet *ls)
Packit 352660
{
Packit 352660
    FcChar32	h = 0;
Packit 352660
    int		i, count;
Packit 352660
Packit 352660
    count = FC_MIN (ls->map_size, NUM_LANG_SET_MAP);
Packit 352660
    for (i = 0; i < count; i++)
Packit 352660
	h ^= ls->map[i];
Packit 352660
    if (ls->extra)
Packit 352660
	h ^= ls->extra->num;
Packit 352660
    return h;
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcNameParseLangSet (const FcChar8 *string)
Packit 352660
{
Packit 352660
    FcChar8	    lang[32], c = 0;
Packit 352660
    int i;
Packit 352660
    FcLangSet	    *ls;
Packit 352660
Packit 352660
    ls = FcLangSetCreate ();
Packit 352660
    if (!ls)
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    for(;;)
Packit 352660
    {
Packit 352660
	for(i = 0; i < 31;i++)
Packit 352660
	{
Packit 352660
	    c = *string++;
Packit 352660
	    if(c == '\0' || c == '|')
Packit 352660
		break; /* end of this code */
Packit 352660
	    lang[i] = c;
Packit 352660
	}
Packit 352660
	lang[i] = '\0';
Packit 352660
	if (!FcLangSetAdd (ls, lang))
Packit 352660
	    goto bail1;
Packit 352660
	if(c == '\0')
Packit 352660
	    break;
Packit 352660
    }
Packit 352660
    return ls;
Packit 352660
bail1:
Packit 352660
    FcLangSetDestroy (ls);
Packit 352660
bail0:
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
Packit 352660
{
Packit 352660
    int		i, bit, count;
Packit 352660
    FcChar32	bits;
Packit 352660
    FcBool	first = FcTrue;
Packit 352660
Packit 352660
    count = FC_MIN (ls->map_size, NUM_LANG_SET_MAP);
Packit 352660
    for (i = 0; i < count; i++)
Packit 352660
    {
Packit 352660
	if ((bits = ls->map[i]))
Packit 352660
	{
Packit 352660
	    for (bit = 0; bit <= 31; bit++)
Packit 352660
		if (bits & (1U << bit))
Packit 352660
		{
Packit 352660
		    int id = (i << 5) | bit;
Packit 352660
		    if (!first)
Packit 352660
			if (!FcStrBufChar (buf, '|'))
Packit 352660
			    return FcFalse;
Packit 352660
		    if (!FcStrBufString (buf, fcLangCharSets[fcLangCharSetIndicesInv[id]].lang))
Packit 352660
			return FcFalse;
Packit 352660
		    first = FcFalse;
Packit 352660
		}
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrList   *list = FcStrListCreate (ls->extra);
Packit 352660
	FcChar8	    *extra;
Packit 352660
Packit 352660
	if (!list)
Packit 352660
	    return FcFalse;
Packit 352660
	while ((extra = FcStrListNext (list)))
Packit 352660
	{
Packit 352660
	    if (!first)
Packit 352660
		if (!FcStrBufChar (buf, '|'))
Packit 352660
                {
Packit 352660
                    FcStrListDone (list);
Packit 352660
		    return FcFalse;
Packit 352660
                }
Packit 352660
	    if (!FcStrBufString (buf, extra))
Packit 352660
                {
Packit 352660
                    FcStrListDone (list);
Packit 352660
                    return FcFalse;
Packit 352660
                }
Packit 352660
	    first = FcFalse;
Packit 352660
	}
Packit 352660
        FcStrListDone (list);
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
Packit 352660
{
Packit 352660
    int	    i, count;
Packit 352660
Packit 352660
    count = FC_MIN (lsa->map_size, lsb->map_size);
Packit 352660
    count = FC_MIN (NUM_LANG_SET_MAP, count);
Packit 352660
    for (i = 0; i < count; i++)
Packit 352660
    {
Packit 352660
	if (lsa->map[i] != lsb->map[i])
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    if (!lsa->extra && !lsb->extra)
Packit 352660
	return FcTrue;
Packit 352660
    if (lsa->extra && lsb->extra)
Packit 352660
	return FcStrSetEqual (lsa->extra, lsb->extra);
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
Packit 352660
{
Packit 352660
    int		    id;
Packit 352660
    int		    i;
Packit 352660
Packit 352660
    id = FcLangSetIndex (lang);
Packit 352660
    if (id < 0)
Packit 352660
	id = -id - 1;
Packit 352660
    else if (FcLangSetBitGet (ls, id))
Packit 352660
	return FcTrue;
Packit 352660
    /*
Packit 352660
     * search up and down among equal languages for a match
Packit 352660
     */
Packit 352660
    for (i = id - 1; i >= 0; i--)
Packit 352660
    {
Packit 352660
	if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
Packit 352660
	    break;
Packit 352660
	if (FcLangSetBitGet (ls, i) &&
Packit 352660
	    FcLangContains (fcLangCharSets[i].lang, lang))
Packit 352660
	    return FcTrue;
Packit 352660
    }
Packit 352660
    for (i = id; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
    {
Packit 352660
	if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
Packit 352660
	    break;
Packit 352660
	if (FcLangSetBitGet (ls, i) &&
Packit 352660
	    FcLangContains (fcLangCharSets[i].lang, lang))
Packit 352660
	    return FcTrue;
Packit 352660
    }
Packit 352660
    if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrList	*list = FcStrListCreate (ls->extra);
Packit 352660
	FcChar8		*extra;
Packit 352660
	
Packit 352660
	if (list)
Packit 352660
	{
Packit 352660
	    while ((extra = FcStrListNext (list)))
Packit 352660
	    {
Packit 352660
		if (FcLangContains (extra, lang))
Packit 352660
		    break;
Packit 352660
	    }
Packit 352660
	    FcStrListDone (list);
Packit 352660
    	    if (extra)
Packit 352660
		return FcTrue;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * return FcTrue if lsa contains every language in lsb
Packit 352660
 */
Packit 352660
FcBool
Packit 352660
FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
Packit 352660
{
Packit 352660
    int		    i, j, count;
Packit 352660
    FcChar32	    missing;
Packit 352660
Packit 352660
    if (FcDebug() & FC_DBG_MATCHV)
Packit 352660
    {
Packit 352660
	printf ("FcLangSet "); FcLangSetPrint (lsa);
Packit 352660
	printf (" contains "); FcLangSetPrint (lsb);
Packit 352660
	printf ("\n");
Packit 352660
    }
Packit 352660
    /*
Packit 352660
     * check bitmaps for missing language support
Packit 352660
     */
Packit 352660
    count = FC_MIN (lsa->map_size, lsb->map_size);
Packit 352660
    count = FC_MIN (NUM_LANG_SET_MAP, count);
Packit 352660
    for (i = 0; i < count; i++)
Packit 352660
    {
Packit 352660
	missing = lsb->map[i] & ~lsa->map[i];
Packit 352660
	if (missing)
Packit 352660
	{
Packit 352660
	    for (j = 0; j < 32; j++)
Packit 352660
		if (missing & (1U << j))
Packit 352660
		{
Packit 352660
		    if (!FcLangSetContainsLang (lsa,
Packit 352660
						fcLangCharSets[fcLangCharSetIndicesInv[i*32 + j]].lang))
Packit 352660
		    {
Packit 352660
			if (FcDebug() & FC_DBG_MATCHV)
Packit 352660
			    printf ("\tMissing bitmap %s\n", fcLangCharSets[fcLangCharSetIndicesInv[i*32+j]].lang);
Packit 352660
			return FcFalse;
Packit 352660
		    }
Packit 352660
		}
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (lsb->extra)
Packit 352660
    {
Packit 352660
	FcStrList   *list = FcStrListCreate (lsb->extra);
Packit 352660
	FcChar8	    *extra;
Packit 352660
Packit 352660
	if (list)
Packit 352660
	{
Packit 352660
	    while ((extra = FcStrListNext (list)))
Packit 352660
	    {
Packit 352660
		if (!FcLangSetContainsLang (lsa, extra))
Packit 352660
		{
Packit 352660
		    if (FcDebug() & FC_DBG_MATCHV)
Packit 352660
			printf ("\tMissing string %s\n", extra);
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
	    }
Packit 352660
	    FcStrListDone (list);
Packit 352660
	    if (extra)
Packit 352660
		return FcFalse;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l)
Packit 352660
{
Packit 352660
    if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet)))
Packit 352660
	return FcFalse;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l)
Packit 352660
{
Packit 352660
    FcLangSet	*l_serialize = FcSerializePtr (serialize, l);
Packit 352660
Packit 352660
    if (!l_serialize)
Packit 352660
	return NULL;
Packit 352660
    memset (l_serialize->map, '\0', sizeof (l_serialize->map));
Packit 352660
    memcpy (l_serialize->map, l->map, FC_MIN (sizeof (l_serialize->map), l->map_size * sizeof (l->map[0])));
Packit 352660
    l_serialize->map_size = NUM_LANG_SET_MAP;
Packit 352660
    l_serialize->extra = NULL; /* We don't serialize ls->extra */
Packit 352660
    return l_serialize;
Packit 352660
}
Packit 352660
Packit 352660
FcStrSet *
Packit 352660
FcLangSetGetLangs (const FcLangSet *ls)
Packit 352660
{
Packit 352660
    FcStrSet *langs;
Packit 352660
    int	      i;
Packit 352660
Packit 352660
    langs = FcStrSetCreate();
Packit 352660
    if (!langs)
Packit 352660
	return 0;
Packit 352660
Packit 352660
    for (i = 0; i < NUM_LANG_CHAR_SET; i++)
Packit 352660
	if (FcLangSetBitGet (ls, i))
Packit 352660
	    FcStrSetAdd (langs, fcLangCharSets[i].lang);
Packit 352660
Packit 352660
    if (ls->extra)
Packit 352660
    {
Packit 352660
	FcStrList	*list = FcStrListCreate (ls->extra);
Packit 352660
	FcChar8		*extra;
Packit 352660
Packit 352660
	if (list)
Packit 352660
	{
Packit 352660
	    while ((extra = FcStrListNext (list)))
Packit 352660
		FcStrSetAdd (langs, extra);
Packit 352660
Packit 352660
	    FcStrListDone (list);
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return langs;
Packit 352660
}
Packit 352660
Packit 352660
static FcLangSet *
Packit 352660
FcLangSetOperate(const FcLangSet	*a,
Packit 352660
		 const FcLangSet	*b,
Packit 352660
		 FcBool			(*func) (FcLangSet 	*ls,
Packit 352660
						 const FcChar8	*s))
Packit 352660
{
Packit 352660
    FcLangSet	*langset = FcLangSetCopy (a);
Packit 352660
    FcStrSet	*set = FcLangSetGetLangs (b);
Packit 352660
    FcStrList	*sl = FcStrListCreate (set);
Packit 352660
    FcChar8	*str;
Packit 352660
Packit 352660
    FcStrSetDestroy (set);
Packit 352660
    while ((str = FcStrListNext (sl)))
Packit 352660
    {
Packit 352660
	func (langset, str);
Packit 352660
    }
Packit 352660
    FcStrListDone (sl);
Packit 352660
Packit 352660
    return langset;
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcLangSetUnion (const FcLangSet *a, const FcLangSet *b)
Packit 352660
{
Packit 352660
    return FcLangSetOperate(a, b, FcLangSetAdd);
Packit 352660
}
Packit 352660
Packit 352660
FcLangSet *
Packit 352660
FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b)
Packit 352660
{
Packit 352660
    return FcLangSetOperate(a, b, FcLangSetDel);
Packit 352660
}
Packit 352660
Packit 352660
#define __fclang__
Packit 352660
#include "fcaliastail.h"
Packit 352660
#include "fcftaliastail.h"
Packit 352660
#undef __fclang__