Added new FcFini function for cleaning up all memory. Fixed a few memory

leaks. fc-list now calls FcFini, (and is now leak-free according to
    valgrind)
This commit is contained in:
Carl Worth 2003-08-15 19:45:20 +00:00
parent 18906a876a
commit 34cd0514a2
15 changed files with 398 additions and 74 deletions

View File

@ -1,3 +1,47 @@
2003-08-15 Carl Worth <cworth@isi.edu>
* src/fcxml.c (FcEditDestroy): Fix leak of FcEdit.
(FcPopExpr): Add comment about unhandled FcVStackGlob case.
* src/fcpat.c (FcValueListEntDestroy): New function to support
FcFini memory cleanup. Some statistics are not kept in
synch. here.
(FcValueListFreeze): Move hashTable outside this function so it
can be accessed by FcValueListThawAll.
(FcValueListThawAll): New function complements FcValueListFreeze.
(FcPatternBaseFreeze): Move hashTable outside this function so it
can be accessed by FcPatternBaseThawAll.
(FcPatternBaseThawAll): New function complements
FcPatternBaseFreeze.
(FcPatternThawAll): New function complements FcPatternFreeze.
* src/fcinit.c (FcFini): Add new FcFini to cleanup everything.
* src/fccharset.c (FcCharLeafEntCreate): Save pointers to all
allocated FcCharLeafEnt "blocks" so they can be freed later.
(FcCharSetFreezeLeaf): Move hashTable outside this function so it
can be accessed by FcCharSetThawAllLeaf.
(FcCharSetThawAllLeaf): New function complements FcCharSetFreezeLeaf.
(FcCharSetFreezeBase): Move hashTable outside this function so it
can be accessed by FcCharSetThawAll.
(FcCharSetThawAll): New function complements FcCharSetFreeze.
* src/fccfg.c (FcSubstDestroy): Fix leak of outer FcSubst.
(FcConfigDestroy): Fic leak of FcBlanks.
* fc-list/fc-list.c (main): Fix leak of FcObjectSet.
(main): Add call to FcFini when finished.
* fc-glyphname/fc-glyphname.c: Mark several local functions as
static. Add prototypes.
* doc/fcinit.fncs: Add documentation for FcFini function.
* doc/edit-sgml.c: Mark several local functions as static. Add
prototypes.
* doc/Makefile.am (DOC_MODULE): Fix "suspicious" lines.
2003-06-15 Tor Lillqvist <tml@iki.fi> 2003-06-15 Tor Lillqvist <tml@iki.fi>
* test/run-test.sh (FONTCONFIG_FILE): Remove CRs from the out file * test/run-test.sh (FONTCONFIG_FILE): Remove CRs from the out file

View File

