]> git.wh0rd.org - fontconfig.git/blobdiff - fc-cat/fc-cat.c
Bug 29995 - fc-cat does not invoke FcFini()
[fontconfig.git] / fc-cat / fc-cat.c
index 63407e1904c417bd353fc395dc6dafb9c304f180..d9a597cbd8ab9e641a085403e55159ae19e02040 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $RCSId: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.8tsi Exp $
+ * fontconfig/fc-cat/fc-cat.c
  *
  * Copyright © 2002 Keith Packard
  *
@@ -13,9 +13,9 @@
  * representations about the suitability of this software for any purpose.  It
  * is provided "as is" without express or implied warranty.
  *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  * 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
 #define HAVE_GETOPT 1
 #endif
 
-#include "../src/fccache.c"
+#include <fontconfig/fontconfig.h>
+#include "../fc-arch/fcarch.h"
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -53,7 +55,8 @@
 const struct option longopts[] = {
     {"version", 0, 0, 'V'},
     {"verbose", 0, 0, 'v'},
-    {"help", 0, 0, '?'},
+    {"recurse", 0, 0, 'r'},
+    {"help", 0, 0, 'h'},
     {NULL,0,0,0},
 };
 #else
@@ -78,11 +81,8 @@ extern int optind, opterr, optopt;
 #define PUTC(c,f) putc(c,f)
 #endif
 
-FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name);
-
 static FcBool
-FcCacheWriteChars (FILE *f, const FcChar8 *chars)
+write_chars (FILE *f, const FcChar8 *chars)
 {
     FcChar8    c;
     while ((c = *chars++))
@@ -102,7 +102,7 @@ FcCacheWriteChars (FILE *f, const FcChar8 *chars)
 }
 
 static FcBool
-FcCacheWriteUlong (FILE *f, unsigned long t)
+write_ulong (FILE *f, unsigned long t)
 {
     int            pow;
     unsigned long   temp, digit;
@@ -127,18 +127,18 @@ FcCacheWriteUlong (FILE *f, unsigned long t)
 }
 
 static FcBool
-FcCacheWriteInt (FILE *f, int i)
+write_int (FILE *f, int i)
 {
-    return FcCacheWriteUlong (f, (unsigned long) i);
+    return write_ulong (f, (unsigned long) i);
 }
 
 static FcBool
-FcCacheWriteStringOld (FILE *f, const FcChar8 *string)
+write_string (FILE *f, const FcChar8 *string)
 {
 
     if (PUTC ('"', f) == EOF)
        return FcFalse;
-    if (!FcCacheWriteChars (f, string))
+    if (!write_chars (f, string))
        return FcFalse;
     if (PUTC ('"', f) == EOF)
        return FcFalse;
@@ -146,43 +146,33 @@ FcCacheWriteStringOld (FILE *f, const FcChar8 *string)
 }
 
 static void
-usage (char *program)
+usage (char *program, int error)
 {
+    FILE *file = error ? stderr : stdout;
 #if HAVE_GETOPT_LONG
-    fprintf (stderr, "usage: %s [-V?] [--version] [--help] <fonts.cache-2>\n",
-            program);
+    fprintf (file, "usage: %s [-rv] [--recurse] [--verbose] [*-%s.cache-2|directory]...\n",
+            program, FC_ARCHITECTURE);
+    fprintf (file, "       %s [-Vh] [--version] [--help]\n", program);
 #else
-    fprintf (stderr, "usage: %s [-fsvV?] <fonts.cache-2>\n",
-            program);
+    fprintf (file, "usage: %s [-rvVh] [*-%s.cache-2|directory]...\n",
+            program, FC_ARCHITECTURE);
 #endif
-    fprintf (stderr, "Reads font information caches in <fonts.cache-2>\n");
-    fprintf (stderr, "\n");
+    fprintf (file, "Reads font information cache from:\n");
+    fprintf (file, " 1) specified fontconfig cache file\n");
+    fprintf (file, " 2) related to a particular font directory\n");
+    fprintf (file, "\n");
 #if HAVE_GETOPT_LONG
-    fprintf (stderr, "  -V, --version        display font config version and exit\n");
-    fprintf (stderr, "  -?, --help           display this help and exit\n");
+    fprintf (file, "  -r, --recurse        recurse into subdirectories\n");
+    fprintf (file, "  -v, --verbose        be verbose\n");
+    fprintf (file, "  -V, --version        display font config version and exit\n");
+    fprintf (file, "  -h, --help           display this help and exit\n");
 #else
-    fprintf (stderr, "  -V         (version) display font config version and exit\n");
-    fprintf (stderr, "  -?         (help)    display this help and exit\n");
+    fprintf (file, "  -r         (recurse) recurse into subdirectories\n");
+    fprintf (file, "  -v         (verbose) be verbose\n");
+    fprintf (file, "  -V         (version) display font config version and exit\n");
+    fprintf (file, "  -h         (help)    display this help and exit\n");
 #endif
-    exit (1);
-}
-
-static int
-FcCacheFileOpen (char *cache_file, off_t *size)
-{
-    int fd;
-    struct stat file_stat;
-
-    fd = open(cache_file, O_RDONLY | O_BINARY);
-    if (fd < 0)
-        return -1;
-
-    if (fstat (fd, &file_stat) < 0) {
-       close (fd); 
-       return -1;
-    }
-    *size = file_stat.st_size;
-    return fd;
+    exit (error);
 }
 
 /*
@@ -190,25 +180,26 @@ FcCacheFileOpen (char *cache_file, off_t *size)
  */
 
 static const FcChar8 *
