No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / texinfo / makeinfo / index.c
blob741ed9ed131a2e88812a87e73e94f889a644b5cd
1 /* $NetBSD$ */
3 /* index.c -- indexing for Texinfo.
4 Id: index.c,v 1.17 2004/11/30 02:03:23 karl Exp
6 Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation,
7 Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "system.h"
24 #include "files.h"
25 #include "footnote.h"
26 #include "html.h"
27 #include "index.h"
28 #include "lang.h"
29 #include "macro.h"
30 #include "sectioning.h"
31 #include "toc.h"
32 #include "xml.h"
34 INDEX_ALIST **name_index_alist = NULL;
36 /* An array of pointers. Each one is for a different index. The
37 "synindex" command changes which array slot is pointed to by a
38 given "index". */
39 INDEX_ELT **the_indices = NULL;
41 /* The number of defined indices. */
42 int defined_indices = 0;
44 /* This is the order of the index. */
45 int index_counter = 0;
47 /* Stuff for defining commands on the fly. */
48 COMMAND **user_command_array = NULL;
49 int user_command_array_len = 0;
51 /* How to compare index entries for sorting. May be set to strcoll. */
52 int (*index_compare_fn) (const char *a, const char *b) = strcasecmp;
54 /* Function to compare index entries for sorting. (Calls
55 `index_compare_fn' above.) */
56 int index_element_compare (const void *element1, const void *element2);
58 /* Find which element in the known list of indices has this name.
59 Returns -1 if NAME isn't found. */
60 static int
61 find_index_offset (char *name)
63 int i;
64 for (i = 0; i < defined_indices; i++)
65 if (name_index_alist[i] && STREQ (name, name_index_alist[i]->name))
66 return i;
67 return -1;
70 /* Return a pointer to the entry of (name . index) for this name.
71 Return NULL if the index doesn't exist. */
72 static INDEX_ALIST *
73 find_index (char *name)
75 int offset = find_index_offset (name);
76 if (offset > -1)
77 return name_index_alist[offset];
78 else
79 return NULL;
82 /* User-defined commands, which happens only from user-defined indexes.
83 Used to initialize the builtin indices, too. */
84 static void
85 define_user_command (char *name, COMMAND_FUNCTION (*proc), int needs_braces_p)
87 int slot = user_command_array_len;
88 user_command_array_len++;
90 if (!user_command_array)
91 user_command_array = xmalloc (1 * sizeof (COMMAND *));
93 user_command_array = xrealloc (user_command_array,
94 (1 + user_command_array_len) * sizeof (COMMAND *));
96 user_command_array[slot] = xmalloc (sizeof (COMMAND));
97 user_command_array[slot]->name = xstrdup (name);
98 user_command_array[slot]->proc = proc;
99 user_command_array[slot]->argument_in_braces = needs_braces_p;
102 /* Please release me, let me go... */
103 static void
104 free_index (INDEX_ELT *index)
106 INDEX_ELT *temp;
108 while ((temp = index))
110 free (temp->entry);
111 free (temp->entry_text);
112 /* Do not free the node, because we already freed the tag table,
113 which freed all the node names. */
114 /* free (temp->node); */
115 index = index->next;
116 free (temp);
120 /* Flush an index by name. This will delete the list of entries that
121 would be written by a @printindex command for this index. */
122 static void
123 undefindex (char *name)
125 int i;
126 int which = find_index_offset (name);
128 /* The index might have already been freed if this was the target of
129 an @synindex. */
130 if (which < 0 || !name_index_alist[which])
131 return;
133 i = name_index_alist[which]->read_index;
135 free_index (the_indices[i]);
136 the_indices[i] = NULL;
138 free (name_index_alist[which]->name);
139 free (name_index_alist[which]);
140 name_index_alist[which] = NULL;
143 /* Add the arguments to the current index command to the index NAME. */
144 static void
145 index_add_arg (char *name)
147 int which;
148 char *index_entry;
149 INDEX_ALIST *tem;
151 tem = find_index (name);
153 which = tem ? tem->write_index : -1;
155 if (macro_expansion_output_stream && !executing_string)
156 append_to_expansion_output (input_text_offset + 1);
158 get_rest_of_line (0, &index_entry);
159 ignore_blank_line ();
161 if (macro_expansion_output_stream && !executing_string)
163 char *index_line = xmalloc (strlen (index_entry) + 2);
164 sprintf (index_line, "%s\n", index_entry);
165 me_execute_string_keep_state (index_line, NULL);
166 free (index_line);
169 if (which < 0)
171 line_error (_("Unknown index `%s'"), name);
172 free (index_entry);
174 else
176 INDEX_ELT *new = xmalloc (sizeof (INDEX_ELT));
178 index_counter++;
180 /* Get output line number updated before doing anything. */
181 if (!html && !xml)
182 flush_output ();
184 new->next = the_indices[which];
185 new->entry = NULL;
186 new->entry_text = index_entry;
187 /* Since footnotes are handled at the very end of the document,
188 node name in the non-split HTML outputs always show the last
189 node. We artificially make it ``Footnotes''. */
190 if (html && !splitting && already_outputting_pending_notes)
191 new->node = xstrdup (_("Footnotes"));
192 else
193 new->node = current_node ? current_node : xstrdup ("");
194 if (!html && !xml && no_headers)
196 new->section = current_sectioning_number ();
197 if (strlen (new->section) == 0)
198 new->section_name = current_sectioning_name ();
199 else
200 new->section_name = "";
202 else
204 new->section = NULL;
205 new->section_name = NULL;
207 new->code = tem->code;
208 new->defining_line = line_number - 1;
209 new->output_line = no_headers ? output_line_number : node_line_number;
210 /* We need to make a copy since input_filename may point to
211 something that goes away, for example, inside a macro.
212 (see the findexerr test). */
213 new->defining_file = xstrdup (input_filename);
215 if (html && splitting)
217 if (current_output_filename && *current_output_filename)
218 new->output_file = filename_part (current_output_filename);
219 else
220 new->output_file = xstrdup ("");
222 else
223 new->output_file = NULL;
225 new->entry_number = index_counter;
226 the_indices[which] = new;
228 #if 0
229 /* The index breaks if there are colons in the entry.
230 -- This is true, but it's too painful to force changing index
231 entries to use `colon', and too confusing for users. The real
232 fix is to change Info support to support arbitrary characters
233 in node names, and we're not ready to do that. --karl,
234 19mar02. */
235 if (strchr (new->entry_text, ':'))
236 warning (_("Info cannot handle `:' in index entry `%s'"),
237 new->entry_text);
238 #endif
240 if (html)
242 /* Anchor. */
243 int removed_empty_elt = 0;
245 /* We must put the anchor outside the <dl> and <ul> blocks. */
246 if (rollback_empty_tag ("dl"))
247 removed_empty_elt = 1;
248 else if (rollback_empty_tag ("ul"))
249 removed_empty_elt = 2;
251 add_word ("<a name=\"index-");
252 add_escaped_anchor_name (index_entry, 0);
253 add_word_args ("-%d\"></a>", index_counter);
255 if (removed_empty_elt == 1)
256 add_html_block_elt_args ("\n<dl>");
257 else if (removed_empty_elt == 2)
258 add_html_block_elt_args ("\n<ul>");
262 if (xml)
263 xml_insert_indexterm (index_entry, name);
266 /* The function which user defined index commands call. */
267 static void
268 gen_index (void)
270 char *name = xstrdup (command);
271 if (strlen (name) >= strlen ("index"))
272 name[strlen (name) - strlen ("index")] = 0;
273 index_add_arg (name);
274 free (name);
277 /* Define an index known as NAME. We assign the slot number.
278 If CODE is nonzero, make this a code index. */
279 static void
280 defindex (char *name, int code)
282 int i, slot;
284 /* If it already exists, flush it. */
285 undefindex (name);
287 /* Try to find an empty slot. */
288 slot = -1;
289 for (i = 0; i < defined_indices; i++)
290 if (!name_index_alist[i])
292 slot = i;
293 break;
296 if (slot < 0)
297 { /* No such luck. Make space for another index. */
298 slot = defined_indices;
299 defined_indices++;
301 name_index_alist = (INDEX_ALIST **)
302 xrealloc (name_index_alist, (1 + defined_indices)
303 * sizeof (INDEX_ALIST *));
304 the_indices = (INDEX_ELT **)
305 xrealloc (the_indices, (1 + defined_indices) * sizeof (INDEX_ELT *));
308 /* We have a slot. Start assigning. */
309 name_index_alist[slot] = xmalloc (sizeof (INDEX_ALIST));
310 name_index_alist[slot]->name = xstrdup (name);
311 name_index_alist[slot]->read_index = slot;
312 name_index_alist[slot]->write_index = slot;
313 name_index_alist[slot]->code = code;
315 the_indices[slot] = NULL;
318 /* Define an index NAME, implicitly @code if CODE is nonzero. */
319 static void
320 top_defindex (char *name, int code)
322 char *temp;
324 temp = xmalloc (1 + strlen (name) + strlen ("index"));
325 sprintf (temp, "%sindex", name);
326 define_user_command (temp, gen_index, 0);
327 defindex (name, code);
328 free (temp);
331 /* Set up predefined indices. */
332 void
333 init_indices (void)
335 int i;
337 /* Create the default data structures. */
339 /* Initialize data space. */
340 if (!the_indices)
342 the_indices = xmalloc ((1 + defined_indices) * sizeof (INDEX_ELT *));
343 the_indices[defined_indices] = NULL;
345 name_index_alist = xmalloc ((1 + defined_indices)
346 * sizeof (INDEX_ALIST *));
347 name_index_alist[defined_indices] = NULL;
350 /* If there were existing indices, get rid of them now. */
351 for (i = 0; i < defined_indices; i++)
353 if (name_index_alist[i])
354 { /* Suppose we're called with two input files, and the first
355 does a @synindex pg cp. Then, when we get here to start
356 the second file, the "pg" element won't get freed by
357 undefindex (because it's pointing to "cp"). So free it
358 here; otherwise, when we try to define the pg index again
359 just below, it will still point to cp. */
360 undefindex (name_index_alist[i]->name);
362 /* undefindex sets all this to null in some cases. */
363 if (name_index_alist[i])
365 free (name_index_alist[i]->name);
366 free (name_index_alist[i]);
367 name_index_alist[i] = NULL;
372 /* Add the default indices. */
373 top_defindex ("cp", 0); /* cp is the only non-code index. */
374 top_defindex ("fn", 1);
375 top_defindex ("ky", 1);
376 top_defindex ("pg", 1);
377 top_defindex ("tp", 1);
378 top_defindex ("vr", 1);
381 /* Given an index name, return the offset in the_indices of this index,
382 or -1 if there is no such index. */
383 static int
384 translate_index (char *name)
386 INDEX_ALIST *which = find_index (name);
388 if (which)
389 return which->read_index;
390 else
391 return -1;
394 /* Return the index list which belongs to NAME. */
395 INDEX_ELT *
396 index_list (char *name)
398 int which = translate_index (name);
399 if (which < 0)
400 return (INDEX_ELT *) -1;
401 else
402 return the_indices[which];
405 /* Define a new index command. Arg is name of index. */
406 static void
407 gen_defindex (int code)
409 char *name;
410 get_rest_of_line (0, &name);
412 if (find_index (name))
414 line_error (_("Index `%s' already exists"), name);
416 else
418 char *temp = xmalloc (strlen (name) + sizeof ("index"));
419 sprintf (temp, "%sindex", name);
420 define_user_command (temp, gen_index, 0);
421 defindex (name, code);
422 free (temp);
425 free (name);
428 void
429 cm_defindex (void)
431 gen_defindex (0);
434 void
435 cm_defcodeindex (void)
437 gen_defindex (1);
440 /* Expects 2 args, on the same line. Both are index abbreviations.
441 Make the first one be a synonym for the second one, i.e. make the
442 first one have the same index as the second one. */
443 void
444 cm_synindex (void)
446 int source, target;
447 char *abbrev1, *abbrev2;
449 skip_whitespace ();
450 get_until_in_line (0, " ", &abbrev1);
451 target = find_index_offset (abbrev1);
452 skip_whitespace ();
453 get_until_in_line (0, " ", &abbrev2);
454 source = find_index_offset (abbrev2);
455 if (source < 0 || target < 0)
457 line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
458 abbrev1, abbrev2);
460 else
462 if (xml && !docbook)
463 xml_synindex (abbrev1, abbrev2);
464 else
465 name_index_alist[target]->write_index
466 = name_index_alist[source]->write_index;
469 free (abbrev1);
470 free (abbrev2);
473 void
474 cm_pindex (void) /* Pinhead index. */
476 index_add_arg ("pg");
479 void
480 cm_vindex (void) /* Variable index. */
482 index_add_arg ("vr");
485 void
486 cm_kindex (void) /* Key index. */
488 index_add_arg ("ky");
491 void
492 cm_cindex (void) /* Concept index. */
494 index_add_arg ("cp");
497 void
498 cm_findex (void) /* Function index. */
500 index_add_arg ("fn");
503 void
504 cm_tindex (void) /* Data Type index. */
506 index_add_arg ("tp");
510 index_element_compare (const void *element1, const void *element2)
512 INDEX_ELT **elt1 = (INDEX_ELT **) element1;
513 INDEX_ELT **elt2 = (INDEX_ELT **) element2;
515 return index_compare_fn ((*elt1)->entry, (*elt2)->entry);
518 /* Force all index entries to be unique. */
519 static void
520 make_index_entries_unique (INDEX_ELT **array, int count)
522 int i, j;
523 INDEX_ELT **copy;
524 int counter = 1;
526 copy = xmalloc ((1 + count) * sizeof (INDEX_ELT *));
528 for (i = 0, j = 0; i < count; i++)
530 if (i == (count - 1)
531 || array[i]->node != array[i + 1]->node
532 || !STREQ (array[i]->entry, array[i + 1]->entry))
533 copy[j++] = array[i];
534 else
536 free (array[i]->entry);
537 free (array[i]->entry_text);
538 free (array[i]);
541 copy[j] = NULL;
543 /* Now COPY contains only unique entries. Duplicated entries in the
544 original array have been freed. Replace the current array with
545 the copy, fixing the NEXT pointers. */
546 for (i = 0; copy[i]; i++)
548 copy[i]->next = copy[i + 1];
550 /* Fix entry names which are the same. They point to different nodes,
551 so we make the entry name unique. */
552 if (copy[i+1]
553 && STREQ (copy[i]->entry, copy[i + 1]->entry)
554 && !html)
556 char *new_entry_name;
558 new_entry_name = xmalloc (10 + strlen (copy[i]->entry));
559 sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
560 free (copy[i]->entry);
561 copy[i]->entry = new_entry_name;
562 counter++;
564 else
565 counter = 1;
567 array[i] = copy[i];
569 array[i] = NULL;
571 /* Free the storage used only by COPY. */
572 free (copy);
576 /* Sort the index passed in INDEX, returning an array of pointers to
577 elements. The array is terminated with a NULL pointer. */
579 static INDEX_ELT **
580 sort_index (INDEX_ELT *index)
582 INDEX_ELT **array;
583 INDEX_ELT *temp;
584 int count = 0;
585 int save_line_number = line_number;
586 char *save_input_filename = input_filename;
587 int save_html = html;
589 /* Pretend we are in non-HTML mode, for the purpose of getting the
590 expanded index entry that lacks any markup and other HTML escape
591 characters which could produce a wrong sort order. */
592 /* fixme: html: this still causes some markup, such as non-ASCII
593 characters @AE{} etc., to sort incorrectly. */
594 html = 0;
596 for (temp = index, count = 0; temp; temp = temp->next, count++)
598 /* We have the length, now we can allocate an array. */
599 array = xmalloc ((count + 1) * sizeof (INDEX_ELT *));
601 for (temp = index, count = 0; temp; temp = temp->next, count++)
603 /* Allocate new memory for the return array, since parts of the
604 original INDEX get freed. Otherwise, if the document calls
605 @printindex twice on the same index, with duplicate entries,
606 we'll have garbage the second time. There are cleaner ways to
607 deal, but this will suffice for now. */
608 array[count] = xmalloc (sizeof (INDEX_ELT));
609 *(array[count]) = *(temp); /* struct assignment, hope it's ok */
611 /* Adjust next pointers to use the new memory. */
612 if (count > 0)
613 array[count-1]->next = array[count];
615 /* Set line number and input filename to the source line for this
616 index entry, as this expansion finds any errors. */
617 line_number = array[count]->defining_line;
618 input_filename = array[count]->defining_file;
620 /* If this particular entry should be printed as a "code" index,
621 then expand it as @code{entry}, i.e., as in fixed-width font. */
622 array[count]->entry = expansion (temp->entry_text, array[count]->code);
624 array[count] = NULL; /* terminate the array. */
626 line_number = save_line_number;
627 input_filename = save_input_filename;
628 html = save_html;
630 #ifdef HAVE_STRCOLL
631 /* This is not perfect. We should set (then restore) the locale to the
632 documentlanguage, so strcoll operates according to the document's
633 locale, not the user's. For now, I'm just going to assume that
634 those few new documents which use @documentlanguage will be
635 processed in the appropriate locale. In any case, don't use
636 strcoll in the C (aka POSIX) locale, that is the ASCII ordering. */
637 if (language_code != en)
639 char *lang_env = getenv ("LANG");
640 if (lang_env && !STREQ (lang_env, "C") && !STREQ (lang_env, "POSIX"))
641 index_compare_fn = strcoll;
643 #endif /* HAVE_STRCOLL */
645 /* Sort the array. */
646 qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
648 /* Remove duplicate entries. */
649 make_index_entries_unique (array, count);
651 /* Replace the original index with the sorted one, in case the
652 document wants to print it again. If the index wasn't empty. */
653 if (index)
654 *index = **array;
656 return array;
659 static void
660 insert_index_output_line_no (int line_number, int output_line_number_len)
662 int last_column;
663 int str_size = output_line_number_len + strlen (_("(line )"))
664 + sizeof (NULL);
665 char *out_line_no_str = (char *) xmalloc (str_size + 1);
667 /* Do not translate ``(line NNN)'' below for !no_headers case (Info output),
668 because it's something like the ``* Menu'' strings. For plaintext output
669 it should be translated though. */
670 sprintf (out_line_no_str,
671 no_headers ? _("(line %*d)") : "(line %*d)",
672 output_line_number_len, line_number);
675 int i = output_paragraph_offset;
676 while (0 < i && output_paragraph[i-1] != '\n')
677 i--;
678 last_column = output_paragraph_offset - i;
681 if (last_column + strlen (out_line_no_str) > fill_column)
683 insert ('\n');
684 last_column = 0;
687 while (last_column + strlen (out_line_no_str) < fill_column)
689 insert (' ');
690 last_column++;
693 insert_string (out_line_no_str);
694 insert ('\n');
696 free (out_line_no_str);
699 /* Nonzero means that we are in the middle of printing an index. */
700 int printing_index = 0;
702 /* Takes one arg, a short name of an index to print.
703 Outputs a menu of the sorted elements of the index. */
704 void
705 cm_printindex (void)
707 char *index_name;
708 get_rest_of_line (0, &index_name);
710 /* get_rest_of_line increments the line number by one,
711 so to make warnings/errors point to the correct line,
712 we decrement the line_number again. */
713 if (!handling_delayed_writes)
714 line_number--;
716 if (xml && !docbook)
718 xml_insert_element (PRINTINDEX, START);
719 insert_string (index_name);
720 xml_insert_element (PRINTINDEX, END);
722 else if (!handling_delayed_writes)
724 int command_len = sizeof ("@ ") + strlen (command) + strlen (index_name);
725 char *index_command = xmalloc (command_len + 1);
727 close_paragraph ();
728 if (docbook)
729 xml_begin_index ();
731 sprintf (index_command, "@%s %s", command, index_name);
732 register_delayed_write (index_command);
733 free (index_command);
735 else
737 int item;
738 INDEX_ELT *index;
739 INDEX_ELT *last_index = 0;
740 INDEX_ELT **array;
741 unsigned line_length;
742 char *line;
743 int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
744 int saved_filling_enabled = filling_enabled;
745 int saved_line_number = line_number;
746 char *saved_input_filename = input_filename;
747 unsigned output_line_number_len;
749 index = index_list (index_name);
750 if (index == (INDEX_ELT *)-1)
752 line_error (_("Unknown index `%s' in @printindex"), index_name);
753 free (index_name);
754 return;
757 /* Do this before sorting, so execute_string is in the good environment */
758 if (xml && docbook)
759 xml_begin_index ();
761 /* Do this before sorting, so execute_string in index_element_compare
762 will give the same results as when we actually print. */
763 printing_index = 1;
764 filling_enabled = 0;
765 inhibit_paragraph_indentation = 1;
766 xml_sort_index = 1;
767 array = sort_index (index);
768 xml_sort_index = 0;
769 close_paragraph ();
770 if (html)
771 add_html_block_elt_args ("<ul class=\"index-%s\" compact>",
772 index_name);
773 else if (!no_headers && !docbook)
774 { /* Info. Add magic cookie for info readers (to treat this
775 menu differently), and the usual start-of-menu. */
776 add_char ('\0');
777 add_word ("\010[index");
778 add_char ('\0');
779 add_word ("\010]\n");
780 add_word ("* Menu:\n\n");
783 me_inhibit_expansion++;
785 /* This will probably be enough. */
786 line_length = 100;
787 line = xmalloc (line_length);
790 char *max_output_line_number = (char *) xmalloc (25 * sizeof (char));
792 if (no_headers)
793 sprintf (max_output_line_number, "%d", output_line_number);
794 else
796 INDEX_ELT *tmp_entry = index;
797 unsigned tmp = 0;
798 for (tmp_entry = index; tmp_entry; tmp_entry = tmp_entry->next)
799 tmp = tmp_entry->output_line > tmp ? tmp_entry->output_line : tmp;
800 sprintf (max_output_line_number, "%d", tmp);
803 output_line_number_len = strlen (max_output_line_number);
804 free (max_output_line_number);
807 for (item = 0; (index = array[item]); item++)
809 /* A pathological document might have an index entry outside of any
810 node. Don't crash; try using the section name instead. */
811 char *index_node = index->node;
813 line_number = index->defining_line;
814 input_filename = index->defining_file;
816 if ((!index_node || !*index_node) && html)
817 index_node = toc_find_section_of_node (index_node);
819 if (!index_node || !*index_node)
821 line_error (_("Entry for index `%s' outside of any node"),
822 index_name);
823 if (html || !no_headers)
824 index_node = (char *) _("(outside of any node)");
827 if (html)
829 /* For HTML, we need to expand and HTML-escape the
830 original entry text, at the same time. Consider
831 @cindex J@"urgen. We want J&uuml;urgen. We can't
832 expand and then escape since we'll end up with
833 J&amp;uuml;rgen. We can't escape and then expand
834 because then `expansion' will see J@&quot;urgen, and
835 @&quot;urgen is not a command. */
836 char *html_entry =
837 maybe_escaped_expansion (index->entry_text, index->code, 1);
839 add_html_block_elt_args ("\n<li><a href=\"%s#index-",
840 (splitting && index->output_file) ? index->output_file : "");
841 add_escaped_anchor_name (index->entry_text, 0);
842 add_word_args ("-%d\">%s</a>: ", index->entry_number,
843 html_entry);
844 free (html_entry);
846 add_word ("<a href=\"");
847 if (index->node && *index->node)
849 /* Ensure any non-macros in the node name are expanded. */
850 char *expanded_index;
852 in_fixed_width_font++;
853 expanded_index = expansion (index_node, 0);
854 in_fixed_width_font--;
855 add_anchor_name (expanded_index, 1);
856 expanded_index = escape_string (expanded_index);
857 add_word_args ("\">%s</a>", expanded_index);
858 free (expanded_index);
860 else if (STREQ (index_node, _("(outside of any node)")))
862 add_anchor_name (index_node, 1);
863 add_word_args ("\">%s</a>", index_node);
865 else
866 /* If we use the section instead of the (missing) node, then
867 index_node already includes all we need except the #. */
868 add_word_args ("#%s</a>", index_node);
870 add_html_block_elt ("</li>");
872 else if (xml && docbook)
874 /* In the DocBook case, the expanded index entry is not
875 good for us, since it was expanded for non-DocBook mode
876 inside sort_index. So we send the original entry text
877 to be used with execute_string. */
878 xml_insert_indexentry (index->entry_text, index_node);
880 else
882 unsigned new_length = strlen (index->entry);
884 if (new_length < 50) /* minimum length used below */
885 new_length = 50;
886 new_length += strlen (index_node) + 7; /* * : .\n\0 */
888 if (new_length > line_length)
890 line_length = new_length;
891 line = xrealloc (line, line_length);
893 /* Print the entry, nicely formatted. We've already
894 expanded any commands in index->entry, including any
895 implicit @code. Thus, can't call execute_string, since
896 @@ has turned into @. */
897 if (!no_headers)
899 sprintf (line, "* %-37s ", index->entry);
900 line[2 + strlen (index->entry)] = ':';
901 insert_string (line);
902 /* Make sure any non-macros in the node name are expanded. */
903 in_fixed_width_font++;
904 execute_string ("%s. ", index_node);
905 insert_index_output_line_no (index->output_line,
906 output_line_number_len);
907 in_fixed_width_font--;
909 else
911 /* With --no-headers, the @node lines are gone, so
912 there's little sense in referring to them in the
913 index. Instead, output the number or name of the
914 section that corresponds to that node. */
915 sprintf (line, "%-*s ", number_sections ? 46 : 1, index->entry);
916 line[strlen (index->entry)] = ':';
917 insert_string (line);
919 if (strlen (index->section) > 0)
920 { /* We got your number. */
921 insert_string ((char *) _("See "));
922 insert_string (index->section);
924 else
925 { /* Sigh, index in an @unnumbered. :-\ */
926 insert_string ("\n ");
927 insert_string ((char *) _("See "));
928 insert_string ("``");
929 insert_string (expansion (index->section_name, 0));
930 insert_string ("''");
933 insert_string (". ");
934 insert_index_output_line_no (index->output_line,
935 output_line_number_len);
939 /* Prevent `output_paragraph' from growing to the size of the
940 whole index. */
941 flush_output ();
942 last_index = index;
945 free (line);
947 me_inhibit_expansion--;
948 printing_index = 0;
950 close_single_paragraph ();
951 filling_enabled = saved_filling_enabled;
952 inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
953 input_filename = saved_input_filename;
954 line_number = saved_line_number;
956 if (html)
957 add_html_block_elt ("</ul>");
958 else if (xml && docbook)
959 xml_end_index ();
962 free (index_name);
963 /* Re-increment the line number, because get_rest_of_line
964 left us looking at the next line after the command. */
965 line_number++;