@ -60,7 +60,7 @@ FcConfigGetConfigDirs.3 FcConfigGetConfigFiles.3 FcConfigGetCurrent.3 \
FcConfigGetFontDirs.3 FcConfigGetFonts.3 FcConfigGetRescanInverval.3 \ FcConfigGetFontDirs.3 FcConfigGetFonts.3 FcConfigGetRescanInverval.3 \
FcConfigParseAndLoad.3 FcConfigSetCurrent.3 FcConfigSetRescanInverval.3 \ FcConfigParseAndLoad.3 FcConfigSetCurrent.3 FcConfigSetRescanInverval.3 \
FcConfigSubstitute.3 FcConfigSubstituteWithPat.3 FcConfigUptoDate.3 \ FcConfigSubstitute.3 FcConfigSubstituteWithPat.3 FcConfigUptoDate.3 \
FcDefaultSubstitute.3 FcDirCacheValid.3 FcDirSave.3 FcDirScan.3 FcFileScan.3 \ FcDefaultSubstitute.3 FcDirCacheValid.3 FcDirSave.3 FcDirScan.3 FcFini.3 FcFileScan.3 \
FcFontList.3 FcFontMatch.3 FcFontRenderPrepare.3 FcFontSetAdd.3 \ FcFontList.3 FcFontMatch.3 FcFontRenderPrepare.3 FcFontSetAdd.3 \
FcFontSetCreate.3 FcFontSetDestroy.3 FcFontSort.3 FcFreeTypeCharIndex.3 \ FcFontSetCreate.3 FcFontSetDestroy.3 FcFontSort.3 FcFreeTypeCharIndex.3 \
FcFreeTypeCharSet.3 FcFreeTypeQuery.3 FcGetVersion.3 FcInit.3 \ FcFreeTypeCharSet.3 FcFreeTypeQuery.3 FcGetVersion.3 FcInit.3 \
@ -89,7 +89,7 @@ DOC_FILES=$(TXT) $(HTML_FILES)
DOC_DIRS=$(HTML_DIRS) DOC_DIRS=$(HTML_DIRS)
LOCAL_DOCS=$(man_MANS) $(DOC_FILES) $(DOC_DIRS) LOCAL_DOCS=$(man_MANS) $(DOC_FILES) $(DOC_DIRS)
EXTRA_DIST = $(LOCAL_DOCS) $(SGML) $(DOC_FUNCS_FNCS) $(FNCS_TMPL) EXTRA_DIST=$(LOCAL_DOCS) $(SGML) $(DOC_FUNCS_FNCS) $(FNCS_TMPL)
SUFFIXES=.fncs .sgml .txt .html SUFFIXES=.fncs .sgml .txt .html

View File