-FcFileBaseName (const char *cache, const FcChar8 *file)
+file_base_name (const FcChar8 *cache, const FcChar8 *file)
 {
-    const FcChar8   *cache_slash;
-    int                    cache_len = strlen (cache);
+    int                    cache_len = strlen ((char *) cache);
 
-    if (!strncmp (cache, file, cache_len) && file[cache_len] == '/')
+    if (!strncmp ((char *) cache, (char *) file, cache_len) && file[cache_len] == '/')
        return file + cache_len + 1;
     return file;
 }
 
-FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name)
+#define FC_FONT_FILE_DIR       ((FcChar8 *) ".dir")
+
+static FcBool
+cache_print_set (FcFontSet *set, FcStrSet *dirs, const FcChar8 *base_name, FcBool verbose)
 {
-    FcPattern      *font;
     FcChar8        *name, *dir;
     const FcChar8   *file, *base;
     int                    ret;
     int                    n;
     int                    id;
+    int                    ndir = 0;
     FcStrList      *list;
 
     list = FcStrListCreate (dirs);
@@ -217,50 +208,51 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name)
     
     while ((dir = FcStrListNext (list)))
     {
-       base = FcFileBaseName (base_name, dir);
-       if (!FcCacheWriteStringOld (stdout, base))
+       base = file_base_name (base_name, dir);
+       if (!write_string (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteInt (stdout, 0))
+       if (!write_int (stdout, 0))
            goto bail3;
         if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteStringOld (stdout, FC_FONT_FILE_DIR))
+       if (!write_string (stdout, FC_FONT_FILE_DIR))
            goto bail3;
        if (PUTC ('\n', stdout) == EOF)
            goto bail3;
+       ndir++;
     }
     
     for (n = 0; n < set->nfont; n++)
     {
-       FcPattern   **fonts = FcFontSetFonts (set);
-       FcPattern   *encoded_font = fonts[n];
-       FcPattern   *font = FcEncodedOffsetToPtr (set, encoded_font, FcPattern);
+       FcPattern   *font = set->fonts[n];
 
        if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
            goto bail3;
-       base = FcFileBaseName (base_name, file);
+       base = file_base_name (base_name, file);
        if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
            goto bail3;
-       if (!FcCacheWriteStringOld (stdout, base))
+       if (!write_string (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
            goto bail3;
-       if (!FcCacheWriteInt (stdout, id))
+       if (!write_int (stdout, id))
            goto bail3;
         if (PUTC (' ', stdout) == EOF)
            goto bail3;
        name = FcNameUnparse (font);
        if (!name)
            goto bail3;
-       ret = FcCacheWriteStringOld (stdout, name);
+       ret = write_string (stdout, name);
        FcStrFree (name);
        if (!ret)
            goto bail3;
        if (PUTC ('\n', stdout) == EOF)
            goto bail3;
     }
+    if (verbose && !set->nfont && !ndir)
+       printf ("<empty>\n");
     
     FcStrListDone (list);
 
@@ -272,28 +264,6 @@ bail2:
     return FcFalse;
 }
 
-FcCache *
-FcCacheFileMap (const FcChar8 *file)
-{
-    FcCache *cache;
-    int            fd;
-    struct stat file_stat;
-
-    fd = open (file, O_RDONLY | O_BINARY);
-    if (fd < 0)
-       return NULL;
-    if (fstat (fd, &file_stat) < 0) {
-       close (fd);
-       return NULL;
-    }
-    if (FcCacheLoad (fd, file_stat.st_size, &cache)) {
-       close (fd);
-       return cache;
-    }
-    close (fd);
-    return NULL;
-}
-
 int
 main (int argc, char **argv)
 {
@@ -301,16 +271,21 @@ main (int argc, char **argv)
     int                ret = 0;
     FcFontSet  *fs;
     FcStrSet    *dirs;
+    FcStrSet   *args = NULL;
+    FcStrList  *arglist;
     FcCache    *cache;
     FcConfig   *config;
+    FcChar8    *arg;
     int                verbose = 0;
+    int                recurse = 0;
+    FcBool     first = FcTrue;
 #if HAVE_GETOPT_LONG || HAVE_GETOPT
     int                c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "Vvrh", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "Vv?")) != -1)
