(root)/
fontconfig-2.14.2/
fc-cat/
fc-cat.c
       1  /*
       2   * fontconfig/fc-cat/fc-cat.c
       3   *
       4   * Copyright © 2002 Keith Packard
       5   *
       6   * Permission to use, copy, modify, distribute, and sell this software and its
       7   * documentation for any purpose is hereby granted without fee, provided that
       8   * the above copyright notice appear in all copies and that both that
       9   * copyright notice and this permission notice appear in supporting
      10   * documentation, and that the name of the author(s) not be used in
      11   * advertising or publicity pertaining to distribution of the software without
      12   * specific, written prior permission.  The authors make no
      13   * representations about the suitability of this software for any purpose.  It
      14   * is provided "as is" without express or implied warranty.
      15   *
      16   * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
      17   * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
      18   * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
      19   * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
      20   * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
      21   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      22   * PERFORMANCE OF THIS SOFTWARE.
      23   */
      24  
      25  #ifdef HAVE_CONFIG_H
      26  #include <config.h>
      27  #else
      28  #ifdef linux
      29  #define HAVE_GETOPT_LONG 1
      30  #endif
      31  #define HAVE_GETOPT 1
      32  #endif
      33  
      34  #include <fontconfig/fontconfig.h>
      35  #include "../src/fcarch.h"
      36  #include <stdio.h>
      37  #include <stdlib.h>
      38  #include <string.h>
      39  #ifdef HAVE_UNISTD_H
      40  #include <unistd.h>
      41  #endif
      42  #include <sys/types.h>
      43  #include <sys/stat.h>
      44  #include <errno.h>
      45  #include <locale.h>
      46  
      47  #ifdef ENABLE_NLS
      48  #include <libintl.h>
      49  #define _(x)		(dgettext(GETTEXT_PACKAGE, x))
      50  #else
      51  #define dgettext(d, s)	(s)
      52  #define _(x)		(x)
      53  #endif
      54  
      55  #ifndef HAVE_GETOPT
      56  #define HAVE_GETOPT 0
      57  #endif
      58  #ifndef HAVE_GETOPT_LONG
      59  #define HAVE_GETOPT_LONG 0
      60  #endif
      61  
      62  #if HAVE_GETOPT_LONG
      63  #undef  _GNU_SOURCE
      64  #define _GNU_SOURCE
      65  #include <getopt.h>
      66  const struct option longopts[] = {
      67      {"version", 0, 0, 'V'},
      68      {"verbose", 0, 0, 'v'},
      69      {"recurse", 0, 0, 'r'},
      70      {"help", 0, 0, 'h'},
      71      {NULL,0,0,0},
      72  };
      73  #else
      74  #if HAVE_GETOPT
      75  extern char *optarg;
      76  extern int optind, opterr, optopt;
      77  #endif
      78  #endif
      79  
      80  /*
      81   * POSIX has broken stdio so that putc must do thread-safe locking,
      82   * this is a serious performance problem for applications doing large
      83   * amounts of IO with putc (as is done here).  If available, use
      84   * the putc_unlocked variant instead.
      85   */
      86   
      87  #if defined(putc_unlocked) || defined(_IO_putc_unlocked)
      88  #define PUTC(c,f) putc_unlocked(c,f)
      89  #else
      90  #define PUTC(c,f) putc(c,f)
      91  #endif
      92  
      93  static FcBool
      94  write_chars (FILE *f, const FcChar8 *chars)
      95  {
      96      FcChar8    c;
      97      while ((c = *chars++))
      98      {
      99  	switch (c) {
     100  	case '"':
     101  	case '\\':
     102  	    if (PUTC ('\\', f) == EOF)
     103  		return FcFalse;
     104  	    /* fall through */
     105  	default:
     106  	    if (PUTC (c, f) == EOF)
     107  		return FcFalse;
     108  	}
     109      }
     110      return FcTrue;
     111  }
     112  
     113  static FcBool
     114  write_ulong (FILE *f, unsigned long t)
     115  {
     116      int	    pow;
     117      unsigned long   temp, digit;
     118  
     119      temp = t;
     120      pow = 1;
     121      while (temp >= 10)
     122      {
     123  	temp /= 10;
     124  	pow *= 10;
     125      }
     126      temp = t;
     127      while (pow)
     128      {
     129  	digit = temp / pow;
     130  	if (PUTC ((char) digit + '0', f) == EOF)
     131  	    return FcFalse;
     132  	temp = temp - pow * digit;
     133  	pow = pow / 10;
     134      }
     135      return FcTrue;
     136  }
     137  
     138  static FcBool
     139  write_int (FILE *f, int i)
     140  {
     141      return write_ulong (f, (unsigned long) i);
     142  }
     143  
     144  static FcBool
     145  write_string (FILE *f, const FcChar8 *string)
     146  {
     147  
     148      if (PUTC ('"', f) == EOF)
     149  	return FcFalse;
     150      if (!write_chars (f, string))
     151  	return FcFalse;
     152      if (PUTC ('"', f) == EOF)
     153  	return FcFalse;
     154      return FcTrue;
     155  }
     156  
     157  static void
     158  usage (char *program, int error)
     159  {
     160      FILE *file = error ? stderr : stdout;
     161  #if HAVE_GETOPT_LONG
     162      fprintf (file, _("usage: %s [-rv] [--recurse] [--verbose] [*-%s" FC_CACHE_SUFFIX "|directory]...\n"),
     163  	     program, FC_ARCHITECTURE);
     164      fprintf (file, "       %s [-Vh] [--version] [--help]\n", program);
     165  #else
     166      fprintf (file, _("usage: %s [-rvVh] [*-%s" FC_CACHE_SUFFIX "|directory]...\n"),
     167  	     program, FC_ARCHITECTURE);
     168  #endif
     169      fprintf (file, _("Reads font information cache from:\n"));
     170      fprintf (file, _(" 1) specified fontconfig cache file\n"));
     171      fprintf (file, _(" 2) related to a particular font directory\n"));
     172      fprintf (file, "\n");
     173  #if HAVE_GETOPT_LONG
     174      fprintf (file, _("  -r, --recurse        recurse into subdirectories\n"));
     175      fprintf (file, _("  -v, --verbose        be verbose\n"));
     176      fprintf (file, _("  -V, --version        display font config version and exit\n"));
     177      fprintf (file, _("  -h, --help           display this help and exit\n"));
     178  #else
     179      fprintf (file, _("  -r         (recurse) recurse into subdirectories\n"));
     180      fprintf (file, _("  -v         (verbose) be verbose\n"));
     181      fprintf (file, _("  -V         (version) display font config version and exit\n"));
     182      fprintf (file, _("  -h         (help)    display this help and exit\n"));
     183  #endif
     184      exit (error);
     185  }
     186  
     187  /*
     188   * return the path from the directory containing 'cache' to 'file'
     189   */
     190  
     191  static const FcChar8 *
     192  file_base_name (const FcChar8 *cache, const FcChar8 *file)
     193  {
     194      int		    cache_len = strlen ((char *) cache);
     195  
     196      if (!strncmp ((char *) cache, (char *) file, cache_len) && file[cache_len] == '/')
     197  	return file + cache_len + 1;
     198      return file;
     199  }
     200  
     201  #define FC_FONT_FILE_DIR	((FcChar8 *) ".dir")
     202  
     203  static FcBool
     204  cache_print_set (FcFontSet *set, FcStrSet *dirs, const FcChar8 *base_name, FcBool verbose)
     205  {
     206      FcChar8	    *dir;
     207      const FcChar8   *base;
     208      int		    n;
     209      int		    ndir = 0;
     210      FcStrList	    *list;
     211  
     212      list = FcStrListCreate (dirs);
     213      if (!list)
     214  	goto bail2;
     215      
     216      while ((dir = FcStrListNext (list)))
     217      {
     218  	base = file_base_name (base_name, dir);
     219  	if (!write_string (stdout, base))
     220  	    goto bail3;
     221  	if (PUTC (' ', stdout) == EOF)
     222  	    goto bail3;
     223  	if (!write_int (stdout, 0))
     224  	    goto bail3;
     225          if (PUTC (' ', stdout) == EOF)
     226  	    goto bail3;
     227  	if (!write_string (stdout, FC_FONT_FILE_DIR))
     228  	    goto bail3;
     229  	if (PUTC ('\n', stdout) == EOF)
     230  	    goto bail3;
     231  	ndir++;
     232      }
     233      
     234      for (n = 0; n < set->nfont; n++)
     235      {
     236  	FcPattern   *font = set->fonts[n];
     237  	FcChar8 *s;
     238  
     239  	s = FcPatternFormat (font, (const FcChar8 *) "%{=fccat}\n");
     240  	if (s)
     241  	{
     242  	    printf ("%s", s);
     243  	    FcStrFree (s);
     244  	}
     245      }
     246      if (verbose && !set->nfont && !ndir)
     247  	printf ("<empty>\n");
     248  
     249      FcStrListDone (list);
     250  
     251      return FcTrue;
     252  
     253  bail3:
     254      FcStrListDone (list);
     255  bail2:
     256      return FcFalse;
     257  }
     258  
     259  int
     260  main (int argc, char **argv)
     261  {
     262      int		i;
     263      int		ret = 0;
     264      FcFontSet	*fs;
     265      FcStrSet    *dirs;
     266      FcStrSet	*args = NULL;
     267      FcStrList	*arglist;
     268      FcCache	*cache;
     269      FcConfig	*config;
     270      FcChar8	*arg;
     271      int		verbose = 0;
     272      int		recurse = 0;
     273      FcBool	first = FcTrue;
     274  #if HAVE_GETOPT_LONG || HAVE_GETOPT
     275      int		c;
     276  
     277      setlocale (LC_ALL, "");
     278  #if HAVE_GETOPT_LONG
     279      while ((c = getopt_long (argc, argv, "Vvrh", longopts, NULL)) != -1)
     280  #else
     281      while ((c = getopt (argc, argv, "Vvrh")) != -1)
     282  #endif
     283      {
     284  	switch (c) {
     285  	case 'V':
     286  	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
     287  		     FC_MAJOR, FC_MINOR, FC_REVISION);
     288  	    exit (0);
     289  	case 'v':
     290  	    verbose++;
     291  	    break;
     292  	case 'r':
     293  	    recurse++;
     294  	    break;
     295  	case 'h':
     296  	    usage (argv[0], 0);
     297  	default:
     298  	    usage (argv[0], 1);
     299  	}
     300      }
     301      i = optind;
     302  #else
     303      i = 1;
     304  #endif
     305  
     306      config = FcInitLoadConfig ();
     307      if (!config)
     308      {
     309  	fprintf (stderr, _("%s: Can't initialize font config library\n"), argv[0]);
     310  	return 1;
     311      }
     312      FcConfigSetCurrent (config);
     313      FcConfigDestroy (config);
     314      
     315      args = FcStrSetCreate ();
     316      if (!args)
     317      {
     318  	fprintf (stderr, _("%s: malloc failure\n"), argv[0]);
     319  	return 1;
     320      }
     321      if (i < argc)
     322      {
     323  	for (; i < argc; i++)
     324  	{
     325  	    if (!FcStrSetAddFilename (args, (const FcChar8 *) argv[i]))
     326  	    {
     327  		fprintf (stderr, _("%s: malloc failure\n"), argv[0]);
     328  		return 1;
     329  	    }
     330  	}
     331      }
     332      else
     333      {
     334  	recurse++;
     335  	arglist = FcConfigGetFontDirs (config);
     336  	while ((arg = FcStrListNext (arglist)))
     337  	    if (!FcStrSetAdd (args, arg))
     338  	    {
     339  		fprintf (stderr, _("%s: malloc failure\n"), argv[0]);
     340  		return 1;
     341  	    }
     342  	FcStrListDone (arglist);
     343      }
     344      arglist = FcStrListCreate (args);
     345      if (!arglist)
     346      {
     347  	fprintf (stderr, _("%s: malloc failure\n"), argv[0]);
     348  	return 1;
     349      }
     350      FcStrSetDestroy (args);
     351  
     352      while ((arg = FcStrListNext (arglist)))
     353      {
     354  	int	    j;
     355  	FcChar8	    *cache_file = NULL;
     356  	struct stat file_stat;
     357  
     358  	/* reset errno */
     359  	errno = 0;
     360  	if (FcFileIsDir (arg))
     361  	    cache = FcDirCacheLoad (arg, config, &cache_file);
     362  	else
     363  	    cache = FcDirCacheLoadFile (arg, &file_stat);
     364  	if (!cache)
     365  	{
     366  	    if (errno != 0)
     367  		perror ((char *) arg);
     368  	    else
     369  		fprintf (stderr, "%s: Unable to load the cache: %s\n", argv[0], arg);
     370  	    ret++;
     371  	    continue;
     372  	}
     373  	
     374  	dirs = FcStrSetCreate ();
     375  	fs = FcCacheCopySet (cache);
     376  	for (j = 0; j < FcCacheNumSubdir (cache); j++) 
     377  	{
     378  	    FcStrSetAdd (dirs, FcCacheSubdir (cache, j));
     379  	    if (recurse)
     380  		FcStrSetAdd (args, FcCacheSubdir (cache, j));
     381  	}
     382  
     383  	if (verbose)
     384  	{
     385  	    if (!first)
     386  		printf ("\n");
     387  	    printf (_("Directory: %s\nCache: %s\n--------\n"),
     388  		    FcCacheDir(cache), cache_file ? cache_file : arg);
     389  	    first = FcFalse;
     390  	}
     391          cache_print_set (fs, dirs, FcCacheDir (cache), verbose);
     392  
     393  	FcStrSetDestroy (dirs);
     394  
     395  	FcFontSetDestroy (fs);
     396  	FcDirCacheUnload (cache);
     397  	if (cache_file)
     398  	    FcStrFree (cache_file);
     399      }
     400      FcStrListDone (arglist);
     401  
     402      FcFini ();
     403      return 0;
     404  }