@ -27,6 +27,15 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
static void *
New (int size);
static void *
Reallocate (void *p, int size);
static void
Dispose (void *p);
typedef enum { False, True } Bool; typedef enum { False, True } Bool;
typedef struct { typedef struct {
@ -35,9 +44,107 @@ typedef struct {
int len; int len;
} String; } String;
static String *
StringNew (void);
static void
StringAdd (String *s, char c);
static void
StringAddString (String *s, char *buf);
static String *
StringMake (char *buf);
static void
StringDel (String *s);
static void
StringPut (FILE *f, String *s);
static void
StringDispose (String *s);
typedef struct {
String *tag;
String *text;
} Replace;
static Replace *
ReplaceNew (void);
static void
ReplaceDispose (Replace *r);
static void
Bail (char *format, char *arg);
static Replace *
ReplaceRead (FILE *f);
typedef struct _replaceList {
struct _replaceList *next;
Replace *r;
} ReplaceList;
static ReplaceList *
ReplaceListNew (Replace *r, ReplaceList *next);
static void
ReplaceListDispose (ReplaceList *l);
typedef struct {
ReplaceList *head;
} ReplaceSet;
static ReplaceSet *
ReplaceSetNew (void);
static void
ReplaceSetDispose (ReplaceSet *s);
static void
ReplaceSetAdd (ReplaceSet *s, Replace *r);
static Replace *
ReplaceSetFind (ReplaceSet *s, char *tag);
static ReplaceSet *
ReplaceSetRead (FILE *f);
typedef struct _skipStack {
struct _skipStack *prev;
int skipping;
} SkipStack;
static SkipStack *
SkipStackPush (SkipStack *prev, int skipping);
static SkipStack *
SkipStackPop (SkipStack *prev);
typedef struct _loopStack {
struct _loopStack *prev;
String *tag;
String *extra;
long pos;
} LoopStack;
static LoopStack *
LoopStackPush (LoopStack *prev, FILE *f, char *tag);
static LoopStack *
LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f);
static void
LineSkip (FILE *f);
static void
DoReplace (FILE *f, ReplaceSet *s);
#define STRING_INIT 128 #define STRING_INIT 128
void * static void *
New (int size) New (int size)
{ {
void *m = malloc (size); void *m = malloc (size);
@ -46,7 +153,7 @@ New (int size)
return m; return m;
} }
void * static void *
Reallocate (void *p, int size) Reallocate (void *p, int size)
{ {
void *r = realloc (p, size); void *r = realloc (p, size);
@ -56,13 +163,13 @@ Reallocate (void *p, int size)
return r; return r;
} }
void static void
Dispose (void *p) Dispose (void *p)
{ {
free (p); free (p);
} }
String * static String *
StringNew (void) StringNew (void)
{ {
String *s; String *s;
@ -75,7 +182,7 @@ StringNew (void)
return s; return s;
} }
void static void
StringAdd (String *s, char c) StringAdd (String *s, char c)
{ {
if (s->len == s->size) if (s->len == s->size)
@ -84,14 +191,14 @@ StringAdd (String *s, char c)
s->buf[s->len] = '\0'; s->buf[s->len] = '\0';
} }
void static void
StringAddString (String *s, char *buf) StringAddString (String *s, char *buf)
{ {
while (*buf) while (*buf)
StringAdd (s, *buf++); StringAdd (s, *buf++);
} }
String * static String *
StringMake (char *buf) StringMake (char *buf)
{ {
String *s = StringNew (); String *s = StringNew ();
@ -99,14 +206,14 @@ StringMake (char *buf)
return s; return s;
} }
void static void
StringDel (String *s) StringDel (String *s)
{ {
if (s->len) if (s->len)
s->buf[--s->len] = '\0'; s->buf[--s->len] = '\0';
} }
void static void
StringPut (FILE *f, String *s) StringPut (FILE *f, String *s)
{ {
char *b = s->buf; char *b = s->buf;
@ -117,19 +224,14 @@ StringPut (FILE *f, String *s)
#define StringLast(s) ((s)->len ? (s)->buf[(s)->len - 1] : '\0') #define StringLast(s) ((s)->len ? (s)->buf[(s)->len - 1] : '\0')
void static void
StringDispose (String *s) StringDispose (String *s)
{ {
Dispose (s->buf); Dispose (s->buf);
Dispose (s); Dispose (s);
} }
typedef struct { static Replace *
String *tag;
String *text;
} Replace;
Replace *
ReplaceNew (void) ReplaceNew (void)
{ {
Replace *r = New (sizeof (Replace)); Replace *r = New (sizeof (Replace));
@ -138,7 +240,7 @@ ReplaceNew (void)
return r; return r;
} }
void static void
ReplaceDispose (Replace *r) ReplaceDispose (Replace *r)
{ {
StringDispose (r->tag); StringDispose (r->tag);
@ -146,7 +248,7 @@ ReplaceDispose (Replace *r)
Dispose (r); Dispose (r);
} }
void static void
Bail (char *format, char *arg) Bail (char *format, char *arg)
{ {
fprintf (stderr, "fatal: "); fprintf (stderr, "fatal: ");
@ -155,7 +257,7 @@ Bail (char *format, char *arg)
exit (1); exit (1);
} }
Replace * static Replace *
ReplaceRead (FILE *f) ReplaceRead (FILE *f)
{ {
int c; int c;
@ -195,12 +297,7 @@ ReplaceRead (FILE *f)
return r; return r;
} }
typedef struct _replaceList { static ReplaceList *
struct _replaceList *next;
Replace *r;
} ReplaceList;
ReplaceList *
ReplaceListNew (Replace *r, ReplaceList *next) ReplaceListNew (Replace *r, ReplaceList *next)
{ {
ReplaceList *l = New (sizeof (ReplaceList)); ReplaceList *l = New (sizeof (ReplaceList));
@ -209,7 +306,7 @@ ReplaceListNew (Replace *r, ReplaceList *next)
return l; return l;
} }
void static void
ReplaceListDispose (ReplaceList *l) ReplaceListDispose (ReplaceList *l)
{ {
if (l) if (l)
@ -220,11 +317,7 @@ ReplaceListDispose (ReplaceList *l)
} }
} }
typedef struct { static ReplaceSet *
ReplaceList *head;
} ReplaceSet;
ReplaceSet *
ReplaceSetNew (void) ReplaceSetNew (void)
{ {
ReplaceSet *s = New (sizeof (ReplaceSet)); ReplaceSet *s = New (sizeof (ReplaceSet));
@ -232,20 +325,20 @@ ReplaceSetNew (void)
return s; return s;
} }
void static void
ReplaceSetDispose (ReplaceSet *s) ReplaceSetDispose (ReplaceSet *s)
{ {
ReplaceListDispose (s->head); ReplaceListDispose (s->head);
Dispose (s); Dispose (s);
} }
void static void
ReplaceSetAdd (ReplaceSet *s, Replace *r) ReplaceSetAdd (ReplaceSet *s, Replace *r)
{ {
s->head = ReplaceListNew (r, s->head); s->head = ReplaceListNew (r, s->head);
} }
Replace * static Replace *
ReplaceSetFind (ReplaceSet *s, char *tag) ReplaceSetFind (ReplaceSet *s, char *tag)
{ {
ReplaceList *l; ReplaceList *l;
@ -256,7 +349,7 @@ ReplaceSetFind (ReplaceSet *s, char *tag)
return 0; return 0;
} }
ReplaceSet * static ReplaceSet *
ReplaceSetRead (FILE *f) ReplaceSetRead (FILE *f)
{ {
ReplaceSet *s = ReplaceSetNew (); ReplaceSet *s = ReplaceSetNew ();
@ -276,12 +369,7 @@ ReplaceSetRead (FILE *f)
return s; return s;
} }
typedef struct _skipStack { static SkipStack *
struct _skipStack *prev;
int skipping;
} SkipStack;
SkipStack *
SkipStackPush (SkipStack *prev, int skipping) SkipStackPush (SkipStack *prev, int skipping)
{ {
SkipStack *ss = New (sizeof (SkipStack)); SkipStack *ss = New (sizeof (SkipStack));
@ -290,7 +378,7 @@ SkipStackPush (SkipStack *prev, int skipping)
return ss; return ss;
} }
SkipStack * static SkipStack *
SkipStackPop (SkipStack *prev) SkipStackPop (SkipStack *prev)
{ {
SkipStack *ss = prev->prev; SkipStack *ss = prev->prev;
@ -298,14 +386,7 @@ SkipStackPop (SkipStack *prev)
return ss; return ss;
} }
typedef struct _loopStack { static LoopStack *
struct _loopStack *prev;
String *tag;
String *extra;
long pos;
} LoopStack;
LoopStack *
LoopStackPush (LoopStack *prev, FILE *f, char *tag) LoopStackPush (LoopStack *prev, FILE *f, char *tag)
{ {
LoopStack *ls = New (sizeof (LoopStack)); LoopStack *ls = New (sizeof (LoopStack));
@ -316,7 +397,7 @@ LoopStackPush (LoopStack *prev, FILE *f, char *tag)
return ls; return ls;
} }
LoopStack * static LoopStack *
LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f) LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f)
{ {
String *s = StringMake (ls->tag->buf); String *s = StringMake (ls->tag->buf);
@ -339,7 +420,7 @@ LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f)
return ret; return ret;
} }
void static void
LineSkip (FILE *f) LineSkip (FILE *f)
{ {
int c; int c;
@ -349,7 +430,7 @@ LineSkip (FILE *f)
ungetc (c, f); ungetc (c, f);
} }
void static void
DoReplace (FILE *f, ReplaceSet *s) DoReplace (FILE *f, ReplaceSet *s)
{ {
int c; int c;

View File

@ -50,6 +50,17 @@ process succeeded or not. If the default configuration has already
been loaded, this routine does nothing and returns FcTrue. been loaded, this routine does nothing and returns FcTrue.
@@ @@
@RET@ void
@FUNC@ FcFini
@TYPE1@ void
@PURPOSE@ finalize fonconfig library
@DESC@
Frees all data structures allocated by previous calls to fontconfig
functions. Fontconfig returns to an uninitialized state, requiring a
new call to one of the FcInit functions before any other fontconfig
function may be called.
@@
@RET@ int @RET@ int
@FUNC@ FcGetVersion @FUNC@ FcGetVersion
@TYPE1@ void @TYPE1@ void

View File

@ -24,6 +24,27 @@
#include "fcint.h" #include "fcint.h"
static int
rawindex (FcGlyphName *gn);
static void
scan (FILE *f, char *filename);
static int
isprime (int i);
static void
find_hash (void);
static FcChar32
FcHashGlyphName (const FcChar8 *name);
static void
insert (FcGlyphName *gn, FcGlyphName **table, FcChar32 h);
static void
dump (FcGlyphName **table, char *name);
static FcGlyphName * static FcGlyphName *
FcAllocGlyphName (FcChar32 ucs, FcChar8 *name) FcAllocGlyphName (FcChar32 ucs, FcChar8 *name)
{ {
@ -55,7 +76,7 @@ FcGlyphName *name_to_ucs[MAX_GLYPHNAME*2];
FcGlyphName *ucs_to_name[MAX_GLYPHNAME*2]; FcGlyphName *ucs_to_name[MAX_GLYPHNAME*2];
int hash, rehash; int hash, rehash;
int static int
rawindex (FcGlyphName *gn) rawindex (FcGlyphName *gn)
{ {
int i; int i;
@ -66,7 +87,7 @@ rawindex (FcGlyphName *gn)
return -1; return -1;
} }
void static void
scan (FILE *f, char *filename) scan (FILE *f, char *filename)
{ {
char buf[MAX_NAMELEN]; char buf[MAX_NAMELEN];
@ -122,7 +143,7 @@ isqrt (int a)
return h; return h;
} }
int static int
isprime (int i) isprime (int i)
{ {
int l, t; int l, t;
@ -146,7 +167,7 @@ isprime (int i)
* Find a prime pair that leaves at least 25% of the hash table empty * Find a prime pair that leaves at least 25% of the hash table empty
*/ */
void static void
find_hash (void) find_hash (void)
{ {
int h; int h;
@ -160,7 +181,7 @@ find_hash (void)
rehash = h-2; rehash = h-2;
} }
FcChar32 static FcChar32
FcHashGlyphName (const FcChar8 *name) FcHashGlyphName (const FcChar8 *name)
{ {
FcChar32 h = 0; FcChar32 h = 0;
@ -173,7 +194,7 @@ FcHashGlyphName (const FcChar8 *name)
return h; return h;
} }
void static void
insert (FcGlyphName *gn, FcGlyphName **table, FcChar32 h) insert (FcGlyphName *gn, FcGlyphName **table, FcChar32 h)
{ {
int i, r = 0; int i, r = 0;
@ -189,7 +210,7 @@ insert (FcGlyphName *gn, FcGlyphName **table, FcChar32 h)
table[i] = gn; table[i] = gn;
} }
void static void
dump (FcGlyphName **table, char *name) dump (FcGlyphName **table, char *name)
{ {
int i; int i;

View File

@ -137,6 +137,7 @@ main (int argc, char **argv)
if (!os) if (!os)
os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, (char *) 0); os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, (char *) 0);
fs = FcFontList (0, pat, os); fs = FcFontList (0, pat, os);
FcObjectSetDestroy (os);
if (pat) if (pat)
FcPatternDestroy (pat); FcPatternDestroy (pat);
@ -157,5 +158,8 @@ main (int argc, char **argv)
} }
FcFontSetDestroy (fs); FcFontSetDestroy (fs);
} }
FcFini ();
return 0; return 0;
} }