+    while ((c = getopt (argc, argv, "Vvrh")) != -1)
 #endif
     {
        switch (c) {
@@ -321,8 +296,13 @@ main (int argc, char **argv)
        case 'v':
            verbose++;
            break;
+       case 'r':
+           recurse++;
+           break;
+       case 'h':
+           usage (argv[0], 0);
        default:
-           usage (argv[0]);
+           usage (argv[0], 1);
        }
     }
     i = optind;
@@ -338,42 +318,92 @@ main (int argc, char **argv)
     }
     FcConfigSetCurrent (config);
     
-    if (i >= argc)
-        usage (argv[0]);
+    args = FcStrSetCreate ();
+    if (!args)
+    {
+       fprintf (stderr, "%s: malloc failure\n", argv[0]);
+       return 1;
+    }
+    if (i < argc)
+    {
+       for (; i < argc; i++)
+       {
+           if (!FcStrSetAddFilename (args, (const FcChar8 *) argv[i]))
+           {
+               fprintf (stderr, "%s: malloc failure\n", argv[0]);
+               return 1;
+           }
+       }
+       arglist = FcStrListCreate (args);
+       if (!arglist)
+       {
+           fprintf (stderr, "%s: malloc failure\n", argv[0]);
+           return 1;
+       }
+    }
+    else
+    {
+       recurse++;
+       arglist = FcConfigGetFontDirs (config);
+       while ((arg = FcStrListNext (arglist)))
+           if (!FcStrSetAdd (args, arg))
+           {
+               fprintf (stderr, "%s: malloc failure\n", argv[0]);
+               return 1;
+           }
+       FcStrListDone (arglist);
+    }
+    arglist = FcStrListCreate (args);
+    if (!arglist)
+    {
+       fprintf (stderr, "%s: malloc failure\n", argv[0]);
+       return 1;
+    }
 
-    for (; i < argc; i++)
+    while ((arg = FcStrListNext (arglist)))
     {
-       int     j;
-       off_t   size;
-       intptr_t        *cache_dirs;
+       int         j;
+       FcChar8     *cache_file = NULL;
+       struct stat file_stat;
        
-       if (FcFileIsDir ((const FcChar8 *)argv[i]))
-           cache = FcDirCacheMap ((const FcChar8 *) argv[i], config);
+       if (FcFileIsDir (arg))
+           cache = FcDirCacheLoad (arg, config, &cache_file);
        else
-           cache = FcCacheFileMap (argv[i]);
+           cache = FcDirCacheLoadFile (arg, &file_stat);
        if (!cache)
        {
-           perror (argv[i]);
+           perror ((char *) arg);
            ret++;
            continue;
        }
        
        dirs = FcStrSetCreate ();
-       fs = FcCacheSet (cache);
-       cache_dirs = FcCacheDirs (cache);
-       for (j = 0; j < cache->dirs_count; j++) 
-           FcStrSetAdd (dirs, FcOffsetToPtr (cache_dirs,
-                                             cache_dirs[j],
-                                             FcChar8));
+       fs = FcCacheCopySet (cache);
+       for (j = 0; j < FcCacheNumSubdir (cache); j++) 
+       {
+           FcStrSetAdd (dirs, FcCacheSubdir (cache, j));
+           if (recurse)
+               FcStrSetAdd (args, FcCacheSubdir (cache, j));
+       }
 
        if (verbose)
-           printf ("Name: %s\nDirectory: %s\n", argv[i], FcCacheDir(cache));
-        FcCachePrintSet (fs, dirs, FcCacheDir (cache));
+       {
+           if (!first)
+               printf ("\n");
+           printf ("Directory: %s\nCache: %s\n--------\n",
+                   FcCacheDir(cache), cache_file ? cache_file : arg);
+           first = FcFalse;
+       }
+        cache_print_set (fs, dirs, FcCacheDir (cache), verbose);
 
        FcStrSetDestroy (dirs);
 
-       FcDirCacheUnmap (cache);
+       FcFontSetDestroy (fs);
+       FcDirCacheUnload (cache);
+       if (cache_file)
+           FcStrFree (cache_file);
     }
 
+    FcFini ();
     return 0;
 }