diff options
Diffstat (limited to 'contrib/texinfo/makeinfo/index.c')
-rw-r--r-- | contrib/texinfo/makeinfo/index.c | 432 |
1 files changed, 259 insertions, 173 deletions
diff --git a/contrib/texinfo/makeinfo/index.c b/contrib/texinfo/makeinfo/index.c index ab6a53c4f1aa..710e8b6855b5 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üurgen. We can't + expand and then escape since we'll end up with + J&uuml;rgen. We can't escape and then expand + because then `expansion' will see J@"urgen, and + @"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++; } |