Back to index

tetex-bin  3.0
Functions | Variables
files.c File Reference
#include "system.h"
#include "files.h"
#include "html.h"
#include "index.h"
#include "macro.h"
#include "makeinfo.h"
#include "node.h"

Go to the source code of this file.

Functions

static char * extract_colon_unit (char *string, int *index)
char * get_file_info_in_path (char *filename, char *path, struct stat *finfo)
void prepend_to_include_path (char *path)
void append_to_include_path (char *path)
void pop_path_from_include_path (void)
char * find_and_load (char *filename, int use_path)
static void push_node_filename (void)
static void pop_node_filename (void)
void pushfile (void)
void popfile (void)
void flush_file_stack (void)
static int skip_directory_part (char *filename)
static char * filename_non_directory (char *name)
char * filename_part (char *filename)
char * pathname_part (char *filename)
static char * full_pathname (char *filename)
char * expand_filename (char *filename, char *input_name)
char * output_name_from_input_name (char *name)
char * normalize_filename (char *fname)
void register_delayed_write (char *delayed_command)
void handle_delayed_writes (void)

Variables

FSTACKfilestack = NULL
static int node_filename_stack_index = 0
static int node_filename_stack_size = 0
static char ** node_filename_stack = NULL
static DELAYED_WRITEdelayed_writes = NULL
int handling_delayed_writes = 0

Function Documentation

void append_to_include_path ( char *  path)

Definition at line 155 of file files.c.

