2002-02-15 00:34:13 +01:00
/*
2008-08-12 22:34:24 +02:00
* fontconfig / src / fcxml . c
2002-02-15 00:34:13 +01:00
*
2004-12-07 02:14:46 +01:00
* Copyright © 2002 Keith Packard
2002-02-15 00:34:13 +01:00
*
* Permission to use , copy , modify , distribute , and sell this software and its
* documentation for any purpose is hereby granted without fee , provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
2010-11-10 22:45:42 +01:00
* documentation , and that the name of the author ( s ) not be used in
2002-02-15 00:34:13 +01:00
* advertising or publicity pertaining to distribution of the software without
2010-11-10 22:45:42 +01:00
* specific , written prior permission . The authors make no
2002-02-15 00:34:13 +01:00
* representations about the suitability of this software for any purpose . It
* is provided " as is " without express or implied warranty .
*
2009-03-12 21:00:08 +01:00
* THE AUTHOR ( S ) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ,
2002-02-15 00:34:13 +01:00
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS , IN NO
2009-03-12 21:00:08 +01:00
* EVENT SHALL THE AUTHOR ( S ) BE LIABLE FOR ANY SPECIAL , INDIRECT OR
2002-02-15 00:34:13 +01:00
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE ,
* DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT , NEGLIGENCE OR OTHER
* TORTIOUS ACTION , ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE .
*/
2018-05-13 07:48:10 +02:00
# include <string.h>
2006-04-25 07:57:41 +02:00
# include "fcint.h"
2005-12-21 04:31:19 +01:00
# include <fcntl.h>
2002-02-15 00:34:13 +01:00
# include <stdarg.h>
2004-12-05 06:03:52 +01:00
# include <dirent.h>
2002-05-22 06:37:07 +02:00
2006-04-06 06:33:11 +02:00
# ifdef ENABLE_LIBXML2
2005-09-29 22:53:30 +02:00
# include <libxml/parser.h>
# define XML_Char xmlChar
# define XML_Parser xmlParserCtxtPtr
# define XML_ParserFree xmlFreeParserCtxt
# define XML_GetCurrentLineNumber xmlSAX2GetLineNumber
# define XML_GetErrorCode xmlCtxtGetLastError
# define XML_ErrorString(Error) (Error)->message
# else /* ENABLE_LIBXML2 */
2002-06-08 19:32:05 +02:00
# ifndef HAVE_XMLPARSE_H
# define HAVE_XMLPARSE_H 0
# endif
2002-08-19 21:32:05 +02:00
2002-05-21 19:06:22 +02:00
# if HAVE_XMLPARSE_H
# include <xmlparse.h>
# else
# include <expat.h>
# endif
2002-02-15 00:34:13 +01:00
2005-09-29 22:53:30 +02:00
# endif /* ENABLE_LIBXML2 */
2003-03-22 22:25:34 +01:00
# ifdef _WIN32
2009-08-13 23:16:18 +02:00
# include <mbstring.h>
2015-04-08 10:41:25 +02:00
extern FcChar8 fontconfig_instprefix [ ] ;
2003-03-22 22:25:34 +01:00
# endif
2015-05-22 09:53:34 +02:00
static FcChar8 * __fc_userdir = NULL ;
static FcChar8 * __fc_userconf = NULL ;
2009-06-06 03:37:01 +02:00
static void
FcExprDestroy ( FcExpr * e ) ;
2018-01-23 14:27:17 +01:00
static FcBool
_FcConfigParse ( FcConfig * config ,
const FcChar8 * name ,
FcBool complain ,
FcBool load ) ;
2002-02-15 00:34:13 +01:00
void
FcTestDestroy ( FcTest * test )
{
FcExprDestroy ( test - > expr ) ;
free ( test ) ;
}
2013-07-04 12:51:03 +02:00
void
FcRuleDestroy ( FcRule * rule )
{
2013-07-09 09:43:26 +02:00
FcRule * n = rule - > next ;
2013-07-04 12:51:03 +02:00
switch ( rule - > type ) {
case FcRuleTest :
FcTestDestroy ( rule - > u . test ) ;
break ;
case FcRuleEdit :
FcEditDestroy ( rule - > u . edit ) ;
break ;
2014-08-20 22:03:02 +02:00
case FcRuleUnknown :
2013-07-04 12:51:03 +02:00
default :
break ;
}
free ( rule ) ;
2013-07-09 09:43:26 +02:00
if ( n )
FcRuleDestroy ( n ) ;
2013-07-04 12:51:03 +02:00
}
2009-06-06 00:40:46 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateInteger ( FcConfig * config , int i )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpInteger ;
e - > u . ival = i ;
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateDouble ( FcConfig * config , double d )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpDouble ;
e - > u . dval = d ;
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateString ( FcConfig * config , const FcChar8 * s )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpString ;
2013-01-02 09:06:15 +01:00
e - > u . sval = FcStrdup ( s ) ;
2002-02-15 00:34:13 +01:00
}
return e ;
}
2012-12-30 03:39:06 +01:00
static FcExprMatrix *
FcExprMatrixCopyShallow ( const FcExprMatrix * matrix )
{
FcExprMatrix * m = malloc ( sizeof ( FcExprMatrix ) ) ;
if ( m )
{
* m = * matrix ;
}
return m ;
}
static void
FcExprMatrixFreeShallow ( FcExprMatrix * m )
{
if ( ! m )
return ;
free ( m ) ;
}
static void
FcExprMatrixFree ( FcExprMatrix * m )
{
if ( ! m )
return ;
FcExprDestroy ( m - > xx ) ;
FcExprDestroy ( m - > xy ) ;
FcExprDestroy ( m - > yx ) ;
FcExprDestroy ( m - > yy ) ;
free ( m ) ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2012-12-30 03:39:06 +01:00
FcExprCreateMatrix ( FcConfig * config , const FcExprMatrix * matrix )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpMatrix ;
2012-12-30 03:39:06 +01:00
e - > u . mexpr = FcExprMatrixCopyShallow ( matrix ) ;
2002-02-15 00:34:13 +01:00
}
return e ;
}
2013-11-20 10:44:59 +01:00
static FcExpr *
FcExprCreateRange ( FcConfig * config , FcRange * range )
{
FcExpr * e = FcConfigAllocExpr ( config ) ;
if ( e )
{
e - > op = FcOpRange ;
e - > u . rval = FcRangeCopy ( range ) ;
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateBool ( FcConfig * config , FcBool b )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpBool ;
e - > u . bval = b ;
}
return e ;
}
2010-12-06 04:10:17 +01:00
static FcExpr *
FcExprCreateCharSet ( FcConfig * config , FcCharSet * charset )
{
FcExpr * e = FcConfigAllocExpr ( config ) ;
if ( e )
{
e - > op = FcOpCharSet ;
e - > u . cval = FcCharSetCopy ( charset ) ;
}
return e ;
}
2010-12-06 04:38:18 +01:00
static FcExpr *
FcExprCreateLangSet ( FcConfig * config , FcLangSet * langset )
{
FcExpr * e = FcConfigAllocExpr ( config ) ;
if ( e )
{
e - > op = FcOpLangSet ;
e - > u . lval = FcLangSetCopy ( langset ) ;
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2012-12-30 05:58:38 +01:00
FcExprCreateName ( FcConfig * config , FcExprName name )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpField ;
2012-12-30 05:58:38 +01:00
e - > u . name = name ;
2002-02-15 00:34:13 +01:00
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateConst ( FcConfig * config , const FcChar8 * constant )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = FcOpConst ;
2013-01-02 09:06:15 +01:00
e - > u . constant = FcStrdup ( constant ) ;
2002-02-15 00:34:13 +01:00
}
return e ;
}
2009-06-06 03:37:01 +02:00
static FcExpr *
2009-06-06 04:32:31 +02:00
FcExprCreateOp ( FcConfig * config , FcExpr * left , FcOp op , FcExpr * right )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
FcExpr * e = FcConfigAllocExpr ( config ) ;
2002-02-15 00:34:13 +01:00
if ( e )
{
e - > op = op ;
e - > u . tree . left = left ;
e - > u . tree . right = right ;
}
return e ;
}
2009-06-06 03:37:01 +02:00
static void
2002-02-15 00:34:13 +01:00
FcExprDestroy ( FcExpr * e )
{
2003-04-16 01:38:06 +02:00
if ( ! e )
return ;
2012-04-11 12:52:35 +02:00
switch ( FC_OP_GET_OP ( e - > op ) ) {
2002-02-15 00:34:13 +01:00
case FcOpInteger :
break ;
case FcOpDouble :
break ;
case FcOpString :
2013-01-02 09:06:15 +01:00
FcFree ( e - > u . sval ) ;
2002-02-15 00:34:13 +01:00
break ;
case FcOpMatrix :
2012-12-30 03:39:06 +01:00
FcExprMatrixFree ( e - > u . mexpr ) ;
2002-02-15 00:34:13 +01:00
break ;
2010-12-06 04:10:17 +01:00
case FcOpRange :
2013-11-20 10:44:59 +01:00
FcRangeDestroy ( e - > u . rval ) ;
2010-12-06 04:10:17 +01:00
break ;
2002-02-15 00:34:13 +01:00
case FcOpCharSet :
FcCharSetDestroy ( e - > u . cval ) ;
break ;
2010-12-06 04:38:18 +01:00
case FcOpLangSet :
FcLangSetDestroy ( e - > u . lval ) ;
break ;
2002-02-15 00:34:13 +01:00
case FcOpBool :
break ;
case FcOpField :
break ;
case FcOpConst :
2013-01-02 09:06:15 +01:00
FcFree ( e - > u . constant ) ;
2002-02-15 00:34:13 +01:00
break ;
case FcOpAssign :
case FcOpAssignReplace :
case FcOpPrepend :
case FcOpPrependFirst :
case FcOpAppend :
case FcOpAppendLast :
2013-01-29 12:19:36 +01:00
case FcOpDelete :
case FcOpDeleteAll :
2002-02-15 00:34:13 +01:00
break ;
case FcOpOr :
case FcOpAnd :
case FcOpEqual :
case FcOpNotEqual :
case FcOpLess :
case FcOpLessEqual :
case FcOpMore :
case FcOpMoreEqual :
2002-08-22 20:53:22 +02:00
case FcOpContains :
2003-07-20 18:06:18 +02:00
case FcOpListing :
2002-08-22 20:53:22 +02:00
case FcOpNotContains :
2002-02-15 00:34:13 +01:00
case FcOpPlus :
case FcOpMinus :
case FcOpTimes :
case FcOpDivide :
case FcOpQuest :
case FcOpComma :
FcExprDestroy ( e - > u . tree . right ) ;
/* fall through */
case FcOpNot :
2003-04-16 01:38:06 +02:00
case FcOpFloor :
case FcOpCeil :
case FcOpRound :
case FcOpTrunc :
2002-02-15 00:34:13 +01:00
FcExprDestroy ( e - > u . tree . left ) ;
break ;
case FcOpNil :
case FcOpInvalid :
break ;
}
2009-06-06 04:32:31 +02:00
e - > op = FcOpNil ;
2002-02-15 00:34:13 +01:00
}
void
FcEditDestroy ( FcEdit * e )
{
if ( e - > expr )
FcExprDestroy ( e - > expr ) ;
2003-08-15 21:45:20 +02:00
free ( e ) ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
typedef enum _FcElement {
FcElementNone ,
FcElementFontconfig ,
FcElementDir ,
2006-08-04 18:13:00 +02:00
FcElementCacheDir ,
2002-02-18 23:29:28 +01:00
FcElementCache ,
FcElementInclude ,
FcElementConfig ,
FcElementMatch ,
FcElementAlias ,
2014-03-27 07:10:44 +01:00
FcElementDescription ,
2019-01-28 10:59:29 +01:00
FcElementRemapDir ,
2019-01-31 08:52:09 +01:00
FcElementResetDirs ,
2002-02-18 23:29:28 +01:00
2002-05-21 19:06:22 +02:00
FcElementRescan ,
2002-02-18 23:29:28 +01:00
FcElementPrefer ,
FcElementAccept ,
FcElementDefault ,
FcElementFamily ,
2003-05-07 18:13:24 +02:00
FcElementSelectfont ,
FcElementAcceptfont ,
FcElementRejectfont ,
FcElementGlob ,
2004-12-04 20:41:10 +01:00
FcElementPattern ,
FcElementPatelt ,
2003-05-07 18:13:24 +02:00
2002-02-18 23:29:28 +01:00
FcElementTest ,
FcElementEdit ,
FcElementInt ,
FcElementDouble ,
FcElementString ,
FcElementMatrix ,
2010-12-06 04:10:17 +01:00
FcElementRange ,
2002-02-18 23:29:28 +01:00
FcElementBool ,
2010-12-06 04:10:17 +01:00
FcElementCharSet ,
2010-12-06 04:38:18 +01:00
FcElementLangSet ,
2002-02-18 23:29:28 +01:00
FcElementName ,
FcElementConst ,
FcElementOr ,
FcElementAnd ,
FcElementEq ,
FcElementNotEq ,
FcElementLess ,
FcElementLessEq ,
FcElementMore ,
FcElementMoreEq ,
2002-08-22 20:53:22 +02:00
FcElementContains ,
FcElementNotContains ,
2002-02-18 23:29:28 +01:00
FcElementPlus ,
FcElementMinus ,
FcElementTimes ,
FcElementDivide ,
FcElementNot ,
FcElementIf ,
2003-04-16 01:38:06 +02:00
FcElementFloor ,
FcElementCeil ,
FcElementRound ,
FcElementTrunc ,
2002-02-18 23:29:28 +01:00
FcElementUnknown
} FcElement ;
2006-04-06 06:52:21 +02:00
static const struct {
2005-09-23 01:45:53 +02:00
const char name [ 16 ] ;
FcElement element ;
} fcElementMap [ ] = {
{ " fontconfig " , FcElementFontconfig } ,
{ " dir " , FcElementDir } ,
2006-08-04 18:13:00 +02:00
{ " cachedir " , FcElementCacheDir } ,
2005-09-23 01:45:53 +02:00
{ " cache " , FcElementCache } ,
{ " include " , FcElementInclude } ,
{ " config " , FcElementConfig } ,
{ " match " , FcElementMatch } ,
{ " alias " , FcElementAlias } ,
2014-03-27 07:10:44 +01:00
{ " description " , FcElementDescription } ,
2019-01-28 10:59:29 +01:00
{ " remap-dir " , FcElementRemapDir } ,
2019-01-31 08:52:09 +01:00
{ " reset-dirs " , FcElementResetDirs } ,
2010-04-12 17:52:09 +02:00
2005-09-23 01:45:53 +02:00
{ " rescan " , FcElementRescan } ,
{ " prefer " , FcElementPrefer } ,
{ " accept " , FcElementAccept } ,
{ " default " , FcElementDefault } ,
{ " family " , FcElementFamily } ,
{ " selectfont " , FcElementSelectfont } ,
{ " acceptfont " , FcElementAcceptfont } ,
{ " rejectfont " , FcElementRejectfont } ,
{ " glob " , FcElementGlob } ,
{ " pattern " , FcElementPattern } ,
{ " patelt " , FcElementPatelt } ,
{ " test " , FcElementTest } ,
{ " edit " , FcElementEdit } ,
{ " int " , FcElementInt } ,
{ " double " , FcElementDouble } ,
{ " string " , FcElementString } ,
{ " matrix " , FcElementMatrix } ,
2010-12-06 04:10:17 +01:00
{ " range " , FcElementRange } ,
2005-09-23 01:45:53 +02:00
{ " bool " , FcElementBool } ,
2010-12-06 04:10:17 +01:00
{ " charset " , FcElementCharSet } ,
2010-12-06 04:38:18 +01:00
{ " langset " , FcElementLangSet } ,
2005-09-23 01:45:53 +02:00
{ " name " , FcElementName } ,
{ " const " , FcElementConst } ,
{ " or " , FcElementOr } ,
{ " and " , FcElementAnd } ,
{ " eq " , FcElementEq } ,
{ " not_eq " , FcElementNotEq } ,
{ " less " , FcElementLess } ,
{ " less_eq " , FcElementLessEq } ,
{ " more " , FcElementMore } ,
{ " more_eq " , FcElementMoreEq } ,
{ " contains " , FcElementContains } ,
{ " not_contains " , FcElementNotContains } ,
{ " plus " , FcElementPlus } ,
{ " minus " , FcElementMinus } ,
{ " times " , FcElementTimes } ,
{ " divide " , FcElementDivide } ,
{ " not " , FcElementNot } ,
{ " if " , FcElementIf } ,
{ " floor " , FcElementFloor } ,
{ " ceil " , FcElementCeil } ,
{ " round " , FcElementRound } ,
{ " trunc " , FcElementTrunc } ,
} ;
# define NUM_ELEMENT_MAPS (int) (sizeof fcElementMap / sizeof fcElementMap[0])
2014-03-27 07:10:44 +01:00
static const char * fcElementIgnoreName [ 16 ] = {
" its: " ,
NULL
} ;
2002-02-18 23:29:28 +01:00
static FcElement
FcElementMap ( const XML_Char * name )
{
int i ;
2005-09-23 01:45:53 +02:00
for ( i = 0 ; i < NUM_ELEMENT_MAPS ; i + + )
2002-02-18 23:29:28 +01:00
if ( ! strcmp ( ( char * ) name , fcElementMap [ i ] . name ) )
return fcElementMap [ i ] . element ;
2014-03-27 07:10:44 +01:00
for ( i = 0 ; fcElementIgnoreName [ i ] ! = NULL ; i + + )
if ( ! strncmp ( ( char * ) name , fcElementIgnoreName [ i ] , strlen ( fcElementIgnoreName [ i ] ) ) )
return FcElementNone ;
2002-02-18 23:29:28 +01:00
return FcElementUnknown ;
}
2019-01-28 10:59:29 +01:00
static const char *
FcElementReverseMap ( FcElement e )
{
int i ;
for ( i = 0 ; i < NUM_ELEMENT_MAPS ; i + + )
if ( fcElementMap [ i ] . element = = e )
return fcElementMap [ i ] . name ;
return NULL ;
}
2002-02-18 23:29:28 +01:00
typedef struct _FcPStack {
struct _FcPStack * prev ;
FcElement element ;
FcChar8 * * attr ;
FcStrBuf str ;
2009-03-12 17:31:57 +01:00
FcChar8 * attr_buf_static [ 16 ] ;
2002-02-18 23:29:28 +01:00
} FcPStack ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
typedef enum _FcVStackTag {
FcVStackNone ,
FcVStackString ,
FcVStackFamily ,
FcVStackConstant ,
2003-05-07 18:13:24 +02:00
FcVStackGlob ,
2012-12-30 05:58:38 +01:00
FcVStackName ,
2004-12-04 20:41:10 +01:00
FcVStackPattern ,
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
FcVStackPrefer ,
FcVStackAccept ,
FcVStackDefault ,
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
FcVStackInteger ,
FcVStackDouble ,
FcVStackMatrix ,
2010-12-06 04:10:17 +01:00
FcVStackRange ,
2002-02-18 23:29:28 +01:00
FcVStackBool ,
2010-12-06 04:10:17 +01:00
FcVStackCharSet ,
2010-12-06 04:38:18 +01:00
FcVStackLangSet ,
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
FcVStackTest ,
FcVStackExpr ,
FcVStackEdit
} FcVStackTag ;
typedef struct _FcVStack {
struct _FcVStack * prev ;
FcPStack * pstack ; /* related parse element */
FcVStackTag tag ;
union {
FcChar8 * string ;
int integer ;
double _double ;
2012-12-30 03:39:06 +01:00
FcExprMatrix * matrix ;
2013-11-20 10:44:59 +01:00
FcRange * range ;
2008-12-28 09:23:58 +01:00
FcBool bool_ ;
2010-12-06 04:10:17 +01:00
FcCharSet * charset ;
2010-12-06 04:38:18 +01:00
FcLangSet * langset ;
2012-12-30 05:58:38 +01:00
FcExprName name ;
2002-02-18 23:29:28 +01:00
FcTest * test ;
FcQual qual ;
FcOp op ;
FcExpr * expr ;
FcEdit * edit ;
2004-12-04 20:41:10 +01:00
FcPattern * pattern ;
2002-02-18 23:29:28 +01:00
} u ;
} FcVStack ;
typedef struct _FcConfigParse {
FcPStack * pstack ;
FcVStack * vstack ;
FcBool error ;
const FcChar8 * name ;
FcConfig * config ;
2014-03-27 07:10:44 +01:00
FcRuleSet * ruleset ;
2002-02-18 23:29:28 +01:00
XML_Parser parser ;
2012-12-30 04:47:49 +01:00
unsigned int pstack_static_used ;
2009-03-12 16:58:04 +01:00
FcPStack pstack_static [ 8 ] ;
2012-12-30 04:47:49 +01:00
unsigned int vstack_static_used ;
2009-03-12 17:22:37 +01:00
FcVStack vstack_static [ 64 ] ;
2018-01-23 14:27:17 +01:00
FcBool scanOnly ;
2002-02-18 23:29:28 +01:00
} FcConfigParse ;
2002-05-21 19:06:22 +02:00
typedef enum _FcConfigSeverity {
FcSevereInfo , FcSevereWarning , FcSevereError
} FcConfigSeverity ;
2002-02-15 00:34:13 +01:00
static void
2005-09-23 01:45:53 +02:00
FcConfigMessage ( FcConfigParse * parse , FcConfigSeverity severe , const char * fmt , . . . )
2002-02-15 00:34:13 +01:00
{
2005-09-23 01:45:53 +02:00
const char * s = " unknown " ;
2002-02-15 00:34:13 +01:00
va_list args ;
va_start ( args , fmt ) ;
2002-05-21 19:06:22 +02:00
switch ( severe ) {
case FcSevereInfo : s = " info " ; break ;
case FcSevereWarning : s = " warning " ; break ;
case FcSevereError : s = " error " ; break ;
}
2002-02-18 23:29:28 +01:00
if ( parse )
{
if ( parse - > name )
2002-05-21 19:06:22 +02:00
fprintf ( stderr , " Fontconfig %s: \" %s \" , line %d: " , s ,
2006-02-05 03:57:21 +01:00
parse - > name , ( int ) XML_GetCurrentLineNumber ( parse - > parser ) ) ;
2002-02-18 23:29:28 +01:00
else
2002-05-21 19:06:22 +02:00
fprintf ( stderr , " Fontconfig %s: line %d: " , s ,
2006-02-05 03:57:21 +01:00
( int ) XML_GetCurrentLineNumber ( parse - > parser ) ) ;
2002-05-21 19:06:22 +02:00
if ( severe > = FcSevereError )
parse - > error = FcTrue ;
2002-02-18 23:29:28 +01:00
}
else
2002-05-21 19:06:22 +02:00
fprintf ( stderr , " Fontconfig %s: " , s ) ;
2002-02-15 00:34:13 +01:00
vfprintf ( stderr , fmt , args ) ;
fprintf ( stderr , " \n " ) ;
va_end ( args ) ;
}
2005-01-29 00:55:14 +01:00
2012-12-30 03:39:06 +01:00
static FcExpr *
FcPopExpr ( FcConfigParse * parse ) ;
2005-09-23 01:45:53 +02:00
static const char *
2005-01-29 00:55:14 +01:00
FcTypeName ( FcType type )
{
switch ( type ) {
case FcTypeVoid :
return " void " ;
case FcTypeInteger :
case FcTypeDouble :
return " number " ;
case FcTypeString :
return " string " ;
case FcTypeBool :
return " bool " ;
case FcTypeMatrix :
return " matrix " ;
case FcTypeCharSet :
return " charset " ;
case FcTypeFTFace :
return " FT_Face " ;
case FcTypeLangSet :
return " langset " ;
2013-11-20 10:44:59 +01:00
case FcTypeRange :
return " range " ;
2014-08-20 22:03:02 +02:00
case FcTypeUnknown :
2005-01-29 00:55:14 +01:00
default :
return " unknown " ;
}
}
static void
FcTypecheckValue ( FcConfigParse * parse , FcType value , FcType type )
{
if ( value = = FcTypeInteger )
value = FcTypeDouble ;
if ( type = = FcTypeInteger )
type = FcTypeDouble ;
if ( value ! = type )
{
if ( ( value = = FcTypeLangSet & & type = = FcTypeString ) | |
2013-11-20 10:44:59 +01:00
( value = = FcTypeString & & type = = FcTypeLangSet ) | |
( value = = FcTypeDouble & & type = = FcTypeRange ) )
2005-01-29 00:55:14 +01:00
return ;
2013-11-11 03:53:09 +01:00
if ( type = = FcTypeUnknown )
2006-09-04 21:46:01 +02:00
return ;
2012-12-31 02:08:42 +01:00
/* It's perfectly fine to use user-define elements in expressions,
* so don ' t warn in that case . */
2013-11-11 03:53:09 +01:00
if ( value = = FcTypeUnknown )
2012-12-31 02:08:42 +01:00
return ;
2005-01-29 00:55:14 +01:00
FcConfigMessage ( parse , FcSevereWarning , " saw %s, expected %s " ,
FcTypeName ( value ) , FcTypeName ( type ) ) ;
}
}
static void
FcTypecheckExpr ( FcConfigParse * parse , FcExpr * expr , FcType type )
{
const FcObjectType * o ;
const FcConstant * c ;
2010-04-12 18:10:05 +02:00
2007-10-18 14:44:28 +02:00
/* If parsing the expression failed, some nodes may be NULL */
if ( ! expr )
return ;
2012-04-11 12:52:35 +02:00
switch ( FC_OP_GET_OP ( expr - > op ) ) {
2005-01-29 00:55:14 +01:00
case FcOpInteger :
case FcOpDouble :
FcTypecheckValue ( parse , FcTypeDouble , type ) ;
break ;
case FcOpString :
FcTypecheckValue ( parse , FcTypeString , type ) ;
break ;
case FcOpMatrix :
FcTypecheckValue ( parse , FcTypeMatrix , type ) ;
break ;
case FcOpBool :
FcTypecheckValue ( parse , FcTypeBool , type ) ;
break ;
case FcOpCharSet :
FcTypecheckValue ( parse , FcTypeCharSet , type ) ;
break ;
2010-12-06 04:38:18 +01:00
case FcOpLangSet :
FcTypecheckValue ( parse , FcTypeLangSet , type ) ;
break ;
2013-11-20 10:44:59 +01:00
case FcOpRange :
FcTypecheckValue ( parse , FcTypeRange , type ) ;
break ;
2005-01-29 00:55:14 +01:00
case FcOpNil :
break ;
case FcOpField :
2012-12-30 05:58:38 +01:00
o = FcNameGetObjectType ( FcObjectName ( expr - > u . name . object ) ) ;
2005-01-29 00:55:14 +01:00
if ( o )
FcTypecheckValue ( parse , o - > type , type ) ;
break ;
case FcOpConst :
c = FcNameGetConstant ( expr - > u . constant ) ;
if ( c )
{
o = FcNameGetObjectType ( c - > object ) ;
if ( o )
FcTypecheckValue ( parse , o - > type , type ) ;
}
2010-04-12 18:10:05 +02:00
else
FcConfigMessage ( parse , FcSevereWarning ,
2005-11-17 17:17:05 +01:00
" invalid constant used : %s " ,
expr - > u . constant ) ;
2005-01-29 00:55:14 +01:00
break ;
case FcOpQuest :
FcTypecheckExpr ( parse , expr - > u . tree . left , FcTypeBool ) ;
FcTypecheckExpr ( parse , expr - > u . tree . right - > u . tree . left , type ) ;
FcTypecheckExpr ( parse , expr - > u . tree . right - > u . tree . right , type ) ;
break ;
case FcOpAssign :
case FcOpAssignReplace :
break ;
case FcOpEqual :
case FcOpNotEqual :
case FcOpLess :
case FcOpLessEqual :
case FcOpMore :
case FcOpMoreEqual :
case FcOpContains :
case FcOpNotContains :
case FcOpListing :
FcTypecheckValue ( parse , FcTypeBool , type ) ;
break ;
case FcOpComma :
case FcOpOr :
case FcOpAnd :
case FcOpPlus :
case FcOpMinus :
case FcOpTimes :
case FcOpDivide :
FcTypecheckExpr ( parse , expr - > u . tree . left , type ) ;
FcTypecheckExpr ( parse , expr - > u . tree . right , type ) ;
break ;
case FcOpNot :
FcTypecheckValue ( parse , FcTypeBool , type ) ;
FcTypecheckExpr ( parse , expr - > u . tree . left , FcTypeBool ) ;
break ;
case FcOpFloor :
case FcOpCeil :
case FcOpRound :
case FcOpTrunc :
FcTypecheckValue ( parse , FcTypeDouble , type ) ;
FcTypecheckExpr ( parse , expr - > u . tree . left , FcTypeDouble ) ;
break ;
default :
break ;
}
}
static FcTest *
FcTestCreate ( FcConfigParse * parse ,
2010-04-12 18:10:05 +02:00
FcMatchKind kind ,
2005-01-29 00:55:14 +01:00
FcQual qual ,
const FcChar8 * field ,
2013-06-28 08:04:11 +02:00
unsigned int compare ,
2005-01-29 00:55:14 +01:00
FcExpr * expr )
{
FcTest * test = ( FcTest * ) malloc ( sizeof ( FcTest ) ) ;
if ( test )
{
const FcObjectType * o ;
test - > kind = kind ;
test - > qual = qual ;
2006-08-30 13:16:22 +02:00
test - > object = FcObjectFromName ( ( const char * ) field ) ;
2005-01-29 00:55:14 +01:00
test - > op = compare ;
test - > expr = expr ;
2006-08-30 13:16:22 +02:00
o = FcNameGetObjectType ( FcObjectName ( test - > object ) ) ;
2005-01-29 00:55:14 +01:00
if ( o )
FcTypecheckExpr ( parse , expr , o - > type ) ;
}
return test ;
}
static FcEdit *
FcEditCreate ( FcConfigParse * parse ,
2006-08-31 06:59:53 +02:00
FcObject object ,
2005-01-29 00:55:14 +01:00
FcOp op ,
FcExpr * expr ,
FcValueBinding binding )
{
FcEdit * e = ( FcEdit * ) malloc ( sizeof ( FcEdit ) ) ;
if ( e )
{
const FcObjectType * o ;
2006-08-31 06:59:53 +02:00
e - > object = object ;
2005-01-29 00:55:14 +01:00
e - > op = op ;
e - > expr = expr ;
e - > binding = binding ;
2006-08-30 13:16:22 +02:00
o = FcNameGetObjectType ( FcObjectName ( e - > object ) ) ;
2005-01-29 00:55:14 +01:00
if ( o )
FcTypecheckExpr ( parse , expr , o - > type ) ;
}
return e ;
}
2013-07-04 12:51:03 +02:00
static FcRule *
FcRuleCreate ( FcRuleType type ,
void * p )
{
FcRule * r = ( FcRule * ) malloc ( sizeof ( FcRule ) ) ;
if ( ! r )
return NULL ;
r - > next = NULL ;
r - > type = type ;
switch ( type )
{
case FcRuleTest :
r - > u . test = ( FcTest * ) p ;
break ;
case FcRuleEdit :
r - > u . edit = ( FcEdit * ) p ;
break ;
2014-08-20 22:03:02 +02:00
case FcRuleUnknown :
2013-07-04 12:51:03 +02:00
default :
free ( r ) ;
r = NULL ;
break ;
}
return r ;
}
2002-02-18 23:29:28 +01:00
static FcVStack *
2009-03-12 17:22:37 +01:00
FcVStackCreateAndPush ( FcConfigParse * parse )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcVStack * new ;
2002-02-15 00:34:13 +01:00
2009-03-12 17:22:37 +01:00
if ( parse - > vstack_static_used < sizeof ( parse - > vstack_static ) / sizeof ( parse - > vstack_static [ 0 ] ) )
new = & parse - > vstack_static [ parse - > vstack_static_used + + ] ;
else
{
new = malloc ( sizeof ( FcVStack ) ) ;
if ( ! new )
return 0 ;
}
2002-02-18 23:29:28 +01:00
new - > tag = FcVStackNone ;
new - > prev = 0 ;
2002-02-15 00:34:13 +01:00
2009-03-12 17:22:37 +01:00
new - > prev = parse - > vstack ;
new - > pstack = parse - > pstack ? parse - > pstack - > prev : 0 ;
parse - > vstack = new ;
2002-02-15 00:34:13 +01:00
2009-03-12 17:22:37 +01:00
return new ;
2002-02-15 00:34:13 +01:00
}
static FcBool
2002-02-18 23:29:28 +01:00
FcVStackPushString ( FcConfigParse * parse , FcVStackTag tag , FcChar8 * string )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
return FcFalse ;
vstack - > u . string = string ;
vstack - > tag = tag ;
return FcTrue ;
2002-02-15 00:34:13 +01:00
}
static FcBool
2002-02-18 23:29:28 +01:00
FcVStackPushInteger ( FcConfigParse * parse , int integer )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
2002-02-15 00:34:13 +01:00
return FcFalse ;
2002-02-18 23:29:28 +01:00
vstack - > u . integer = integer ;
vstack - > tag = FcVStackInteger ;
return FcTrue ;
2002-02-15 00:34:13 +01:00
}
static FcBool
2002-02-18 23:29:28 +01:00
FcVStackPushDouble ( FcConfigParse * parse , double _double )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
2002-02-15 00:34:13 +01:00
return FcFalse ;
2002-02-18 23:29:28 +01:00
vstack - > u . _double = _double ;
vstack - > tag = FcVStackDouble ;
return FcTrue ;
2002-02-15 00:34:13 +01:00
}
static FcBool
2012-12-30 03:39:06 +01:00
FcVStackPushMatrix ( FcConfigParse * parse , FcExprMatrix * matrix )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack ;
vstack = FcVStackCreateAndPush ( parse ) ;
if ( ! vstack )
return FcFalse ;
2012-12-30 03:39:06 +01:00
vstack - > u . matrix = FcExprMatrixCopyShallow ( matrix ) ;
2002-02-18 23:29:28 +01:00
vstack - > tag = FcVStackMatrix ;
return FcTrue ;
2002-02-15 00:34:13 +01:00
}
2010-12-06 04:10:17 +01:00
static FcBool
FcVStackPushRange ( FcConfigParse * parse , FcRange * range )
{
2013-11-20 10:44:59 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2010-12-06 04:10:17 +01:00
if ( ! vstack )
return FcFalse ;
2013-11-20 10:44:59 +01:00
vstack - > u . range = range ;
2010-12-06 04:10:17 +01:00
vstack - > tag = FcVStackRange ;
return FcTrue ;
}
2002-02-15 00:34:13 +01:00
static FcBool
2008-12-28 09:23:58 +01:00
FcVStackPushBool ( FcConfigParse * parse , FcBool bool_ )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
return FcFalse ;
2008-12-28 09:23:58 +01:00
vstack - > u . bool_ = bool_ ;
2002-02-18 23:29:28 +01:00
vstack - > tag = FcVStackBool ;
return FcTrue ;
}
2002-02-15 00:34:13 +01:00
2010-12-06 04:10:17 +01:00
static FcBool
FcVStackPushCharSet ( FcConfigParse * parse , FcCharSet * charset )
{
FcVStack * vstack ;
if ( ! charset )
return FcFalse ;
vstack = FcVStackCreateAndPush ( parse ) ;
if ( ! vstack )
return FcFalse ;
vstack - > u . charset = charset ;
vstack - > tag = FcVStackCharSet ;
return FcTrue ;
}
2010-12-06 04:38:18 +01:00
static FcBool
FcVStackPushLangSet ( FcConfigParse * parse , FcLangSet * langset )
{
FcVStack * vstack ;
if ( ! langset )
return FcFalse ;
vstack = FcVStackCreateAndPush ( parse ) ;
if ( ! vstack )
return FcFalse ;
vstack - > u . langset = langset ;
vstack - > tag = FcVStackLangSet ;
return FcTrue ;
}
2012-12-30 05:58:38 +01:00
static FcBool
FcVStackPushName ( FcConfigParse * parse , FcMatchKind kind , FcObject object )
{
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
if ( ! vstack )
return FcFalse ;
vstack - > u . name . object = object ;
vstack - > u . name . kind = kind ;
vstack - > tag = FcVStackName ;
return FcTrue ;
}
2002-02-18 23:29:28 +01:00
static FcBool
FcVStackPushTest ( FcConfigParse * parse , FcTest * test )
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
2002-02-15 00:34:13 +01:00
return FcFalse ;
2002-02-18 23:29:28 +01:00
vstack - > u . test = test ;
vstack - > tag = FcVStackTest ;
2002-02-15 00:34:13 +01:00
return FcTrue ;
}
static FcBool
2002-02-18 23:29:28 +01:00
FcVStackPushExpr ( FcConfigParse * parse , FcVStackTag tag , FcExpr * expr )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
return FcFalse ;
vstack - > u . expr = expr ;
vstack - > tag = tag ;
return FcTrue ;
}
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
static FcBool
FcVStackPushEdit ( FcConfigParse * parse , FcEdit * edit )
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( ! vstack )
2002-02-15 00:34:13 +01:00
return FcFalse ;
2002-02-18 23:29:28 +01:00
vstack - > u . edit = edit ;
vstack - > tag = FcVStackEdit ;
2002-02-15 00:34:13 +01:00
return FcTrue ;
}
2004-12-04 20:41:10 +01:00
static FcBool
FcVStackPushPattern ( FcConfigParse * parse , FcPattern * pattern )
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackCreateAndPush ( parse ) ;
2004-12-04 20:41:10 +01:00
if ( ! vstack )
return FcFalse ;
vstack - > u . pattern = pattern ;
vstack - > tag = FcVStackPattern ;
return FcTrue ;
}
2002-02-18 23:29:28 +01:00
static FcVStack *
FcVStackFetch ( FcConfigParse * parse , int off )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcVStack * vstack ;
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
for ( vstack = parse - > vstack ; vstack & & off - - > 0 ; vstack = vstack - > prev ) ;
return vstack ;
}
2009-03-12 17:22:37 +01:00
static FcVStack *
FcVStackPeek ( FcConfigParse * parse )
2002-02-18 23:29:28 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = parse - > vstack ;
return vstack & & vstack - > pstack = = parse - > pstack ? vstack : 0 ;
2002-02-15 00:34:13 +01:00
}
2009-03-12 17:22:37 +01:00
static void
FcVStackPopAndDestroy ( FcConfigParse * parse )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcVStack * vstack = parse - > vstack ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! vstack | | vstack - > pstack ! = parse - > pstack )
2009-03-12 17:22:37 +01:00
return ;
2002-02-18 23:29:28 +01:00
parse - > vstack = vstack - > prev ;
2009-03-12 17:22:37 +01:00
switch ( vstack - > tag ) {
case FcVStackNone :
break ;
2012-12-30 05:58:38 +01:00
case FcVStackName :
break ;
2009-03-12 17:22:37 +01:00
case FcVStackFamily :
2009-06-06 04:59:06 +02:00
break ;
2009-07-20 22:30:12 +02:00
case FcVStackString :
2009-03-12 17:22:37 +01:00
case FcVStackConstant :
case FcVStackGlob :
FcStrFree ( vstack - > u . string ) ;
break ;
case FcVStackPattern :
FcPatternDestroy ( vstack - > u . pattern ) ;
break ;
case FcVStackInteger :
case FcVStackDouble :
break ;
case FcVStackMatrix :
2012-12-30 03:39:06 +01:00
FcExprMatrixFreeShallow ( vstack - > u . matrix ) ;
2009-03-12 17:22:37 +01:00
break ;
case FcVStackBool :
break ;
2013-11-20 10:44:59 +01:00
case FcVStackRange :
FcRangeDestroy ( vstack - > u . range ) ;
break ;
2010-12-06 04:10:17 +01:00
case FcVStackCharSet :
FcCharSetDestroy ( vstack - > u . charset ) ;
break ;
2010-12-06 04:38:18 +01:00
case FcVStackLangSet :
FcLangSetDestroy ( vstack - > u . langset ) ;
break ;
2009-03-12 17:22:37 +01:00
case FcVStackTest :
FcTestDestroy ( vstack - > u . test ) ;
break ;
case FcVStackExpr :
case FcVStackPrefer :
case FcVStackAccept :
case FcVStackDefault :
FcExprDestroy ( vstack - > u . expr ) ;
break ;
case FcVStackEdit :
FcEditDestroy ( vstack - > u . edit ) ;
break ;
}
if ( vstack = = & parse - > vstack_static [ parse - > vstack_static_used - 1 ] )
parse - > vstack_static_used - - ;
else
free ( vstack ) ;
}
static void
FcVStackClear ( FcConfigParse * parse )
{
while ( FcVStackPeek ( parse ) )
FcVStackPopAndDestroy ( parse ) ;
2002-02-18 23:29:28 +01:00
}
static int
FcVStackElements ( FcConfigParse * parse )
{
int h = 0 ;
FcVStack * vstack = parse - > vstack ;
while ( vstack & & vstack - > pstack = = parse - > pstack )
{
h + + ;
vstack = vstack - > prev ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
return h ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
static FcChar8 * *
2009-03-12 17:31:57 +01:00
FcConfigSaveAttr ( const XML_Char * * attr , FcChar8 * * buf , int size_bytes )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
int slen ;
int i ;
FcChar8 * * new ;
FcChar8 * s ;
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
if ( ! attr )
return 0 ;
slen = 0 ;
for ( i = 0 ; attr [ i ] ; i + + )
2005-11-18 21:32:30 +01:00
slen + = strlen ( ( char * ) attr [ i ] ) + 1 ;
2009-03-12 14:27:20 +01:00
if ( i = = 0 )
return 0 ;
2009-03-12 17:31:57 +01:00
slen + = ( i + 1 ) * sizeof ( FcChar8 * ) ;
if ( slen < = size_bytes )
new = buf ;
else
2009-03-12 14:27:20 +01:00
{
2009-03-12 17:31:57 +01:00
new = malloc ( slen ) ;
if ( ! new )
{
FcConfigMessage ( 0 , FcSevereError , " out of memory " ) ;
return 0 ;
}
2009-03-12 14:27:20 +01:00
}
2002-02-18 23:29:28 +01:00
s = ( FcChar8 * ) ( new + ( i + 1 ) ) ;
for ( i = 0 ; attr [ i ] ; i + + )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
new [ i ] = s ;
strcpy ( ( char * ) s , ( char * ) attr [ i ] ) ;
s + = strlen ( ( char * ) s ) + 1 ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
new [ i ] = 0 ;
return new ;
}
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
static FcBool
FcPStackPush ( FcConfigParse * parse , FcElement element , const XML_Char * * attr )
{
2009-03-12 16:58:04 +01:00
FcPStack * new ;
if ( parse - > pstack_static_used < sizeof ( parse - > pstack_static ) / sizeof ( parse - > pstack_static [ 0 ] ) )
new = & parse - > pstack_static [ parse - > pstack_static_used + + ] ;
else
{
new = malloc ( sizeof ( FcPStack ) ) ;
if ( ! new )
return FcFalse ;
}
2002-02-18 23:29:28 +01:00
new - > prev = parse - > pstack ;
new - > element = element ;
2009-03-12 17:31:57 +01:00
new - > attr = FcConfigSaveAttr ( attr , new - > attr_buf_static , sizeof ( new - > attr_buf_static ) ) ;
2002-02-18 23:29:28 +01:00
FcStrBufInit ( & new - > str , 0 , 0 ) ;
parse - > pstack = new ;
return FcTrue ;
}
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
static FcBool
FcPStackPop ( FcConfigParse * parse )
{
FcPStack * old ;
2010-04-12 18:10:05 +02:00
if ( ! parse - > pstack )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " mismatching element " ) ;
2002-02-18 23:29:28 +01:00
return FcFalse ;
2002-02-15 00:34:13 +01:00
}
2013-01-02 08:31:34 +01:00
2014-03-27 07:10:44 +01:00
/* Don't check the attributes for FcElementNone */
if ( parse - > pstack - > element ! = FcElementNone & &
parse - > pstack - > attr )
2013-01-02 08:31:34 +01:00
{
/* Warn about unused attrs. */
FcChar8 * * attrs = parse - > pstack - > attr ;
while ( * attrs )
{
if ( attrs [ 0 ] [ 0 ] )
{
FcConfigMessage ( parse , FcSevereError , " invalid attribute '%s' " , attrs [ 0 ] ) ;
}
attrs + = 2 ;
}
}
2002-02-18 23:29:28 +01:00
FcVStackClear ( parse ) ;
old = parse - > pstack ;
parse - > pstack = old - > prev ;
FcStrBufDestroy ( & old - > str ) ;
2013-01-02 08:31:34 +01:00
2009-03-12 17:31:57 +01:00
if ( old - > attr & & old - > attr ! = old - > attr_buf_static )
2002-02-18 23:29:28 +01:00
free ( old - > attr ) ;
2009-03-12 16:58:04 +01:00
if ( old = = & parse - > pstack_static [ parse - > pstack_static_used - 1 ] )
parse - > pstack_static_used - - ;
else
free ( old ) ;
2002-02-18 23:29:28 +01:00
return FcTrue ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
static FcBool
2014-03-27 07:10:44 +01:00
FcConfigParseInit ( FcConfigParse * parse ,
const FcChar8 * name ,
FcConfig * config ,
XML_Parser parser ,
FcBool enabled )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
parse - > pstack = 0 ;
2009-03-12 16:58:04 +01:00
parse - > pstack_static_used = 0 ;
2002-02-18 23:29:28 +01:00
parse - > vstack = 0 ;
2009-03-12 17:22:37 +01:00
parse - > vstack_static_used = 0 ;
2002-02-18 23:29:28 +01:00
parse - > error = FcFalse ;
parse - > name = name ;
parse - > config = config ;
2014-03-27 07:10:44 +01:00
parse - > ruleset = FcRuleSetCreate ( name ) ;
2002-02-18 23:29:28 +01:00
parse - > parser = parser ;
2018-01-23 14:27:17 +01:00
parse - > scanOnly = ! enabled ;
2014-03-27 07:10:44 +01:00
FcRuleSetEnable ( parse - > ruleset , enabled ) ;
2002-02-18 23:29:28 +01:00
return FcTrue ;
}
static void
FcConfigCleanup ( FcConfigParse * parse )
{
while ( parse - > pstack )
FcPStackPop ( parse ) ;
2014-03-27 07:10:44 +01:00
FcRuleSetDestroy ( parse - > ruleset ) ;
parse - > ruleset = NULL ;
2002-02-18 23:29:28 +01:00
}
static const FcChar8 *
2005-09-23 01:45:53 +02:00
FcConfigGetAttribute ( FcConfigParse * parse , const char * attr )
2002-02-18 23:29:28 +01:00
{
FcChar8 * * attrs ;
if ( ! parse - > pstack )
2002-02-15 00:34:13 +01:00
return 0 ;
2002-02-18 23:29:28 +01:00
attrs = parse - > pstack - > attr ;
2005-12-12 14:20:41 +01:00
if ( ! attrs )
return 0 ;
2002-02-18 23:29:28 +01:00
while ( * attrs )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
if ( ! strcmp ( ( char * ) * attrs , attr ) )
2013-01-02 08:31:34 +01:00
{
attrs [ 0 ] [ 0 ] = ' \0 ' ; /* Mark as used. */
2002-02-18 23:29:28 +01:00
return attrs [ 1 ] ;
2013-01-02 08:31:34 +01:00
}
2002-02-18 23:29:28 +01:00
attrs + = 2 ;
2002-02-15 00:34:13 +01:00
}
return 0 ;
}
2019-01-28 10:59:29 +01:00
static FcChar8 *
_get_real_path_from_prefix ( FcConfigParse * parse , const FcChar8 * path , const FcChar8 * prefix )
{
# ifdef _WIN32
2019-03-25 11:58:15 +01:00
FcChar8 buffer [ 1000 ] = { 0 } ;
2019-01-28 10:59:29 +01:00
# endif
FcChar8 * parent = NULL , * retval = NULL ;
if ( prefix )
{
if ( FcStrCmp ( prefix , ( const FcChar8 * ) " xdg " ) = = 0 )
{
parent = FcConfigXdgDataHome ( ) ;
if ( ! parent )
{
/* Home directory might be disabled */
return NULL ;
}
}
else if ( FcStrCmp ( prefix , ( const FcChar8 * ) " default " ) = = 0 | |
FcStrCmp ( prefix , ( const FcChar8 * ) " cwd " ) = = 0 )
{
/* Nothing to do */
}
else if ( FcStrCmp ( prefix , ( const FcChar8 * ) " relative " ) = = 0 )
{
parent = FcStrDirname ( parse - > name ) ;
if ( ! parent )
return NULL ;
}
}
# ifndef _WIN32
/* For Win32, check this later for dealing with special cases */
else
{
if ( ! FcStrIsAbsoluteFilename ( path ) & & path [ 0 ] ! = ' ~ ' )
FcConfigMessage ( parse , FcSevereWarning , " Use of ambiguous path in <%s> element. please add prefix= \" cwd \" if current behavior is desired. " , FcElementReverseMap ( parse - > pstack - > element ) ) ;
}
2019-03-25 11:58:15 +01:00
# else
2019-01-28 10:59:29 +01:00
if ( strcmp ( ( const char * ) path , " CUSTOMFONTDIR " ) = = 0 )
{
FcChar8 * p ;
2019-06-24 10:07:27 +02:00
path = buffer ;
2019-01-28 10:59:29 +01:00
if ( ! GetModuleFileName ( NULL , ( LPCH ) buffer , sizeof ( buffer ) - 20 ) )
{
FcConfigMessage ( parse , FcSevereError , " GetModuleFileName failed " ) ;
2019-03-25 08:17:33 +01:00
return NULL ;
2019-01-28 10:59:29 +01:00
}
/*
* Must use the multi - byte aware function to search
* for backslash because East Asian double - byte code
* pages have characters with backslash as the second
* byte .
*/
2019-06-24 10:07:27 +02:00
p = _mbsrchr ( path , ' \\ ' ) ;
2019-01-28 10:59:29 +01:00
if ( p ) * p = ' \0 ' ;
2019-06-24 10:07:27 +02:00
strcat ( ( char * ) path , " \\ fonts " ) ;
2019-01-28 10:59:29 +01:00
}
else if ( strcmp ( ( const char * ) path , " APPSHAREFONTDIR " ) = = 0 )
{
FcChar8 * p ;
2019-06-24 10:07:27 +02:00
path = buffer ;
2019-01-28 10:59:29 +01:00
if ( ! GetModuleFileName ( NULL , ( LPCH ) buffer , sizeof ( buffer ) - 20 ) )
{
FcConfigMessage ( parse , FcSevereError , " GetModuleFileName failed " ) ;
2019-03-25 08:17:33 +01:00
return NULL ;
2019-01-28 10:59:29 +01:00
}
2019-06-24 10:07:27 +02:00
p = _mbsrchr ( path , ' \\ ' ) ;
2019-01-28 10:59:29 +01:00
if ( p ) * p = ' \0 ' ;
2019-06-24 10:07:27 +02:00
strcat ( ( char * ) path , " \\ .. \\ share \\ fonts " ) ;
2019-01-28 10:59:29 +01:00
}
else if ( strcmp ( ( const char * ) path , " WINDOWSFONTDIR " ) = = 0 )
{
int rc ;
2019-06-24 10:07:27 +02:00
path = buffer ;
2019-01-28 10:59:29 +01:00
rc = pGetSystemWindowsDirectory ( ( LPSTR ) buffer , sizeof ( buffer ) - 20 ) ;
if ( rc = = 0 | | rc > sizeof ( buffer ) - 20 )
{
FcConfigMessage ( parse , FcSevereError , " GetSystemWindowsDirectory failed " ) ;
2019-03-25 08:17:33 +01:00
return NULL ;
2019-01-28 10:59:29 +01:00
}
2019-06-24 10:07:27 +02:00
if ( path [ strlen ( ( const char * ) path ) - 1 ] ! = ' \\ ' )
strcat ( ( char * ) path , " \\ " ) ;
strcat ( ( char * ) path , " fonts " ) ;
2019-01-28 10:59:29 +01:00
}
2019-03-25 11:58:15 +01:00
else
2019-01-28 10:59:29 +01:00
{
2019-03-25 11:58:15 +01:00
if ( ! prefix )
{
if ( ! FcStrIsAbsoluteFilename ( path ) & & path [ 0 ] ! = ' ~ ' )
FcConfigMessage ( parse , FcSevereWarning , " Use of ambiguous path in <%s> element. please add prefix= \" cwd \" if current behavior is desired. " , FcElementReverseMap ( parse - > pstack - > element ) ) ;
}
2019-01-28 10:59:29 +01:00
}
# endif
2019-06-24 10:07:27 +02:00
if ( parent )
{
retval = FcStrBuildFilename ( parent , path , NULL ) ;
2019-07-23 12:54:36 +02:00
FcStrFree ( parent ) ;
2019-06-24 10:07:27 +02:00
}
else
{
retval = FcStrdup ( path ) ;
}
2019-01-28 10:59:29 +01:00
return retval ;
}
2002-02-18 23:29:28 +01:00
static void
FcStartElement ( void * userData , const XML_Char * name , const XML_Char * * attr )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcConfigParse * parse = userData ;
FcElement element ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
element = FcElementMap ( name ) ;
if ( element = = FcElementUnknown )
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " unknown element \" %s \" " , name ) ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! FcPStackPush ( parse , element , attr ) )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
return ;
}
2002-02-15 00:34:13 +01:00
2002-05-21 19:06:22 +02:00
static void
FcParseRescan ( FcConfigParse * parse )
{
int n = FcVStackElements ( parse ) ;
while ( n - - > 0 )
{
FcVStack * v = FcVStackFetch ( parse , n ) ;
if ( v - > tag ! = FcVStackInteger )
FcConfigMessage ( parse , FcSevereWarning , " non-integer rescan " ) ;
else
parse - > config - > rescanInterval = v - > u . integer ;
}
}
2002-02-18 23:29:28 +01:00
static void
FcParseInt ( FcConfigParse * parse )
{
FcChar8 * s , * end ;
int l ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! parse - > pstack )
return ;
2009-03-11 19:07:15 +01:00
s = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! s )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
end = 0 ;
l = ( int ) strtol ( ( char * ) s , ( char * * ) & end , 0 ) ;
if ( end ! = s + strlen ( ( char * ) s ) )
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " \" %s \" : not a valid integer " , s ) ;
2002-02-18 23:29:28 +01:00
else
FcVStackPushInteger ( parse , l ) ;
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2002-02-15 00:34:13 +01:00
}
2002-06-26 18:11:29 +02:00
/*
2010-04-12 18:10:05 +02:00
* idea copied from glib g_ascii_strtod with
* permission of the author ( Alexander Larsson )
2002-06-26 18:11:29 +02:00
*/
# include <locale.h>
2010-04-12 18:10:05 +02:00
static double
2002-06-26 18:11:29 +02:00
FcStrtod ( char * s , char * * end )
{
2016-05-27 04:16:09 +02:00
# ifndef __BIONIC__
2002-06-26 18:11:29 +02:00
struct lconv * locale_data ;
2016-05-27 04:16:09 +02:00
# endif
const char * decimal_point ;
int dlen ;
2002-06-26 18:11:29 +02:00
char * dot ;
double v ;
/*
* Have to swap the decimal point to match the current locale
* if that locale doesn ' t use 0x2e
*/
2016-05-27 04:16:09 +02:00
# ifndef __BIONIC__
locale_data = localeconv ( ) ;
decimal_point = locale_data - > decimal_point ;
dlen = strlen ( decimal_point ) ;
# else
decimal_point = " . " ;
dlen = 1 ;
# endif
2002-06-26 18:11:29 +02:00
if ( ( dot = strchr ( s , 0x2e ) ) & &
2016-05-27 04:16:09 +02:00
( decimal_point [ 0 ] ! = 0x2e | |
decimal_point [ 1 ] ! = 0 ) )
2002-06-26 18:11:29 +02:00
{
char buf [ 128 ] ;
int slen = strlen ( s ) ;
2005-09-23 01:45:53 +02:00
if ( slen + dlen > ( int ) sizeof ( buf ) )
2002-06-26 18:11:29 +02:00
{
if ( end )
* end = s ;
v = 0 ;
}
else
{
char * buf_end ;
/* mantissa */
strncpy ( buf , s , dot - s ) ;
/* decimal point */
2016-05-27 04:16:09 +02:00
strcpy ( buf + ( dot - s ) , decimal_point ) ;
2002-06-26 18:11:29 +02:00
/* rest of number */
strcpy ( buf + ( dot - s ) + dlen , dot + 1 ) ;
buf_end = 0 ;
v = strtod ( buf , & buf_end ) ;
2003-11-10 18:34:36 +01:00
if ( buf_end ) {
buf_end = s + ( buf_end - buf ) ;
if ( buf_end > dot )
buf_end - = dlen - 1 ;
}
2002-06-26 18:11:29 +02:00
if ( end )
* end = buf_end ;
}
}
else
v = strtod ( s , end ) ;
return v ;
}
2002-02-18 23:29:28 +01:00
static void
FcParseDouble ( FcConfigParse * parse )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcChar8 * s , * end ;
double d ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! parse - > pstack )
return ;
2009-03-11 19:07:15 +01:00
s = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! s )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
end = 0 ;
2002-06-26 18:11:29 +02:00
d = FcStrtod ( ( char * ) s , ( char * * ) & end ) ;
2002-02-18 23:29:28 +01:00
if ( end ! = s + strlen ( ( char * ) s ) )
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " \" %s \" : not a valid double " , s ) ;
2002-02-15 00:34:13 +01:00
else
2002-02-18 23:29:28 +01:00
FcVStackPushDouble ( parse , d ) ;
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
}
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
static void
FcParseString ( FcConfigParse * parse , FcVStackTag tag )
{
FcChar8 * s ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! parse - > pstack )
return ;
s = FcStrBufDone ( & parse - > pstack - > str ) ;
if ( ! s )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
}
if ( ! FcVStackPushString ( parse , tag , s ) )
FcStrFree ( s ) ;
}
2012-12-30 05:58:38 +01:00
static void
FcParseName ( FcConfigParse * parse )
{
const FcChar8 * kind_string ;
FcMatchKind kind ;
FcChar8 * s ;
FcObject object ;
kind_string = FcConfigGetAttribute ( parse , " target " ) ;
if ( ! kind_string )
kind = FcMatchDefault ;
else
{
if ( ! strcmp ( ( char * ) kind_string , " pattern " ) )
kind = FcMatchPattern ;
else if ( ! strcmp ( ( char * ) kind_string , " font " ) )
kind = FcMatchFont ;
else if ( ! strcmp ( ( char * ) kind_string , " default " ) )
kind = FcMatchDefault ;
else
{
FcConfigMessage ( parse , FcSevereWarning , " invalid name target \" %s \" " , kind_string ) ;
return ;
}
}
if ( ! parse - > pstack )
return ;
s = FcStrBufDone ( & parse - > pstack - > str ) ;
if ( ! s )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
return ;
}
object = FcObjectFromName ( ( const char * ) s ) ;
FcVStackPushName ( parse , kind , object ) ;
FcStrFree ( s ) ;
}
2002-02-18 23:29:28 +01:00
static void
FcParseMatrix ( FcConfigParse * parse )
{
2012-12-30 03:39:06 +01:00
FcExprMatrix m ;
2010-04-12 18:10:05 +02:00
2012-12-30 03:39:06 +01:00
m . yy = FcPopExpr ( parse ) ;
m . yx = FcPopExpr ( parse ) ;
m . xy = FcPopExpr ( parse ) ;
m . xx = FcPopExpr ( parse ) ;
2019-01-23 06:59:24 +01:00
if ( ! m . yy | | ! m . yx | | ! m . xy | | ! m . xx )
{
FcConfigMessage ( parse , FcSevereWarning , " Missing values in matrix element " ) ;
return ;
}
2012-12-30 03:39:06 +01:00
if ( FcPopExpr ( parse ) )
FcConfigMessage ( parse , FcSevereError , " wrong number of matrix elements " ) ;
2002-02-18 23:29:28 +01:00
else
2012-12-30 03:39:06 +01:00
FcVStackPushMatrix ( parse , & m ) ;
2002-02-15 00:34:13 +01:00
}
2010-12-06 04:10:17 +01:00
static void
FcParseRange ( FcConfigParse * parse )
{
FcVStack * vstack ;
2013-11-20 10:44:59 +01:00
FcRange * r ;
FcChar32 n [ 2 ] = { 0 , 0 } ;
2010-12-06 04:10:17 +01:00
int count = 1 ;
2013-11-20 10:44:59 +01:00
double d [ 2 ] = { 0.0 L , 0.0 L } ;
FcBool dflag = FcFalse ;
2010-12-06 04:10:17 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
{
if ( count < 0 )
{
FcConfigMessage ( parse , FcSevereError , " too many elements in range " ) ;
return ;
}
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2010-12-06 04:10:17 +01:00
case FcVStackInteger :
2013-11-20 10:44:59 +01:00
if ( dflag )
d [ count ] = ( double ) vstack - > u . integer ;
else
n [ count ] = vstack - > u . integer ;
break ;
case FcVStackDouble :
if ( count = = 0 & & ! dflag )
d [ 1 ] = ( double ) n [ 1 ] ;
d [ count ] = vstack - > u . _double ;
dflag = FcTrue ;
2010-12-06 04:10:17 +01:00
break ;
default :
FcConfigMessage ( parse , FcSevereError , " invalid element in range " ) ;
2013-11-20 10:44:59 +01:00
if ( dflag )
d [ count ] = 0.0 L ;
else
n [ count ] = 0 ;
2010-12-06 04:10:17 +01:00
break ;
}
count - - ;
FcVStackPopAndDestroy ( parse ) ;
}
2013-11-20 10:44:59 +01:00
if ( count > = 0 )
{
FcConfigMessage ( parse , FcSevereError , " invalid range " ) ;
return ;
}
if ( dflag )
2010-12-06 04:10:17 +01:00
{
2013-11-20 10:44:59 +01:00
if ( d [ 0 ] > d [ 1 ] )
2010-12-06 04:10:17 +01:00
{
FcConfigMessage ( parse , FcSevereError , " invalid range " ) ;
return ;
}
2013-11-20 10:44:59 +01:00
r = FcRangeCreateDouble ( d [ 0 ] , d [ 1 ] ) ;
2010-12-06 04:10:17 +01:00
}
else
2013-11-20 10:44:59 +01:00
{
if ( n [ 0 ] > n [ 1 ] )
{
FcConfigMessage ( parse , FcSevereError , " invalid range " ) ;
return ;
}
r = FcRangeCreateInteger ( n [ 0 ] , n [ 1 ] ) ;
}
FcVStackPushRange ( parse , r ) ;
2010-12-06 04:10:17 +01:00
}
2002-02-15 00:34:13 +01:00
static FcBool
2008-12-28 09:23:58 +01:00
FcConfigLexBool ( FcConfigParse * parse , const FcChar8 * bool_ )
2002-02-18 23:29:28 +01:00
{
2005-01-29 00:55:14 +01:00
FcBool result = FcFalse ;
2008-12-28 09:23:58 +01:00
if ( ! FcNameBool ( bool_ , & result ) )
2005-01-29 00:55:14 +01:00
FcConfigMessage ( parse , FcSevereWarning , " \" %s \" is not known boolean " ,
2008-12-28 09:23:58 +01:00
bool_ ) ;
2005-01-29 00:55:14 +01:00
return result ;
2002-02-18 23:29:28 +01:00
}
static void
FcParseBool ( FcConfigParse * parse )
{
FcChar8 * s ;
if ( ! parse - > pstack )
return ;
2009-03-11 19:07:15 +01:00
s = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! s )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
}
2005-01-29 00:55:14 +01:00
FcVStackPushBool ( parse , FcConfigLexBool ( parse , s ) ) ;
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
}
2010-12-06 04:10:17 +01:00
static void
FcParseCharSet ( FcConfigParse * parse )
{
FcVStack * vstack ;
FcCharSet * charset = FcCharSetCreate ( ) ;
2013-11-20 10:44:59 +01:00
FcChar32 i , begin , end ;
2010-12-06 04:10:17 +01:00
int n = 0 ;
while ( ( vstack = FcVStackPeek ( parse ) ) )
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2010-12-06 04:10:17 +01:00
case FcVStackInteger :
if ( ! FcCharSetAddChar ( charset , vstack - > u . integer ) )
{
FcConfigMessage ( parse , FcSevereWarning , " invalid character: 0x%04x " , vstack - > u . integer ) ;
}
else
n + + ;
break ;
case FcVStackRange :
2014-08-20 22:07:26 +02:00
begin = ( FcChar32 ) vstack - > u . range - > begin ;
end = ( FcChar32 ) vstack - > u . range - > end ;
2013-11-20 10:44:59 +01:00
if ( begin < = end )
2010-12-06 04:10:17 +01:00
{
2013-11-20 10:44:59 +01:00
for ( i = begin ; i < = end ; i + + )
2010-12-28 09:55:31 +01:00
{
if ( ! FcCharSetAddChar ( charset , i ) )
{
FcConfigMessage ( parse , FcSevereWarning , " invalid character: 0x%04x " , i ) ;
}
else
n + + ;
}
2010-12-06 04:10:17 +01:00
}
break ;
default :
FcConfigMessage ( parse , FcSevereError , " invalid element in charset " ) ;
break ;
}
FcVStackPopAndDestroy ( parse ) ;
}
if ( n > 0 )
FcVStackPushCharSet ( parse , charset ) ;
else
FcCharSetDestroy ( charset ) ;
}
2010-12-06 04:38:18 +01:00
static void
FcParseLangSet ( FcConfigParse * parse )
{
FcVStack * vstack ;
FcLangSet * langset = FcLangSetCreate ( ) ;
int n = 0 ;
while ( ( vstack = FcVStackPeek ( parse ) ) )
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2010-12-06 04:38:18 +01:00
case FcVStackString :
if ( ! FcLangSetAdd ( langset , vstack - > u . string ) )
{
FcConfigMessage ( parse , FcSevereWarning , " invalid langset: %s " , vstack - > u . string ) ;
}
else
n + + ;
break ;
default :
FcConfigMessage ( parse , FcSevereError , " invalid element in langset " ) ;
break ;
}
FcVStackPopAndDestroy ( parse ) ;
}
if ( n > 0 )
FcVStackPushLangSet ( parse , langset ) ;
else
FcLangSetDestroy ( langset ) ;
}
2007-10-26 07:30:49 +02:00
static FcBool
FcConfigLexBinding ( FcConfigParse * parse ,
const FcChar8 * binding_string ,
FcValueBinding * binding_ret )
{
FcValueBinding binding ;
2010-04-12 18:10:05 +02:00
2007-10-26 07:30:49 +02:00
if ( ! binding_string )
binding = FcValueBindingWeak ;
else
{
if ( ! strcmp ( ( char * ) binding_string , " weak " ) )
binding = FcValueBindingWeak ;
else if ( ! strcmp ( ( char * ) binding_string , " strong " ) )
binding = FcValueBindingStrong ;
else if ( ! strcmp ( ( char * ) binding_string , " same " ) )
binding = FcValueBindingSame ;
else
{
FcConfigMessage ( parse , FcSevereWarning , " invalid binding \" %s \" " , binding_string ) ;
return FcFalse ;
}
}
* binding_ret = binding ;
return FcTrue ;
}
2002-02-18 23:29:28 +01:00
static void
FcParseFamilies ( FcConfigParse * parse , FcVStackTag tag )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
FcVStack * vstack ;
FcExpr * left , * expr = 0 , * new ;
2009-03-12 17:22:37 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
2002-02-18 23:29:28 +01:00
{
if ( vstack - > tag ! = FcVStackFamily )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " non-family " ) ;
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2002-05-21 19:06:22 +02:00
continue ;
2002-02-18 23:29:28 +01:00
}
left = vstack - > u . expr ;
vstack - > tag = FcVStackNone ;
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2002-02-18 23:29:28 +01:00
if ( expr )
{
2009-06-06 04:32:31 +02:00
new = FcExprCreateOp ( parse - > config , left , FcOpComma , expr ) ;
2002-02-18 23:29:28 +01:00
if ( ! new )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
FcExprDestroy ( left ) ;
FcExprDestroy ( expr ) ;
break ;
}
expr = new ;
}
else
expr = left ;
}
if ( expr )
{
if ( ! FcVStackPushExpr ( parse , tag , expr ) )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2006-02-21 16:50:19 +01:00
FcExprDestroy ( expr ) ;
2002-02-18 23:29:28 +01:00
}
}
}
static void
FcParseFamily ( FcConfigParse * parse )
{
FcChar8 * s ;
FcExpr * expr ;
if ( ! parse - > pstack )
return ;
2009-03-11 19:07:15 +01:00
s = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! s )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
}
2009-06-06 04:32:31 +02:00
expr = FcExprCreateString ( parse - > config , s ) ;
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( expr )
FcVStackPushExpr ( parse , FcVStackFamily , expr ) ;
}
static void
FcParseAlias ( FcConfigParse * parse )
{
2002-05-21 19:06:22 +02:00
FcExpr * family = 0 , * accept = 0 , * prefer = 0 , * def = 0 , * new = 0 ;
2013-07-04 12:51:03 +02:00
FcEdit * edit = 0 ;
2002-02-18 23:29:28 +01:00
FcVStack * vstack ;
2013-07-04 12:51:03 +02:00
FcRule * rule = NULL , * r ;
2007-10-26 07:30:49 +02:00
FcValueBinding binding ;
2014-03-27 07:10:44 +01:00
int n ;
2002-02-15 00:34:13 +01:00
2007-10-26 07:30:49 +02:00
if ( ! FcConfigLexBinding ( parse , FcConfigGetAttribute ( parse , " binding " ) , & binding ) )
return ;
2009-03-12 17:22:37 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
2002-02-15 00:34:13 +01:00
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2002-02-18 23:29:28 +01:00
case FcVStackFamily :
if ( family )
2002-05-21 19:06:22 +02:00
{
2012-08-16 13:33:12 +02:00
FcConfigMessage ( parse , FcSevereWarning , " Having multiple <family> in <alias> isn't supported and may not work as expected " ) ;
2009-06-06 04:32:31 +02:00
new = FcExprCreateOp ( parse - > config , vstack - > u . expr , FcOpComma , family ) ;
2002-05-21 19:06:22 +02:00
if ( ! new )
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
else
family = new ;
}
else
new = vstack - > u . expr ;
if ( new )
{
family = new ;
vstack - > tag = FcVStackNone ;
}
2002-02-18 23:29:28 +01:00
break ;
case FcVStackPrefer :
if ( prefer )
FcExprDestroy ( prefer ) ;
prefer = vstack - > u . expr ;
vstack - > tag = FcVStackNone ;
break ;
case FcVStackAccept :
if ( accept )
FcExprDestroy ( accept ) ;
accept = vstack - > u . expr ;
vstack - > tag = FcVStackNone ;
break ;
case FcVStackDefault :
if ( def )
FcExprDestroy ( def ) ;
def = vstack - > u . expr ;
vstack - > tag = FcVStackNone ;
break ;
2012-04-04 07:47:57 +02:00
case FcVStackTest :
2013-07-04 12:51:03 +02:00
if ( rule )
{
r = FcRuleCreate ( FcRuleTest , vstack - > u . test ) ;
r - > next = rule ;
rule = r ;
}
else
rule = FcRuleCreate ( FcRuleTest , vstack - > u . test ) ;
2012-04-04 07:47:57 +02:00
vstack - > tag = FcVStackNone ;
break ;
2002-02-18 23:29:28 +01:00
default :
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " bad alias " ) ;
2002-02-18 23:29:28 +01:00
break ;
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2002-02-15 00:34:13 +01:00
}
2002-02-15 07:01:28 +01:00
if ( ! family )
2002-02-18 23:29:28 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " missing family in alias " ) ;
if ( prefer )
FcExprDestroy ( prefer ) ;
if ( accept )
FcExprDestroy ( accept ) ;
if ( def )
FcExprDestroy ( def ) ;
2013-07-04 12:51:03 +02:00
if ( rule )
FcRuleDestroy ( rule ) ;
return ;
}
if ( ! prefer & &
! accept & &
! def )
{
FcExprDestroy ( family ) ;
2018-07-25 06:41:47 +02:00
if ( rule )
FcRuleDestroy ( rule ) ;
2002-02-18 23:29:28 +01:00
return ;
}
2013-07-04 12:51:03 +02:00
else
{
FcTest * t = FcTestCreate ( parse , FcMatchPattern ,
FcQualAny ,
( FcChar8 * ) FC_FAMILY ,
FC_OP ( FcOpEqual , FcOpFlagIgnoreBlanks ) ,
family ) ;
if ( rule )
{
for ( r = rule ; r - > next ; r = r - > next ) ;
r - > next = FcRuleCreate ( FcRuleTest , t ) ;
r = r - > next ;
}
else
{
r = rule = FcRuleCreate ( FcRuleTest , t ) ;
}
}
2002-02-15 00:34:13 +01:00
if ( prefer )
{
2010-04-12 18:10:05 +02:00
edit = FcEditCreate ( parse ,
2006-08-31 06:59:53 +02:00
FC_FAMILY_OBJECT ,
2002-02-15 00:34:13 +01:00
FcOpPrepend ,
2002-07-31 03:36:37 +02:00
prefer ,
2007-10-26 07:30:49 +02:00
binding ) ;
2013-07-04 12:51:03 +02:00
if ( ! edit )
2002-02-18 23:29:28 +01:00
FcExprDestroy ( prefer ) ;
2013-07-04 12:51:03 +02:00
else
{
r - > next = FcRuleCreate ( FcRuleEdit , edit ) ;
r = r - > next ;
}
2002-02-15 00:34:13 +01:00
}
if ( accept )
{
2005-01-29 00:55:14 +01:00
edit = FcEditCreate ( parse ,
2006-08-31 06:59:53 +02:00
FC_FAMILY_OBJECT ,
2002-02-15 00:34:13 +01:00
FcOpAppend ,
2002-07-31 03:36:37 +02:00
accept ,
2007-10-26 07:30:49 +02:00
binding ) ;
2013-07-04 12:51:03 +02:00
if ( ! edit )
2002-02-18 23:29:28 +01:00
FcExprDestroy ( accept ) ;
2013-07-04 12:51:03 +02:00
else
{
r - > next = FcRuleCreate ( FcRuleEdit , edit ) ;
r = r - > next ;
}
2002-02-15 00:34:13 +01:00
}
if ( def )
{
2005-01-29 00:55:14 +01:00
edit = FcEditCreate ( parse ,
2006-08-31 06:59:53 +02:00
FC_FAMILY_OBJECT ,
2002-07-31 03:36:37 +02:00
FcOpAppendLast ,
def ,
2007-10-26 07:30:49 +02:00
binding ) ;
2013-07-04 12:51:03 +02:00
if ( ! edit )
2002-02-18 23:29:28 +01:00
FcExprDestroy ( def ) ;
2013-07-04 12:51:03 +02:00
else
2012-04-04 07:47:57 +02:00
{
2013-07-04 12:51:03 +02:00
r - > next = FcRuleCreate ( FcRuleEdit , edit ) ;
r = r - > next ;
2012-04-04 07:47:57 +02:00
}
2002-02-15 00:34:13 +01:00
}
2014-03-27 07:10:44 +01:00
if ( ( n = FcRuleSetAdd ( parse - > ruleset , rule , FcMatchPattern ) ) = = - 1 )
2013-07-04 12:51:03 +02:00
FcRuleDestroy ( rule ) ;
2014-03-27 07:10:44 +01:00
else
if ( parse - > config - > maxObjects < n )
parse - > config - > maxObjects = n ;
}
static void
FcParseDescription ( FcConfigParse * parse )
{
const FcChar8 * domain ;
FcChar8 * desc ;
domain = FcConfigGetAttribute ( parse , " domain " ) ;
desc = FcStrBufDone ( & parse - > pstack - > str ) ;
if ( ! desc )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
return ;
}
FcRuleSetAddDescription ( parse - > ruleset , domain , desc ) ;
FcStrFree ( desc ) ;
2002-02-15 00:34:13 +01:00
}
2019-01-28 10:59:29 +01:00
static void
FcParseRemapDir ( FcConfigParse * parse )
{
2019-01-31 11:17:47 +01:00
const FcChar8 * path , * attr , * data , * salt ;
2019-01-28 10:59:29 +01:00
FcChar8 * prefix = NULL ;
data = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
if ( ! data )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
return ;
}
2019-04-02 11:37:49 +02:00
if ( data [ 0 ] = = 0 )
{
FcConfigMessage ( parse , FcSevereWarning , " empty font directory name for remap ignored " ) ;
return ;
}
2019-01-28 10:59:29 +01:00
path = FcConfigGetAttribute ( parse , " as-path " ) ;
if ( ! path )
{
FcConfigMessage ( parse , FcSevereWarning , " Missing as-path in remap-dir " ) ;
return ;
}
attr = FcConfigGetAttribute ( parse , " prefix " ) ;
2019-01-31 11:17:47 +01:00
salt = FcConfigGetAttribute ( parse , " salt " ) ;
2019-01-28 10:59:29 +01:00
prefix = _get_real_path_from_prefix ( parse , data , attr ) ;
if ( ! prefix | | prefix [ 0 ] = = 0 )
2019-04-02 11:37:49 +02:00
{
/* nop */
}
2019-01-28 10:59:29 +01:00
else if ( ! parse - > scanOnly & & ( ! FcStrUsesHome ( prefix ) | | FcConfigHome ( ) ) )
{
2019-01-31 11:17:47 +01:00
if ( ! FcConfigAddFontDir ( parse - > config , prefix , path , salt ) )
2019-01-28 10:59:29 +01:00
FcConfigMessage ( parse , FcSevereError , " out of memory; cannot create remap data for %s as %s " , prefix , path ) ;
}
FcStrBufDestroy ( & parse - > pstack - > str ) ;
if ( prefix )
FcStrFree ( prefix ) ;
}
2019-01-31 08:52:09 +01:00
static void
FcParseResetDirs ( FcConfigParse * parse )
{
if ( ! parse - > scanOnly )
{
if ( ! FcConfigResetFontDirs ( parse - > config ) )
FcConfigMessage ( parse , FcSevereError , " Unable to reset fonts dirs " ) ;
}
}
2002-02-18 23:29:28 +01:00
static FcExpr *
FcPopExpr ( FcConfigParse * parse )
2002-02-15 00:34:13 +01:00
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackPeek ( parse ) ;
2002-02-18 23:29:28 +01:00
FcExpr * expr = 0 ;
if ( ! vstack )
return 0 ;
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2002-02-18 23:29:28 +01:00
case FcVStackNone :
break ;
case FcVStackString :
case FcVStackFamily :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateString ( parse - > config , vstack - > u . string ) ;
2002-02-22 19:54:07 +01:00
break ;
2012-12-30 05:58:38 +01:00
case FcVStackName :
expr = FcExprCreateName ( parse - > config , vstack - > u . name ) ;
2002-02-22 19:54:07 +01:00
break ;
2002-02-18 23:29:28 +01:00
case FcVStackConstant :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateConst ( parse - > config , vstack - > u . string ) ;
2002-02-18 23:29:28 +01:00
break ;
2003-08-15 21:45:20 +02:00
case FcVStackGlob :
/* XXX: What's the correct action here? (CDW) */
break ;
2002-02-18 23:29:28 +01:00
case FcVStackPrefer :
case FcVStackAccept :
case FcVStackDefault :
expr = vstack - > u . expr ;
vstack - > tag = FcVStackNone ;
break ;
case FcVStackInteger :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateInteger ( parse - > config , vstack - > u . integer ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcVStackDouble :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateDouble ( parse - > config , vstack - > u . _double ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcVStackMatrix :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateMatrix ( parse - > config , vstack - > u . matrix ) ;
2002-02-18 23:29:28 +01:00
break ;
2010-12-06 04:10:17 +01:00
case FcVStackRange :
2013-11-20 10:44:59 +01:00
expr = FcExprCreateRange ( parse - > config , vstack - > u . range ) ;
2010-12-06 04:10:17 +01:00
break ;
2002-02-18 23:29:28 +01:00
case FcVStackBool :
2009-06-06 04:32:31 +02:00
expr = FcExprCreateBool ( parse - > config , vstack - > u . bool_ ) ;
2002-02-18 23:29:28 +01:00
break ;
2010-12-06 04:10:17 +01:00
case FcVStackCharSet :
expr = FcExprCreateCharSet ( parse - > config , vstack - > u . charset ) ;
break ;
2010-12-06 04:38:18 +01:00
case FcVStackLangSet :
expr = FcExprCreateLangSet ( parse - > config , vstack - > u . langset ) ;
break ;
2002-02-18 23:29:28 +01:00
case FcVStackTest :
break ;
case FcVStackExpr :
expr = vstack - > u . expr ;
2002-06-02 21:51:36 +02:00
vstack - > tag = FcVStackNone ;
2002-02-18 23:29:28 +01:00
break ;
case FcVStackEdit :
break ;
2004-12-04 20:41:10 +01:00
default :
break ;
2002-02-18 23:29:28 +01:00
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2002-02-18 23:29:28 +01:00
return expr ;
}
2003-04-16 01:38:06 +02:00
/*
* This builds a tree of binary operations . Note
* that every operator is defined so that if only
* a single operand is contained , the value of the
* whole expression is the value of the operand .
*
* This code reduces in that case to returning that
* operand .
*/
2002-02-18 23:29:28 +01:00
static FcExpr *
2003-04-16 01:38:06 +02:00
FcPopBinary ( FcConfigParse * parse , FcOp op )
2002-02-18 23:29:28 +01:00
{
FcExpr * left , * expr = 0 , * new ;
2002-02-15 00:34:13 +01:00
2002-02-18 23:29:28 +01:00
while ( ( left = FcPopExpr ( parse ) ) )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
if ( expr )
2002-02-15 00:34:13 +01:00
{
2009-06-06 04:32:31 +02:00
new = FcExprCreateOp ( parse - > config , left , op , expr ) ;
2002-02-18 23:29:28 +01:00
if ( ! new )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
FcExprDestroy ( left ) ;
FcExprDestroy ( expr ) ;
2006-04-11 18:54:24 +02:00
return 0 ;
2002-02-18 23:29:28 +01:00
}
expr = new ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
else
expr = left ;
}
return expr ;
}
static void
2003-04-16 01:38:06 +02:00
FcParseBinary ( FcConfigParse * parse , FcOp op )
{
FcExpr * expr = FcPopBinary ( parse , op ) ;
if ( expr )
FcVStackPushExpr ( parse , FcVStackExpr , expr ) ;
}
/*
* This builds a a unary operator , it consumes only
* a single operand
*/
static FcExpr *
FcPopUnary ( FcConfigParse * parse , FcOp op )
{
FcExpr * operand , * new = 0 ;
if ( ( operand = FcPopExpr ( parse ) ) )
{
2009-06-06 04:32:31 +02:00
new = FcExprCreateOp ( parse - > config , operand , op , 0 ) ;
2003-04-16 01:38:06 +02:00
if ( ! new )
{
FcExprDestroy ( operand ) ;
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
}
}
return new ;
}
static void
FcParseUnary ( FcConfigParse * parse , FcOp op )
2002-02-18 23:29:28 +01:00
{
2003-04-16 01:38:06 +02:00
FcExpr * expr = FcPopUnary ( parse , op ) ;
2002-02-18 23:29:28 +01:00
if ( expr )
FcVStackPushExpr ( parse , FcVStackExpr , expr ) ;
}
2012-03-12 11:18:19 +01:00
static void
FcParseDir ( FcConfigParse * parse )
{
2019-01-31 11:17:47 +01:00
const FcChar8 * attr , * data , * salt ;
2019-01-28 10:59:29 +01:00
FcChar8 * prefix = NULL ;
2012-03-12 11:18:19 +01:00
2018-10-02 11:32:03 +02:00
data = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2012-03-12 11:18:19 +01:00
if ( ! data )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2019-01-28 10:59:29 +01:00
return ;
2018-10-02 11:32:03 +02:00
}
2019-04-02 11:37:49 +02:00
if ( data [ 0 ] = = 0 )
{
FcConfigMessage ( parse , FcSevereWarning , " empty font directory name ignored " ) ;
return ;
}
2019-01-28 10:59:29 +01:00
attr = FcConfigGetAttribute ( parse , " prefix " ) ;
2019-01-31 11:17:47 +01:00
salt = FcConfigGetAttribute ( parse , " salt " ) ;
2019-01-28 10:59:29 +01:00
prefix = _get_real_path_from_prefix ( parse , data , attr ) ;
if ( ! prefix | | prefix [ 0 ] = = 0 )
2019-04-02 11:37:49 +02:00
{
/* nop */
}
2019-01-28 10:59:29 +01:00
else if ( ! parse - > scanOnly & & ( ! FcStrUsesHome ( prefix ) | | FcConfigHome ( ) ) )
2012-03-12 11:18:19 +01:00
{
2019-01-31 11:17:47 +01:00
if ( ! FcConfigAddFontDir ( parse - > config , prefix , NULL , salt ) )
2019-01-28 10:59:29 +01:00
FcConfigMessage ( parse , FcSevereError , " out of memory; cannot add directory %s " , prefix ) ;
2012-03-12 11:18:19 +01:00
}
FcStrBufDestroy ( & parse - > pstack - > str ) ;
if ( prefix )
2012-06-01 12:06:17 +02:00
FcStrFree ( prefix ) ;
2012-03-12 11:18:19 +01:00
}
static void
FcParseCacheDir ( FcConfigParse * parse )
{
const FcChar8 * attr ;
2014-06-30 05:37:36 +02:00
FcChar8 * prefix = NULL , * p , * data = NULL ;
2012-03-12 11:18:19 +01:00
attr = FcConfigGetAttribute ( parse , " prefix " ) ;
if ( attr & & FcStrCmp ( attr , ( const FcChar8 * ) " xdg " ) = = 0 )
2014-06-30 05:37:36 +02:00
{
2012-03-12 11:18:19 +01:00
prefix = FcConfigXdgCacheHome ( ) ;
2014-06-30 05:37:36 +02:00
/* home directory might be disabled.
* simply ignore this element .
*/
if ( ! prefix )
goto bail ;
}
2012-03-12 11:18:19 +01:00
data = FcStrBufDone ( & parse - > pstack - > str ) ;
if ( ! data )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2018-07-19 06:29:01 +02:00
data = prefix ;
2012-03-12 11:18:19 +01:00
goto bail ;
}
2019-10-08 12:35:10 +02:00
if ( data [ 0 ] = = 0 )
{
FcConfigMessage ( parse , FcSevereWarning , " empty cache directory name ignored " ) ;
return ;
}
2012-03-12 11:18:19 +01:00
if ( prefix )
{
size_t plen = strlen ( ( const char * ) prefix ) ;
size_t dlen = strlen ( ( const char * ) data ) ;
2012-12-07 11:09:36 +01:00
p = realloc ( prefix , plen + 1 + dlen + 1 ) ;
if ( ! p )
2012-03-12 11:18:19 +01:00
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2018-07-19 06:29:01 +02:00
FcStrFree ( prefix ) ;
2012-03-12 11:18:19 +01:00
goto bail ;
}
2012-12-07 11:09:36 +01:00
prefix = p ;
2012-03-12 11:18:19 +01:00
prefix [ plen ] = FC_DIR_SEPARATOR ;
memcpy ( & prefix [ plen + 1 ] , data , dlen ) ;
prefix [ plen + 1 + dlen ] = 0 ;
FcStrFree ( data ) ;
data = prefix ;
}
# ifdef _WIN32
2015-04-08 10:41:25 +02:00
else if ( data [ 0 ] = = ' / ' & & fontconfig_instprefix [ 0 ] ! = ' \0 ' )
{
size_t plen = strlen ( ( const char * ) fontconfig_instprefix ) ;
size_t dlen = strlen ( ( const char * ) data ) ;
prefix = malloc ( plen + 1 + dlen + 1 ) ;
if ( ! prefix )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
goto bail ;
}
strcpy ( ( char * ) prefix , ( char * ) fontconfig_instprefix ) ;
prefix [ plen ] = FC_DIR_SEPARATOR ;
memcpy ( & prefix [ plen + 1 ] , data , dlen ) ;
prefix [ plen + 1 + dlen ] = 0 ;
FcStrFree ( data ) ;
data = prefix ;
}
else if ( strcmp ( ( const char * ) data , " WINDOWSTEMPDIR_FONTCONFIG_CACHE " ) = = 0 )
2012-03-12 11:18:19 +01:00
{
int rc ;
2018-07-19 06:29:01 +02:00
2012-03-12 11:18:19 +01:00
FcStrFree ( data ) ;
data = malloc ( 1000 ) ;
if ( ! data )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
goto bail ;
}
2012-06-13 13:01:30 +02:00
rc = GetTempPath ( 800 , ( LPSTR ) data ) ;
2012-03-12 11:18:19 +01:00
if ( rc = = 0 | | rc > 800 )
{
FcConfigMessage ( parse , FcSevereError , " GetTempPath failed " ) ;
goto bail ;
}
2012-06-13 13:01:30 +02:00
if ( data [ strlen ( ( const char * ) data ) - 1 ] ! = ' \\ ' )
2013-01-03 00:35:56 +01:00
strcat ( ( char * ) data , " \\ " ) ;
strcat ( ( char * ) data , " fontconfig \\ cache " ) ;
2012-03-12 11:18:19 +01:00
}
2012-06-13 13:01:30 +02:00
else if ( strcmp ( ( const char * ) data , " LOCAL_APPDATA_FONTCONFIG_CACHE " ) = = 0 )
2012-03-12 11:18:19 +01:00
{
char szFPath [ MAX_PATH + 1 ] ;
size_t len ;
if ( ! ( pSHGetFolderPathA & & SUCCEEDED ( pSHGetFolderPathA ( NULL , /* CSIDL_LOCAL_APPDATA */ 28 , NULL , 0 , szFPath ) ) ) )
{
FcConfigMessage ( parse , FcSevereError , " SHGetFolderPathA failed " ) ;
goto bail ;
}
strncat ( szFPath , " \\ fontconfig \\ cache " , MAX_PATH - 1 - strlen ( szFPath ) ) ;
len = strlen ( szFPath ) + 1 ;
FcStrFree ( data ) ;
data = malloc ( len ) ;
if ( ! data )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
goto bail ;
}
2012-06-13 13:01:30 +02:00
strncpy ( ( char * ) data , szFPath , len ) ;
2012-03-12 11:18:19 +01:00
}
# endif
if ( strlen ( ( char * ) data ) = = 0 )
FcConfigMessage ( parse , FcSevereWarning , " empty cache directory name ignored " ) ;
2018-01-23 14:27:17 +01:00
else if ( ! parse - > scanOnly & & ( ! FcStrUsesHome ( data ) | | FcConfigHome ( ) ) )
2012-03-12 11:18:19 +01:00
{
if ( ! FcConfigAddCacheDir ( parse - > config , data ) )
FcConfigMessage ( parse , FcSevereError , " out of memory; cannot add cache directory %s " , data ) ;
}
FcStrBufDestroy ( & parse - > pstack - > str ) ;
bail :
if ( data )
FcStrFree ( data ) ;
}
2015-05-22 09:53:34 +02:00
void
FcConfigPathFini ( void )
{
FcChar8 * s ;
retry_dir :
s = fc_atomic_ptr_get ( & __fc_userdir ) ;
if ( ! fc_atomic_ptr_cmpexch ( & __fc_userdir , s , NULL ) )
goto retry_dir ;
free ( s ) ;
retry_conf :
s = fc_atomic_ptr_get ( & __fc_userconf ) ;
if ( ! fc_atomic_ptr_cmpexch ( & __fc_userconf , s , NULL ) )
goto retry_conf ;
free ( s ) ;
}
2002-02-18 23:29:28 +01:00
static void
FcParseInclude ( FcConfigParse * parse )
{
FcChar8 * s ;
2012-03-12 11:18:19 +01:00
const FcChar8 * attr ;
2002-02-18 23:29:28 +01:00
FcBool ignore_missing = FcFalse ;
2015-02-24 07:01:14 +01:00
# ifndef _WIN32
2012-06-21 21:01:10 +02:00
FcBool deprecated = FcFalse ;
2015-02-24 07:01:14 +01:00
# endif
2012-12-07 11:09:36 +01:00
FcChar8 * prefix = NULL , * p ;
2015-05-22 13:45:05 +02:00
FcChar8 * userdir = NULL , * userconf = NULL ;
2018-01-03 14:15:11 +01:00
FcRuleSet * ruleset ;
FcMatchKind k ;
2010-04-12 18:10:05 +02:00
2009-03-11 19:07:15 +01:00
s = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! s )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2012-03-12 11:18:19 +01:00
goto bail ;
2002-02-18 23:29:28 +01:00
}
2012-03-12 11:18:19 +01:00
attr = FcConfigGetAttribute ( parse , " ignore_missing " ) ;
if ( attr & & FcConfigLexBool ( parse , ( FcChar8 * ) attr ) = = FcTrue )
2002-02-18 23:29:28 +01:00
ignore_missing = FcTrue ;
2012-06-21 21:01:10 +02:00
attr = FcConfigGetAttribute ( parse , " deprecated " ) ;
2015-03-25 04:10:48 +01:00
# ifndef _WIN32
2012-06-21 21:01:10 +02:00
if ( attr & & FcConfigLexBool ( parse , ( FcChar8 * ) attr ) = = FcTrue )
deprecated = FcTrue ;
2015-02-24 07:01:14 +01:00
# endif
2012-03-12 11:18:19 +01:00
attr = FcConfigGetAttribute ( parse , " prefix " ) ;
if ( attr & & FcStrCmp ( attr , ( const FcChar8 * ) " xdg " ) = = 0 )
2014-06-30 05:37:36 +02:00
{
2012-03-12 11:18:19 +01:00
prefix = FcConfigXdgConfigHome ( ) ;
2014-06-30 05:37:36 +02:00
/* home directory might be disabled.
* simply ignore this element .
*/
if ( ! prefix )
goto bail ;
}
2012-03-12 11:18:19 +01:00
if ( prefix )
{
size_t plen = strlen ( ( const char * ) prefix ) ;
size_t dlen = strlen ( ( const char * ) s ) ;
2015-05-22 09:53:34 +02:00
FcChar8 * u ;
2012-03-12 11:18:19 +01:00
2012-12-07 11:09:36 +01:00
p = realloc ( prefix , plen + 1 + dlen + 1 ) ;
if ( ! p )
2012-03-12 11:18:19 +01:00
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
goto bail ;
}
2012-12-07 11:09:36 +01:00
prefix = p ;
2012-03-12 11:18:19 +01:00
prefix [ plen ] = FC_DIR_SEPARATOR ;
memcpy ( & prefix [ plen + 1 ] , s , dlen ) ;
prefix [ plen + 1 + dlen ] = 0 ;
s = prefix ;
2013-08-07 04:57:19 +02:00
if ( FcFileIsDir ( s ) )
{
userdir :
2015-05-22 09:53:34 +02:00
userdir = fc_atomic_ptr_get ( & __fc_userdir ) ;
2013-08-07 04:57:19 +02:00
if ( ! userdir )
2015-05-22 09:53:34 +02:00
{
u = FcStrdup ( s ) ;
if ( ! fc_atomic_ptr_cmpexch ( & __fc_userdir , userdir , u ) )
{
free ( u ) ;
goto userdir ;
}
userdir = u ;
}
2013-08-07 04:57:19 +02:00
}
else if ( FcFileIsFile ( s ) )
{
userconf :
2015-05-22 09:53:34 +02:00
userconf = fc_atomic_ptr_get ( & __fc_userconf ) ;
2013-08-07 04:57:19 +02:00
if ( ! userconf )
2015-05-22 09:53:34 +02:00
{
u = FcStrdup ( s ) ;
if ( ! fc_atomic_ptr_cmpexch ( & __fc_userconf , userconf , u ) )
{
free ( u ) ;
goto userconf ;
}
userconf = u ;
}
2013-08-07 04:57:19 +02:00
}
else
{
/* No config dir nor file on the XDG directory spec compliant place
* so need to guess what it is supposed to be .
*/
if ( FcStrStr ( s , ( const FcChar8 * ) " conf.d " ) ! = NULL )
goto userdir ;
else
goto userconf ;
}
2012-03-12 11:18:19 +01:00
}
2018-01-03 14:15:11 +01:00
/* flush the ruleset into the queue */
ruleset = parse - > ruleset ;
parse - > ruleset = FcRuleSetCreate ( ruleset - > name ) ;
FcRuleSetEnable ( parse - > ruleset , ruleset - > enabled ) ;
FcRuleSetAddDescription ( parse - > ruleset , ruleset - > domain , ruleset - > description ) ;
for ( k = FcMatchKindBegin ; k < FcMatchKindEnd ; k + + )
{
FcPtrListIter iter ;
FcPtrListIterInit ( ruleset - > subst [ k ] , & iter ) ;
if ( FcPtrListIterIsValid ( ruleset - > subst [ k ] , & iter ) )
{
FcPtrListIterInitAtLast ( parse - > config - > subst [ k ] , & iter ) ;
FcRuleSetReference ( ruleset ) ;
FcPtrListIterAdd ( parse - > config - > subst [ k ] , & iter , ruleset ) ;
}
}
FcRuleSetDestroy ( ruleset ) ;
2018-01-23 14:27:17 +01:00
if ( ! _FcConfigParse ( parse - > config , s , ! ignore_missing , ! parse - > scanOnly ) )
2002-02-18 23:29:28 +01:00
parse - > error = FcTrue ;
2013-08-07 04:57:19 +02:00
# ifndef _WIN32
2012-03-12 11:18:19 +01:00
else
{
2012-06-21 21:01:10 +02:00
FcChar8 * filename ;
2013-08-07 04:57:19 +02:00
static FcBool warn_conf = FcFalse , warn_confd = FcFalse ;
2012-06-21 21:01:10 +02:00
2019-10-21 09:17:42 +02:00
filename = FcConfigGetFilename ( parse - > config , s ) ;
2012-12-05 10:13:25 +01:00
if ( deprecated = = FcTrue & &
filename ! = NULL & &
2015-05-22 13:46:54 +02:00
userdir ! = NULL & &
2012-12-05 10:13:25 +01:00
! FcFileIsLink ( filename ) )
{
2013-08-07 04:57:19 +02:00
if ( FcFileIsDir ( filename ) )
{
2013-09-02 13:51:46 +02:00
FcChar8 * parent = FcStrDirname ( userdir ) ;
if ( ! FcFileIsDir ( parent ) )
FcMakeDirectory ( parent ) ;
FcStrFree ( parent ) ;
2013-08-07 04:57:19 +02:00
if ( FcFileIsDir ( userdir ) | |
rename ( ( const char * ) filename , ( const char * ) userdir ) ! = 0 | |
symlink ( ( const char * ) userdir , ( const char * ) filename ) ! = 0 )
{
if ( ! warn_confd )
{
FcConfigMessage ( parse , FcSevereWarning , " reading configurations from %s is deprecated. please move it to %s manually " , s , userdir ) ;
warn_confd = FcTrue ;
}
}
}
else
{
2013-09-02 13:51:46 +02:00
FcChar8 * parent = FcStrDirname ( userconf ) ;
if ( ! FcFileIsDir ( parent ) )
FcMakeDirectory ( parent ) ;
FcStrFree ( parent ) ;
2013-08-07 04:57:19 +02:00
if ( FcFileIsFile ( userconf ) | |
rename ( ( const char * ) filename , ( const char * ) userconf ) ! = 0 | |
symlink ( ( const char * ) userconf , ( const char * ) filename ) ! = 0 )
{
if ( ! warn_conf )
{
FcConfigMessage ( parse , FcSevereWarning , " reading configurations from %s is deprecated. please move it to %s manually " , s , userconf ) ;
warn_conf = FcTrue ;
}
}
}
2012-06-21 21:01:10 +02:00
}
if ( filename )
FcStrFree ( filename ) ;
2012-03-12 11:18:19 +01:00
}
2013-08-07 04:57:19 +02:00
# endif
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2012-03-12 11:18:19 +01:00
bail :
if ( prefix )
2012-06-01 12:06:17 +02:00
FcStrFree ( prefix ) ;
2002-02-18 23:29:28 +01:00
}
typedef struct _FcOpMap {
2005-09-23 01:45:53 +02:00
char name [ 16 ] ;
2002-02-18 23:29:28 +01:00
FcOp op ;
} FcOpMap ;
static FcOp
FcConfigLexOp ( const FcChar8 * op , const FcOpMap * map , int nmap )
{
int i ;
for ( i = 0 ; i < nmap ; i + + )
2010-04-12 18:10:05 +02:00
if ( ! strcmp ( ( char * ) op , map [ i ] . name ) )
2002-02-18 23:29:28 +01:00
return map [ i ] . op ;
return FcOpInvalid ;
}
static const FcOpMap fcCompareOps [ ] = {
{ " eq " , FcOpEqual } ,
{ " not_eq " , FcOpNotEqual } ,
{ " less " , FcOpLess } ,
{ " less_eq " , FcOpLessEqual } ,
{ " more " , FcOpMore } ,
2002-08-22 20:53:22 +02:00
{ " more_eq " , FcOpMoreEqual } ,
{ " contains " , FcOpContains } ,
{ " not_contains " , FcOpNotContains }
2002-02-18 23:29:28 +01:00
} ;
2005-09-23 01:45:53 +02:00
# define NUM_COMPARE_OPS (int) (sizeof fcCompareOps / sizeof fcCompareOps[0])
2002-02-18 23:29:28 +01:00
static FcOp
FcConfigLexCompare ( const FcChar8 * compare )
{
return FcConfigLexOp ( compare , fcCompareOps , NUM_COMPARE_OPS ) ;
}
static void
FcParseTest ( FcConfigParse * parse )
{
2002-08-11 20:11:04 +02:00
const FcChar8 * kind_string ;
FcMatchKind kind ;
2002-02-18 23:29:28 +01:00
const FcChar8 * qual_string ;
FcQual qual ;
const FcChar8 * name ;
const FcChar8 * compare_string ;
FcOp compare ;
FcExpr * expr ;
FcTest * test ;
2012-04-11 12:52:35 +02:00
const FcChar8 * iblanks_string ;
int flags = 0 ;
2002-02-18 23:29:28 +01:00
2002-08-11 20:11:04 +02:00
kind_string = FcConfigGetAttribute ( parse , " target " ) ;
if ( ! kind_string )
kind = FcMatchDefault ;
else
{
if ( ! strcmp ( ( char * ) kind_string , " pattern " ) )
kind = FcMatchPattern ;
else if ( ! strcmp ( ( char * ) kind_string , " font " ) )
kind = FcMatchFont ;
2006-09-03 02:52:12 +02:00
else if ( ! strcmp ( ( char * ) kind_string , " scan " ) )
kind = FcMatchScan ;
2002-08-11 20:11:04 +02:00
else if ( ! strcmp ( ( char * ) kind_string , " default " ) )
kind = FcMatchDefault ;
else
{
FcConfigMessage ( parse , FcSevereWarning , " invalid test target \" %s \" " , kind_string ) ;
return ;
}
}
2002-02-18 23:29:28 +01:00
qual_string = FcConfigGetAttribute ( parse , " qual " ) ;
if ( ! qual_string )
qual = FcQualAny ;
else
{
if ( ! strcmp ( ( char * ) qual_string , " any " ) )
qual = FcQualAny ;
else if ( ! strcmp ( ( char * ) qual_string , " all " ) )
qual = FcQualAll ;
2002-06-19 22:08:22 +02:00
else if ( ! strcmp ( ( char * ) qual_string , " first " ) )
qual = FcQualFirst ;
else if ( ! strcmp ( ( char * ) qual_string , " not_first " ) )
qual = FcQualNotFirst ;
2002-02-18 23:29:28 +01:00
else
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " invalid test qual \" %s \" " , qual_string ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
}
name = FcConfigGetAttribute ( parse , " name " ) ;
if ( ! name )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " missing test name " ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-18 23:29:28 +01:00
}
compare_string = FcConfigGetAttribute ( parse , " compare " ) ;
if ( ! compare_string )
compare = FcOpEqual ;
else
{
compare = FcConfigLexCompare ( compare_string ) ;
if ( compare = = FcOpInvalid )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " invalid test compare \" %s \" " , compare_string ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
}
2012-04-11 12:52:35 +02:00
iblanks_string = FcConfigGetAttribute ( parse , " ignore-blanks " ) ;
if ( iblanks_string )
{
FcBool f = FcFalse ;
if ( ! FcNameBool ( iblanks_string , & f ) )
{
FcConfigMessage ( parse ,
FcSevereWarning ,
" invalid test ignore-blanks \" %s \" " , iblanks_string ) ;
}
if ( f )
flags | = FcOpFlagIgnoreBlanks ;
}
2003-04-16 01:38:06 +02:00
expr = FcPopBinary ( parse , FcOpComma ) ;
2002-02-18 23:29:28 +01:00
if ( ! expr )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " missing test expression " ) ;
2002-02-18 23:29:28 +01:00
return ;
}
2012-05-21 06:43:20 +02:00
if ( expr - > op = = FcOpComma )
{
2012-08-16 13:33:12 +02:00
FcConfigMessage ( parse , FcSevereWarning , " Having multiple values in <test> isn't supported and may not work as expected " ) ;
2012-05-21 06:43:20 +02:00
}
2012-04-11 12:52:35 +02:00
test = FcTestCreate ( parse , kind , qual , name , FC_OP ( compare , flags ) , expr ) ;
2002-02-18 23:29:28 +01:00
if ( ! test )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
return ;
}
FcVStackPushTest ( parse , test ) ;
}
static const FcOpMap fcModeOps [ ] = {
{ " assign " , FcOpAssign } ,
{ " assign_replace " , FcOpAssignReplace } ,
{ " prepend " , FcOpPrepend } ,
{ " prepend_first " , FcOpPrependFirst } ,
{ " append " , FcOpAppend } ,
{ " append_last " , FcOpAppendLast } ,
2013-01-29 12:19:36 +01:00
{ " delete " , FcOpDelete } ,
{ " delete_all " , FcOpDeleteAll } ,
2002-02-18 23:29:28 +01:00
} ;
2005-09-23 01:45:53 +02:00
# define NUM_MODE_OPS (int) (sizeof fcModeOps / sizeof fcModeOps[0])
2002-02-18 23:29:28 +01:00
static FcOp
FcConfigLexMode ( const FcChar8 * mode )
{
return FcConfigLexOp ( mode , fcModeOps , NUM_MODE_OPS ) ;
}
static void
FcParseEdit ( FcConfigParse * parse )
{
const FcChar8 * name ;
const FcChar8 * mode_string ;
FcOp mode ;
2002-07-31 03:36:37 +02:00
FcValueBinding binding ;
2002-02-18 23:29:28 +01:00
FcExpr * expr ;
FcEdit * edit ;
name = FcConfigGetAttribute ( parse , " name " ) ;
if ( ! name )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " missing edit name " ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-18 23:29:28 +01:00
}
mode_string = FcConfigGetAttribute ( parse , " mode " ) ;
if ( ! mode_string )
2002-06-02 21:51:36 +02:00
mode = FcOpAssign ;
2002-02-18 23:29:28 +01:00
else
{
mode = FcConfigLexMode ( mode_string ) ;
if ( mode = = FcOpInvalid )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " invalid edit mode \" %s \" " , mode_string ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
}
2007-10-26 07:30:49 +02:00
if ( ! FcConfigLexBinding ( parse , FcConfigGetAttribute ( parse , " binding " ) , & binding ) )
return ;
2003-04-16 01:38:06 +02:00
expr = FcPopBinary ( parse , FcOpComma ) ;
2013-01-29 12:19:36 +01:00
if ( ( mode = = FcOpDelete | | mode = = FcOpDeleteAll ) & &
expr ! = NULL )
{
FcConfigMessage ( parse , FcSevereWarning , " Expression doesn't take any effects for delete and delete_all " ) ;
FcExprDestroy ( expr ) ;
expr = NULL ;
}
2006-08-31 06:59:53 +02:00
edit = FcEditCreate ( parse , FcObjectFromName ( ( char * ) name ) ,
mode , expr , binding ) ;
2002-02-18 23:29:28 +01:00
if ( ! edit )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
FcExprDestroy ( expr ) ;
return ;
}
if ( ! FcVStackPushEdit ( parse , edit ) )
FcEditDestroy ( edit ) ;
}
static void
FcParseMatch ( FcConfigParse * parse )
{
const FcChar8 * kind_name ;
FcMatchKind kind ;
FcVStack * vstack ;
2013-07-04 12:51:03 +02:00
FcRule * rule = NULL , * r ;
2014-03-27 07:10:44 +01:00
int n ;
2002-02-18 23:29:28 +01:00
kind_name = FcConfigGetAttribute ( parse , " target " ) ;
if ( ! kind_name )
kind = FcMatchPattern ;
else
{
if ( ! strcmp ( ( char * ) kind_name , " pattern " ) )
kind = FcMatchPattern ;
else if ( ! strcmp ( ( char * ) kind_name , " font " ) )
kind = FcMatchFont ;
2006-09-03 02:52:12 +02:00
else if ( ! strcmp ( ( char * ) kind_name , " scan " ) )
kind = FcMatchScan ;
2002-02-18 23:29:28 +01:00
else
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " invalid match target \" %s \" " , kind_name ) ;
2002-07-12 21:19:16 +02:00
return ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
}
2009-03-12 17:22:37 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
2002-02-18 23:29:28 +01:00
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2002-02-18 23:29:28 +01:00
case FcVStackTest :
2013-07-04 12:51:03 +02:00
r = FcRuleCreate ( FcRuleTest , vstack - > u . test ) ;
if ( rule )
r - > next = rule ;
rule = r ;
2002-02-18 23:29:28 +01:00
vstack - > tag = FcVStackNone ;
break ;
case FcVStackEdit :
2013-07-04 12:51:03 +02:00
if ( kind = = FcMatchScan & & vstack - > u . edit - > object > FC_MAX_BASE_OBJECT )
2006-12-02 22:57:45 +01:00
{
2010-04-12 18:10:05 +02:00
FcConfigMessage ( parse , FcSevereError ,
2006-12-02 22:57:45 +01:00
" <match target= \" scan \" > cannot edit user-defined object \" %s \" " ,
2013-08-23 12:58:43 +02:00
FcObjectName ( vstack - > u . edit - > object ) ) ;
if ( rule )
FcRuleDestroy ( rule ) ;
return ;
2006-12-02 22:57:45 +01:00
}
2013-07-04 12:51:03 +02:00
r = FcRuleCreate ( FcRuleEdit , vstack - > u . edit ) ;
if ( rule )
r - > next = rule ;
rule = r ;
vstack - > tag = FcVStackNone ;
2002-02-18 23:29:28 +01:00
break ;
default :
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereWarning , " invalid match element " ) ;
2002-02-18 23:29:28 +01:00
break ;
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2002-02-18 23:29:28 +01:00
}
2013-01-24 11:48:48 +01:00
if ( ! rule )
{
FcConfigMessage ( parse , FcSevereWarning , " No <test> nor <edit> elements in <match> " ) ;
return ;
}
2014-03-27 07:10:44 +01:00
if ( ( n = FcRuleSetAdd ( parse - > ruleset , rule , kind ) ) = = - 1 )
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2014-03-27 07:10:44 +01:00
FcRuleDestroy ( rule ) ;
}
else
if ( parse - > config - > maxObjects < n )
parse - > config - > maxObjects = n ;
2002-02-18 23:29:28 +01:00
}
2003-05-07 18:13:24 +02:00
static void
FcParseAcceptRejectFont ( FcConfigParse * parse , FcElement element )
{
FcVStack * vstack ;
2009-03-12 17:22:37 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
2003-05-07 18:13:24 +02:00
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2003-05-07 18:13:24 +02:00
case FcVStackGlob :
2018-01-23 14:27:17 +01:00
if ( ! parse - > scanOnly & & ! FcConfigGlobAdd ( parse - > config ,
vstack - > u . string ,
element = = FcElementAcceptfont ) )
2003-05-07 18:13:24 +02:00
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
}
2018-05-25 06:51:10 +02:00
else
{
if ( parse - > scanOnly & & vstack - > u . string )
2018-05-25 08:20:10 +02:00
{
2018-05-25 06:51:10 +02:00
FcStrFree ( vstack - > u . string ) ;
2018-05-25 08:20:10 +02:00
vstack - > tag = FcVStackNone ;
}
2018-05-25 06:51:10 +02:00
}
2003-05-07 18:13:24 +02:00
break ;
2004-12-04 20:41:10 +01:00
case FcVStackPattern :
2018-01-23 14:27:17 +01:00
if ( ! parse - > scanOnly & & ! FcConfigPatternsAdd ( parse - > config ,
vstack - > u . pattern ,
element = = FcElementAcceptfont ) )
2004-12-04 20:41:10 +01:00
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
}
else
2018-05-25 06:51:10 +02:00
{
if ( parse - > scanOnly & & vstack - > u . pattern )
FcPatternDestroy ( vstack - > u . pattern ) ;
2004-12-04 20:41:10 +01:00
vstack - > tag = FcVStackNone ;
2018-05-25 06:51:10 +02:00
}
2004-12-04 20:41:10 +01:00
break ;
2003-05-07 18:13:24 +02:00
default :
FcConfigMessage ( parse , FcSevereWarning , " bad font selector " ) ;
break ;
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2003-05-07 18:13:24 +02:00
}
}
2004-12-04 20:41:10 +01:00
static FcValue
FcPopValue ( FcConfigParse * parse )
{
2009-03-12 17:22:37 +01:00
FcVStack * vstack = FcVStackPeek ( parse ) ;
2004-12-04 20:41:10 +01:00
FcValue value ;
2010-04-12 18:10:05 +02:00
2004-12-04 20:41:10 +01:00
value . type = FcTypeVoid ;
2010-04-12 18:10:05 +02:00
2004-12-04 20:41:10 +01:00
if ( ! vstack )
return value ;
2010-04-12 18:10:05 +02:00
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2004-12-04 20:41:10 +01:00
case FcVStackString :
2013-01-02 09:06:15 +01:00
value . u . s = FcStrdup ( vstack - > u . string ) ;
2005-08-24 08:21:30 +02:00
if ( value . u . s )
2004-12-04 20:41:10 +01:00
value . type = FcTypeString ;
break ;
case FcVStackConstant :
if ( FcNameConstant ( vstack - > u . string , & value . u . i ) )
value . type = FcTypeInteger ;
break ;
case FcVStackInteger :
value . u . i = vstack - > u . integer ;
value . type = FcTypeInteger ;
break ;
case FcVStackDouble :
value . u . d = vstack - > u . _double ;
2012-12-30 02:14:07 +01:00
value . type = FcTypeDouble ;
2004-12-04 20:41:10 +01:00
break ;
case FcVStackBool :
2008-12-28 09:23:58 +01:00
value . u . b = vstack - > u . bool_ ;
2004-12-04 20:41:10 +01:00
value . type = FcTypeBool ;
break ;
2010-12-06 04:10:17 +01:00
case FcVStackCharSet :
value . u . c = FcCharSetCopy ( vstack - > u . charset ) ;
if ( value . u . c )
value . type = FcTypeCharSet ;
break ;
2010-12-06 04:38:18 +01:00
case FcVStackLangSet :
value . u . l = FcLangSetCopy ( vstack - > u . langset ) ;
if ( value . u . l )
value . type = FcTypeLangSet ;
break ;
2013-11-20 10:44:59 +01:00
case FcVStackRange :
value . u . r = FcRangeCopy ( vstack - > u . range ) ;
if ( value . u . r )
value . type = FcTypeRange ;
break ;
2004-12-04 20:41:10 +01:00
default :
2010-04-12 18:10:05 +02:00
FcConfigMessage ( parse , FcSevereWarning , " unknown pattern element %d " ,
2004-12-04 20:41:10 +01:00
vstack - > tag ) ;
break ;
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2010-04-12 18:10:05 +02:00
2004-12-04 20:41:10 +01:00
return value ;
}
static void
FcParsePatelt ( FcConfigParse * parse )
{
FcValue value ;
FcPattern * pattern = FcPatternCreate ( ) ;
const char * name ;
if ( ! pattern )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
return ;
}
2005-09-11 04:16:09 +02:00
name = ( char * ) FcConfigGetAttribute ( parse , " name " ) ;
2004-12-04 20:41:10 +01:00
if ( ! name )
{
FcConfigMessage ( parse , FcSevereWarning , " missing pattern element name " ) ;
2006-04-11 18:54:24 +02:00
FcPatternDestroy ( pattern ) ;
2004-12-04 20:41:10 +01:00
return ;
}
2010-04-12 18:10:05 +02:00
2004-12-04 20:41:10 +01:00
for ( ; ; )
{
value = FcPopValue ( parse ) ;
if ( value . type = = FcTypeVoid )
break ;
if ( ! FcPatternAdd ( pattern , name , value , FcTrue ) )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2008-09-23 00:16:30 +02:00
FcValueDestroy ( value ) ;
2004-12-04 20:41:10 +01:00
break ;
}
2008-09-23 00:16:30 +02:00
FcValueDestroy ( value ) ;
2004-12-04 20:41:10 +01:00
}
2006-04-27 09:54:07 +02:00
FcVStackPushPattern ( parse , pattern ) ;
2004-12-04 20:41:10 +01:00
}
static void
FcParsePattern ( FcConfigParse * parse )
{
FcVStack * vstack ;
FcPattern * pattern = FcPatternCreate ( ) ;
if ( ! pattern )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
return ;
}
2009-03-12 17:22:37 +01:00
while ( ( vstack = FcVStackPeek ( parse ) ) )
2004-12-04 20:41:10 +01:00
{
2012-12-30 04:11:09 +01:00
switch ( ( int ) vstack - > tag ) {
2004-12-04 20:41:10 +01:00
case FcVStackPattern :
if ( ! FcPatternAppend ( pattern , vstack - > u . pattern ) )
{
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2006-04-11 18:54:24 +02:00
FcPatternDestroy ( pattern ) ;
2004-12-04 20:41:10 +01:00
return ;
}
break ;
default :
FcConfigMessage ( parse , FcSevereWarning , " unknown pattern element " ) ;
break ;
}
2009-03-12 17:22:37 +01:00
FcVStackPopAndDestroy ( parse ) ;
2004-12-04 20:41:10 +01:00
}
FcVStackPushPattern ( parse , pattern ) ;
}
2002-02-18 23:29:28 +01:00
static void
2012-12-30 04:32:56 +01:00
FcEndElement ( void * userData , const XML_Char * name FC_UNUSED )
2002-02-18 23:29:28 +01:00
{
FcConfigParse * parse = userData ;
FcChar8 * data ;
2009-08-13 23:08:17 +02:00
2002-02-18 23:29:28 +01:00
if ( ! parse - > pstack )
return ;
switch ( parse - > pstack - > element ) {
case FcElementNone :
break ;
case FcElementFontconfig :
break ;
case FcElementDir :
2012-03-12 11:18:19 +01:00
FcParseDir ( parse ) ;
2002-02-18 23:29:28 +01:00
break ;
2006-08-04 18:13:00 +02:00
case FcElementCacheDir :
2012-03-12 11:18:19 +01:00
FcParseCacheDir ( parse ) ;
2006-08-04 18:13:00 +02:00
break ;
2002-02-18 23:29:28 +01:00
case FcElementCache :
2009-03-11 19:07:15 +01:00
data = FcStrBufDoneStatic ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
if ( ! data )
2002-02-15 00:34:13 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-15 00:34:13 +01:00
break ;
2002-02-18 23:29:28 +01:00
}
2006-08-31 06:59:53 +02:00
/* discard this data; no longer used */
2009-03-11 19:07:15 +01:00
FcStrBufDestroy ( & parse - > pstack - > str ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementInclude :
FcParseInclude ( parse ) ;
break ;
case FcElementConfig :
break ;
case FcElementMatch :
FcParseMatch ( parse ) ;
break ;
case FcElementAlias :
FcParseAlias ( parse ) ;
break ;
2014-03-27 07:10:44 +01:00
case FcElementDescription :
FcParseDescription ( parse ) ;
break ;
2019-01-28 10:59:29 +01:00
case FcElementRemapDir :
FcParseRemapDir ( parse ) ;
break ;
2019-01-31 08:52:09 +01:00
case FcElementResetDirs :
FcParseResetDirs ( parse ) ;
break ;
2002-02-18 23:29:28 +01:00
2002-05-21 19:06:22 +02:00
case FcElementRescan :
FcParseRescan ( parse ) ;
break ;
2002-02-18 23:29:28 +01:00
case FcElementPrefer :
FcParseFamilies ( parse , FcVStackPrefer ) ;
break ;
case FcElementAccept :
FcParseFamilies ( parse , FcVStackAccept ) ;
break ;
case FcElementDefault :
FcParseFamilies ( parse , FcVStackDefault ) ;
break ;
case FcElementFamily :
FcParseFamily ( parse ) ;
break ;
case FcElementTest :
FcParseTest ( parse ) ;
break ;
case FcElementEdit :
FcParseEdit ( parse ) ;
break ;
case FcElementInt :
FcParseInt ( parse ) ;
break ;
case FcElementDouble :
FcParseDouble ( parse ) ;
break ;
case FcElementString :
FcParseString ( parse , FcVStackString ) ;
break ;
case FcElementMatrix :
FcParseMatrix ( parse ) ;
break ;
2010-12-06 04:10:17 +01:00
case FcElementRange :
FcParseRange ( parse ) ;
break ;
2002-02-18 23:29:28 +01:00
case FcElementBool :
FcParseBool ( parse ) ;
break ;
2010-12-06 04:10:17 +01:00
case FcElementCharSet :
FcParseCharSet ( parse ) ;
2002-02-18 23:29:28 +01:00
break ;
2010-12-06 04:38:18 +01:00
case FcElementLangSet :
FcParseLangSet ( parse ) ;
break ;
2003-05-07 18:13:24 +02:00
case FcElementSelectfont :
break ;
case FcElementAcceptfont :
case FcElementRejectfont :
FcParseAcceptRejectFont ( parse , parse - > pstack - > element ) ;
break ;
case FcElementGlob :
FcParseString ( parse , FcVStackGlob ) ;
break ;
2004-12-04 20:41:10 +01:00
case FcElementPattern :
FcParsePattern ( parse ) ;
break ;
case FcElementPatelt :
FcParsePatelt ( parse ) ;
break ;
2002-02-18 23:29:28 +01:00
case FcElementName :
2012-12-30 05:58:38 +01:00
FcParseName ( parse ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementConst :
FcParseString ( parse , FcVStackConstant ) ;
break ;
case FcElementOr :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpOr ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementAnd :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpAnd ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementEq :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpEqual ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementNotEq :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpNotEqual ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementLess :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpLess ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementLessEq :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpLessEqual ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementMore :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpMore ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementMoreEq :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpMoreEqual ) ;
2002-02-18 23:29:28 +01:00
break ;
2002-08-22 20:53:22 +02:00
case FcElementContains :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpContains ) ;
2002-08-22 20:53:22 +02:00
break ;
case FcElementNotContains :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpNotContains ) ;
2002-08-22 20:53:22 +02:00
break ;
2002-02-18 23:29:28 +01:00
case FcElementPlus :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpPlus ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementMinus :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpMinus ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementTimes :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpTimes ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementDivide :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpDivide ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementNot :
2003-04-16 01:38:06 +02:00
FcParseUnary ( parse , FcOpNot ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementIf :
2003-04-16 01:38:06 +02:00
FcParseBinary ( parse , FcOpQuest ) ;
break ;
case FcElementFloor :
FcParseUnary ( parse , FcOpFloor ) ;
break ;
case FcElementCeil :
FcParseUnary ( parse , FcOpCeil ) ;
break ;
case FcElementRound :
FcParseUnary ( parse , FcOpRound ) ;
break ;
case FcElementTrunc :
FcParseUnary ( parse , FcOpTrunc ) ;
2002-02-18 23:29:28 +01:00
break ;
case FcElementUnknown :
break ;
2002-02-15 00:34:13 +01:00
}
2002-02-18 23:29:28 +01:00
( void ) FcPStackPop ( parse ) ;
}
static void
FcCharacterData ( void * userData , const XML_Char * s , int len )
{
FcConfigParse * parse = userData ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
if ( ! parse - > pstack )
return ;
if ( ! FcStrBufData ( & parse - > pstack - > str , ( FcChar8 * ) s , len ) )
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " out of memory " ) ;
2002-02-18 23:29:28 +01:00
}
static void
FcStartDoctypeDecl ( void * userData ,
const XML_Char * doctypeName ,
2012-12-30 04:32:56 +01:00
const XML_Char * sysid FC_UNUSED ,
const XML_Char * pubid FC_UNUSED ,
int has_internal_subset FC_UNUSED )
2002-02-18 23:29:28 +01:00
{
FcConfigParse * parse = userData ;
if ( strcmp ( ( char * ) doctypeName , " fontconfig " ) ! = 0 )
2002-05-21 19:06:22 +02:00
FcConfigMessage ( parse , FcSevereError , " invalid doctype \" %s \" " , doctypeName ) ;
2002-02-18 23:29:28 +01:00
}
2006-04-06 06:33:11 +02:00
# ifdef ENABLE_LIBXML2
2005-09-29 22:53:30 +02:00
static void
FcInternalSubsetDecl ( void * userData ,
const XML_Char * doctypeName ,
const XML_Char * sysid ,
const XML_Char * pubid )
{
FcStartDoctypeDecl ( userData , doctypeName , sysid , pubid , 1 ) ;
}
static void
FcExternalSubsetDecl ( void * userData ,
const XML_Char * doctypeName ,
const XML_Char * sysid ,
const XML_Char * pubid )
{
FcStartDoctypeDecl ( userData , doctypeName , sysid , pubid , 0 ) ;
}
# else /* ENABLE_LIBXML2 */
2002-02-18 23:29:28 +01:00
static void
2012-12-30 04:32:56 +01:00
FcEndDoctypeDecl ( void * userData FC_UNUSED )
2002-02-18 23:29:28 +01:00
{
2002-02-15 00:34:13 +01:00
}
2005-09-29 22:53:30 +02:00
# endif /* ENABLE_LIBXML2 */
2006-09-10 06:21:01 +02:00
static int
FcSortCmpStr ( const void * a , const void * b )
{
const FcChar8 * as = * ( ( FcChar8 * * ) a ) ;
const FcChar8 * bs = * ( ( FcChar8 * * ) b ) ;
return FcStrCmp ( as , bs ) ;
}
2004-12-05 06:03:52 +01:00
static FcBool
FcConfigParseAndLoadDir ( FcConfig * config ,
const FcChar8 * name ,
const FcChar8 * dir ,
2014-03-27 07:10:44 +01:00
FcBool complain ,
FcBool load )
2004-12-05 06:03:52 +01:00
{
DIR * d ;
struct dirent * e ;
FcBool ret = FcTrue ;
FcChar8 * file ;
FcChar8 * base ;
FcStrSet * files ;
d = opendir ( ( char * ) dir ) ;
if ( ! d )
{
if ( complain )
FcConfigMessage ( 0 , FcSevereError , " Cannot open config dir \" %s \" " ,
name ) ;
ret = FcFalse ;
goto bail0 ;
}
/* freed below */
file = ( FcChar8 * ) malloc ( strlen ( ( char * ) dir ) + 1 + FC_MAX_FILE_LEN + 1 ) ;
if ( ! file )
{
ret = FcFalse ;
goto bail1 ;
}
2010-04-12 18:10:05 +02:00
2004-12-05 06:03:52 +01:00
strcpy ( ( char * ) file , ( char * ) dir ) ;
strcat ( ( char * ) file , " / " ) ;
base = file + strlen ( ( char * ) file ) ;
2010-04-12 18:10:05 +02:00
2016-01-09 03:06:31 +01:00
files = FcStrSetCreateEx ( FCSS_GROW_BY_64 ) ;
2004-12-05 06:03:52 +01:00
if ( ! files )
{
ret = FcFalse ;
goto bail2 ;
}
2010-04-12 18:10:05 +02:00
2004-12-05 06:03:52 +01:00
if ( FcDebug ( ) & FC_DBG_CONFIG )
printf ( " \t Scanning config dir %s \n " , dir ) ;
2018-02-05 04:47:01 +01:00
if ( load )
FcConfigAddConfigDir ( config , dir ) ;
2004-12-05 06:03:52 +01:00
while ( ret & & ( e = readdir ( d ) ) )
{
2005-09-11 04:16:09 +02:00
int d_len ;
# define TAIL ".conf"
# define TAIL_LEN 5
2004-12-05 06:03:52 +01:00
/*
2005-09-11 04:16:09 +02:00
* Add all files of the form [ 0 - 9 ] * . conf
2004-12-05 06:03:52 +01:00
*/
2018-11-12 06:01:50 +01:00
d_len = strlen ( e - > d_name ) ;
2004-12-05 06:03:52 +01:00
if ( ' 0 ' < = e - > d_name [ 0 ] & & e - > d_name [ 0 ] < = ' 9 ' & &
2005-09-11 04:16:09 +02:00
d_len > TAIL_LEN & &
strcmp ( e - > d_name + d_len - TAIL_LEN , TAIL ) = = 0 )
2004-12-05 06:03:52 +01:00
{
strcpy ( ( char * ) base , ( char * ) e - > d_name ) ;
if ( ! FcStrSetAdd ( files , file ) )
{
ret = FcFalse ;
goto bail3 ;
}
}
}
if ( ret )
{
int i ;
2010-04-12 18:10:05 +02:00
qsort ( files - > strs , files - > num , sizeof ( FcChar8 * ) ,
2006-09-10 06:21:01 +02:00
( int ( * ) ( const void * , const void * ) ) FcSortCmpStr ) ;
2004-12-05 06:03:52 +01:00
for ( i = 0 ; ret & & i < files - > num ; i + + )
2018-01-23 14:27:17 +01:00
ret = _FcConfigParse ( config , files - > strs [ i ] , complain , load ) ;
2004-12-05 06:03:52 +01:00
}
bail3 :
FcStrSetDestroy ( files ) ;
bail2 :
free ( file ) ;
bail1 :
closedir ( d ) ;
bail0 :
return ret | | ! complain ;
}
2012-04-12 07:01:25 +02:00
# ifdef _WIN32
pfnGetSystemWindowsDirectory pGetSystemWindowsDirectory = NULL ;
pfnSHGetFolderPathA pSHGetFolderPathA = NULL ;
# endif
2015-06-11 10:30:04 +02:00
static FcBool
FcConfigParseAndLoadFromMemoryInternal ( FcConfig * config ,
const FcChar8 * filename ,
const FcChar8 * buffer ,
2014-03-27 07:10:44 +01:00
FcBool complain ,
FcBool load )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
XML_Parser p ;
2015-06-11 10:30:04 +02:00
size_t len ;
2002-02-18 23:29:28 +01:00
FcConfigParse parse ;
FcBool error = FcTrue ;
2014-03-27 07:10:44 +01:00
FcMatchKind k ;
FcPtrListIter liter ;
2010-04-12 18:10:05 +02:00
2006-04-06 06:33:11 +02:00
# ifdef ENABLE_LIBXML2
2005-09-29 22:53:30 +02:00
xmlSAXHandler sax ;
# else
2017-07-11 08:34:50 +02:00
void * buf ;
2015-06-11 10:30:04 +02:00
const FcChar8 * s ;
size_t buflen ;
2012-04-12 07:01:25 +02:00
# endif
2015-06-11 10:30:04 +02:00
if ( ! buffer )
return FcFalse ;
len = strlen ( ( const char * ) buffer ) ;
2004-12-05 06:03:52 +01:00
if ( FcDebug ( ) & FC_DBG_CONFIG )
2017-11-16 03:37:36 +01:00
printf ( " \t %s config file from %s \n " , load ? " Loading " : " Scanning " , filename ) ;
2010-04-12 18:10:05 +02:00
2006-04-06 06:33:11 +02:00
# ifdef ENABLE_LIBXML2
2005-09-29 22:53:30 +02:00
memset ( & sax , 0 , sizeof ( sax ) ) ;
sax . internalSubset = FcInternalSubsetDecl ;
sax . externalSubset = FcExternalSubsetDecl ;
sax . startElement = FcStartElement ;
sax . endElement = FcEndElement ;
sax . characters = FcCharacterData ;
2005-11-18 21:32:30 +01:00
p = xmlCreatePushParserCtxt ( & sax , & parse , NULL , 0 , ( const char * ) filename ) ;
2005-09-29 22:53:30 +02:00
# else
2002-02-18 23:29:28 +01:00
p = XML_ParserCreate ( " UTF-8 " ) ;
2005-09-29 22:53:30 +02:00
# endif
2002-02-18 23:29:28 +01:00
if ( ! p )
goto bail1 ;
2014-03-27 07:10:44 +01:00
if ( ! FcConfigParseInit ( & parse , filename , config , p , load ) )
2002-02-18 23:29:28 +01:00
goto bail2 ;
2006-04-06 06:33:11 +02:00
# ifndef ENABLE_LIBXML2
2005-09-29 22:53:30 +02:00
2002-02-18 23:29:28 +01:00
XML_SetUserData ( p , & parse ) ;
2010-04-12 18:10:05 +02:00
2002-02-18 23:29:28 +01:00
XML_SetDoctypeDeclHandler ( p , FcStartDoctypeDecl , FcEndDoctypeDecl ) ;
XML_SetElementHandler ( p , FcStartElement , FcEndElement ) ;
XML_SetCharacterDataHandler ( p , FcCharacterData ) ;
2005-09-29 22:53:30 +02:00
# endif /* ENABLE_LIBXML2 */
2006-04-06 06:33:11 +02:00
# ifndef ENABLE_LIBXML2
2015-06-11 10:30:04 +02:00
s = buffer ;
do {
2002-02-18 23:29:28 +01:00
buf = XML_GetBuffer ( p , BUFSIZ ) ;
if ( ! buf )
2002-02-28 17:51:48 +01:00
{
2002-05-21 19:06:22 +02:00
FcConfigMessage ( & parse , FcSevereError , " cannot get parse buffer " ) ;
2002-02-18 23:29:28 +01:00
goto bail3 ;
2002-02-28 17:51:48 +01:00
}
2015-06-11 10:30:04 +02:00
if ( len > BUFSIZ )
2002-02-28 17:51:48 +01:00
{
2015-06-11 10:30:04 +02:00
buflen = BUFSIZ ;
len - = BUFSIZ ;
}
else
{
buflen = len ;
len = 0 ;
2002-02-28 17:51:48 +01:00
}
2015-06-11 10:30:04 +02:00
memcpy ( buf , s , buflen ) ;
s = s + buflen ;
# endif
2005-09-29 22:53:30 +02:00
2006-04-06 06:33:11 +02:00
# ifdef ENABLE_LIBXML2
2017-07-11 08:34:50 +02:00
if ( xmlParseChunk ( p , ( const char * ) buffer , len , len = = 0 ) )
2005-09-29 22:53:30 +02:00
# else
2015-06-11 10:30:04 +02:00
if ( ! XML_ParseBuffer ( p , buflen , buflen = = 0 ) )
2005-09-29 22:53:30 +02:00
# endif
2002-02-28 17:51:48 +01:00
{
2010-04-12 18:10:05 +02:00
FcConfigMessage ( & parse , FcSevereError , " %s " ,
2002-02-28 17:51:48 +01:00
XML_ErrorString ( XML_GetErrorCode ( p ) ) ) ;
2002-02-18 23:29:28 +01:00
goto bail3 ;
2002-02-28 17:51:48 +01:00
}
2015-06-11 10:30:04 +02:00
# ifndef ENABLE_LIBXML2
} while ( buflen ! = 0 ) ;
# endif
2002-02-18 23:29:28 +01:00
error = parse . error ;
2014-03-27 07:10:44 +01:00
if ( load )
{
for ( k = FcMatchKindBegin ; k < FcMatchKindEnd ; k + + )
{
FcPtrListIter iter ;
FcPtrListIterInit ( parse . ruleset - > subst [ k ] , & iter ) ;
if ( FcPtrListIterIsValid ( parse . ruleset - > subst [ k ] , & iter ) )
{
FcPtrListIterInitAtLast ( parse . config - > subst [ k ] , & iter ) ;
FcRuleSetReference ( parse . ruleset ) ;
FcPtrListIterAdd ( parse . config - > subst [ k ] , & iter , parse . ruleset ) ;
}
}
}
FcPtrListIterInitAtLast ( parse . config - > rulesetList , & liter ) ;
FcRuleSetReference ( parse . ruleset ) ;
FcPtrListIterAdd ( parse . config - > rulesetList , & liter , parse . ruleset ) ;
2002-02-18 23:29:28 +01:00
bail3 :
FcConfigCleanup ( & parse ) ;
bail2 :
XML_ParserFree ( p ) ;
bail1 :
2015-06-11 10:30:04 +02:00
if ( error & & complain )
{
2017-11-16 03:37:36 +01:00
FcConfigMessage ( 0 , FcSevereError , " Cannot %s config file from %s " , load ? " load " : " scan " , filename ) ;
2015-06-11 10:30:04 +02:00
return FcFalse ;
}
2018-01-03 14:15:11 +01:00
if ( FcDebug ( ) & FC_DBG_CONFIG )
printf ( " \t %s config file from %s done \n " , load ? " Loading " : " Scanning " , filename ) ;
2015-06-11 10:30:04 +02:00
return FcTrue ;
}
2014-03-27 07:10:44 +01:00
static FcBool
_FcConfigParse ( FcConfig * config ,
const FcChar8 * name ,
FcBool complain ,
FcBool load )
2015-06-11 10:30:04 +02:00
{
2014-03-27 07:10:44 +01:00
FcChar8 * filename = NULL , * realfilename = NULL ;
2015-06-11 10:30:04 +02:00
int fd ;
int len ;
FcStrBuf sbuf ;
char buf [ BUFSIZ ] ;
2019-08-28 10:46:03 +02:00
FcBool ret = FcFalse , complain_again = complain ;
2019-10-21 09:17:42 +02:00
FcStrBuf reason ;
2015-06-11 10:30:04 +02:00
2019-10-21 09:17:42 +02:00
FcStrBufInit ( & reason , NULL , 0 ) ;
2015-06-11 10:30:04 +02:00
# ifdef _WIN32
if ( ! pGetSystemWindowsDirectory )
{
HMODULE hk32 = GetModuleHandleA ( " kernel32.dll " ) ;
if ( ! ( pGetSystemWindowsDirectory = ( pfnGetSystemWindowsDirectory ) GetProcAddress ( hk32 , " GetSystemWindowsDirectoryA " ) ) )
pGetSystemWindowsDirectory = ( pfnGetSystemWindowsDirectory ) GetWindowsDirectory ;
}
if ( ! pSHGetFolderPathA )
{
HMODULE hSh = LoadLibraryA ( " shfolder.dll " ) ;
/* the check is done later, because there is no provided fallback */
if ( hSh )
pSHGetFolderPathA = ( pfnSHGetFolderPathA ) GetProcAddress ( hSh , " SHGetFolderPathA " ) ;
}
# endif
2019-10-21 09:17:42 +02:00
filename = FcConfigGetFilename ( config , name ) ;
2014-03-27 07:10:44 +01:00
if ( ! filename )
2019-10-21 09:17:42 +02:00
{
FcStrBufString ( & reason , ( FcChar8 * ) " No such file: " ) ;
FcStrBufString ( & reason , name ? name : ( FcChar8 * ) " (null) " ) ;
2015-06-11 10:30:04 +02:00
goto bail0 ;
2019-10-21 09:17:42 +02:00
}
2014-03-27 07:10:44 +01:00
realfilename = FcConfigRealFilename ( config , name ) ;
if ( ! realfilename )
2019-10-21 09:17:42 +02:00
{
FcStrBufString ( & reason , ( FcChar8 * ) " No such realfile: " ) ;
FcStrBufString ( & reason , name ? name : ( FcChar8 * ) " (null) " ) ;
2014-03-27 07:10:44 +01:00
goto bail0 ;
2019-10-21 09:17:42 +02:00
}
2014-03-27 07:10:44 +01:00
if ( FcStrSetMember ( config - > availConfigFiles , realfilename ) )
2015-06-11 10:30:04 +02:00
{
FcStrFree ( filename ) ;
2014-03-27 07:10:44 +01:00
FcStrFree ( realfilename ) ;
2015-06-11 10:30:04 +02:00
return FcTrue ;
}
2014-03-27 07:10:44 +01:00
if ( load )
2015-06-11 10:30:04 +02:00
{
2014-03-27 07:10:44 +01:00
if ( ! FcStrSetAdd ( config - > configFiles , filename ) )
goto bail0 ;
2015-06-11 10:30:04 +02:00
}
2014-03-27 07:10:44 +01:00
if ( ! FcStrSetAdd ( config - > availConfigFiles , realfilename ) )
goto bail0 ;
2015-06-11 10:30:04 +02:00
2014-03-27 07:10:44 +01:00
if ( FcFileIsDir ( realfilename ) )
2015-06-11 10:30:04 +02:00
{
2014-03-27 07:10:44 +01:00
ret = FcConfigParseAndLoadDir ( config , name , realfilename , complain , load ) ;
2015-06-11 10:30:04 +02:00
FcStrFree ( filename ) ;
2014-03-27 07:10:44 +01:00
FcStrFree ( realfilename ) ;
2015-06-11 10:30:04 +02:00
return ret ;
}
FcStrBufInit ( & sbuf , NULL , 0 ) ;
2018-04-12 02:24:43 +02:00
fd = FcOpen ( ( char * ) realfilename , O_RDONLY ) ;
2014-03-27 07:10:44 +01:00
if ( fd = = - 1 )
2019-10-21 09:17:42 +02:00
{
FcStrBufString ( & reason , ( FcChar8 * ) " Unable to open " ) ;
FcStrBufString ( & reason , realfilename ) ;
2015-06-11 10:30:04 +02:00
goto bail1 ;
2019-10-21 09:17:42 +02:00
}
2015-06-11 10:30:04 +02:00
do {
len = read ( fd , buf , BUFSIZ ) ;
if ( len < 0 )
{
2018-05-13 07:48:10 +02:00
int errno_ = errno ;
char ebuf [ BUFSIZ + 1 ] ;
# if HAVE_STRERROR_R
2018-07-26 01:35:54 +02:00
strerror_r ( errno_ , ebuf , BUFSIZ ) ;
2018-05-13 07:48:10 +02:00
# elif HAVE_STRERROR
char * tmp = strerror ( errno_ ) ;
size_t len = strlen ( tmp ) ;
strncpy ( ebuf , tmp , FC_MIN ( BUFSIZ , len ) ) ;
ebuf [ FC_MIN ( BUFSIZ , len ) ] = 0 ;
# else
ebuf [ 0 ] = 0 ;
# endif
FcConfigMessage ( 0 , FcSevereError , " failed reading config file: %s: %s (errno %d) " , realfilename , ebuf , errno_ ) ;
2015-06-11 10:30:04 +02:00
close ( fd ) ;
goto bail1 ;
}
FcStrBufData ( & sbuf , ( const FcChar8 * ) buf , len ) ;
} while ( len ! = 0 ) ;
2005-12-21 04:31:19 +01:00
close ( fd ) ;
2015-06-11 10:30:04 +02:00
2014-03-27 07:10:44 +01:00
ret = FcConfigParseAndLoadFromMemoryInternal ( config , filename , FcStrBufDoneStatic ( & sbuf ) , complain , load ) ;
2019-08-28 10:46:03 +02:00
complain_again = FcFalse ; /* no need to reclaim here */
2015-06-11 10:30:04 +02:00
bail1 :
FcStrBufDestroy ( & sbuf ) ;
2002-02-18 23:29:28 +01:00
bail0 :
2014-03-27 07:10:44 +01:00
if ( filename )
FcStrFree ( filename ) ;
if ( realfilename )
FcStrFree ( realfilename ) ;
2019-08-28 10:46:03 +02:00
if ( ! complain )
return FcTrue ;
if ( ! ret & & complain_again )
2002-02-15 00:34:13 +01:00
{
2002-02-18 23:29:28 +01:00
if ( name )
2019-10-21 09:17:42 +02:00
FcConfigMessage ( 0 , FcSevereError , " Cannot %s config file \" %s \" : %s " , load ? " load " : " scan " , name , FcStrBufDoneStatic ( & reason ) ) ;
2002-02-15 00:34:13 +01:00
else
2019-10-21 09:17:42 +02:00
FcConfigMessage ( 0 , FcSevereError , " Cannot %s default config file: %s " , load ? " load " : " scan " , FcStrBufDoneStatic ( & reason ) ) ;
FcStrBufDestroy ( & reason ) ;
2002-02-15 00:34:13 +01:00
return FcFalse ;
}
2019-10-21 09:17:42 +02:00
FcStrBufDestroy ( & reason ) ;
2019-07-22 07:35:21 +02:00
return ret ;
2002-02-15 00:34:13 +01:00
}
2014-03-27 07:10:44 +01:00
FcBool
FcConfigParseOnly ( FcConfig * config ,
const FcChar8 * name ,
FcBool complain )
{
return _FcConfigParse ( config , name , complain , FcFalse ) ;
}
FcBool
FcConfigParseAndLoad ( FcConfig * config ,
const FcChar8 * name ,
FcBool complain )
{
return _FcConfigParse ( config , name , complain , FcTrue ) ;
}
FcBool
FcConfigParseAndLoadFromMemory ( FcConfig * config ,
const FcChar8 * buffer ,
FcBool complain )
{
return FcConfigParseAndLoadFromMemoryInternal ( config , ( const FcChar8 * ) " memory " , buffer , complain , FcTrue ) ;
}
2006-09-05 11:24:01 +02:00
# define __fcxml__
# include "fcaliastail.h"
# undef __fcxml__