View File

@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#else #else
@ -91,7 +92,6 @@ main (int argc, char **argv)
int verbose = 0; int verbose = 0;
int sort = 0; int sort = 0;
int i; int i;
FcObjectSet *os = 0;
FcFontSet *fs; FcFontSet *fs;
FcPattern *pat; FcPattern *pat;
FcResult result; FcResult result;

View File

@ -452,6 +452,9 @@ FcInitLoadConfigAndFonts (void);
FcBool FcBool
FcInit (void); FcInit (void);
void
FcFini (void);
int int
FcGetVersion (void); FcGetVersion (void);

View File

@ -160,6 +160,8 @@ FcSubstDestroy (FcSubst *s)
FcTestDestroy (s->test); FcTestDestroy (s->test);
if (s->edit) if (s->edit)
FcEditDestroy (s->edit); FcEditDestroy (s->edit);
free (s);
FcMemFree (FC_MEM_SUBST, sizeof (FcSubst));
s = n; s = n;
} }
} }
@ -178,6 +180,9 @@ FcConfigDestroy (FcConfig *config)
FcStrSetDestroy (config->acceptGlobs); FcStrSetDestroy (config->acceptGlobs);
FcStrSetDestroy (config->rejectGlobs); FcStrSetDestroy (config->rejectGlobs);
if (config->blanks)
FcBlanksDestroy (config->blanks);
if (config->cache) if (config->cache)
FcStrFree (config->cache); FcStrFree (config->cache);
@ -186,6 +191,7 @@ FcConfigDestroy (FcConfig *config)
for (set = FcSetSystem; set <= FcSetApplication; set++) for (set = FcSetSystem; set <= FcSetApplication; set++)
if (config->fonts[set]) if (config->fonts[set])
FcFontSetDestroy (config->fonts[set]); FcFontSetDestroy (config->fonts[set]);
free (config); free (config);
FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig)); FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
} }

