summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo/makeinfo/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/texinfo/makeinfo/index.c')
-rw-r--r--contrib/texinfo/makeinfo/index.c432
1 files changed, 259 insertions, 173 deletions
diff --git a/contrib/texinfo/makeinfo/index.c b/contrib/texinfo/makeinfo/index.c
index ab6a53c..710e8b6 100644
--- a/contrib/texinfo/makeinfo/index.c
+++ b/contrib/texinfo/makeinfo/index.c
@@ -1,7 +1,8 @@
/* index.c -- indexing for Texinfo.
- $Id: index.c,v 1.8 2003/05/16 23:52:40 karl Exp $
+ $Id: index.c,v 1.17 2004/11/30 02:03:23 karl Exp $
- Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation,
+ Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,59 +19,16 @@
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
+#include "files.h"
+#include "footnote.h"
+#include "html.h"
#include "index.h"
#include "lang.h"
#include "macro.h"
+#include "sectioning.h"
#include "toc.h"
#include "xml.h"
-/* An index element... */
-typedef struct index_elt
-{
- struct index_elt *next;
- char *entry; /* The index entry itself, after expansion. */
- char *entry_text; /* The original, non-expanded entry text. */
- char *node; /* The node from whence it came. */
- int code; /* Nonzero means add `@code{...}' when
- printing this element. */
- int defining_line; /* Line number where this entry was written. */
- char *defining_file; /* Source file for defining_line. */
-} INDEX_ELT;
-
-
-/* A list of short-names for each index.
- There are two indices into the the_indices array.
- * read_index is the index that points to the list of index
- entries that we will find if we ask for the list of entries for
- this name.
- * write_index is the index that points to the list of index entries
- that we will add new entries to.
-
- Initially, read_index and write_index are the same, but the
- @syncodeindex and @synindex commands can change the list we add
- entries to.
-
- For example, after the commands
- @cindex foo
- @defindex ii
- @synindex cp ii
- @cindex bar
-
- the cp index will contain the entry `foo', and the new ii
- index will contain the entry `bar'. This is consistent with the
- way texinfo.tex handles the same situation.
-
- In addition, for each index, it is remembered whether that index is
- a code index or not. Code indices have @code{} inserted around the
- first word when they are printed with printindex. */
-typedef struct
-{
- char *name;
- int read_index; /* index entries for `name' */
- int write_index; /* store index entries here, @synindex can change it */
- int code;
-} INDEX_ALIST;
-
INDEX_ALIST **name_index_alist = NULL;
/* An array of pointers. Each one is for a different index. The
@@ -81,18 +39,24 @@ INDEX_ELT **the_indices = NULL;
/* The number of defined indices. */
int defined_indices = 0;
+/* This is the order of the index. */
+int index_counter = 0;
+
/* Stuff for defining commands on the fly. */
COMMAND **user_command_array = NULL;
int user_command_array_len = 0;
/* How to compare index entries for sorting. May be set to strcoll. */
-int (*index_compare_fn) () = strcasecmp;
+int (*index_compare_fn) (const char *a, const char *b) = strcasecmp;
+
+/* Function to compare index entries for sorting. (Calls
+ `index_compare_fn' above.) */
+int index_element_compare (const void *element1, const void *element2);
/* Find which element in the known list of indices has this name.
Returns -1 if NAME isn't found. */
static int
-find_index_offset (name)
- char *name;
+find_index_offset (char *name)
{
int i;
for (i = 0; i < defined_indices; i++)
@@ -103,9 +67,8 @@ find_index_offset (name)
/* Return a pointer to the entry of (name . index) for this name.
Return NULL if the index doesn't exist. */
-INDEX_ALIST *
-find_index (name)
- char *name;
+static INDEX_ALIST *
+find_index (char *name)
{
int offset = find_index_offset (name);
if (offset > -1)
@@ -116,11 +79,8 @@ find_index (name)
/* User-defined commands, which happens only from user-defined indexes.
Used to initialize the builtin indices, too. */
-void
-define_user_command (name, proc, needs_braces_p)
- char *name;
- COMMAND_FUNCTION *proc;
- int needs_braces_p;
+static void
+define_user_command (char *name, COMMAND_FUNCTION (*proc), int needs_braces_p)
{
int slot = user_command_array_len;
user_command_array_len++;
@@ -139,8 +99,7 @@ define_user_command (name, proc, needs_braces_p)
/* Please release me, let me go... */
static void
-free_index (index)
- INDEX_ELT *index;
+free_index (INDEX_ELT *index)
{
INDEX_ELT *temp;
@@ -159,8 +118,7 @@ free_index (index)
/* Flush an index by name. This will delete the list of entries that
would be written by a @printindex command for this index. */
static void
-undefindex (name)
- char *name;
+undefindex (char *name)
{
int i;
int which = find_index_offset (name);
@@ -180,11 +138,9 @@ undefindex (name)
name_index_alist[which] = NULL;
}
-/* Add the arguments to the current index command to the index NAME.
- html fixxme generate specific html anchor */
+/* Add the arguments to the current index command to the index NAME. */
static void
-index_add_arg (name)
- char *name;
+index_add_arg (char *name)
{
int which;
char *index_entry;
@@ -216,17 +172,57 @@ index_add_arg (name)
else
{
INDEX_ELT *new = xmalloc (sizeof (INDEX_ELT));
+
+ index_counter++;
+
+ /* Get output line number updated before doing anything. */
+ if (!html && !xml)
+ flush_output ();
+
new->next = the_indices[which];
- new->entry_text = index_entry;
new->entry = NULL;
- new->node = current_node ? current_node : xstrdup ("");
+ new->entry_text = index_entry;
+ /* Since footnotes are handled at the very end of the document,
+ node name in the non-split HTML outputs always show the last
+ node. We artificially make it ``Footnotes''. */
+ if (html && !splitting && already_outputting_pending_notes)
+ new->node = xstrdup (_("Footnotes"));
+ else
+ new->node = current_node ? current_node : xstrdup ("");
+ if (!html && !xml && no_headers)
+ {
+ new->section = current_sectioning_number ();
+ if (strlen (new->section) == 0)
+ new->section_name = current_sectioning_name ();
+ else
+ new->section_name = "";
+ }
+ else
+ {
+ new->section = NULL;
+ new->section_name = NULL;
+ }
new->code = tem->code;
new->defining_line = line_number - 1;
+ new->output_line = no_headers ? output_line_number : node_line_number;
/* We need to make a copy since input_filename may point to
something that goes away, for example, inside a macro.
(see the findexerr test). */
new->defining_file = xstrdup (input_filename);
+
+ if (html && splitting)
+ {
+ if (current_output_filename && *current_output_filename)
+ new->output_file = filename_part (current_output_filename);
+ else
+ new->output_file = xstrdup ("");
+ }
+ else
+ new->output_file = NULL;
+
+ new->entry_number = index_counter;
the_indices[which] = new;
+
#if 0
/* The index breaks if there are colons in the entry.
-- This is true, but it's too painful to force changing index
@@ -238,14 +234,36 @@ index_add_arg (name)
warning (_("Info cannot handle `:' in index entry `%s'"),
new->entry_text);
#endif
+
+ if (html)
+ {
+ /* Anchor. */
+ int removed_empty_elt = 0;
+
+ /* We must put the anchor outside the <dl> and <ul> blocks. */
+ if (rollback_empty_tag ("dl"))
+ removed_empty_elt = 1;
+ else if (rollback_empty_tag ("ul"))
+ removed_empty_elt = 2;
+
+ add_word ("<a name=\"index-");
+ add_escaped_anchor_name (index_entry, 0);
+ add_word_args ("-%d\"></a>", index_counter);
+
+ if (removed_empty_elt == 1)
+ add_html_block_elt_args ("\n<dl>");
+ else if (removed_empty_elt == 2)
+ add_html_block_elt_args ("\n<ul>");
+ }
}
+
if (xml)
xml_insert_indexterm (index_entry, name);
}
/* The function which user defined index commands call. */
static void
-gen_index ()
+gen_index (void)
{
char *name = xstrdup (command);
if (strlen (name) >= strlen ("index"))
@@ -257,9 +275,7 @@ gen_index ()
/* Define an index known as NAME. We assign the slot number.
If CODE is nonzero, make this a code index. */
static void
-defindex (name, code)
- char *name;
- int code;
+defindex (char *name, int code)
{
int i, slot;
@@ -299,9 +315,7 @@ defindex (name, code)
/* Define an index NAME, implicitly @code if CODE is nonzero. */
static void
-top_defindex (name, code)
- char *name;
- int code;
+top_defindex (char *name, int code)
{
char *temp;
@@ -314,7 +328,7 @@ top_defindex (name, code)
/* Set up predefined indices. */
void
-init_indices ()
+init_indices (void)
{
int i;
@@ -364,9 +378,8 @@ init_indices ()
/* Given an index name, return the offset in the_indices of this index,
or -1 if there is no such index. */
-int
-translate_index (name)
- char *name;
+static int
+translate_index (char *name)
{
INDEX_ALIST *which = find_index (name);
@@ -378,8 +391,7 @@ translate_index (name)
/* Return the index list which belongs to NAME. */
INDEX_ELT *
-index_list (name)
- char *name;
+index_list (char *name)
{
int which = translate_index (name);
if (which < 0)
@@ -390,8 +402,7 @@ index_list (name)
/* Define a new index command. Arg is name of index. */
static void
-gen_defindex (code)
- int code;
+gen_defindex (int code)
{
char *name;
get_rest_of_line (0, &name);
@@ -413,13 +424,13 @@ gen_defindex (code)
}
void
-cm_defindex ()
+cm_defindex (void)
{
gen_defindex (0);
}
void
-cm_defcodeindex ()
+cm_defcodeindex (void)
{
gen_defindex (1);
}
@@ -428,7 +439,7 @@ cm_defcodeindex ()
Make the first one be a synonym for the second one, i.e. make the
first one have the same index as the second one. */
void
-cm_synindex ()
+cm_synindex (void)
{
int source, target;
char *abbrev1, *abbrev2;
@@ -446,8 +457,11 @@ cm_synindex ()
}
else
{
- name_index_alist[target]->write_index
- = name_index_alist[source]->write_index;
+ if (xml && !docbook)
+ xml_synindex (abbrev1, abbrev2);
+ else
+ name_index_alist[target]->write_index
+ = name_index_alist[source]->write_index;
}
free (abbrev1);
@@ -455,53 +469,53 @@ cm_synindex ()
}
void
-cm_pindex () /* Pinhead index. */
+cm_pindex (void) /* Pinhead index. */
{
index_add_arg ("pg");
}
void
-cm_vindex () /* Variable index. */
+cm_vindex (void) /* Variable index. */
{
index_add_arg ("vr");
}
void
-cm_kindex () /* Key index. */
+cm_kindex (void) /* Key index. */
{
index_add_arg ("ky");
}
void
-cm_cindex () /* Concept index. */
+cm_cindex (void) /* Concept index. */
{
index_add_arg ("cp");
}
void
-cm_findex () /* Function index. */
+cm_findex (void) /* Function index. */
{
index_add_arg ("fn");
}
void
-cm_tindex () /* Data Type index. */
+cm_tindex (void) /* Data Type index. */
{
index_add_arg ("tp");
}
int
-index_element_compare (element1, element2)
- INDEX_ELT **element1, **element2;
+index_element_compare (const void *element1, const void *element2)
{
- return index_compare_fn ((*element1)->entry, (*element2)->entry);
+ INDEX_ELT **elt1 = (INDEX_ELT **) element1;
+ INDEX_ELT **elt2 = (INDEX_ELT **) element2;
+
+ return index_compare_fn ((*elt1)->entry, (*elt2)->entry);
}
/* Force all index entries to be unique. */
-void
-make_index_entries_unique (array, count)
- INDEX_ELT **array;
- int count;
+static void
+make_index_entries_unique (INDEX_ELT **array, int count)
{
int i, j;
INDEX_ELT **copy;
@@ -560,9 +574,8 @@ make_index_entries_unique (array, count)
/* Sort the index passed in INDEX, returning an array of pointers to
elements. The array is terminated with a NULL pointer. */
-INDEX_ELT **
-sort_index (index)
- INDEX_ELT *index;
+static INDEX_ELT **
+sort_index (INDEX_ELT *index)
{
INDEX_ELT **array;
INDEX_ELT *temp;
@@ -641,38 +654,95 @@ sort_index (index)
return array;
}
+static void
+insert_index_output_line_no (int line_number, int output_line_number_len)
+{
+ int last_column;
+ int str_size = output_line_number_len + strlen (_("(line )"))
+ + sizeof (NULL);
+ char *out_line_no_str = (char *) xmalloc (str_size + 1);
+
+ /* Do not translate ``(line NNN)'' below for !no_headers case (Info output),
+ because it's something like the ``* Menu'' strings. For plaintext output
+ it should be translated though. */
+ sprintf (out_line_no_str,
+ no_headers ? _("(line %*d)") : "(line %*d)",
+ output_line_number_len, line_number);
+
+ {
+ int i = output_paragraph_offset;
+ while (0 < i && output_paragraph[i-1] != '\n')
+ i--;
+ last_column = output_paragraph_offset - i;
+ }
+
+ if (last_column + strlen (out_line_no_str) > fill_column)
+ {
+ insert ('\n');
+ last_column = 0;
+ }
+
+ while (last_column + strlen (out_line_no_str) < fill_column)
+ {
+ insert (' ');
+ last_column++;
+ }
+
+ insert_string (out_line_no_str);
+ insert ('\n');
+
+ free (out_line_no_str);
+}
+
/* Nonzero means that we are in the middle of printing an index. */
int printing_index = 0;
/* Takes one arg, a short name of an index to print.
Outputs a menu of the sorted elements of the index. */
void
-cm_printindex ()
+cm_printindex (void)
{
+ char *index_name;
+ get_rest_of_line (0, &index_name);
+
+ /* get_rest_of_line increments the line number by one,
+ so to make warnings/errors point to the correct line,
+ we decrement the line_number again. */
+ if (!handling_delayed_writes)
+ line_number--;
+
if (xml && !docbook)
{
- char *index_name;
- get_rest_of_line (0, &index_name);
xml_insert_element (PRINTINDEX, START);
insert_string (index_name);
xml_insert_element (PRINTINDEX, END);
}
+ else if (!handling_delayed_writes)
+ {
+ int command_len = sizeof ("@ ") + strlen (command) + strlen (index_name);
+ char *index_command = xmalloc (command_len + 1);
+
+ close_paragraph ();
+ if (docbook)
+ xml_begin_index ();
+
+ sprintf (index_command, "@%s %s", command, index_name);
+ register_delayed_write (index_command);
+ free (index_command);
+ }
else
{
int item;
INDEX_ELT *index;
INDEX_ELT *last_index = 0;
INDEX_ELT **array;
- char *index_name;
unsigned line_length;
char *line;
int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
int saved_filling_enabled = filling_enabled;
int saved_line_number = line_number;
char *saved_input_filename = input_filename;
-
- close_paragraph ();
- get_rest_of_line (0, &index_name);
+ unsigned output_line_number_len;
index = index_list (index_name);
if (index == (INDEX_ELT *)-1)
@@ -696,9 +766,17 @@ cm_printindex ()
xml_sort_index = 0;
close_paragraph ();
if (html)
- add_word_args ("<ul class=\"index-%s\" compact>", index_name);
+ add_html_block_elt_args ("<ul class=\"index-%s\" compact>",
+ index_name);
else if (!no_headers && !docbook)
- add_word ("* Menu:\n\n");
+ { /* Info. Add magic cookie for info readers (to treat this
+ menu differently), and the usual start-of-menu. */
+ add_char ('\0');
+ add_word ("\010[index");
+ add_char ('\0');
+ add_word ("\010]\n");
+ add_word ("* Menu:\n\n");
+ }
me_inhibit_expansion++;
@@ -706,11 +784,29 @@ cm_printindex ()
line_length = 100;
line = xmalloc (line_length);
+ {
+ char *max_output_line_number = (char *) xmalloc (25 * sizeof (char));
+
+ if (no_headers)
+ sprintf (max_output_line_number, "%d", output_line_number);
+ else
+ {
+ INDEX_ELT *tmp_entry = index;
+ unsigned tmp = 0;
+ for (tmp_entry = index; tmp_entry; tmp_entry = tmp_entry->next)
+ tmp = tmp_entry->output_line > tmp ? tmp_entry->output_line : tmp;
+ sprintf (max_output_line_number, "%d", tmp);
+ }
+
+ output_line_number_len = strlen (max_output_line_number);
+ free (max_output_line_number);
+ }
+
for (item = 0; (index = array[item]); item++)
{
/* A pathological document might have an index entry outside of any
node. Don't crash; try using the section name instead. */
- const char *index_node = index->node;
+ char *index_node = index->node;
line_number = index->defining_line;
input_filename = index->defining_file;
@@ -723,44 +819,39 @@ cm_printindex ()
line_error (_("Entry for index `%s' outside of any node"),
index_name);
if (html || !no_headers)
- index_node = _("(outside of any node)");
+ index_node = (char *) _("(outside of any node)");
}
if (html)
- /* fixme: html: we should use specific index anchors pointing
- to the actual location of the indexed position (but then we
- have to find something to wrap the anchor around). */
{
- if (last_index
- && STREQ (last_index->entry_text, index->entry_text))
- add_word (", "); /* Don't repeat the previous entry. */
- else
- {
- /* In the HTML case, the expanded index entry is not
- good for us, since it was expanded for non-HTML mode
- inside sort_index. So we need to HTML-escape and
- expand the original entry text here. */
- char *escaped_entry = xstrdup (index->entry_text);
- char *expanded_entry;
-
- /* expansion() doesn't HTML-escape the argument, so need
- to do it separately. */
- escaped_entry = escape_string (escaped_entry);
- expanded_entry = expansion (escaped_entry, index->code);
- add_word_args ("\n<li>%s: ", expanded_entry);
- free (escaped_entry);
- free (expanded_entry);
- }
+ /* For HTML, we need to expand and HTML-escape the
+ original entry text, at the same time. Consider
+ @cindex J@"urgen. We want J&uuml;urgen. We can't
+ expand and then escape since we'll end up with
+ J&amp;uuml;rgen. We can't escape and then expand
+ because then `expansion' will see J@&quot;urgen, and
+ @&quot;urgen is not a command. */
+ char *html_entry =
+ maybe_escaped_expansion (index->entry_text, index->code, 1);
+
+ add_html_block_elt_args ("\n<li><a href=\"%s#index-",
+ (splitting && index->output_file) ? index->output_file : "");
+ add_escaped_anchor_name (index->entry_text, 0);
+ add_word_args ("-%d\">%s</a>: ", index->entry_number,
+ html_entry);
+ free (html_entry);
+
add_word ("<a href=\"");
if (index->node && *index->node)
{
- /* Make sure any non-macros in the node name are expanded. */
+ /* Ensure any non-macros in the node name are expanded. */
char *expanded_index;
in_fixed_width_font++;
expanded_index = expansion (index_node, 0);
in_fixed_width_font--;
add_anchor_name (expanded_index, 1);
+ expanded_index = escape_string (expanded_index);
add_word_args ("\">%s</a>", expanded_index);
free (expanded_index);
}
@@ -773,6 +864,8 @@ cm_printindex ()
/* If we use the section instead of the (missing) node, then
index_node already includes all we need except the #. */
add_word_args ("#%s</a>", index_node);
+
+ add_html_block_elt ("</li>");
}
else if (xml && docbook)
{
@@ -806,7 +899,9 @@ cm_printindex ()
insert_string (line);
/* Make sure any non-macros in the node name are expanded. */
in_fixed_width_font++;
- execute_string ("%s.\n", index_node);
+ execute_string ("%s. ", index_node);
+ insert_index_output_line_no (index->output_line,
+ output_line_number_len);
in_fixed_width_font--;
}
else
@@ -815,40 +910,27 @@ cm_printindex ()
there's little sense in referring to them in the
index. Instead, output the number or name of the
section that corresponds to that node. */
- char *section_name = toc_find_section_of_node (index_node);
-
- sprintf (line, "%-*s ", number_sections ? 50 : 1, index->entry);
+ sprintf (line, "%-*s ", number_sections ? 46 : 1, index->entry);
line[strlen (index->entry)] = ':';
insert_string (line);
- if (section_name)
- {
- int idx = 0;
- unsigned ref_len = strlen (section_name) + 30;
-
- if (ref_len > line_length)
- {
- line_length = ref_len;
- line = xrealloc (line, line_length);
- }
-
- if (number_sections)
- {
- while (section_name[idx]
- && (isdigit (section_name[idx])
- || (idx && section_name[idx] == '.')))
- idx++;
- }
- if (idx)
- sprintf (line, " See %.*s.\n", idx, section_name);
- else
- sprintf (line, "\n See ``%s''.\n", section_name);
- insert_string (line);
+
+ if (strlen (index->section) > 0)
+ { /* We got your number. */
+ insert_string ((char *) _("See "));
+ insert_string (index->section);
}
else
- {
- insert_string (" "); /* force a blank */
- execute_string ("See node %s.\n", index_node);
+ { /* Sigh, index in an @unnumbered. :-\ */
+ insert_string ("\n ");
+ insert_string ((char *) _("See "));
+ insert_string ("``");
+ insert_string (expansion (index->section_name, 0));
+ insert_string ("''");
}
+
+ insert_string (". ");
+ insert_index_output_line_no (index->output_line,
+ output_line_number_len);
}
}
@@ -859,7 +941,6 @@ cm_printindex ()
}
free (line);
- free (index_name);
me_inhibit_expansion--;
printing_index = 0;
@@ -871,8 +952,13 @@ cm_printindex ()
line_number = saved_line_number;
if (html)
- add_word ("</ul>");
+ add_html_block_elt ("</ul>");
else if (xml && docbook)
xml_end_index ();
}
+
+ free (index_name);
+ /* Re-increment the line number, because get_rest_of_line
+ left us looking at the next line after the command. */
+ line_number++;
}
OpenPOWER on IntegriCloud