summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo/makeinfo/files.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/texinfo/makeinfo/files.c')
-rw-r--r--contrib/texinfo/makeinfo/files.c407
1 files changed, 308 insertions, 99 deletions
diff --git a/contrib/texinfo/makeinfo/files.c b/contrib/texinfo/makeinfo/files.c
index a6a69d2..db11226 100644
--- a/contrib/texinfo/makeinfo/files.c
+++ b/contrib/texinfo/makeinfo/files.c
@@ -1,7 +1,7 @@
/* files.c -- file-related functions for makeinfo.
- $Id: files.c,v 1.3 2003/03/06 14:05:30 karl Exp $
+ $Id: files.c,v 1.5 2004/07/27 00:06:31 karl Exp $
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -20,15 +20,17 @@
#include "system.h"
#include "files.h"
+#include "html.h"
+#include "index.h"
#include "macro.h"
#include "makeinfo.h"
+#include "node.h"
FSTACK *filestack = NULL;
static int node_filename_stack_index = 0;
static int node_filename_stack_size = 0;
static char **node_filename_stack = NULL;
-
/* Looking for include files. */
@@ -36,9 +38,7 @@ static char **node_filename_stack = NULL;
return the next one pointed to by INDEX, or NULL if there are no more.
Advance INDEX to the character after the colon. */
static char *
-extract_colon_unit (string, index)
- char *string;
- int *index;
+extract_colon_unit (char *string, int *index)
{
int start;
int path_sep_char = PATH_SEP[0];
@@ -84,9 +84,7 @@ extract_colon_unit (string, index)
If PATH is NULL, only the current directory is searched.
If the file could not be found, return a NULL pointer. */
char *
-get_file_info_in_path (filename, path, finfo)
- char *filename, *path;
- struct stat *finfo;
+get_file_info_in_path (char *filename, char *path, struct stat *finfo)
{
char *dir;
int result, index = 0;
@@ -129,12 +127,68 @@ get_file_info_in_path (filename, path, finfo)
}
return NULL;
}
+
+/* Prepend and append new paths to include_files_path. */
+void
+prepend_to_include_path (char *path)
+{
+ 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);
+ }
+}
+
+void
+append_to_include_path (char *path)
+{
+ 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);
+}
+
+/* Remove the first path from the include_files_path. */
+void
+pop_path_from_include_path (void)
+{
+ 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;
+}
/* Find and load the file named FILENAME. Return a pointer to
- the loaded file, or NULL if it can't be loaded. */
+ the loaded file, or NULL if it can't be loaded. If USE_PATH is zero,
+ just look for the given file (this is used in handle_delayed_writes),
+ else search along include_files_path. */
+
char *
-find_and_load (filename)
- char *filename;
+find_and_load (char *filename, int use_path)
{
struct stat fileinfo;
long file_size;
@@ -144,7 +198,9 @@ find_and_load (filename)
result = fullpath = NULL;
- fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
+ fullpath
+ = get_file_info_in_path (filename, use_path ? include_files_path : NULL,
+ &fileinfo);
if (!fullpath)
goto error_exit;
@@ -205,8 +261,8 @@ error_exit:
}
/* Pushing and popping files. */
-void
-push_node_filename ()
+static void
+push_node_filename (void)
{
if (node_filename_stack_index + 1 > node_filename_stack_size)
node_filename_stack = xrealloc
@@ -216,15 +272,15 @@ push_node_filename ()
node_filename_stack_index++;
}
-void
-pop_node_filename ()
+static void
+pop_node_filename (void)
{
node_filename = node_filename_stack[--node_filename_stack_index];
}
/* Save the state of the current input file. */
void
-pushfile ()
+pushfile (void)
{
FSTACK *newstack = xmalloc (sizeof (FSTACK));
newstack->filename = input_filename;
@@ -240,7 +296,7 @@ pushfile ()
/* Make the current file globals be what is on top of the file stack. */
void
-popfile ()
+popfile (void)
{
FSTACK *tos = filestack;
@@ -274,7 +330,7 @@ popfile ()
/* Flush all open files on the file stack. */
void
-flush_file_stack ()
+flush_file_stack (void)
{
while (filestack)
{
@@ -289,8 +345,7 @@ flush_file_stack ()
/* Return the index of the first character in the filename
which is past all the leading directory characters. */
static int
-skip_directory_part (filename)
- char *filename;
+skip_directory_part (char *filename)
{
int i = strlen (filename) - 1;
@@ -304,9 +359,8 @@ skip_directory_part (filename)
return i;
}
-char *
-filename_non_directory (name)
- char *name;
+static char *
+filename_non_directory (char *name)
{
return xstrdup (name + skip_directory_part (name));
}
@@ -315,8 +369,7 @@ filename_non_directory (name)
filename without the path information, or extensions.
This conses up a new string. */
char *
-filename_part (filename)
- char *filename;
+filename_part (char *filename)
{
char *basename = filename_non_directory (filename);
@@ -333,10 +386,8 @@ filename_part (filename)
/* Return the pathname part of filename. This can be NULL. */
char *
-pathname_part (filename)
- char *filename;
+pathname_part (char *filename)
{
- char *expand_filename ();
char *result = NULL;
int i;
@@ -353,72 +404,9 @@ pathname_part (filename)
return result;
}
-/* Return the expansion of FILENAME. */
-char *
-expand_filename (filename, input_name)
- char *filename, *input_name;
-{
- int i;
- char *full_pathname ();
-
- 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;
-}
-
/* Return the full path to FILENAME. */
-char *
-full_pathname (filename)
- char *filename;
+static char *
+full_pathname (char *filename)
{
int initial_character;
char *result;
@@ -508,9 +496,68 @@ full_pathname (filename)
return result;
}
+/* Return the expansion of FILENAME. */
char *
-output_name_from_input_name (name)
- char *name;
+expand_filename (char *filename, char *input_name)
+{
+ 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;
+}
+
+char *
+output_name_from_input_name (char *name)
{
return expand_filename (NULL, name);
}
@@ -522,8 +569,7 @@ output_name_from_input_name (name)
never be longer than the original, otherwise we couldn't be sure we
have enough space in the original string to modify it in place. */
char *
-normalize_filename (fname)
- char *fname;
+normalize_filename (char *fname)
{
int maxlen;
char orig[PATH_MAX + 1];
@@ -573,3 +619,166 @@ normalize_filename (fname)
return fname;
}
+
+/* Delayed writing functions. A few of the commands
+ needs to be handled at the end, namely @contents,
+ @shortcontents, @printindex and @listoffloats.
+ These functions take care of that. */
+static DELAYED_WRITE *delayed_writes = NULL;
+int handling_delayed_writes = 0;
+
+void
+register_delayed_write (char *delayed_command)
+{
+ 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;
+}
+
+void
+handle_delayed_writes (void)
+{
+ 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;
+ }
+}
OpenPOWER on IntegriCloud