[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[5500] single_file
From: |
Gavin D. Smith |
Subject: |
[5500] single_file |
Date: |
Thu, 01 May 2014 18:22:24 +0000 |
Revision: 5500
http://svn.sv.gnu.org/viewvc/?view=rev&root=texinfo&revision=5500
Author: gavin
Date: 2014-05-01 18:22:24 +0000 (Thu, 01 May 2014)
Log Message:
-----------
single_file
Modified Paths:
--------------
trunk/ChangeLog
trunk/info/Makefile.am
trunk/info/filesys.c
trunk/info/indices.c
trunk/info/indices.h
trunk/info/info.c
trunk/info/nodes.c
trunk/info/nodes.h
trunk/info/session.c
trunk/info/session.h
trunk/info/t/Init-intera.inc
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/ChangeLog 2014-05-01 18:22:24 UTC (rev 5500)
@@ -1,3 +1,46 @@
+2014-05-01 Gavin Smith <address@hidden>
+
+ * info/filesys.c (info_absolute_file, info_add_extension):
+ Function renamed.
+ (info_find_fullpath): Call info_add_extension.
+ (filesys_read_info_file): Use finfo as an output parameter instead
+ of an input parameter.
+
+ * info/indices.c (info_indices_of_window): Unused function deleted.
+ (index_entry_exists): Use FILE_BUFFER argument instead of WINDOW.
+
+ * info/info.c (single_file, main, get_initial_file)
+ (add_initial_nodes): single_file split between main and new functions.
+ --node flag works without using --file. Search in indices if
+ following menus fails.
+
+ * info/nodes.c (get_nodes_of_tags_table): Set filename on entries
+ from filename field of FILE_BUFFER, not the fullpath field.
+ (info_find_file): Deleted.
+ (info_find_file_internal, info_find_file): Renamed and argument
+ get_tags removed.
+ (info_find_subfile): New function to be used instead of
+ info_find_file_internal for retrieving subfiles.
+ (info_load_file): No longer static.
+ (make_file_buffer): Set encoding field of FILE_BUFFER.
+
+ * info/session.c (begin_multiple_window_info_session): Work
+ just as well for only one window. Don't call info_session.
+ (begin_info_session): Function deleted.
+ (display_startup_message_and_start, display_startup_message):
+ Renamed, and don't call info_session.
+ (initialize_info_session): Don't initialize the session with a
+ given NODE.
+
+ * info/session.c (info_follow_menus): Don't handle man pages or
+ look for reference labels as files. Return name of destination
+ node. All callers updated.
+ (info_intuit_options_node): Don't take window argument and return
+ name of node. Callers updated.
+ (dump_nodes_to_file): Arguments changed.
+
+ * info/t/Init-intera.inc: Redirect stdout as well as stdin.
+
2014-05-01 Karl Berry <address@hidden>
* util/gendocs.sh (copy_images): look for images in . as well
Modified: trunk/info/Makefile.am
===================================================================
--- trunk/info/Makefile.am 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/Makefile.am 2014-05-01 18:22:24 UTC (rev 5500)
@@ -109,6 +109,5 @@
t/help.sh
XFAIL_TESTS = \
- t/index-long-nodeline.sh \
- t/dir-file-node.sh
+ t/index-long-nodeline.sh
Modified: trunk/info/filesys.c
===================================================================
--- trunk/info/filesys.c 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/filesys.c 2014-05-01 18:22:24 UTC (rev 5500)
@@ -28,7 +28,7 @@
/* Local to this file. */
static char *info_file_in_path (char *filename, char *path, struct stat
*finfo);
static char *lookup_info_filename (char *filename);
-static char *info_absolute_file (char *fname, struct stat *finfo);
+static char *info_add_extension (char *fname, struct stat *finfo);
static void remember_info_filename (char *filename, char *expansion);
@@ -103,12 +103,17 @@
/* IS_SLASH and IS_ABSOLUTE defined in ../system.h. */
+ /* If path is absolute already, see if it needs an extension. */
if (IS_ABSOLUTE (partial))
- fullpath = xstrdup (partial);
+ {
+ fullpath = info_add_extension (partial, finfo);
+ }
+ /* Tilde expansion. FIXME: Not needed, because done by shell. */
else if (partial[0] == '~')
{
- fullpath = tilde_expand_word (partial);
+ partial = tilde_expand_word (partial);
+ fullpath = info_add_extension (partial, finfo);
}
/* If filename begins with "./" or "../", view it relative to
@@ -117,7 +122,7 @@
&& (IS_SLASH (partial[1])
|| (partial[1] == '.' && IS_SLASH (partial[2]))))
{
- fullpath = xstrdup (partial);
+ fullpath = info_add_extension (partial, finfo);
#if 0
/* Don't limit paths to 1023 bytes, and don't ask for
1024 bytes when it isn't needed.
@@ -141,21 +146,14 @@
#endif
}
+ /* If just a simple name element, look for it in the path. */
else
fullpath = info_file_in_path (partial, infopath (), finfo);
- /* If we have the full path to this file, we still may have to add
- various extensions to it. */
- if (fullpath)
- {
- char *tmp = fullpath;
- fullpath = info_absolute_file (fullpath, finfo);
- free (tmp);
- return fullpath;
- }
+ if (!fullpath)
+ filesys_error_number = ENOENT;
- filesys_error_number = ENOENT;
- return 0;
+ return fullpath;
}
/* Scan the list of directories in PATH looking for FILENAME. If we find
@@ -269,12 +267,12 @@
return info_file_find_next_in_path (filename, path, &i, finfo);
}
-/* Assume FNAME is an absolute file name, and look for it, adding
- file extensions if necessary. Return it as a new string; otherwise
+/* Look for a file with a path of FNAME, adding file extensions if necessary.
+ FNAME must contain directory elements. Return it as a new string; otherwise
return a NULL pointer. We do it by taking the file name apart
into its directory and basename parts, and calling info_file_in_path.*/
static char *
-info_absolute_file (char *fname, struct stat *finfo)
+info_add_extension (char *fname, struct stat *finfo)
{
char *containing_dir = xstrdup (fname);
char *base = filename_non_directory (containing_dir);
@@ -353,7 +351,6 @@
/* Read the contents of PATHNAME, returning a buffer with the contents of
that file in it, and returning the size of that buffer in FILESIZE.
- FINFO is a stat struct which has already been filled in by the caller.
If the file turns out to be compressed, set IS_COMPRESSED to non-zero.
If the file cannot be read, return a NULL pointer. Set *FINFO with
information about file. */
@@ -366,6 +363,9 @@
fsize = filesys_error_number = 0;
+ stat (pathname, finfo);
+ fsize = (long) finfo->st_size;
+
if (compressed_filename_p (pathname))
{
*is_compressed = 1;
@@ -386,7 +386,6 @@
}
/* Try to read the contents of this file. */
- fsize = (long) finfo->st_size;
contents = xmalloc (1 + fsize);
if ((read (descriptor, contents, fsize)) != fsize)
{
Modified: trunk/info/indices.c
===================================================================
--- trunk/info/indices.c 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/indices.c 2014-05-01 18:22:24 UTC (rev 5500)
@@ -87,23 +87,11 @@
index_nodenames_slots, 10);
}
-/* Find and return the indices of WINDOW's file. The indices are defined
+/* Find and return the indices of FILE_BUFFER. The indices are defined
as the first node in the file containing the word "Index" and any
immediately following nodes whose names also contain "Index". All such
- indices are concatenated and the result returned. If WINDOW's info file
- doesn't have any indices, a NULL pointer is returned. */
+ indices are concatenated and the result returned. */
REFERENCE **
-info_indices_of_window (WINDOW *window)
-{
- FILE_BUFFER *fb;
-
- fb = file_buffer_of_window (window);
-
- return info_indices_of_file_buffer (fb);
-}
-
-/* Search for index nodes in FILE_BUFFER and built up composite menu. */
-REFERENCE **
info_indices_of_file_buffer (FILE_BUFFER *file_buffer)
{
register int i;
@@ -297,20 +285,17 @@
}
}
-/* Return 1 if STRING appears in indicies of file_buffer_of_window (WINDOW),
- 0 otherwise. */
+/* Return 1 if STRING appears in indicies of FB, 0 otherwise. */
int
-index_entry_exists (WINDOW *window, char *string)
+index_entry_exists (FILE_BUFFER *fb, char *string)
{
register int i;
- FILE_BUFFER *fb;
/* If there is no previous search string, the user hasn't built an index
yet. */
if (!string)
return 0;
- fb = file_buffer_of_window (window);
if (!initial_index_filename ||
!fb ||
(FILENAME_CMP (initial_index_filename, fb->filename) != 0))
Modified: trunk/info/indices.h
===================================================================
--- trunk/info/indices.h 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/indices.h 2014-05-01 18:22:24 UTC (rev 5500)
@@ -25,7 +25,6 @@
/* User-visible variable controls the output of info-index-next. */
extern int show_index_match;
-extern REFERENCE **info_indices_of_window (WINDOW *window);
extern REFERENCE **info_indices_of_file_buffer (FILE_BUFFER *file_buffer);
extern void info_apropos (char *string);
@@ -37,7 +36,7 @@
extern void info_next_index_match (WINDOW *window, int count, unsigned char
key);
extern void info_index_apropos (WINDOW *window, int count, unsigned char key);
extern void do_info_index_search (WINDOW *window, int count, char
*search_string);
-extern int index_entry_exists (WINDOW *window, char *string);
+extern int index_entry_exists (FILE_BUFFER *fb, char *string);
NODE *allfiles_create_node (char *term, REFERENCE **fref);
Modified: trunk/info/info.c
===================================================================
--- trunk/info/info.c 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/info.c 2014-05-01 18:22:24 UTC (rev 5500)
@@ -24,6 +24,7 @@
#include "indices.h"
#include "dribble.h"
#include "getopt.h"
+#include "man.h"
#include "variables.h"
char *program_name = "info";
@@ -154,7 +155,7 @@
static void init_messages (void);
-static const char *
+static char *
node_file_name (NODE *node, int dirok)
{
if (node->parent)
@@ -166,168 +167,196 @@
return 0;
}
-static int
-single_file (char *filename, int argc, char **argv)
+/* Get the initial Info file, either by following menus from "(dir)Top",
+ or what the user specifed with values in filename. */
+static char *
+get_initial_file (char *filename, int *argc, char ***argv, NODE **error_node)
{
- NODE *initial_node; /* First node loaded by Info. */
- NODE *new_initial_node, *error_node;
-
- /* Get the initial Info node. It is either "(dir)Top", or what the user
- specifed with values in filename and user_nodenames. */
- initial_node = info_get_node (filename,
- user_nodenames ? user_nodenames[0] : 0,
- PARSE_NODE_DFLT);
+ char *initial_file = 0; /* First file loaded by Info. */
- /* If we couldn't get the initial node, this user is in trouble. */
- if (!initial_node)
+ if (!filename)
{
- if (info_recent_file_error)
- info_error ("%s", info_recent_file_error);
+ NODE *dir_node;
+ REFERENCE *entry = 0;
+
+ /* If there are any more arguments, the initial file is the
+ dir entry given by the first one. */
+ if ((*argv)[0])
+ {
+ dir_node = info_get_node (0, 0, PARSE_NODE_DFLT);
+
+ entry = info_get_menu_entry_by_label ((*argv)[0],
+ dir_node->references);
+ if (entry)
+ initial_file = info_find_fullpath (entry->filename, 0);
+
+ if (!initial_file)
+ /* Try finding a file with this name, in case
+ it exists, but wasn't listed in dir. */
+ initial_file = info_find_fullpath ((*argv)[0], 0);
+
+ if (initial_file)
+ {
+ (*argv)++; /* Advance past first remaining argument. */
+ (*argc)--;
+ }
+ else
+ *error_node = format_message_node (_("No menu item `%s' in node
`%s'."),
+ (*argv)[0],
+ "(dir)Top");
+ }
+ /* Otherwise, we want the dir node. The only node to be displayed
+ or output will be "Top". */
else
- info_error (msg_cant_find_node,
- user_nodenames ? user_nodenames[0] : "Top");
- return EXIT_FAILURE;
+ {
+ return 0;
+ }
}
+ else
+ {
+ initial_file = info_find_fullpath (filename, 0);
- /* Special cases for when the user specifies multiple nodes. If we
- are dumping to an output file, dump all of the nodes specified.
- Otherwise, attempt to create enough windows to handle the nodes
- that this user wants displayed. */
- if (user_nodenames_index > 1)
+ if (!initial_file && filesys_error_number)
+ {
+ char *error_string;
+
+ error_string = filesys_error_string
+ (filename, filesys_error_number);
+ *error_node = format_message_node ("%s", error_string);
+ free (error_string);
+ }
+ }
+
+ /* Fall back to loading man page. */
+ if (!initial_file)
{
- free (initial_node);
+ NODE *man_node;
- if (print_where_p)
- printf ("%s\n", filename ? filename : "unknown?!");
- else if (user_output_filename)
- dump_nodes_to_file (filename, user_nodenames,
- user_output_filename, dump_subnodes);
- else
- begin_multiple_window_info_session (filename, user_nodenames);
+ debug (3, ("falling back to manpage node"));
- return EXIT_SUCCESS;
+ if (!filename)
+ filename = (*argv)[0];
+
+ man_node = get_manpage_node (filename);
+
+ if (man_node)
+ {
+ free (man_node);
+ initial_file = MANPAGE_FILE_BUFFER_NAME;
+ add_pointer_to_array (filename, user_nodenames_index,
+ user_nodenames, user_nodenames_slots, 10);
+ return initial_file;
+ }
}
- /* If there are arguments remaining, they are the names of menu items
- in sequential info files starting from the first one loaded. That
- file name is either "dir", or the contents of filename if one
- was specified. */
- /* If they say info -O info, we want to show them the invocation node
- for standalone info; there's nothing useful in info.texi. */
- if (goto_invocation_p && *argv
- && mbscasecmp (*argv, "info") == 0)
- *argv = "info-stnd";
+ return initial_file;
+}
- new_initial_node = info_follow_menus (initial_node, argv, &error_node, 0);
+/* Expand list of nodes to be loaded. */
+static void
+add_initial_nodes (FILE_BUFFER *initial_file, int argc, char **argv, NODE
**error_node)
+{
+ NODE *initial_node;
+ char *node_via_menus;
- if (new_initial_node && new_initial_node != initial_node)
- initial_node = new_initial_node;
+ if (goto_invocation_p)
+ {
+ NODE *top_node;
+ char *invoc_node;
- if (print_where_p)
+ char **p = argv;
+ char *program;
+
+ /* If they say info -O info, we want to show them the invocation node
+ for standalone info; there's nothing useful in info.texi. */
+ if (argv[0] && mbscasecmp (*argv, "info") == 0)
+ *argv = "info-stnd";
+
+ /* If they said "info --show-options foo bar baz",
+ the last of the arguments is the program whose
+ options they want to see. */
+ p = argv;
+ if (*p)
+ {
+ while (p[1])
+ p++;
+ program = xstrdup (*p);
+ }
+ else if (initial_file->filename)
+ /* If there's no command-line arguments to
+ supply the program name, use the Info file
+ name (sans extension and leading directories)
+ instead. */
+ program = program_name_from_file_name (initial_file->filename);
+ else
+ program = xstrdup ("");
+
+ top_node = info_get_node_of_file_buffer ("Top", initial_file);
+ invoc_node = info_intuit_options_node (top_node, program);
+ if (invoc_node)
+ add_pointer_to_array (invoc_node, user_nodenames_index,
+ user_nodenames, user_nodenames_slots, 10);
+ }
+
+ /* If there are arguments remaining, they are the names of menu items
+ in sequential info files starting from the first one loaded. Add
+ this to the list of nodes specified with --node. */
+ else if (*argv)
{
- const char *name = node_file_name (initial_node, 0);
- if (!name)
- return EXIT_FAILURE;
- printf ("%s\n", name);
- return EXIT_SUCCESS;
+ NODE *initial_node;
+
+ initial_node = info_get_node_of_file_buffer ("Top", initial_file);
+ node_via_menus = info_follow_menus (initial_node, argv, error_node, 1);
+ if (node_via_menus)
+ add_pointer_to_array (node_via_menus, user_nodenames_index,
+ user_nodenames, user_nodenames_slots, 10);
}
- /* If the user specified that this node should be output, then do that
- now. Otherwise, start the Info session with this node. Or act
- accordingly if the initial node was not found. */
- if (user_output_filename && !goto_invocation_p)
+ /* If no nodes found, and there is exactly one argument, check for
+ it as an index entry. */
+ /* FIXME: This works, but doesn't go to the right position in the
+ node. Maybe we could do it along with --index-search somehow? */
+ if (user_nodenames_index == 0 && argc == 1 && argv[0])
{
- if (error_node)
- show_error_node (error_node);
- else
- dump_node_to_file (initial_node, user_output_filename,
- dump_subnodes);
+ REFERENCE **index;
+ REFERENCE **index_ptr;
+
+ //debug (3. "looking in indices);
+ index = info_indices_of_file_buffer (initial_file);
+
+ for (index_ptr = index; index && *index_ptr; index_ptr++)
+ {
+ if (!strcmp (argv[0], (*index_ptr)->label))
+ {
+ /* TODO: Clear error_node */
+ add_pointer_to_array ((*index_ptr)->nodename,
+ user_nodenames_index, user_nodenames,
+ user_nodenames_slots, 10);
+ break;
+ }
+ }
}
- else
+
+ /* If still no nodes and there are arguments remaining, follow menus
+ inexactly. */
+ if (user_nodenames_index == 0 && *argv)
{
- if (error_node)
- {
- initialize_info_session (initial_node, 1);
- show_error_node (error_node);
- info_session ();
- }
-
- /* If the user specified `--index-search=STRING' or
- --show-options, start the info session in the node
- corresponding to what they want. */
- else if (index_search_p || goto_invocation_p)
- {
- int status = EXIT_SUCCESS;
-
- initialize_info_session (initial_node, 0);
-
- if (goto_invocation_p ||
- index_entry_exists (windows, index_search_string))
- {
- terminal_prep_terminal ();
- terminal_clear_screen ();
- info_last_executed_command = NULL;
-
- if (index_search_p)
- do_info_index_search (windows, 0, index_search_string);
- else
- {
- /* If they said "info --show-options foo bar baz",
- the last of the arguments is the program whose
- options they want to see. */
- char **p = argv;
- char *program;
-
- if (*p)
- {
- while (p[1])
- p++;
- program = xstrdup (*p);
- }
- else if (filename)
- /* If there's no command-line arguments to
- supply the program name, use the Info file
- name (sans extension and leading directories)
- instead. */
- program = program_name_from_file_name (filename);
- else
- program = xstrdup ("");
-
- info_intuit_options_node (windows, initial_node, program);
- free (program);
- }
-
- if (user_output_filename)
- {
- dump_node_to_file (windows->node, user_output_filename,
- dump_subnodes);
- }
- else
- info_read_and_dispatch ();
-
- /* On program exit, leave the cursor at the bottom of the
- window, and restore the terminal IO. */
- terminal_goto_xy (0, screenheight - 1);
- terminal_clear_to_eol ();
- fflush (stdout);
- terminal_unprep_terminal ();
- }
- else
- {
- fprintf (stderr, _("no index entries found for `%s'\n"),
- index_search_string);
- status = EXIT_FAILURE;
- }
-
- close_dribble_file ();
- return status;
- }
- else
- begin_info_session (initial_node);
+ NODE *initial_node;
+
+ initial_node = info_get_node_of_file_buffer ("Top", initial_file);
+ node_via_menus = info_follow_menus (initial_node, argv, error_node, 0);
+ if (node_via_menus)
+ add_pointer_to_array (node_via_menus, user_nodenames_index,
+ user_nodenames, user_nodenames_slots, 10);
}
- return EXIT_SUCCESS;
+ /* Default in case there were no other nodes. */
+ if (user_nodenames_index == 0)
+ add_pointer_to_array ("Top", user_nodenames_index,
+ user_nodenames, user_nodenames_slots, 10);
+
}
+
static char *
dirname (const char *file)
@@ -416,7 +445,9 @@
if (node)
{
- NODE *subnode = info_follow_menus (node, argv, NULL, 1);
+ char *subnode_name = info_follow_menus (node, argv, NULL, 1);
+ NODE *subnode = info_get_node (node->filename, subnode_name,
+ PARSE_NODE_DFLT);
if (!subnode)
{
forget_info_file (fref[i]->filename);
@@ -473,10 +504,19 @@
if (print_where_p || user_output_filename)
return EXIT_SUCCESS;
+#if 0
if (i <= 1)
- return single_file (user_filename, argc, argv);
+ {
+ if (!single_file (user_filename, argc, argv))
+ return EXIT_FAILURE;
+ info_session ();
+ }
+#endif
- begin_info_session (allfiles_create_node (argc ? argv[0] : fname, fref));
+ initialize_info_session (1);
+ info_set_node_of_window (0, active_window, allfiles_create_node (argc ?
argv[0] : fname, fref));;
+ display_startup_message ();
+ info_session ();
return EXIT_SUCCESS;
}
@@ -506,8 +546,11 @@
int
main (int argc, char *argv[])
{
- int getopt_long_index; /* Index returned by getopt_long (). */
- char *init_file = 0; /* Name of init file specified. */
+ int getopt_long_index; /* Index returned by getopt_long (). */
+ char *init_file = 0; /* Name of init file specified. */
+ char *initial_file = 0; /* File to start session with. */
+ FILE_BUFFER *initial_fb = 0; /* File to start session with. */
+ NODE *error_node = 0; /* Error message to display in mini-buffer. */
#ifdef HAVE_SETLOCALE
/* Set locale via LC_ALL. */
@@ -732,7 +775,83 @@
if (all_matches_p)
return all_files (user_filename, argc, argv);
- return single_file (user_filename, argc, argv);
+ initial_file = get_initial_file (user_filename, &argc, &argv, &error_node);
+
+ /* --where */
+ if (print_where_p)
+ {
+ if (initial_file)
+ {
+ printf ("%s\n", initial_file);
+ return 0;
+ }
+ else
+ return 1;
+ }
+
+ /* If the user specified `--index-search=STRING',
+ start the info session in the node corresponding
+ to what they want. */
+ if (index_search_p && initial_file && !user_output_filename)
+ {
+ NODE *initial_node;
+
+ initial_fb = info_load_file (initial_file, 1);
+ if (initial_fb && index_entry_exists (initial_fb, index_search_string))
+ {
+ initialize_info_session (1);
+ initial_node = info_get_node (initial_file, "Top", PARSE_NODE_DFLT);
+ info_set_node_of_window (0, active_window, initial_node);
+ do_info_index_search (windows, 0, index_search_string);
+ }
+ else
+ {
+ fprintf (stderr, _("no index entries found for `%s'\n"),
+ index_search_string);
+ close_dribble_file ();
+ return 1;
+ }
+
+ info_session ();
+ return 0;
+ }
+
+ /* Add nodes to start with (unless we fell back to the man page). */
+ else if (initial_file && strcmp (MANPAGE_FILE_BUFFER_NAME, initial_file))
+ {
+ initial_fb = info_load_file (initial_file, 1);
+ add_initial_nodes (initial_fb, argc, argv, &error_node);
+ }
+
+ if (!user_output_filename
+ && !(user_filename && error_node))
+ initialize_info_session (1);
+
+ if (error_node)
+ show_error_node (error_node);
+ else if (!user_output_filename)
+ display_startup_message ();
+
+ /* --output */
+ if (user_output_filename)
+ {
+ if (!initial_fb) return 0;
+ /* FIXME: Was two separate functions, dump_node_to_file as well.
+ Check behaviour is the same. */
+ dump_nodes_to_file (initial_fb, user_nodenames,
+ user_output_filename, dump_subnodes);
+ return 0;
+ }
+
+ /* Initialize the Info session. */
+
+ if (!(user_filename && error_node))
+ begin_multiple_window_info_session (initial_file, user_nodenames);
+ else
+ return 1;
+
+ info_session ();
+ return 0;
}
void
@@ -867,7 +986,7 @@
{
if (info_error_rings_bell_p)
terminal_ring_bell ();
- if (user_output_filename)
+ if (!info_windows_initialized_p)
{
if (node->contents[node->nodelen - 1] == '\n')
node->contents[node->nodelen - 1] = 0;
Modified: trunk/info/nodes.c
===================================================================
--- trunk/info/nodes.c 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/nodes.c 2014-05-01 18:22:24 UTC (rev 5500)
@@ -335,7 +335,7 @@
/* The filename of this node is currently known as the same as the
name of this file. */
- entry->filename = file_buffer->fullpath;
+ entry->filename = file_buffer->filename;
/* Add this node structure to the array of node structures in this
FILE_BUFFER. */
@@ -565,15 +565,14 @@
/* Functions for retrieving files. */
-/* Passed to info_find_file_internal and info_load_file. INFO_GET_TAGS
+/* Passed to info_load_file. INFO_GET_TAGS
says to do what is neccessary to fill in the nodes or tags arrays in
FILE_BUFFER. */
#define INFO_NO_TAGS 0
#define INFO_GET_TAGS 1
-static FILE_BUFFER *info_find_file_internal (char *filename, int get_tags);
+static FILE_BUFFER *info_find_subfile (char *filename);
static void get_file_character_encoding (FILE_BUFFER *fb);
-static FILE_BUFFER *info_load_file (char *filename, int get_tags);
static void remember_info_file (FILE_BUFFER *file_buffer);
static void info_reload_file_buffer_contents (FILE_BUFFER *fb);
@@ -582,22 +581,18 @@
already, or it may not. If it does not already appear, find the file,
and add it to the list of loaded files. If the file cannot be found,
return a NULL FILE_BUFFER *. */
-FILE_BUFFER *
-info_find_file (char *filename)
-{
- return info_find_file_internal (filename, INFO_GET_TAGS);
-}
/* The workhorse for info_find_file (). Non-zero 2nd argument says to
try to build a tags table (or otherwise glean the nodes) for this
file once found. By default, we build the tags table, but when this
function is called by info_get_node () when we already have a valid
tags table describing the nodes, it is unnecessary. */
-static FILE_BUFFER *
-info_find_file_internal (char *filename, int get_tags)
+FILE_BUFFER *
+info_find_file (char *filename)
{
int i;
FILE_BUFFER *file_buffer;
+ char *fullpath;
/* First try to find the file in our list of already loaded files. */
if (info_loaded_files)
@@ -644,7 +639,7 @@
return NULL;
}
- if (get_tags && !file_buffer->tags)
+ if (!file_buffer->tags)
build_tags_and_nodes (file_buffer);
return file_buffer;
@@ -653,80 +648,13 @@
}
/* The file wasn't loaded. Try to load it now. */
- file_buffer = info_load_file (filename, get_tags);
- /* If the file was loaded, remember the name under which it was found. */
- if (file_buffer)
- remember_info_file (file_buffer);
-
- return file_buffer;
-}
-
-/* Look for local variables section in FB and set encoding */
-static void
-get_file_character_encoding (FILE_BUFFER *fb)
-{
- SEARCH_BINDING binding;
- long position;
-
- long int enc_start, enc_end;
- char *enc_string;
-
- char **encoding_name;
-
- /* See if there is a local variables section in this info file. */
- binding.buffer = fb->contents;
- binding.start = fb->filesize;
- binding.end = binding.start - 1000;
- if (binding.end < 0)
- binding.end = 0;
- binding.flags = S_FoldCase;
-
- /* Null means the encoding is unknown. */
- fb->encoding = 0;
-
- if (search_backward (LOCAL_VARIABLES_LABEL, &binding, &position)
- != search_success)
- return;
-
- binding.start = position;
- binding.end = fb->filesize;
-
- if (search_forward (CHARACTER_ENCODING_LABEL, &binding, &enc_start)
- != search_success)
- return;
-
- enc_start += strlen(CHARACTER_ENCODING_LABEL); /* Skip to after "coding:" */
- enc_start += skip_whitespace(fb->contents + enc_start);
- binding.start = enc_start;
-
- search_forward ("\n", &binding, &enc_end);
-
- enc_string = xmalloc (enc_end - enc_start + 1);
- strncpy (enc_string, fb->contents + enc_start, enc_end - enc_start);
- enc_string[enc_end - enc_start] = '\0';
-
- fb->encoding = enc_string;
-}
-
-/* Force load the file named FILENAME, and return the information structure
- describing this file, even if the file was already loaded. Non-zero
- second argument says to build a list of tags (or nodes) for this file.
- This is not necessary when loading a subfile for which we already have
- tags. */
-static FILE_BUFFER *
-info_load_file (char *filename, int get_tags)
-{
- char *fullpath, *contents;
- size_t filesize;
- struct stat finfo;
- int compressed;
- FILE_BUFFER *file_buffer = NULL;
-
/* Get the full pathname of this file, as known by the info system.
That is to say, search along INFOPATH and expand tildes, etc. */
- fullpath = info_find_fullpath (filename, &finfo);
+ fullpath = info_find_fullpath (filename, 0);
+ /* FIXME: Put the following in info_find_fullpath, or remove
+ it altogether. */
/* If the file referenced by the name returned from info_find_fullpath ()
doesn't exist, then try again with the last part of the filename
appearing in lowercase. */
@@ -749,7 +677,7 @@
tmp_basename++;
}
- fullpath = info_find_fullpath (lowered_name, &finfo);
+ fullpath = info_find_fullpath (lowered_name, 0);
free (lowered_name);
}
@@ -758,7 +686,53 @@
if (!fullpath)
return NULL;
- /* Otherwise, try to load the file. */
+ file_buffer = info_load_file (fullpath, INFO_GET_TAGS);
+
+ return file_buffer;
+}
+
+/* Find a subfile of a split file. This differs from info_load_file in
+ that it does not fill in a tag table for the file.
+ FIXME: Only look for subfile in same directory as master file. */
+static FILE_BUFFER *
+info_find_subfile (char *filename)
+{
+ int i;
+ FILE_BUFFER *file_buffer = 0;
+ char *fullpath;
+
+ /* First try to find the file in our list of already loaded files. */
+ if (info_loaded_files)
+ {
+ for (i = 0; (file_buffer = info_loaded_files[i]); i++)
+ if (FILENAME_CMP (filename, file_buffer->filename) == 0
+ || FILENAME_CMP (filename, file_buffer->fullpath) == 0)
+ {
+ /* TODO: Check if it's changed since last time. */
+ return file_buffer;
+ }
+ }
+
+ fullpath = info_find_fullpath (filename, 0);
+ if (fullpath)
+ file_buffer = info_load_file (fullpath, INFO_NO_TAGS);
+ return file_buffer;
+}
+
+/* Load the file with path FULLPATH, and return the information structure
+ describing this file, even if the file was already loaded. Non-zero
+ second argument says to build a list of tags (or nodes) for this file.
+ This is not necessary when loading a subfile for which we already have
+ tags. */
+FILE_BUFFER *
+info_load_file (char *fullpath, int get_tags)
+{
+ char *contents;
+ size_t filesize;
+ struct stat finfo;
+ int compressed;
+ FILE_BUFFER *file_buffer = NULL;
+
contents = filesys_read_info_file (fullpath, &filesize, &finfo, &compressed);
if (!contents)
@@ -767,8 +741,8 @@
/* The file was found, and can be read. Allocate FILE_BUFFER and fill
in the various members. */
file_buffer = make_file_buffer ();
- file_buffer->filename = xstrdup (filename);
file_buffer->fullpath = fullpath;
+ file_buffer->filename = filename_non_directory (fullpath);
file_buffer->finfo = finfo;
file_buffer->filesize = filesize;
file_buffer->contents = contents;
@@ -782,9 +756,60 @@
if (get_tags)
build_tags_and_nodes (file_buffer);
+ /* If the file was loaded, remember the name under which it was found. */
+ if (file_buffer)
+ remember_info_file (file_buffer);
+
return file_buffer;
}
+/* Look for local variables section in FB and set encoding */
+static void
+get_file_character_encoding (FILE_BUFFER *fb)
+{
+ SEARCH_BINDING binding;
+ long position;
+
+ long int enc_start, enc_end;
+ char *enc_string;
+
+ char **encoding_name;
+
+ /* See if there is a local variables section in this info file. */
+ binding.buffer = fb->contents;
+ binding.start = fb->filesize;
+ binding.end = binding.start - 1000;
+ if (binding.end < 0)
+ binding.end = 0;
+ binding.flags = S_FoldCase;
+
+ /* Null means the encoding is unknown. */
+ fb->encoding = 0;
+
+ if (search_backward (LOCAL_VARIABLES_LABEL, &binding, &position)
+ != search_success)
+ return;
+
+ binding.start = position;
+ binding.end = fb->filesize;
+
+ if (search_forward (CHARACTER_ENCODING_LABEL, &binding, &enc_start)
+ != search_success)
+ return;
+
+ enc_start += strlen(CHARACTER_ENCODING_LABEL); /* Skip to after "coding:" */
+ enc_start += skip_whitespace(fb->contents + enc_start);
+ binding.start = enc_start;
+
+ search_forward ("\n", &binding, &enc_end);
+
+ enc_string = xmalloc (enc_end - enc_start + 1);
+ strncpy (enc_string, fb->contents + enc_start, enc_end - enc_start);
+ enc_string[enc_end - enc_start] = '\0';
+
+ fb->encoding = enc_string;
+}
+
/* Create a new, empty file buffer. */
FILE_BUFFER *
make_file_buffer (void)
@@ -797,6 +822,7 @@
file_buffer->subfiles = NULL;
file_buffer->tags_slots = 0;
file_buffer->flags = 0;
+ file_buffer->encoding = 0;
return file_buffer;
}
@@ -828,7 +854,6 @@
if (FILENAME_CMP (filename, file_buffer->filename) == 0
|| FILENAME_CMP (filename, file_buffer->fullpath) == 0)
{
- free (file_buffer->filename);
free (file_buffer->fullpath);
if (file_buffer->contents)
@@ -1180,7 +1205,7 @@
if (!strcmp (fb->filename, tag->filename))
subfile = fb;
else
- subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS);
+ subfile = info_find_subfile (tag->filename);
if (!subfile)
return NULL;
Modified: trunk/info/nodes.h
===================================================================
--- trunk/info/nodes.h 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/nodes.h 2014-05-01 18:22:24 UTC (rev 5500)
@@ -149,6 +149,10 @@
return a NULL FILE_BUFFER *. */
extern FILE_BUFFER *info_find_file (char *filename);
+/* Load the file with path FULLPATH, and return pointer to FILE_BUFFER
+ structure. If GET_TAGS == 0, don't fill in the tag table. */
+extern FILE_BUFFER *info_load_file (char *fullpath, int get_tags);
+
/* Return a pointer to a new NODE structure. */
extern NODE *info_create_node (void);
Modified: trunk/info/session.c
===================================================================
--- trunk/info/session.c 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/session.c 2014-05-01 18:22:24 UTC (rev 5500)
@@ -84,7 +84,7 @@
void remember_window_and_node (WINDOW *window, NODE *node);
void forget_window_and_nodes (WINDOW *window);
-void display_startup_message_and_start (void);
+void display_startup_message (void);
/* Begin an info session finding the nodes specified by FILENAME and NODENAMES.
For each loaded node, create a new window. Always split the largest of the
@@ -93,22 +93,46 @@
begin_multiple_window_info_session (char *filename, char **nodenames)
{
register int i;
- WINDOW *window = NULL;
+ WINDOW *window = 0;
+ FILE_BUFFER *fb;
+ /* Load dir node as a back-up. */
+ if (!filename || !nodenames || !nodenames[0])
+ {
+ /* Used to build `dir' menu from `localdir' files found in INFOPATH. */
+ extern NODE *dir_node (void);
+
+ NODE *node;
+
+ node = dir_node ();
+ info_set_node_of_window (0, active_window, node);
+ return;
+ }
+
+ if (!strcmp (MANPAGE_FILE_BUFFER_NAME, filename))
+ {
+ NODE *node;
+
+ node = get_manpage_node (nodenames[0]);
+ if (node)
+ info_set_node_of_window (0, active_window, node);
+ return;
+ }
+
+ fb = info_find_file (filename);
for (i = 0; nodenames[i]; i++)
{
NODE *node;
- node = info_get_node (filename, nodenames[i], PARSE_NODE_DFLT);
+ node = info_get_node_of_file_buffer (nodenames[i], fb);
if (!node)
break;
- /* If this is the first node, initialize the info session. */
if (!window)
{
- initialize_info_session (node, 1);
window = active_window;
+ info_set_node_of_window (0, window, node);
}
else
{
@@ -149,20 +173,11 @@
}
}
}
- display_startup_message_and_start ();
}
-/* Start an info session with INITIAL_NODE. */
void
-begin_info_session (NODE *initial_node)
+display_startup_message (void)
{
- initialize_info_session (initial_node, 1);
- display_startup_message_and_start ();
-}
-
-void
-display_startup_message_and_start (void)
-{
char *format;
format = replace_in_documentation
@@ -170,7 +185,6 @@
0);
window_message_in_echo_area (format, VERSION, NULL);
- info_session ();
}
/* Run an info session with an already initialized window and node. */
@@ -275,7 +289,7 @@
/* Initialize the first info session by starting the terminal, window,
and display systems. If CLEAR_SCREEN is 0, don't clear the screen. */
void
-initialize_info_session (NODE *node, int clear_screen)
+initialize_info_session (int clear_screen)
{
if (clear_screen)
{
@@ -286,7 +300,6 @@
window_initialize_windows (screenwidth, screenheight);
initialize_info_signal_handler ();
display_initialize_display (screenwidth, screenheight);
- info_set_node_of_window (0, active_window, node);
/* Tell the window system how to notify us when a window needs to be
asynchronously deleted (e.g., user resizes window very small). */
@@ -2778,13 +2791,12 @@
}
/* Follow the menu list in MENUS (list of strings terminated by a NULL
- entry) from INITIAL_NODE. If can't continue at any point (no menu or
- no menu entry for the next item), return the node so far -- that
- might be INITIAL_NODE itself. If error, *ERRSTR and *ERRARG[12] will
- be set to the error message and argument for message, otherwise they
- will be NULL. */
-
-NODE *
+ entry) from INITIAL_NODE. If there is an error, place a message
+ in ERR_NODE. STRICT says whether to accept incomplete strings as
+ menu entries, and whether to return the node so far if we can't
+ continue at any point (that might be INITIAL_NODE itself), or to
+ return null. */
+char *
info_follow_menus (NODE *initial_node, char **menus, NODE **err_node,
int strict)
{
@@ -2792,59 +2804,38 @@
if (err_node)
*err_node = NULL;
+
for (; *menus; menus++)
{
static char *first_arg = NULL;
- REFERENCE **menu;
REFERENCE *entry;
char *arg = *menus; /* Remember the name of the menu entry we want. */
debug (3, ("looking for %s in %s:%s", arg, initial_node->filename,
initial_node->nodename));
- /* A leading space is certainly NOT part of a node name. Most
- probably, they typed a space after the separating comma. The
- strings in menus[] have their whitespace canonicalized, so
- there's at most one space to ignore. */
- if (*arg == ' ')
- arg++;
- if (!first_arg)
- first_arg = arg;
- menu = initial_node->references;
-
- /* If no menu item in this node, stop here, but let the user
- continue to use Info. Perhaps they wanted this node and didn't
- realize it. */
- if (!menu)
+ if (!initial_node->references)
{
- debug (3, ("no menu found"));
- if (arg == first_arg && !strict)
- {
- node = get_manpage_node (first_arg);
- if (node)
- {
- debug (3, ("falling back to manpage node"));
- goto maybe_got_node;
- }
- }
- if (err_node)
- *err_node = format_message_node (_("No menu in node `%s'."),
- node_printed_rep (initial_node));
- return strict ? NULL : initial_node;
+ if (err_node)
+ *err_node = format_message_node (_("No menu in node `%s'."),
+ node_printed_rep (initial_node));
+ debug (3, ("no menu found"));
+ free (initial_node);
+ return strict ? 0 : initial_node->nodename;
}
/* Find the specified menu item. */
- entry = info_get_menu_entry_by_label (arg, menu);
+ entry = info_get_menu_entry_by_label (arg, initial_node->references);
/* If the item wasn't found, search the list sloppily. Perhaps this
user typed "buffer" when they really meant "Buffers". */
- if (!entry)
+ if (!strict && !entry)
{
int i;
int best_guess = -1;
debug (3, ("no entry found: guessing"));
- for (i = 0; (entry = menu[i]); i++)
+ for (i = 0; (entry = initial_node->references[i]); i++)
{
if (mbscasecmp (entry->label, arg) == 0)
break;
@@ -2854,59 +2845,26 @@
}
if (!entry && best_guess != -1)
- entry = menu[best_guess];
+ entry = initial_node->references[best_guess];
}
- /* If we still failed to find the reference, start Info with the current
- node anyway. It is probably a misspelling. */
+ /* If we still failed to find the reference: */
if (!entry)
{
- if (arg == first_arg)
- {
- /* Maybe they typed "info foo" instead of "info -f foo". */
- node = info_get_node (first_arg, NULL, PARSE_NODE_DFLT);
- if (node)
- add_file_directory_to_path (first_arg);
- else if (strict)
- return NULL;
- else
- node = get_manpage_node (first_arg);
- if (node)
- goto maybe_got_node;
- }
-
- if (err_node)
- *err_node = format_message_node (_("No menu item `%s' in node
`%s'."),
- arg,
- node_printed_rep (initial_node));
- return strict ? NULL : initial_node;
+ if (err_node)
+ *err_node = format_message_node (_("No menu item `%s' in node
`%s'."),
+ arg,
+ node_printed_rep (initial_node));
+ debug (3, ("no entry found"));
+ free (initial_node);
+ return strict ? 0 : initial_node->nodename;
}
- /* We have found the reference that the user specified. If no
- filename in this reference, define it. */
- if (!entry->filename)
- entry->filename = xstrdup (initial_node->parent ? initial_node->parent
- : initial_node->filename);
-
debug (3, ("entry: %s, %s", entry->filename, entry->nodename));
/* Try to find this node. */
- node = info_get_node (entry->filename, entry->nodename,
- PARSE_NODE_VERBATIM);
- if (!strict && !node && arg == first_arg)
- {
- node = get_manpage_node (first_arg);
- if (node)
- goto maybe_got_node;
- }
-
- /* Since we cannot find it, try using the label of the entry as a
- file, i.e., "(LABEL)Top". */
- if (!node && entry->nodename
- && strcmp (entry->label, entry->nodename) == 0)
- node = info_get_node (entry->label, "Top", PARSE_NODE_DFLT);
-
- maybe_got_node:
+ node = info_get_node (initial_node->filename, entry->nodename,
+ PARSE_NODE_DFLT);
if (!node)
{
debug (3, ("no matching node found"));
@@ -2915,7 +2873,8 @@
_("Unable to find node referenced by `%s' in `%s'."),
entry->label,
node_printed_rep (initial_node));
- return strict ? NULL : initial_node;
+ free (initial_node);
+ return strict ? 0 : initial_node->nodename;
}
debug (3, ("node: %s, %s", node->filename, node->nodename));
@@ -2925,7 +2884,8 @@
initial_node = node;
}
- return initial_node;
+ free (initial_node);
+ return initial_node->nodename;
}
/* Split STR into individual node names by writing null bytes in wherever
@@ -2979,7 +2939,7 @@
NODE *err_node;
NODE *dir_node = info_get_node (NULL, NULL, PARSE_NODE_DFLT);
char **nodes = split_list_of_nodenames (line);
- NODE *node = NULL;
+ char *node = NULL;
/* If DIR_NODE is NULL, they might be reading a file directly,
like in "info -d . -f ./foo". Try using "Top" instead. */
@@ -3003,7 +2963,11 @@
if (err_node)
show_error_node (err_node);
else
- info_set_node_of_window (1, window, node);
+ {
+ NODE *n;
+ n = info_get_node_with_defaults (0, node, PARSE_NODE_DFLT, window);
+ info_set_node_of_window (1, window, n);
+ }
}
free (line);
@@ -3051,8 +3015,8 @@
/* Find the node that is the best candidate to list the PROGRAM's
invocation info and its command-line options, by looking for menu
items and chains of menu items with characteristic names. */
-void
-info_intuit_options_node (WINDOW *window, NODE *initial_node, char *program)
+char *
+info_intuit_options_node (NODE *initial_node, char *program)
{
/* The list of node names typical for GNU manuals where the program
usage and specifically the command-line arguments are described.
@@ -3125,11 +3089,7 @@
break;
}
- /* We've got our best shot at the invocation node. Now select it. */
- if (initial_node)
- info_set_node_of_window (1, window, initial_node);
- if (!info_error_was_printed)
- window_clear_echo_area ();
+ return initial_node->nodename;
}
/* Given a name of an Info file, find the name of the package it
@@ -3162,6 +3122,7 @@
char *program_name, *line;
char *default_program_name, *prompt, *file_name;
NODE *top_node;
+ char *invocation_node;
/* Intuit the name of the program they are likely to want.
We use the file name of the current Info file as a hint. */
@@ -3190,7 +3151,20 @@
if (!top_node)
info_error (msg_cant_find_node, "Top");
- info_intuit_options_node (window, top_node, program_name);
+ invocation_node = info_intuit_options_node (top_node, program_name);
+
+ /* We've got our best shot at the invocation node. Now select it. */
+ if (invocation_node)
+ {
+ NODE *node;
+
+ node = info_get_node_with_defaults (0, invocation_node,
+ PARSE_NODE_DFLT, window);
+ info_set_node_of_window (1, window, node);
+ }
+
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
free (line);
free (default_program_name);
}
@@ -3448,16 +3422,21 @@
FILE *stream, int dump_subnodes);
static void initialize_dumping (void);
-/* Dump the nodes specified by FILENAME and NODENAMES to the file named
+/* Dump the nodes in FILE_BUFFER called NODENAMES to the file named
in OUTPUT_FILENAME. If DUMP_SUBNODES is set, recursively dump
the nodes which appear in the menu of each node dumped. */
void
-dump_nodes_to_file (char *filename, char **nodenames,
+dump_nodes_to_file (FILE_BUFFER *file_buffer, char **nodenames,
char *output_filename, int flags)
{
int i;
FILE *output_stream;
+ char *filename;
+ if (!file_buffer)
+ return;
+
+ filename = file_buffer->filename;
debug (1, (_("writing file %s"), filename));
/* Get the stream to print the nodes to. Special case of an output
Modified: trunk/info/session.h
===================================================================
--- trunk/info/session.h 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/session.h 2014-05-01 18:22:24 UTC (rev 5500)
@@ -101,7 +101,7 @@
extern void dump_node_to_file (NODE *node, char *filename,
int flags);
-extern void dump_nodes_to_file (char *filename, char **nodenames,
+extern void dump_nodes_to_file (FILE_BUFFER *file_buffer, char **nodenames,
char *output_filename, int flags);
extern char *program_name_from_file_name (char *file_name);
@@ -125,13 +125,11 @@
/* Starting an info session. */
extern void begin_multiple_window_info_session (char *filename,
char **nodenames);
-extern void begin_info_session (NODE *initial_node);
extern void info_session (void);
extern void initialize_terminal_and_keymaps (char *init_file);
-extern void initialize_info_session (NODE *node, int clear_screen);
+extern void initialize_info_session (int clear_screen);
extern void info_read_and_dispatch (void);
-extern void info_intuit_options_node (WINDOW *window,
- NODE *initial_node, char *program);
+extern char *info_intuit_options_node (NODE *initial_node, char *program);
/* Moving the point within a node. */
extern void info_next_line (WINDOW *window, int count, unsigned char key);
@@ -204,7 +202,7 @@
extern void info_kill_node (WINDOW *window, int count, unsigned char key);
extern void info_view_file (WINDOW *window, int count, unsigned char key);
extern void info_menu_sequence (WINDOW *window, int count, unsigned char key);
-extern NODE *info_follow_menus (NODE *initial_node, char **menus,
+extern char *info_follow_menus (NODE *initial_node, char **menus,
NODE **err_node, int strict);
extern void info_man (WINDOW *window, int count, unsigned char key);
extern void list_visited_nodes (WINDOW *window, int count, unsigned char key);
Modified: trunk/info/t/Init-intera.inc
===================================================================
--- trunk/info/t/Init-intera.inc 2014-05-01 17:25:21 UTC (rev 5499)
+++ trunk/info/t/Init-intera.inc 2014-05-01 18:22:24 UTC (rev 5500)
@@ -12,5 +12,6 @@
# Wait for pseudotty process to create file
while test ! -f $GINFO_PTY_FILE; do sleep 1; done
exec >"$(cat $GINFO_PTY_FILE | tr -d '\n')"
+exec 2>"$(cat $GINFO_PTY_FILE | tr -d '\n')"
rm -f $GINFO_PTY_FILE
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [5500] single_file,
Gavin D. Smith <=