Back to index

tetex-bin  3.0
Defines | Functions | Variables
cnf.c File Reference
#include <kpathsea/config.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/c-ctype.h>
#include <kpathsea/c-pathch.h>
#include <kpathsea/cnf.h>
#include <kpathsea/db.h>
#include <kpathsea/hash.h>
#include <kpathsea/line.h>
#include <kpathsea/paths.h>
#include <kpathsea/pathsearch.h>
#include <kpathsea/progname.h>
#include <kpathsea/tex-file.h>
#include <kpathsea/variable.h>

Go to the source code of this file.

Defines

#define CNF_HASH_SIZE   751
#define CNF_NAME   "texmf.cnf"

Functions

static void do_line P1C (string, line)
static void read_all_cnf P1H (void)
string kpse_cnf_get P1C (const_string, name)

Variables

static hash_table_type cnf_hash

Define Documentation

#define CNF_HASH_SIZE   751

Definition at line 41 of file cnf.c.

#define CNF_NAME   "texmf.cnf"

Definition at line 42 of file cnf.c.


Function Documentation

static void do_line P1C ( string  ,
line   
) [static]

Definition at line 51 of file cnf.c.

{
  unsigned len;
  string start;
  string value, var;
  string prog = NULL;
  
  /* Skip leading whitespace.  */
  while (ISSPACE (*line))
    line++;
  
  /* More to do only if we have non-comment material left.  */
  if (*line == 0 || *line == '%' || *line == '#')
    return;
  
  /* The variable name is everything up to the next space or = or `.'.  */
  start = line;
  while (!ISSPACE (*line) && *line != '=' && *line != '.')
    line++;

  /* `line' is now one character past the end of the variable name.  */
  len = line - start;
  var = (string)xmalloc (len + 1);
  strncpy (var, start, len);
  var[len] = 0;
  
  /* If the variable is qualified with a program name, find out which. */
  while (ISSPACE (*line))
    line++;
  if (*line == '.') {
    /* Skip spaces, then everything up to the next space or =.  */
    line++;
    while (ISSPACE (*line))
      line++;
    start = line;
    while (!ISSPACE (*line) && *line != '=')
      line++;

    /* It's annoying to repeat all this, but making a tokenizing
       subroutine would be just as long and annoying.  */
    len = line - start;
    prog = (string)xmalloc (len + 1);
    strncpy (prog, start, len);
    prog[len] = 0;
  }

  /* Skip whitespace, an optional =, more whitespace.  */
  while (ISSPACE (*line))
    line++;
  if (*line == '=') {
    line++;
    while (ISSPACE (*line))
      line++;
  }
  
  /* The value is whatever remains.  Remove trailing whitespace.  */
  start = line;
  len = strlen (start);
  while (len > 0 && ISSPACE (start[len - 1]))
    len--;
  
  value = (string)xmalloc (len + 1);
  strncpy (value, start, len);
  value[len] = 0;

  /* Suppose we want to write a single texmf.cnf that can be used under
     both NT and Unix.  This is feasible except for the path separators
     : on Unix, ; on NT.  We can't switch NT to allowing :'s, since :
     is the drive separator.  So we switch Unix to allowing ;'s.  On the
     other hand, we don't want to change IS_ENV_SEP and all the rest.
     
     So, simply translate all ;'s in the path
     values to :'s if we are a Unix binary.  (Fortunately we don't use ;
     in other kinds of texmf.cnf values.)
     
     If you really want to put ; in your filenames, add
     -DALLOW_SEMICOLON_IN_FILENAMES.  (And there's no way to get :'s in
     your filenames, sorry.)  */
     
#if IS_ENV_SEP(':') && !defined (ALLOW_SEMICOLON_IN_FILENAMES)
  {
    string loc;
    for (loc = value; *loc; loc++) {
      if (*loc == ';')
        *loc = ':';
    }
  }
#endif

  /* We want TEXINPUTS.prog to override plain TEXINPUTS.  The simplest
     way is to put both in the hash table (so we don't have to write
     hash_delete and hash_replace, and keep track of values' sources),
     and then look up the .prog version first in `kpse_cnf_get'.  */
  if (prog) {
    string lhs = concat3 (var, ".", prog);
    free (var);
    free (prog);
    var = lhs;
  }
  hash_insert (&cnf_hash, var, value);
  
  /* We could check that anything remaining is preceded by a comment
     character, but let's not bother.  */
}

Here is the call graph for this function:

string kpse_cnf_get P1C ( const_string  ,
name   
)

Definition at line 210 of file cnf.c.

{
  string ret, ctry;
  string *ret_list;
  static boolean doing_cnf_init = false;

  /* When we expand the compile-time value for DEFAULT_TEXMFCNF,
     we end up needing the value for TETEXDIR and other variables,
     so kpse_var_expand ends up calling us again.  No good.  */
  if (doing_cnf_init)
    return NULL;
    
  if (cnf_hash.size == 0) {
    doing_cnf_init = true;
    read_all_cnf ();
    doing_cnf_init = false;
    
    /* Here's a pleasant kludge: Since `kpse_init_dbs' recursively calls
       us, we must call it from outside a `kpse_path_element' loop
       (namely, the one in `read_all_cnf' above): `kpse_path_element' is
       not reentrant.  */
    kpse_init_db ();
  }
  
  /* First look up NAME.`kpse_program_name', then NAME.  */
  assert (kpse_program_name);
  ctry = concat3 (name, ".", kpse_program_name);
  ret_list = hash_lookup (cnf_hash, ctry);
  free (ctry);
  if (ret_list) {
    ret = *ret_list;
    free (ret_list);
  } else {
    ret_list = hash_lookup (cnf_hash, name);
    if (ret_list) {
      ret = *ret_list;
      free (ret_list);
    } else {
      ret = NULL;
    }
  }
  
  return ret;

}

Here is the call graph for this function:

static void read_all_cnf P1H ( void  ) [static]

Definition at line 159 of file cnf.c.

{
  string *cnf_files;
  string *cnf;
  const_string cnf_path = kpse_init_format (kpse_cnf_format);

  cnf_hash = hash_create (CNF_HASH_SIZE);

  cnf_files = kpse_all_path_search (cnf_path, CNF_NAME);
  if (cnf_files) {
    for (cnf = cnf_files; *cnf; cnf++) {
      string line;
      FILE *cnf_file = xfopen (*cnf, FOPEN_R_MODE);

      while ((line = read_line (cnf_file)) != NULL) {
        unsigned len = strlen (line);
        /* Strip trailing spaces. */
        while (len > 0 && ISSPACE(line[len-1])) {
          line[len - 1] = 0;
          --len;
        }
        /* Concatenate consecutive lines that end with \.  */
        while (len > 0 && line[len - 1] == '\\') {
          string next_line = read_line (cnf_file);
          line[len - 1] = 0;
          if (!next_line) {
            WARNING1 ("%s: Last line ends with \\", *cnf);
          } else {
            string new_line;
            new_line = concat (line, next_line);
            free (line);
            line = new_line;
            len = strlen (line);
          }
        }

        do_line (line);
        free (line);
      }

      xfclose (cnf_file, *cnf);
      free (*cnf);
    }
    free (cnf_files);
  }
}

Here is the call graph for this function:


Variable Documentation

Definition at line 40 of file cnf.c.