{
  if (!include_files_path)
    include_files_path = xstrdup (".");

  include_files_path = (char *) xrealloc (include_files_path,
        2 + strlen (include_files_path) + strlen (path));
  strcat (include_files_path, PATH_SEP);
  strcat (include_files_path, path);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* expand_filename ( char *  filename,
char *  input_name 
)

Definition at line 501 of file files.c.

{
  int i;

  if (filename)
    {
      filename = full_pathname (filename);
      if (IS_ABSOLUTE (filename)
         || (*filename == '.' &&
             (IS_SLASH (filename[1]) ||
              (filename[1] == '.' && IS_SLASH (filename[2])))))
       return filename;
    }
  else
    {
      filename = filename_non_directory (input_name);

      if (!*filename)
        {
          free (filename);
          filename = xstrdup ("noname.texi");
        }

      for (i = strlen (filename) - 1; i; i--)
        if (filename[i] == '.')
          break;

      if (!i)
        i = strlen (filename);

      if (i + 6 > (strlen (filename)))
        filename = xrealloc (filename, i + 6);
      strcpy (filename + i, html ? ".html" : ".info");
      return filename;
    }

  if (IS_ABSOLUTE (input_name))
    {
      /* Make it so that relative names work. */
      char *result;
      
      i = strlen (input_name) - 1;

      result = xmalloc (1 + strlen (input_name) + strlen (filename));
      strcpy (result, input_name);

      while (!IS_SLASH (result[i]) && i)
        i--;
      if (IS_SLASH (result[i]))
        i++;

      strcpy (&result[i], filename);
      free (filename);
      return result;
    }
  return filename;
}

Here is the call graph for this function:

static char* extract_colon_unit ( char *  string,
int index 
) [static]

Definition at line 41 of file files.c.

{
  int start;
  int path_sep_char = PATH_SEP[0];
  int i = *index;

  if (!string || (i >= strlen (string)))
    return NULL;

  /* Each call to this routine leaves the index pointing at a colon if
     there is more to the path.  If i > 0, then increment past the
     `:'.  If i == 0, then the path has a leading colon.  Trailing colons
     are handled OK by the `else' part of the if statement; an empty
     string is returned in that case. */
  if (i && string[i] == path_sep_char)
    i++;

  start = i;
  while (string[i] && string[i] != path_sep_char) i++;
  *index = i;

  if (i == start)
    {
      if (string[i])
        (*index)++;

      /* Return "" in the case of a trailing `:'. */
      return xstrdup ("");
    }
  else
    {
      char *value;

      value = xmalloc (1 + (i - start));
      memcpy (value, &string[start], (i - start));
      value [i - start] = 0;

      return value;
    }
}

Here is the call graph for this function:

static char* filename_non_directory ( char *  name) [static]

Definition at line 363 of file files.c.

Here is the call graph for this function:

char* filename_part ( char *  filename)

Definition at line 372 of file files.c.

{
  char *basename = filename_non_directory (filename);

#ifdef REMOVE_OUTPUT_EXTENSIONS
  /* See if there is an extension to remove.  If so, remove it. */
  {
    char *temp = strrchr (basename, '.');
    if (temp)
      *temp = 0;
  }
#endif /* REMOVE_OUTPUT_EXTENSIONS */
  return basename;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* find_and_load ( char *  filename,
int  use_path 
)

Definition at line 191 of file files.c.

{
  struct stat fileinfo;
  long file_size;
  int file = -1, count = 0;
  char *fullpath, *result;
  int n, bytes_to_read;

  result = fullpath = NULL;

  fullpath
    = get_file_info_in_path (filename, use_path ? include_files_path : NULL, 
                             &fileinfo);

  if (!fullpath)
    goto error_exit;

  filename = fullpath;
  file_size = (long) fileinfo.st_size;

  file = open (filename, O_RDONLY);
  if (file < 0)
    goto error_exit;

  /* Load the file, with enough room for a newline and a null. */
  result = xmalloc (file_size + 2);

  /* VMS stat lies about the st_size value.  The actual number of
     readable bytes is always less than this value.  The arcane
     mysteries of VMS/RMS are too much to probe, so this hack
    suffices to make things work.  It's also needed on Cygwin.  And so
    we might as well use it everywhere.  */
  bytes_to_read = file_size;
  while ((n = read (file, result + count, bytes_to_read)) > 0)
    {
      count += n;
      bytes_to_read -= n;
    }
  if (0 < count && count < file_size)
    result = xrealloc (result, count + 2); /* why waste the slack? */
  else if (n == -1)
error_exit:
    {
      if (result)
        free (result);

      if (fullpath)
        free (fullpath);

      if (file != -1)
        close (file);

      return NULL;
    }
  close (file);

  /* Set the globals to the new file. */
  input_text = result;
  input_text_length = count;
  input_filename = fullpath;
  node_filename = xstrdup (fullpath);
  input_text_offset = 0;
  line_number = 1;
  /* Not strictly necessary.  This magic prevents read_token () from doing
     extra unnecessary work each time it is called (that is a lot of times).
     INPUT_TEXT_LENGTH is one past the actual end of the text. */
  input_text[input_text_length] = '\n';
  /* This, on the other hand, is always necessary.  */
  input_text[input_text_length+1] = 0;
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 333 of file files.c.

{
  while (filestack)
    {
      char *fname = input_filename;
      char *text = input_text;
      popfile ();
      free (fname);
      free (text);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* full_pathname ( char *  filename) [static]

Definition at line 409 of file files.c.

{
  int initial_character;
  char *result;

  /* No filename given? */
  if (!filename || !*filename)
    return xstrdup ("");
  
  /* Already absolute? */
  if (IS_ABSOLUTE (filename) ||
      (*filename == '.' &&
       (IS_SLASH (filename[1]) ||
        (filename[1] == '.' && IS_SLASH (filename[2])))))
    return xstrdup (filename);

  initial_character = *filename;
  if (initial_character != '~')
    {
      char *localdir = xmalloc (1025);
#ifdef HAVE_GETCWD
      if (!getcwd (localdir, 1024))
#else
      if (!getwd (localdir))
#endif
        {
          fprintf (stderr, _("%s: getwd: %s, %s\n"),
                   progname, filename, localdir);
          xexit (1);
        }

      strcat (localdir, "/");
      strcat (localdir, filename);
      result = xstrdup (localdir);
      free (localdir);
    }
  else
    { /* Does anybody know why WIN32 doesn't want to support $HOME?
         If the reason is they don't have getpwnam, they should
         only disable the else clause below.  */
#ifndef WIN32
      if (IS_SLASH (filename[1]))
        {
          /* Return the concatenation of the environment variable HOME
             and the rest of the string. */
          char *temp_home;

          temp_home = (char *) getenv ("HOME");
          result = xmalloc (strlen (&filename[1])
                                    + 1
                                    + temp_home ? strlen (temp_home)
                                    : 0);
          *result = 0;

          if (temp_home)
            strcpy (result, temp_home);

          strcat (result, &filename[1]);
        }
      else
        {
          struct passwd *user_entry;
          int i, c;
          char *username = xmalloc (257);

          for (i = 1; (c = filename[i]); i++)
            {
              if (IS_SLASH (c))
                break;
              else
                username[i - 1] = c;
            }
          if (c)
            username[i - 1] = 0;

          user_entry = getpwnam (username);

          if (!user_entry)
            return xstrdup (filename);

          result = xmalloc (1 + strlen (user_entry->pw_dir)
                                    + strlen (&filename[i]));
          strcpy (result, user_entry->pw_dir);
          strcat (result, &filename[i]);
        }
#endif /* not WIN32 */
    }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* get_file_info_in_path ( char *  filename,
char *  path,
struct stat finfo 
)

Definition at line 87 of file files.c.

{
  char *dir;
  int result, index = 0;

  if (path == NULL)
    path = ".";

  /* Handle absolute pathnames.  */
  if (IS_ABSOLUTE (filename)
      || (*filename == '.'
          && (IS_SLASH (filename[1])
              || (filename[1] == '.' && IS_SLASH (filename[2])))))
    {
      if (stat (filename, finfo) == 0)
        return xstrdup (filename);
      else
        return NULL;
    }

  while ((dir = extract_colon_unit (path, &index)))
    {
      char *fullpath;

      if (!*dir)
        {
          free (dir);
          dir = xstrdup (".");
        }

      fullpath = xmalloc (2 + strlen (dir) + strlen (filename));
      sprintf (fullpath, "%s/%s", dir, filename);
      free (dir);

      result = stat (fullpath, finfo);

      if (result == 0)
        return fullpath;
      else
        free (fullpath);
    }
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 679 of file files.c.

{
  DELAYED_WRITE *temp = (DELAYED_WRITE *) reverse_list
    ((GENERIC_LIST *) delayed_writes);
  int position_shift_amount, line_number_shift_amount;
  char *delayed_buf;

  handling_delayed_writes = 1;

  while (temp)
    {
      delayed_buf = find_and_load (temp->filename, 0);

      if (output_paragraph_offset > 0)
        {
          error (_("Output buffer not empty."));
          return;
        }

      if (!delayed_buf)
        {
          fs_error (temp->filename);
          return;
        }

      output_stream = fopen (temp->filename, "w");
      if (!output_stream)
        {
          fs_error (temp->filename);
          return;
        }

      if (fwrite (delayed_buf, 1, temp->position, output_stream) != temp->position)
        {
          fs_error (temp->filename);
          return;
        }

      {
        int output_position_at_start = output_position;
        int line_number_at_start = output_line_number;

        /* In order to make warnings and errors
           refer to the correct line number.  */
        input_filename = temp->input_filename;
        line_number = temp->calling_line;

        execute_string ("%s", temp->command);
        flush_output ();

        /* Since the output file is modified, following delayed writes
           need to be updated by this amount.  */
        position_shift_amount = output_position - output_position_at_start;
        line_number_shift_amount = output_line_number - line_number_at_start;
      }

      if (fwrite (delayed_buf + temp->position, 1,
            input_text_length - temp->position, output_stream)
          != input_text_length - temp->position
          || fclose (output_stream) != 0)
        fs_error (temp->filename);

      /* Done with the buffer.  */
      free (delayed_buf);

      /* Update positions in tag table for nodes that are defined after
         the line this delayed write is registered.  */
      if (!html && !xml)
        {
          TAG_ENTRY *node;
          for (node = tag_table; node; node = node->next_ent)
            if (node->order > temp->node_order)
              node->position += position_shift_amount;
        }

      /* Something similar for the line numbers in all of the defined
         indices.  */
      {
        int i;
        for (i = 0; i < defined_indices; i++)
          if (name_index_alist[i])
            {
              char *name = ((INDEX_ALIST *) name_index_alist[i])->name;
              INDEX_ELT *index;
              for (index = index_list (name); index; index = index->next)
                if ((no_headers || STREQ (index->node, temp->node))
                    && index->entry_number > temp->index_order)
                  index->output_line += line_number_shift_amount;
            }
      }

      /* Shift remaining delayed positions
         by the length of this write.  */
      {
        DELAYED_WRITE *future_write = temp->next;
        while (future_write)
          {
            if (STREQ (temp->filename, future_write->filename))
              future_write->position += position_shift_amount;
            future_write = future_write->next;
          }
      }

      temp = temp->next;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* normalize_filename ( char *  fname)

Definition at line 572 of file files.c.

{
  int maxlen;
  char orig[PATH_MAX + 1];
  int i;
  char *lastdot, *p;

#ifdef _PC_NAME_MAX
  maxlen = pathconf (fname, _PC_NAME_MAX);
  if (maxlen < 1)
#endif
    maxlen = PATH_MAX;

  i = skip_directory_part (fname);
  if (fname[i] == '\0')
    return fname;    /* only a directory name -- don't modify */
  strcpy (orig, fname + i);

  switch (maxlen)
    {
      case 12:       /* MS-DOS 8+3 filesystem */
       if (orig[0] == '.')  /* leading dots are not allowed */
         orig[0] = '_';
       lastdot = strrchr (orig, '.');
       if (!lastdot)
         lastdot = orig + strlen (orig);
       strncpy (fname + i, orig, lastdot - orig);
       for (p = fname + i;
            p < fname + i + (lastdot - orig) && p < fname + i + 8;
            p++)
         if (*p == '.')
           *p = '_';
       *p = '\0';
       if (*lastdot == '.')
         strncat (fname + i, lastdot, 4);
       break;
      case 14:       /* old Unix systems with 14-char limitation */
       strcpy (fname + i, orig);
       if (strlen (fname + i) > 14)
         fname[i + 14] = '\0';
       break;
      default:
       strcpy (fname + i, orig);
       if (strlen (fname) > maxlen - 1)
         fname[maxlen - 1] = '\0';
       break;
    }

  return fname;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* output_name_from_input_name ( char *  name)

Definition at line 560 of file files.c.

{
  return expand_filename (NULL, name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* pathname_part ( char *  filename)

Definition at line 389 of file files.c.

{
  char *result = NULL;
  int i;

  filename = expand_filename (filename, "");

  i = skip_directory_part (filename);
  if (i)
    {
      result = xmalloc (1 + i);
      strncpy (result, filename, i);
      result[i] = 0;
    }
  free (filename);
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void pop_node_filename ( void  ) [static]

Definition at line 276 of file files.c.

Here is the caller graph for this function:

Definition at line 168 of file files.c.

{
  int i = 0;
  char *tmp;

  if (include_files_path)
    for (i = 0; i < strlen (include_files_path)
        && include_files_path[i] != ':'; i++);

  /* Advance include_files_path to the next char from ':'  */
  tmp = (char *) xmalloc (strlen (include_files_path) - i);
  strcpy (tmp, (char *) include_files_path + i + 1);

  free (include_files_path);
  include_files_path = tmp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void popfile ( void  )

Definition at line 299 of file files.c.

{
  FSTACK *tos = filestack;

  if (!tos)
    abort ();                   /* My fault.  I wonder what I did? */

  if (macro_expansion_output_stream)
    {
      maybe_write_itext (input_text, input_text_offset);
      forget_itext (input_text);
    }

  /* Pop the stack. */
  filestack = filestack->next;

  /* Make sure that commands with braces have been satisfied. */
  if (!executing_string && !me_executing_string)
    discard_braces ();

  /* Get the top of the stack into the globals. */
  input_filename = tos->filename;
  input_text = tos->text;
  input_text_length = tos->size;
  input_text_offset = tos->offset;
  line_number = tos->line_number;
  free (tos);

  /* Go back to the (now) current node. */
  pop_node_filename ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void prepend_to_include_path ( char *  path)

Definition at line 133 of file files.c.

{
  if (!include_files_path)
    {
      include_files_path = xstrdup (path);
      include_files_path = xrealloc (include_files_path,
          strlen (include_files_path) + 3); /* 3 for ":.\0" */
      strcat (strcat (include_files_path, PATH_SEP), ".");
    }
  else
    {
      char *tmp = xstrdup (include_files_path);
      include_files_path = xrealloc (include_files_path,
          strlen (include_files_path) + strlen (path) + 2); /* 2 for ":\0" */
      strcpy (include_files_path, path);
      strcat (include_files_path, PATH_SEP);
      strcat (include_files_path, tmp);
      free (tmp);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void push_node_filename ( void  ) [static]

Definition at line 265 of file files.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 283 of file files.c.

{
  FSTACK *newstack = xmalloc (sizeof (FSTACK));
  newstack->filename = input_filename;
  newstack->text = input_text;
  newstack->size = input_text_length;
  newstack->offset = input_text_offset;
  newstack->line_number = line_number;
  newstack->next = filestack;

  filestack = newstack;
  push_node_filename ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void register_delayed_write ( char *  delayed_command)

Definition at line 631 of file files.c.

{
  DELAYED_WRITE *new;

  if (!current_output_filename || !*current_output_filename)
    {
      /* Cannot register if we don't know what the output file is.  */
      warning (_("`%s' omitted before output filename"), delayed_command);
      return;
    }

  if (STREQ (current_output_filename, "-"))
    {
      /* Do not register a new write if the output file is not seekable.
         Let the user know about it first, though.  */
      warning (_("`%s' omitted since writing to stdout"), delayed_command);
      return;
    }

  /* Don't complain if the user is writing /dev/null, since surely they
     don't care, but don't register the delayed write, either.  */
  if (FILENAME_CMP (current_output_filename, NULL_DEVICE) == 0
      || FILENAME_CMP (current_output_filename, ALSO_NULL_DEVICE) == 0)
    return;
    
  /* We need the HTML header in the output,
     to get a proper output_position.  */
  if (!executing_string && html)
    html_output_head ();
  /* Get output_position updated.  */
  flush_output ();

  new = xmalloc (sizeof (DELAYED_WRITE));
  new->command = xstrdup (delayed_command);
  new->filename = xstrdup (current_output_filename);
  new->input_filename = xstrdup (input_filename);
  new->position = output_position;
  new->calling_line = line_number;
  new->node = current_node ? xstrdup (current_node): "";

  new->node_order = node_order;
  new->index_order = index_counter;

  new->next = delayed_writes;
  delayed_writes = new;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int skip_directory_part ( char *  filename) [static]

Definition at line 348 of file files.c.

{
  int i = strlen (filename) - 1;

  while (i && !IS_SLASH (filename[i]))
    i--;
  if (IS_SLASH (filename[i]))
    i++;
  else if (filename[i] && HAVE_DRIVE (filename))
    i = 2;

  return i;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 627 of file files.c.

Definition at line 29 of file files.c.

Definition at line 628 of file files.c.

char** node_filename_stack = NULL [static]

Definition at line 33 of file files.c.

Definition at line 31 of file files.c.

Definition at line 32 of file files.c.