diff options
Diffstat (limited to 'contrib/texinfo/makeinfo/files.c')
-rw-r--r-- | contrib/texinfo/makeinfo/files.c | 407 |
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; + } +} |