View File

@ -845,6 +845,8 @@ struct _FcCharLeafEnt {
}; };
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt)) #define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
static FcCharLeafEnt **FcCharLeafBlocks;
static int FcCharLeafBlockCount;
static FcCharLeafEnt * static FcCharLeafEnt *
FcCharLeafEntCreate (void) FcCharLeafEntCreate (void)
@ -854,7 +856,14 @@ FcCharLeafEntCreate (void)
if (!remain) if (!remain)
{ {
block = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt)); FcCharLeafEnt **newBlocks;
FcCharLeafBlockCount++;
newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
if (!newBlocks)
return 0;
FcCharLeafBlocks = newBlocks;
block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
if (!block) if (!block)
return 0; return 0;
FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt)); FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
@ -880,12 +889,13 @@ FcCharLeafHash (FcCharLeaf *leaf)
static int FcCharLeafTotal; static int FcCharLeafTotal;
static int FcCharLeafUsed; static int FcCharLeafUsed;
static FcCharLeafEnt *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
static FcCharLeaf * static FcCharLeaf *
FcCharSetFreezeLeaf (FcCharLeaf *leaf) FcCharSetFreezeLeaf (FcCharLeaf *leaf)
{ {
static FcCharLeafEnt *hashTable[FC_CHAR_LEAF_HASH_SIZE];
FcChar32 hash = FcCharLeafHash (leaf); FcChar32 hash = FcCharLeafHash (leaf);
FcCharLeafEnt **bucket = &hashTable[hash % FC_CHAR_LEAF_HASH_SIZE]; FcCharLeafEnt **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
FcCharLeafEnt *ent; FcCharLeafEnt *ent;
FcCharLeafTotal++; FcCharLeafTotal++;
@ -906,6 +916,25 @@ FcCharSetFreezeLeaf (FcCharLeaf *leaf)
return &ent->leaf; return &ent->leaf;
} }
static void
FcCharSetThawAllLeaf (void)
{
int i;
for (i = 0; i < FC_CHAR_LEAF_HASH_SIZE; i++)
FcCharLeafHashTable[i] = 0;
FcCharLeafTotal = 0;
FcCharLeafUsed = 0;
for (i = 0; i < FcCharLeafBlockCount; i++)
free (FcCharLeafBlocks[i]);
free (FcCharLeafBlocks);
FcCharLeafBlocks = 0;
FcCharLeafBlockCount = 0;
}
typedef struct _FcCharSetEnt FcCharSetEnt; typedef struct _FcCharSetEnt FcCharSetEnt;
struct _FcCharSetEnt { struct _FcCharSetEnt {
@ -937,12 +966,13 @@ static int FcCharSetTotal;
static int FcCharSetUsed; static int FcCharSetUsed;
static int FcCharSetTotalEnts, FcCharSetUsedEnts; static int FcCharSetTotalEnts, FcCharSetUsedEnts;
static FcCharSetEnt *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
static FcCharSet * static FcCharSet *
FcCharSetFreezeBase (FcCharSet *fcs) FcCharSetFreezeBase (FcCharSet *fcs)
{ {
static FcCharSetEnt *hashTable[FC_CHAR_SET_HASH_SIZE];
FcChar32 hash = FcCharSetHash (fcs); FcChar32 hash = FcCharSetHash (fcs);
FcCharSetEnt **bucket = &hashTable[hash % FC_CHAR_SET_HASH_SIZE]; FcCharSetEnt **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
FcCharSetEnt *ent; FcCharSetEnt *ent;
int size; int size;
@ -992,6 +1022,30 @@ FcCharSetFreezeBase (FcCharSet *fcs)
return &ent->set; return &ent->set;
} }
void
FcCharSetThawAll (void)
{
int i;
FcCharSetEnt *ent, *next;
for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
{
for (ent = FcCharSetHashTable[i]; ent; ent = next)
{
next = ent->next;
free (ent);
}
FcCharSetHashTable[i] = 0;
}
FcCharSetTotal = 0;
FcCharSetTotalEnts = 0;
FcCharSetUsed = 0;
FcCharSetUsedEnts = 0;
FcCharSetThawAllLeaf ();
}
FcCharSet * FcCharSet *
FcCharSetFreeze (FcCharSet *fcs) FcCharSetFreeze (FcCharSet *fcs)
{ {

View File

@ -107,6 +107,19 @@ FcInit (void)
return FcTrue; return FcTrue;
} }
/*
* Free all library-allocated data structures.
*/
void
FcFini (void)
{
if (_fcConfig)
FcConfigDestroy (_fcConfig);
FcPatternThawAll ();
FcCharSetThawAll ();
}
/* /*
* Reread the configuration and available font lists * Reread the configuration and available font lists
*/ */

View File

@ -469,6 +469,9 @@ FcConfigAcceptFilename (FcConfig *config,
FcCharSet * FcCharSet *
FcCharSetFreeze (FcCharSet *cs); FcCharSetFreeze (FcCharSet *cs);
void
FcCharSetThawAll (void);
FcBool FcBool
FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c); FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
@ -663,6 +666,9 @@ FcPatternAddWithBinding (FcPattern *p,
FcPattern * FcPattern *
FcPatternFreeze (FcPattern *p); FcPatternFreeze (FcPattern *p);
void
FcPatternThawAll (void);
/* fcrender.c */ /* fcrender.c */
/* fcmatrix.c */ /* fcmatrix.c */

View File

@ -366,15 +366,43 @@ FcValueListEntCreate (FcValueList *h)
return e; return e;
} }
static void
FcValueListEntDestroy (FcValueListEnt *e)
{
FcValueList *l;
FcValueListFrozenCount[e->list->value.type]--;
/* XXX: We should perform these two operations with "size" as
computed in FcValueListEntCreate, but we don't have access to
that value here. Without this, the FcValueListFrozenBytes
values will be wrong as will the FcMemFree counts.
FcValueListFrozenBytes[e->list->value.type] -= size;
FcMemFree (FC_MEM_VALLIST, size);
*/
for (l = e->list; l; l = l->next)
{
if (l->value.type != FcTypeString)
FcValueDestroy (l->value);
}
/* XXX: Are we being too chummy with the implementation here to
free(e) when it was actually the enclosing FcValueListAlign
that was allocated? */
free (e);
}
static int FcValueListTotal; static int FcValueListTotal;
static int FcValueListUsed; static int FcValueListUsed;
static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE];
static FcValueList * static FcValueList *
FcValueListFreeze (FcValueList *l) FcValueListFreeze (FcValueList *l)
{ {
static FcValueListEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
FcChar32 hash = FcValueListHash (l); FcChar32 hash = FcValueListHash (l);
FcValueListEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE]; FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
FcValueListEnt *ent; FcValueListEnt *ent;
FcValueListTotal++; FcValueListTotal++;
@ -395,6 +423,26 @@ FcValueListFreeze (FcValueList *l)
return ent->list; return ent->list;
} }
static void
FcValueListThawAll (void)
{
int i;
FcValueListEnt *ent, *next;
for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
{
for (ent = FcValueListHashTable[i]; ent; ent = next)
{
next = ent->next;
FcValueListEntDestroy (ent);
}
FcValueListHashTable[i] = 0;
}
FcValueListTotal = 0;
FcValueListUsed = 0;
}
static FcChar32 static FcChar32
FcPatternBaseHash (FcPattern *b) FcPatternBaseHash (FcPattern *b)
{ {
@ -417,12 +465,13 @@ struct _FcPatternEnt {
static int FcPatternTotal; static int FcPatternTotal;
static int FcPatternUsed; static int FcPatternUsed;
static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE];
static FcPattern * static FcPattern *
FcPatternBaseFreeze (FcPattern *b) FcPatternBaseFreeze (FcPattern *b)
{ {
static FcPatternEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
FcChar32 hash = FcPatternBaseHash (b); FcChar32 hash = FcPatternBaseHash (b);
FcPatternEnt **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE]; FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
FcPatternEnt *ent; FcPatternEnt *ent;
int i; int i;
char *objects; char *objects;
@ -481,6 +530,26 @@ FcPatternBaseFreeze (FcPattern *b)
return &ent->pattern; return &ent->pattern;
} }
static void
FcPatternBaseThawAll (void)
{
int i;
FcPatternEnt *ent, *next;
for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
{
for (ent = FcPatternHashTable[i]; ent; ent = next)
{
next = ent->next;
free (ent);
}
FcPatternHashTable[i] = 0;
}
FcPatternTotal = 0;
FcPatternUsed = 0;
}
FcPattern * FcPattern *
FcPatternFreeze (FcPattern *p) FcPatternFreeze (FcPattern *p)
{ {
@ -526,6 +595,13 @@ bail:
return n; return n;
} }
void
FcPatternThawAll (void)
{
FcPatternBaseThawAll ();
FcValueListThawAll ();
}
static int static int
FcPatternPosition (const FcPattern *p, const char *object) FcPatternPosition (const FcPattern *p, const char *object)
{ {

View File

@ -292,6 +292,7 @@ FcEditDestroy (FcEdit *e)
FcStrFree ((FcChar8 *) e->field); FcStrFree ((FcChar8 *) e->field);
if (e->expr) if (e->expr)
FcExprDestroy (e->expr); FcExprDestroy (e->expr);
free (e);
} }
char * char *
@ -1288,6 +1289,9 @@ FcPopExpr (FcConfigParse *parse)
case FcVStackConstant: case FcVStackConstant:
expr = FcExprCreateConst (vstack->u.string); expr = FcExprCreateConst (vstack->u.string);
break; break;
case FcVStackGlob:
/* XXX: What's the correct action here? (CDW) */
break;
case FcVStackPrefer: case FcVStackPrefer:
case FcVStackAccept: case FcVStackAccept:
case FcVStackDefault: case FcVStackDefault:

View File

@ -53,6 +53,7 @@ EXPORTS
FcDirSave FcDirSave
FcDirScan FcDirScan
FcFileScan FcFileScan
FcFini
FcFontList FcFontList
FcFontMatch FcFontMatch
FcFontRenderPrepare FcFontRenderPrepare