src/fsearch.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. NAMLENGTH
  2. NAMLENGTH
  3. vf_kpathsea_init
  4. vf_add_uncompresser_alist
  5. vf_open_uncompress_stream
  6. vf_close_uncompress_stream
  7. vf_search_file
  8. search_in_fdb
  9. search_fdb_fp
  10. vf_find_file_in_directory
  11. search_file_kpathsea
  12. search_file
  13. ext2uncprog
  14. vf_tex_make_glyph
  15. search_file_recursive
  16. search_file_recursive
  17. traverse_directory
  18. dtr_elem_alloc
  19. dtr_elem_free
  20. dtr_alloc
  21. dtr_free
  22. dtr_get_path
  23. dtr_add_subdir
  24. dtr_go_subdir
  25. dtr_go_updir
  26. dtr_subdir_list
  27. dtr_next_subdir
  28. dtr_add_name
  29. dtr_del_name
  30. recursive_searcher
  31. recursive_searcher_found

   1 /*
   2  * fsearch.c - search a file 
   3  * by Hirotsugu Kakugawa
   4  *
   5  *  28 May 1997  Added recursive file searching feature.
   6  *  24 Dec 1998  Added searching in "VFlib.fdb" file that contain file list
   7  *  21 Sep 1999  Added a feature to generate PK & GF files on the fly.
   8  *
   9  */
  10 /*
  11  * Copyright (C) 1996-1999   Hirotsugu Kakugawa. 
  12  * All rights reserved.
  13  *
  14  * This file is part of the VFlib Library.  This library is free
  15  * software; you can redistribute it and/or modify it under the terms of
  16  * the GNU Library General Public License as published by the Free
  17  * Software Foundation; either version 2 of the License, or (at your
  18  * option) any later version.  This library is distributed in the hope
  19  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  20  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  21  * PURPOSE.  See the GNU Library General Public License for more details.
  22  * You should have received a copy of the GNU Library General Public
  23  * License along with this library; if not, write to the Free Software
  24  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25  */
  26 
  27 #include "config.h"
  28 #include "with.h"
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <ctype.h>
  32 #ifdef HAVE_UNISTD_H
  33 #  include <unistd.h>
  34 #endif
  35 #include <sys/types.h>
  36 #include <sys/param.h>
  37 
  38 #ifdef HAVE_DIRENT_H
  39 
  40 # include <dirent.h>
  41 #  define NAMLENGTH(dirent) strlen((dirent)->d_name)
     /* [<][>][^][v][top][bottom][index][help] */
  42 
  43 #else /* not DIRENT */
  44 
  45 # define dirent direct
  46 # define NAMLENGTH(dirent)  ((dirent)->d_namlen)
     /* [<][>][^][v][top][bottom][index][help] */
  47 
  48 #ifdef HAVE_SYS_NDIR_H
  49 # include <sys/ndir.h>
  50 #endif
  51 
  52 #ifdef HAVE_SYS_DIR_H
  53 # include <sys/dir.h>
  54 #endif
  55 
  56 #ifdef HAVE_NDIR_H
  57 # include <ndir.h>
  58 #endif
  59 
  60 #endif /* not DIRENT */
  61 
  62 #ifdef HAVE_SYS_STAT_H
  63 #  ifdef __linux__
  64 #    define __USE_BSD
  65 #  endif
  66 # include <sys/stat.h>
  67 #endif
  68 
  69 #include "VFlib-3_6.h"
  70 #include "VFsys.h"
  71 #include "consts.h"
  72 #include "fsearch.h"
  73 #include "texfonts.h"
  74 #include "sexp.h"
  75 #include "path.h"
  76 #include "str.h"
  77 
  78 #ifdef WITH_KPATHSEA
  79 # include  "kpathsea/kpathsea.h"
  80 #endif
  81 
  82 
  83 #ifdef HAVE_DIRENT_H
  84 # ifdef HAVE_SYS_STAT_H
  85 #  ifdef HAVE_OPENDIR
  86 #   define  RECURSIVE_FILE_SEARCH
  87 #  endif
  88 # endif
  89 #endif
  90 
  91 
  92 
  93 
  94 /**
  95  ** kpathsea
  96  **/
  97 Private int        kps_switch = DEFAULT_KPS_SWITCH;
  98 Private char      *kps_mode   = DEFAULT_KPS_MODE;
  99 Private int        kps_dpi    = DEFAULT_KPS_DPI;
 100 #ifdef WITH_KPATHSEA
 101 Private char      *kps_path   = DEFAULT_KPS_PROGRAM_PATH;
 102 #endif
 103 Private char      *kps_prog   = DEFAULT_KPS_PROGRAM_NAME;
 104 
 105 
 106 Glocal void
 107 vf_kpathsea_init(char *prog, char *mode, int dpi, int kps_sw)
     /* [<][>][^][v][top][bottom][index][help] */
 108 {
 109 #ifdef WITH_KPATHSEA
 110   static int  inited_prog = 0;
 111   int   f;
 112 #endif
 113 
 114   kps_switch  = kps_sw; 
 115   kps_dpi     = dpi; 
 116   if (mode != NULL)
 117     kps_mode  = mode;
 118   if (prog != NULL)
 119     kps_prog  = prog;
 120 
 121 #ifdef WITH_KPATHSEA
 122   if (inited_prog == 1)
 123     return;
 124 
 125   inited_prog = 1;
 126 
 127   if (vf_dbg_kpathsea == 1){
 128     if (kps_switch == TRUE)
 129       printf(">>Kpathsea: enabled\n");
 130     else
 131       printf(">>Kpathsea: disabled\n");
 132   }
 133 
 134   if (vf_dbg_kpathsea == 1)
 135     printf(">>Kpathsea: mode=%s, dpi=%d program=%s\n",
 136            kps_mode, kps_dpi, kps_prog);
 137 
 138   kpse_set_program_name(kps_path, kps_prog);
 139   kpse_init_prog(kps_prog, kps_dpi, kps_mode, NULL);
 140   for (f = 0; f < kpse_last_format; f++) {
 141     kpse_init_format(f);
 142   }
 143 #else
 144   if (vf_dbg_kpathsea == 1)
 145     printf(">>Kpathsea: disabled by configure\n");
 146 #endif
 147 }
 148 
 149 
 150 
 151 /**
 152  **  VF_AddUncompresser()
 153  **/
 154 
 155 Private SEXP_ALIST  vf_uncompresser_alist = NULL; 
 156 
 157 Public int
 158 vf_add_uncompresser_alist(SEXP_ALIST alist)
     /* [<][>][^][v][top][bottom][index][help] */
 159 {
 160   SEXP  t;
 161 
 162   if (alist == NULL)
 163     return 0;
 164 
 165   if (!vf_sexp_alistp(alist)){
 166     fprintf(stderr, "VFlib Error [fsearch.c:VF_AddUncompresser]: %s\n",
 167             "Not an alist.");
 168     return -1;
 169   }
 170 
 171   t = vf_uncompresser_alist;
 172   vf_sexp_nconc(alist, t);
 173   vf_uncompresser_alist = alist;
 174 
 175   return 0;
 176 }
 177 
 178 
 179 Glocal FILE*
 180 vf_open_uncompress_stream(char *compressed_file, char *uncompress_prog)
     /* [<][>][^][v][top][bottom][index][help] */
 181 {
 182 #ifndef HAVE_POPEN
 183 
 184   return NULL;
 185 
 186 #else
 187 
 188   FILE  *fp;
 189   char  *cmdline;
 190 
 191   cmdline = malloc(strlen(uncompress_prog) + strlen(compressed_file) + 16);
 192   if (cmdline == NULL)
 193     return NULL;
 194   sprintf(cmdline, "%s %s", uncompress_prog, compressed_file);
 195   fp = popen(cmdline, "r");
 196   vf_free(cmdline);
 197 
 198   return fp;
 199 
 200 #endif /* HAVE_POPEN */
 201 }
 202 
 203 Glocal int
 204 vf_close_uncompress_stream(FILE* fp)
     /* [<][>][^][v][top][bottom][index][help] */
 205 {
 206 #ifdef HAVE_POPEN
 207 
 208   if (fp != NULL){
 209     pclose(fp);
 210   }
 211 
 212 #endif
 213 
 214   return 0;
 215 }
 216 
 217 
 218 
 219 /**
 220  ** Search a File 
 221  **/
 222 
 223 Private char *search_in_fdb(char *name, char *dir,
 224                             SEXP_LIST compressed_ext_list, 
 225                             char **p_uncompr_prog, int *ret_val);
 226 Private int   search_fdb_fp(FILE *fp, char *d, char *f,
 227                             char *ret_path, int ret_path_size);
 228 Private char *search_file_kpathsea(char*,int,char*,int);
 229 Private char *search_file(char*,char*,SEXP_LIST,char**);
 230 Private char *search_file_recursive(char*, char*,SEXP_LIST,char**);
 231 Private int   ext2uncprog(char *ext, SEXP_LIST compressed_ext_list, 
 232                           char **p_uncompr_prog);
 233 
 234 
 235 
 236 Glocal char*
 237 vf_search_file(char *name, int opt_arg1, char *opt_arg2,
     /* [<][>][^][v][top][bottom][index][help] */
 238                int use_kpathsea, int kpathsea_file_format,
 239                SEXP_LIST dir_list, 
 240                SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
 241      /* NOTE: CALLER OF THIS FUNCTION *SHOULD* RELEASE RETURN VALUE.
 242               (STRING RETURNED BY P_UNCOMPR_PROG SHOULD NOT BE RELEASED.) */
 243 {
 244   SEXP   d;
 245   char  *path, *dir;
 246   int    v;
 247 
 248   if (name == NULL)
 249     return NULL;
 250 
 251   if (vf_dbg_font_search == 1){
 252     printf(">> File search: %s\n", name);
 253   }
 254 
 255   if (p_uncompr_prog != NULL)
 256     *p_uncompr_prog = NULL;
 257 
 258   if (vf_path_absolute(name)){
 259     if (vf_path_file_read_ok(name)){
 260       if (vf_dbg_font_search == 1)
 261         printf(">>  File search: Found %s\n", name);
 262       return vf_strdup(name);
 263     }
 264     if (vf_dbg_font_search == 1)
 265       printf(">>  File search: Not found (no such absolute path)\n");
 266     return NULL;
 267   }
 268 
 269   if ((dir_list == NULL) || (!vf_sexp_listp(dir_list))){
 270     if (vf_dbg_font_search == 1)
 271       printf(">>  File search: Not found (empty dir list)\n");
 272     return NULL;
 273   }
 274 
 275   path = NULL;
 276   for (d = dir_list; vf_sexp_consp(d); d = vf_sexp_cdr(d)){
 277     dir = vf_sexp_get_cstring(vf_sexp_car(d));
 278     if (dir == NULL)
 279       continue;
 280     if ((vf_strcmp_ci(dir, "TEXMF") == 0) 
 281         || (vf_strcmp_ci(dir, "KPATHSEA") == 0)){
 282       /* Search by 'KPATHSEA' */
 283       if (use_kpathsea == FALSE){
 284         fprintf(stderr, 
 285                 "VFlib Warning: Unsupported file format by kpathsea.\n");
 286         continue;
 287       }
 288       if (kps_switch == FALSE)
 289         continue;
 290       path = search_file_kpathsea(name, opt_arg1, opt_arg2, 
 291                                   kpathsea_file_format);
 292     } else {
 293       /* check font file hint db */
 294       path = search_in_fdb(name, dir, compressed_ext_list, p_uncompr_prog, &v);
 295       if (v == -2){
 296         if (vf_path_terminated_by_2delims(dir) == FALSE){
 297           /* Search under dir */
 298           path = search_file(name, dir, compressed_ext_list, p_uncompr_prog);
 299         } else {
 300           /* Recursive search under dir */
 301           path = search_file_recursive(name, dir, 
 302                                        compressed_ext_list, p_uncompr_prog);
 303         }
 304       }
 305     }
 306 
 307     if (path != NULL)
 308       break;
 309   }
 310 
 311   if (vf_dbg_font_search == 1){
 312     if (path != NULL){
 313       printf(">>  File search: Found %s\n", path);
 314     } else {
 315       printf(">>  File search: Not found\n");
 316     }
 317   }
 318 
 319   if (path == NULL)
 320     return NULL;
 321 
 322   return path;
 323 }
 324 
 325 
 326 Private char*
 327 search_in_fdb(char *name, char *dir,
     /* [<][>][^][v][top][bottom][index][help] */
 328               SEXP_LIST compressed_ext_list, char **p_uncompr_prog,
 329               int *p_ret_val)
 330      /* NOTE: CALLER OF THIS FUNCTION *SHOULD* RELEASE RETURN VALUE. */
 331 {
 332   char   fdb[MAXPATHLEN], name_ext[MAXPATHLEN],  *path;
 333   int    pathsize;
 334   FILE  *fp;
 335   SEXP   s;
 336   char  *ext; 
 337 
 338   if (dir == NULL){
 339     *p_ret_val = -2;
 340     return NULL;
 341   }
 342 
 343   if ((vf_path_cons_path(fdb, sizeof(fdb), dir, VF_FONT_FILE_HINT_DB) < 0)
 344       || (! vf_path_file_read_ok(fdb))
 345       || ((fp = fopen(fdb, FOPEN_RD_MODE_TEXT)) == NULL)){
 346     if (vf_dbg_font_search == 1)
 347       printf(">> No font hint db file: %s\n", fdb);
 348     *p_ret_val = -2;  /* hint db not found */
 349     return NULL;  
 350   }
 351   
 352   if (vf_dbg_font_search == 1)
 353     printf(">> Reading hint db file: %s\n", fdb);
 354 
 355   pathsize = MAXPATHLEN;
 356   ALLOCN_IF_ERR(path, char, pathsize){
 357     *p_ret_val = -2;  /* hint db not found */
 358     fclose(fp);
 359     return NULL;
 360   }
 361 
 362   /* look for font without compression */
 363   if (search_fdb_fp(fp, dir, name, path, pathsize) >= 0){  /* found */
 364     *p_ret_val = 0; /* found */
 365     goto end;
 366   }
 367 
 368   /* look for font with compression */
 369   *p_ret_val = -1; 
 370   for (s = compressed_ext_list; vf_sexp_consp(s); s = vf_sexp_cdr(s)){
 371     ext = vf_sexp_get_cstring(vf_sexp_car(s));
 372     strncpy(name_ext, name, sizeof(name_ext));
 373     strncat(name_ext, ext,  sizeof(name_ext) - strlen(name));
 374     fseek(fp, 0, SEEK_SET);
 375     if ((search_fdb_fp(fp, dir, name_ext, path, pathsize) >= 0) 
 376         && (ext2uncprog(ext, compressed_ext_list, p_uncompr_prog) >= 0)){
 377       *p_ret_val = 0;  /* found */
 378       break;
 379     }
 380   }
 381   
 382 end:
 383   fclose(fp);
 384   if (*p_ret_val != 0){
 385     vf_free(path);
 386     path = NULL;
 387   }
 388 
 389   if (vf_dbg_font_search == 1){
 390     if (path != NULL)
 391       printf(">> Found in db file: %s\n", path);
 392     else
 393       printf(">> Not found in db file\n");
 394   }
 395 
 396   return path;
 397 }
 398 
 399 Private int
 400 search_fdb_fp(FILE *fp, char *d, char *f, char *ret_path, int ret_path_size)
     /* [<][>][^][v][top][bottom][index][help] */
 401 {
 402   char   linebuff[MAXPATHLEN], *p;
 403   int    flen, dlen, i;
 404 
 405   if ((fp == NULL) || (d == NULL) || (f == NULL) || (ret_path == NULL))
 406     return -1;
 407 
 408   dlen = strlen(d);
 409   flen = strlen(f);
 410   while (fgets(linebuff, sizeof(linebuff), fp) != NULL){
 411     if ((strncmp(f, linebuff, flen) == 0) && isspace((int)linebuff[flen])){
 412       for (p = &linebuff[flen]; (*p != '\0') && isspace((int)*p); p++)
 413         ;
 414       if (*p == '\0')
 415         break;
 416       for (i = 0; p[i] != '\0'; i++){
 417         if (isspace((int)p[i])){
 418           p[i] = '\0';
 419           break;
 420         }
 421       }
 422       vf_path_cons_path(ret_path, ret_path_size, d, p);
 423       return 0;
 424     }
 425   } 
 426 
 427   return -1;
 428 }
 429 
 430 
 431 
 432 Glocal char*
 433 vf_find_file_in_directory(char *name, char *dir)
     /* [<][>][^][v][top][bottom][index][help] */
 434      /* NOTE: CALLER OF THIS FUNCTION *SHOULD* RELEASE RETURN VALUE. */
 435 {
 436   return search_file(name, dir, NULL, NULL);
 437 }
 438 
 439 
 440 Private char*
 441 search_file_kpathsea(char *name, int dpi, char *name2, int file_format)
     /* [<][>][^][v][top][bottom][index][help] */
 442      /* NOTE: CALLER OF THIS FUNCTION *SHOULD* RELEASE RETURN VALUE. */
 443 {
 444 #ifndef WITH_KPATHSEA
 445 
 446   return NULL;
 447 
 448 #else 
 449 
 450   char   *s;
 451   kpse_glyph_file_type  g_ret;
 452 
 453 #if 0
 454   printf("search_file_kpathsea(%s, %s, %d, %d)\n", 
 455          name, name2, dpi, file_format);
 456 #endif
 457 
 458   if (kps_switch == FALSE)
 459     return NULL;
 460 
 461   if (vf_dbg_kpathsea == 1)
 462     printf(">> Kpathsea: Search %s\n", name);
 463 
 464   s = NULL;
 465 
 466   switch (file_format){
 467   case FSEARCH_FORMAT_TYPE_GF:
 468     s = kpse_find_gf(name2, dpi, &g_ret);
 469     break;
 470   case FSEARCH_FORMAT_TYPE_PK:
 471     s = kpse_find_pk(name2, dpi, &g_ret);
 472     break;
 473   case FSEARCH_FORMAT_TYPE_VF:
 474     s = kpse_find_vf(name);
 475     if (s == NULL)
 476       s = kpse_find_ovf(name);
 477     break;
 478   case FSEARCH_FORMAT_TYPE_TFM:
 479     s = kpse_find_tfm(name);
 480     if (s == NULL)
 481       s = kpse_find_ofm(name);
 482     break;
 483   case FSEARCH_FORMAT_TYPE_OVF:
 484     s = kpse_find_ovf(name);
 485     break;
 486   case FSEARCH_FORMAT_TYPE_OFM:
 487     s = kpse_find_ofm(name);
 488     break;
 489   case FSEARCH_FORMAT_TYPE_TTF:
 490     s = kpse_find_file(name, kpse_truetype_format, 0);
 491     break;
 492   case FSEARCH_FORMAT_TYPE_TYPE1:
 493     s = kpse_find_file(name, kpse_type1_format, 0);
 494     break;
 495   case FSEARCH_FORMAT_TYPE_TYPE42:
 496     s = kpse_find_file(name, kpse_type42_format, 0);
 497     break;
 498   case FSEARCH_FORMAT_TYPE_AFM:
 499     s = kpse_find_file(name, kpse_afm_format, 0);
 500     break;
 501   case FSEARCH_FORMAT_TYPE_PSHEADER:
 502     s = kpse_find_file(name, kpse_tex_ps_header_format, 0);
 503     break;
 504   default:
 505     s = NULL;
 506     break;
 507   }
 508 
 509   if (vf_dbg_kpathsea == 1){
 510     if (s != NULL){
 511       printf(">> Kpathsea: Found %s\n", s);
 512     } else {
 513       printf(">> Kpathsea: Not found\n");
 514     }
 515   }
 516 
 517   if (s == NULL)
 518     return NULL;
 519 
 520 #if 0
 521   return vf_strdup(s);
 522 #else
 523   return s;
 524 #endif
 525 
 526 #endif
 527 }
 528 
 529 Private char*
 530 search_file(char *name, char *dir, 
     /* [<][>][^][v][top][bottom][index][help] */
 531             SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
 532      /* NOTE: CALLER OF THIS FUNCTION *SHOULD* RELEASE RETURN VALUE. */
 533 {
 534   char   *path;
 535   char   *ext = NULL;  
 536   int    path_len, found;
 537   SEXP   s;
 538 
 539   if ((dir != NULL) && (vf_path_directory_read_ok(dir) == FALSE))
 540     return NULL;
 541 
 542   if (dir == NULL)
 543     dir = "";
 544 
 545   path_len = strlen(dir) + strlen(name) + 64;
 546        /* +64 for compressed extensions. Their lengths must be less 64. */
 547   ALLOCN_IF_ERR(path, char, path_len){
 548     vf_error = VF_ERR_NO_MEMORY;
 549     return NULL;
 550   }
 551 
 552   /* search non-compressed file */
 553   vf_path_cons_path(path, path_len, dir, name);
 554   if (vf_path_file_read_ok(path))
 555     return path;
 556 
 557   if (compressed_ext_list == NULL){
 558     vf_free(path);
 559     return NULL;
 560   }
 561 
 562   /* search compressed file */
 563   found = 0;
 564   for (s = compressed_ext_list; vf_sexp_consp(s); s = vf_sexp_cdr(s)){
 565     ext = vf_sexp_get_cstring(vf_sexp_car(s));
 566     vf_path_cons_path2(path, path_len, dir, name, ext);
 567     if (vf_path_file_read_ok(path) == TRUE){
 568       found = 1;
 569       break;
 570     }
 571   }
 572   if (found == 0){
 573     vf_free(path);
 574     return NULL;
 575   }
 576 
 577   if (ext2uncprog(ext, compressed_ext_list, p_uncompr_prog) < 0){
 578     vf_free(path);
 579     path = NULL;
 580   }
 581 
 582   return path;
 583 }
 584 
 585 
 586 /* Obtain uncompression program name from extension */
 587 Private int
 588 ext2uncprog(char *ext, SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
     /* [<][>][^][v][top][bottom][index][help] */
 589      /* NOTE: CALLER OF THIS FUNCTION *SHOULD NOT* RELEASE 
 590         RETURN VALUE IN P_UNCOMPR_PROG. */
 591 {
 592   char  *uncext;
 593   SEXP   p, q;
 594 
 595   if (p_uncompr_prog == NULL)
 596     return -1;
 597 
 598   *p_uncompr_prog = NULL;
 599   for (q = vf_uncompresser_alist; vf_sexp_consp(q); q = vf_sexp_cdr(q)){
 600     p = vf_sexp_car(q);
 601     uncext = vf_sexp_get_cstring(vf_sexp_car(p));
 602     if (strcmp(uncext, ext) == 0){
 603       *p_uncompr_prog = vf_sexp_get_cstring(vf_sexp_cadr(p));
 604       break;
 605     }
 606   }
 607   if (*p_uncompr_prog == NULL){
 608     fprintf(stderr, "VFlib Warning: %s %s\n",
 609             "Undefined uncompression program for file extension", ext);
 610     return -1;
 611   }
 612   if (vf_dbg_font_search == 1)
 613     printf(">>   Uncompression program: %s\n", *p_uncompr_prog);
 614   return 0;
 615 }
 616 
 617 
 618 Glocal int
 619 vf_tex_make_glyph(int type, char *font_name, int dpi, double mag)
     /* [<][>][^][v][top][bottom][index][help] */
 620 {
 621 
 622 #ifndef WITH_KPATHSEA
 623 
 624   return -1;
 625 
 626 #else
 627 
 628   char  *name,  *filename;
 629   char  *ext;
 630   int    kp_fmt;
 631   kpse_glyph_file_type file_ret;
 632 
 633   name = NULL;
 634 
 635   switch (type){
 636   case FSEARCH_FORMAT_TYPE_PK:
 637     ext = "pk";
 638     kp_fmt = kpse_pk_format;
 639     break;
 640   default:
 641     return -1;
 642   }
 643 
 644   if ((name = vf_path_base_core(font_name)) == NULL)
 645     return -1;
 646 
 647   fprintf(stderr, "Generating %s.%d%s (dpi=%d, mag=%.3f)...\n",
 648           name, (unsigned)(dpi*mag+0.5), ext, dpi, mag);
 649   fflush(stderr);
 650 
 651   kpse_set_program_enabled(kp_fmt, MAKE_TEX_PK_BY_DEFAULT, kpse_src_compile);
 652 
 653   filename = kpse_find_glyph(name, (unsigned)(dpi*mag+0.5), kp_fmt, &file_ret);
 654   if (filename == NULL){
 655     fprintf(stderr, "\nFailed.\n");
 656     vf_free(name);
 657     return -1;
 658   }
 659 
 660   fprintf(stderr, "Done.\n");
 661 
 662   vf_free(name);
 663   return 0;
 664 
 665 #endif /*WITH_KPATHSEA*/
 666 }
 667 
 668 
 669 
 670 
 671 #ifndef RECURSIVE_FILE_SEARCH
 672 
 673 Private char*
 674 search_file_recursive(char *name, char *dir,
     /* [<][>][^][v][top][bottom][index][help] */
 675                       SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
 676 {
 677   char  *d, *path;
 678   int   len;
 679 
 680   if (dir == NULL)
 681     return NULL;
 682 
 683   len = strlen(dir) + 1;
 684   ALLOCN_IF_ERR(d, char, len){
 685     vf_error = VF_ERR_NO_MEMORY;
 686     return NULL;
 687   }
 688   strcpy(d, dir);
 689 
 690   vf_path_del_terminating_2delims(d);
 691   if (vf_path_directory_read_ok(d) == FALSE){
 692     vf_free(d);
 693     return NULL;
 694   }
 695   path = search_file(name, d, compressed_ext_list, p_uncompr_prog);
 696 
 697   vf_free(d);
 698   return path;
 699 }
 700 
 701 #else /*RECURSIVE_FILE_SEARCH*/
 702 
 703 struct s_dtr_list {
 704   char              *name;
 705   struct stat       st;
 706   struct s_dtr_list *prev;
 707   struct s_dtr_list *next;
 708 };
 709 struct s_dtr_elem {
 710   int       path_index;
 711   dev_t     dev;
 712   ino_t     ino;
 713   struct s_dtr_elem   *next;
 714   struct s_dtr_elem   *prev;
 715   struct s_dtr_list   subdirs;
 716 };
 717 struct s_dtr {
 718   char      path[MAXPATHLEN];
 719   struct s_dtr_elem  *direc_head;
 720   struct s_dtr_elem  *direc_tail;
 721 };
 722 
 723 typedef struct s_dtr_list  *DTR_LIST;
 724 typedef struct s_dtr_elem  *DTR_ELEM;
 725 typedef struct s_dtr       *DTR;
 726 
 727 Private DTR      dtr_alloc(char*);
 728 Private void     dtr_free(DTR);
 729 Private char*    dtr_get_path(DTR);
 730 Private int      dtr_add_name(DTR, char*, int);
 731 Private void     dtr_del_name(DTR);
 732 Private int      dtr_add_subdir(DTR, struct dirent*, struct stat*);
 733 Private DTR_LIST dtr_subdir_list(DTR);
 734 Private DTR_LIST dtr_next_subdir(DTR, DTR_LIST);
 735 Private int      dtr_go_subdir(DTR, DTR_LIST);
 736 Private int      dtr_go_updir(DTR);
 737 
 738 Private char *traverse_directory(DTR, char*, SEXP_LIST, char**);
 739 
 740 
 741 Private char*
 742 search_file_recursive(char *name, char *dir,
     /* [<][>][^][v][top][bottom][index][help] */
 743                       SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
 744 {
 745   char   *d, *path;
 746   int    len;
 747   DTR    dtr;
 748 
 749   if (dir == NULL)
 750     return NULL;
 751 
 752   len = strlen(dir) + 1;
 753   ALLOCN_IF_ERR(d, char, len){
 754     vf_error = VF_ERR_NO_MEMORY;
 755     return NULL;
 756   }
 757   strcpy(d, dir);
 758   vf_path_del_terminating_2delims(d);
 759 
 760   if (vf_path_directory_read_ok(d) == FALSE){
 761     vf_free(d);
 762     return NULL;
 763   }
 764 
 765   if (vf_dbg_font_search == 1)
 766     printf(">>  Search Recursively in: %s\n", d);
 767 
 768   if ((dtr = dtr_alloc(d)) == NULL){
 769     vf_free(d);
 770     return NULL;
 771   }
 772 
 773   path = traverse_directory(dtr, name, compressed_ext_list, p_uncompr_prog);
 774 
 775   dtr_free(dtr);
 776   vf_free(d);
 777 
 778   return path;
 779 }
 780 
 781 Private char*
 782 traverse_directory(DTR dtr, char *name, 
     /* [<][>][^][v][top][bottom][index][help] */
 783                    SEXP_LIST compressed_ext_list, char **p_uncompr_prog)
 784 {
 785   char           *path;
 786   int            v;
 787   DIR            *dir;
 788   DTR_LIST       sd;
 789   struct dirent  *ent;
 790   struct stat    st; 
 791   
 792   if (vf_dbg_font_search == 1)
 793     printf(">>    Searching in: %s\n", dtr_get_path(dtr));
 794 
 795   /* search a file in a directory */
 796   path = search_file(name, dtr_get_path(dtr), 
 797                      compressed_ext_list, p_uncompr_prog);
 798   if (path != NULL)
 799     return path;
 800 
 801   /* obtain a set of subdirectories in a directory */
 802   if ((dir = opendir(dtr_get_path(dtr))) == NULL)
 803     return NULL;
 804   while ((ent = readdir(dir)) != NULL){
 805     if ((NAMLENGTH(ent) == 1) && (strcmp(ent->d_name, ".") == 0))
 806       continue;
 807     if ((NAMLENGTH(ent) == 2) && (strcmp(ent->d_name, "..") == 0))
 808       continue;
 809 
 810     dtr_add_name(dtr, ent->d_name, NAMLENGTH(ent));
 811     v = stat(dtr_get_path(dtr), &st);
 812     dtr_del_name(dtr);
 813     if (v < 0)
 814       continue;
 815     if ((st.st_mode & S_IFMT) == S_IFDIR){
 816       dtr_add_subdir(dtr, ent, &st);
 817     }
 818   }
 819   closedir(dir);
 820 
 821   /* search a file under subdirectories */
 822   path = NULL;
 823   for (sd = dtr_subdir_list(dtr); sd != NULL; sd = dtr_next_subdir(dtr, sd)){
 824     if (dtr_go_subdir(dtr, sd) >= 0){
 825       path = traverse_directory(dtr, name,
 826                                 compressed_ext_list, p_uncompr_prog);
 827       if (path != NULL)
 828         break;
 829       dtr_go_updir(dtr);
 830     }
 831   }
 832 
 833   return path;
 834 }
 835 
 836 
 837 Private DTR_ELEM
 838 dtr_elem_alloc()
     /* [<][>][^][v][top][bottom][index][help] */
 839 {
 840   DTR_ELEM  dtr_elem;
 841 
 842   if ((dtr_elem = (DTR_ELEM)malloc(sizeof(struct s_dtr_elem))) == NULL)
 843     return NULL;
 844 
 845   dtr_elem->path_index = 0;
 846   dtr_elem->dev     = 0;
 847   dtr_elem->ino     = 0;
 848   dtr_elem->next    = NULL;
 849   dtr_elem->prev    = NULL;
 850   dtr_elem->subdirs.name = NULL;
 851   dtr_elem->subdirs.prev = &dtr_elem->subdirs;
 852   dtr_elem->subdirs.next = &dtr_elem->subdirs;
 853   return dtr_elem;
 854 }
 855 
 856 Private void
 857 dtr_elem_free(DTR_ELEM dtr_elem)
     /* [<][>][^][v][top][bottom][index][help] */
 858 {
 859   DTR_LIST  dl, dl_next;
 860 
 861   dl = dtr_elem->subdirs.next;
 862   while (dl != &dtr_elem->subdirs){
 863     dl_next = dl->next;
 864     vf_free(dl->name);
 865     vf_free(dl);
 866     dl = dl_next;
 867   }
 868   vf_free(dtr_elem);
 869 }
 870 
 871 
 872 Private DTR
 873 dtr_alloc(char *topdir)
     /* [<][>][^][v][top][bottom][index][help] */
 874 {
 875   DTR         dtr;
 876   DTR_ELEM    dtr_elem;
 877   struct stat st; 
 878 
 879   if ((dtr = (DTR)malloc(sizeof(struct s_dtr))) == NULL)
 880     return NULL;
 881   dtr->direc_head = NULL;
 882   dtr->direc_tail = NULL;
 883   strcpy(dtr->path, topdir);
 884   vf_path_del_terminating_2delims(dtr->path);
 885   if (stat(dtr->path, &st) < 0)
 886     goto Error;
 887 
 888   if ((dtr_elem = dtr_elem_alloc()) == NULL)
 889     goto Error;
 890   dtr->direc_head = dtr_elem;
 891   dtr->direc_tail = dtr_elem;
 892   dtr_elem->path_index = strlen(dtr->path);
 893   dtr_elem->dev = st.st_dev;
 894   dtr_elem->ino = st.st_ino;
 895   return dtr;
 896 
 897 Error: 
 898   dtr_free(dtr);
 899   return NULL;
 900 }
 901 
 902 Private void
 903 dtr_free(DTR dtr)
     /* [<][>][^][v][top][bottom][index][help] */
 904 {
 905   DTR_ELEM  dtr_elem, dtr_elem_next;
 906 
 907   if (dtr == NULL)
 908     return;
 909   dtr_elem = dtr->direc_head;
 910   while (dtr_elem != NULL){
 911     dtr_elem_next = dtr_elem->next;
 912     dtr_elem_free(dtr_elem);
 913     dtr_elem = dtr_elem_next;
 914   }
 915   vf_free(dtr);
 916 }
 917 
 918 Private char*
 919 dtr_get_path(DTR dtr)
     /* [<][>][^][v][top][bottom][index][help] */
 920 {
 921   return dtr->path;
 922 }
 923 
 924 Private int
 925 dtr_add_subdir(DTR dtr, struct dirent *ent, struct stat* st)
     /* [<][>][^][v][top][bottom][index][help] */
 926 {
 927   DTR_LIST  dl_new, dl_0, dl_1;
 928 
 929   if ((dl_new = (DTR_LIST)malloc(sizeof(struct s_dtr_list))) == NULL)
 930     return -1;
 931   if ((dl_new->name = (char*)malloc(NAMLENGTH(ent)+1)) == NULL){
 932     vf_free(dl_new);
 933     return -1;
 934   }
 935 
 936   memcpy(dl_new->name, ent->d_name, NAMLENGTH(ent));
 937   dl_new->name[NAMLENGTH(ent)] = '\0';
 938   memcpy(&dl_new->st, st, sizeof(struct stat));
 939 
 940   dl_0 = &dtr->direc_tail->subdirs;
 941   dl_1 = dl_0->next;
 942   dl_new->next = dl_1;
 943   dl_new->prev = dl_0;
 944   dl_0->next   = dl_new;
 945   dl_1->prev   = dl_new;
 946 
 947   return 0;
 948 }
 949 
 950 Private int
 951 dtr_go_subdir(DTR dtr, DTR_LIST sd)
     /* [<][>][^][v][top][bottom][index][help] */
 952 {
 953   DTR_ELEM     dtr_elem, elem;
 954   
 955   if (dtr_add_name(dtr, sd->name, strlen(sd->name)) < 0)
 956     return -1;
 957 
 958   for (elem = dtr->direc_head; elem != NULL; elem = elem->next){
 959     if ((elem->dev == sd->st.st_dev) && (elem->ino == sd->st.st_ino)){
 960       /* LOOP! */
 961       dtr_del_name(dtr);
 962       return -1;
 963     }
 964   }
 965 
 966   if ((dtr_elem = dtr_elem_alloc()) == NULL){
 967     dtr_del_name(dtr);
 968     return -1;
 969   }
 970 
 971   dtr_elem->path_index   = strlen(dtr->path);
 972   dtr_elem->dev          = sd->st.st_dev;
 973   dtr_elem->ino          = sd->st.st_ino;
 974   dtr_elem->prev         = dtr->direc_tail;
 975   dtr->direc_tail->next  = dtr_elem; 
 976   dtr->direc_tail        = dtr_elem;
 977 
 978   return 0;
 979 }
 980 
 981 Private int
 982 dtr_go_updir(DTR dtr)
     /* [<][>][^][v][top][bottom][index][help] */
 983 {
 984   DTR_ELEM   tail_elem;
 985 
 986   tail_elem = dtr->direc_tail;
 987   if (tail_elem == NULL){
 988     fprintf(stderr, "FATAL: CANNOT HAPPEN --- in dtr_go_updir().\n");
 989     exit(1);
 990   }
 991   tail_elem->prev->next = NULL;
 992   dtr->direc_tail = tail_elem->prev;
 993   dtr_elem_free(tail_elem);
 994 
 995   dtr_del_name(dtr);
 996 
 997   return 0;
 998 }
 999 
1000 
1001 Private DTR_LIST
1002 dtr_subdir_list(DTR dtr)
     /* [<][>][^][v][top][bottom][index][help] */
1003 {
1004   DTR_LIST  sd;
1005 #if 0
1006   DTR_LIST  ss;
1007 
1008   ss = dtr->direc_tail->subdirs.prev;
1009   printf("  ");
1010   while (ss != &dtr->direc_tail->subdirs){
1011     printf("%s, ", ss->name);
1012     ss = ss->prev;
1013   }
1014   printf("\n");
1015 #endif
1016 
1017   if ((sd = dtr->direc_tail->subdirs.prev) == &dtr->direc_tail->subdirs)
1018     return NULL;
1019 
1020   return sd;
1021 }
1022 
1023 Private DTR_LIST
1024 dtr_next_subdir(DTR dtr, DTR_LIST sd)
     /* [<][>][^][v][top][bottom][index][help] */
1025 {
1026   DTR_LIST  next;
1027 
1028   if ((next = sd->prev) == &dtr->direc_tail->subdirs)
1029     return NULL;
1030   return next;
1031 }
1032 
1033 
1034 Private int 
1035 dtr_add_name(DTR dtr, char *name, int len)
     /* [<][>][^][v][top][bottom][index][help] */
1036 {
1037   char  *p;
1038   int   index;
1039 
1040   index = dtr->direc_tail->path_index;
1041 
1042   for (p = vf_directory_delimiter; *p != '\0'; p++){
1043     dtr->path[index++] = *p;
1044   }
1045   while (len > 0){
1046     dtr->path[index++] = *(name++);
1047     --len;
1048   }
1049   dtr->path[index] = '\0';
1050 
1051   return 0;
1052 }
1053 
1054 Private void
1055 dtr_del_name(DTR dtr)
     /* [<][>][^][v][top][bottom][index][help] */
1056 {
1057   dtr->path[dtr->direc_tail->path_index] = '\0';
1058 }
1059 
1060 #endif /* RECURSIVE_FILE_SEARCH */
1061 
1062 
1063 
1064 
1065 #if 0
1066 
1067 Private int
1068 recursive_searcher(char *path, struct dirent *ent, struct stat *st)
     /* [<][>][^][v][top][bottom][index][help] */
1069 {
1070   SEXP_ALIST   iter, q, s;
1071   char         *ext, *uncext, *uncprog;
1072   int          ext_len;
1073 
1074   if (rec_target_file_len > NAMLENGTH(ent))
1075     return -1;
1076   if (strncmp(ent->d_name, rec_target_file, rec_target_file_len) != 0)
1077     return -1;
1078 
1079   if ((rec_target_file_len == NAMLENGTH(ent))
1080       && (strncmp(rec_target_file, ent->d_name, NAMLENGTH(ent)) == 0)){
1081     recursive_searcher_found(path);
1082     return 1;
1083   }
1084 
1085   if (rec_compressed_ext != NULL){
1086     for (iter = rec_compressed_ext;
1087          vf_sexp_consp(iter); 
1088          iter = vf_sexp_cdr(iter)){
1089       ext = vf_sexp_get_cstring(vf_sexp_car(iter));
1090       if ((ext == NULL) || (strcmp(ext, "") == 0))
1091         continue;
1092       ext_len = strlen(ext);
1093       if ((ext_len == (NAMLENGTH(ent) - rec_target_file_len))
1094            && (strncmp(&ent->d_name[rec_target_file_len], ext, ext_len) == 0)){
1095         uncprog = NULL;
1096         for (s = vf_uncompresser_alist; vf_sexp_consp(s); s = vf_sexp_cdr(s)){
1097           q = vf_sexp_car(s);
1098           uncext = vf_sexp_get_cstring(vf_sexp_car(q));
1099           if (strcmp(uncext, ext) == 0){
1100             uncprog = vf_sexp_get_cstring(vf_sexp_cadr(q));
1101             break;
1102           }
1103         }
1104         if (rec_p_uncompression_program != NULL)
1105           *rec_p_uncompression_program = uncprog;
1106         if (uncprog == NULL){
1107           fprintf(stderr, "VFlib Warning: %s %s\n",
1108                   "Undefined compression program for file extension", ext);
1109           return -1;
1110         }
1111         if (vf_dbg_font_search == 1)
1112           printf(">>       Uncompression program: %s\n", uncprog);
1113         recursive_searcher_found(path);
1114         return 1;
1115       }
1116     }
1117   }
1118 
1119   return -1;
1120 }
1121 
1122 Private void
1123 recursive_searcher_found(char *path)
     /* [<][>][^][v][top][bottom][index][help] */
1124 {
1125   int  len;
1126 
1127   if ((len = strlen(file_path) + 32) > file_path_length){
1128     vf_free(file_path);
1129     file_path_length = len;
1130     ALLOCN_IF_ERR(file_path, char, file_path_length){
1131       file_path_length = 0;
1132       vf_error = VF_ERR_NO_MEMORY;
1133       return;
1134     }
1135   }
1136   strcpy(file_path, path);
1137   rec_found_file = file_path;
1138 }
1139 
1140 #endif 
1141 
1142 /*EOF*/

/* [<][>][^][v][top][bottom][index][help] */