kernel - TMPFS - Stabilization pass, fix accounting for rmdir
[dragonfly.git] / contrib / texinfo-4 / makeinfo / index.c
blob710e8b6855b51687342f3af2ae9000bb0eb48b75
1 /* index.c -- indexing for Texinfo.
2 $Id: index.c,v 1.17 2004/11/30 02:03:23 karl Exp $
4 Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation,
5 Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "system.h"
22 #include "files.h"
23 #include "footnote.h"
24 #include "html.h"
25 #include "index.h"
26 #include "lang.h"
27 #include "macro.h"
28 #include "sectioning.h"
29 #include "toc.h"
30 #include "xml.h"
32 INDEX_ALIST **name_index_alist = NULL;
34 /* An array of pointers. Each one is for a different index. The
35 "synindex" command changes which array slot is pointed to by a
36 given "index". */
37 INDEX_ELT **the_indices = NULL;
39 /* The number of defined indices. */
40 int defined_indices = 0;
42 /* This is the order of the index. */
43 int index_counter = 0;
45 /* Stuff for defining commands on the fly. */
46 COMMAND **user_command_array = NULL;
47 int user_command_array_len = 0;
49 /* How to compare index entries for sorting. May be set to strcoll. */
50 int (*index_compare_fn) (const char *a, const char *b) = strcasecmp;
52 /* Function to compare index entries for sorting. (Calls
53 `index_compare_fn' above.) */
54 int index_element_compare (const void *element1, const void *element2);
56 /* Find which element in the known list of indices has this name.
57 Returns -1 if NAME isn't found. */
58 static int
59 find_index_offset (char *name)
61 int i;
62 for (i = 0; i < defined_indices; i++)
63 if (name_index_alist[i] && STREQ (name, name_index_alist[i]->name))
64 return i;
65 return -1;
68 /* Return a pointer to the entry of (name . index) for this name.
69 Return NULL if the index doesn't exist. */
70 static INDEX_ALIST *
71 find_index (char *name)
73 int offset = find_index_offset (name);
74 if (offset > -1)
75 return name_index_alist[offset];
76 else
77 return NULL;
80 /* User-defined commands, which happens only from user-defined indexes.
81 Used to initialize the builtin indices, too. */
82 static void
83 define_user_command (char *name, COMMAND_FUNCTION (*proc), int needs_braces_p)
85 int slot = user_command_array_len;
86 user_command_array_len++;
88 if (!user_command_array)
89 user_command_array = xmalloc (1 * sizeof (COMMAND *));
91 user_command_array = xrealloc (user_command_array,
92 (1 + user_command_array_len) * sizeof (COMMAND *));
94 user_command_array[slot] = xmalloc (sizeof (COMMAND));
95 user_command_array[slot]->name = xstrdup (name);
96 user_command_array[slot]->proc = proc;
97 user_command_array[slot]->argument_in_braces = needs_braces_p;
100 /* Please release me, let me go... */
101 static void
102 free_index (INDEX_ELT *index)
104 INDEX_ELT *temp;
106 while ((temp = index))
108 free (temp->entry);
109 free (temp->entry_text);
110 /* Do not free the node, because we already freed the tag table,
111 which freed all the node names. */
112 /* free (temp->node); */
113 index = index->next;
114 free (temp);
118 /* Flush an index by name. This will delete the list of entries that
119 would be written by a @printindex command for this index. */
120 static void
121 undefindex (char *name)
123 int i;
124 int which = find_index_offset (name);
126 /* The index might have already been freed if this was the target of
127 an @synindex. */
128 if (which < 0 || !name_index_alist[which])
129 return;
131 i = name_index_alist[which]->read_index;
133 free_index (the_indices[i]);
134 the_indices[i] = NULL;
136 free (name_index_alist[which]->name);
137 free (name_index_alist[which]);
138 name_index_alist[which] = NULL;
141 /* Add the arguments to the current index command to the index NAME. */
142 static void
143 index_add_arg (char *name)
145 int which;
146 char *index_entry;
147 INDEX_ALIST *tem;
149 tem = find_index (name);
151 which = tem ? tem->write_index : -1;
153 if (macro_expansion_output_stream && !executing_string)
154 append_to_expansion_output (input_text_offset + 1);
156 get_rest_of_line (0, &index_entry);
157 ignore_blank_line ();
159 if (macro_expansion_output_stream && !executing_string)
161 char *index_line = xmalloc (strlen (index_entry) + 2);
162 sprintf (index_line, "%s\n", index_entry);
163 me_execute_string_keep_state (index_line, NULL);
164 free (index_line);
167 if (which < 0)
169 line_error (_("Unknown index `%s'"), name);
170 free (index_entry);
172 else
174 INDEX_ELT *new = xmalloc (sizeof (INDEX_ELT));
176 index_counter++;
178 /* Get output line number updated before doing anything. */
179 if (!html && !xml)
180 flush_output ();
182 new->next = the_indices[which];
183 new->entry = NULL;
184 new->entry_text = index_entry;
185 /* Since footnotes are handled at the very end of the document,
186 node name in the non-split HTML outputs always show the last
187 node. We artificially make it ``Footnotes''. */
188 if (html && !splitting && already_outputting_pending_notes)
189 new->node = xstrdup (_("Footnotes"));
190 else
191 new->node = current_node ? current_node : xstrdup ("");
192 if (!html && !xml && no_headers)
194 new->section = current_sectioning_number ();
195 if (strlen (new->section) == 0)
196 new->section_name = current_sectioning_name ();
197 else
198 new->section_name = "";
200 else
202 new->section = NULL;
203 new->section_name = NULL;
205 new->code = tem->code;
206 new->defining_line = line_number - 1;
207 new->output_line = no_headers ? output_line_number : node_line_number;
208 /* We need to make a copy since input_filename may point to
209 something that goes away, for example, inside a macro.
210 (see the findexerr test). */
211 new->defining_file = xstrdup (input_filename);
213 if (html && splitting)
215 if (current_output_filename && *current_output_filename)
216 new->output_file = filename_part (current_output_filename);
217 else
218 new->output_file = xstrdup ("");
220 else
221 new->output_file = NULL;
223 new->entry_number = index_counter;
224 the_indices[which] = new;
226 #if 0
227 /* The index breaks if there are colons in the entry.
228 -- This is true, but it's too painful to force changing index
229 entries to use `colon', and too confusing for users. The real
230 fix is to change Info support to support arbitrary characters
231 in node names, and we're not ready to do that. --karl,
232 19mar02. */
233 if (strchr (new->entry_text, ':'))
234 warning (_("Info cannot handle `:' in index entry `%s'"),
235 new->entry_text);
236 #endif
238 if (html)
240 /* Anchor. */
241 int removed_empty_elt = 0;
243 /* We must put the anchor outside the <dl> and <ul> blocks. */
244 if (rollback_empty_tag ("dl"))
245 removed_empty_elt = 1;
246 else if (rollback_empty_tag ("ul"))
247 removed_empty_elt = 2;
249 add_word ("<a name=\"index-");
250 add_escaped_anchor_name (index_entry, 0);
251 add_word_args ("-%d\"></a>", index_counter);
253 if (removed_empty_elt == 1)
254 add_html_block_elt_args ("\n<dl>");
255 else if (removed_empty_elt == 2)
256 add_html_block_elt_args ("\n<ul>");
260 if (xml)
261 xml_insert_indexterm (index_entry, name);
264 /* The function which user defined index commands call. */
265 static void
266 gen_index (void)
268 char *name = xstrdup (command);
269 if (strlen (name) >= strlen ("index"))
270 name[strlen (name) - strlen ("index")] = 0;
271 index_add_arg (name);
272 free (name);
275 /* Define an index known as NAME. We assign the slot number.
276 If CODE is nonzero, make this a code index. */
277 static void
278 defindex (char *name, int code)
280 int i, slot;
282 /* If it already exists, flush it. */
283 undefindex (name);
285 /* Try to find an empty slot. */
286 slot = -1;
287 for (i = 0; i < defined_indices; i++)
288 if (!name_index_alist[i])
290 slot = i;
291 break;
294 if (slot < 0)
295 { /* No such luck. Make space for another index. */
296 slot = defined_indices;
297 defined_indices++;
299 name_index_alist = (INDEX_ALIST **)
300 xrealloc (name_index_alist, (1 + defined_indices)
301 * sizeof (INDEX_ALIST *));
302 the_indices = (INDEX_ELT **)
303 xrealloc (the_indices, (1 + defined_indices) * sizeof (INDEX_ELT *));
306 /* We have a slot. Start assigning. */
307 name_index_alist[slot] = xmalloc (sizeof (INDEX_ALIST));
308 name_index_alist[slot]->name = xstrdup (name);
309 name_index_alist[slot]->read_index = slot;
310 name_index_alist[slot]->write_index = slot;
311 name_index_alist[slot]->code = code;
313 the_indices[slot] = NULL;
316 /* Define an index NAME, implicitly @code if CODE is nonzero. */
317 static void
318 top_defindex (char *name, int code)
320 char *temp;
322 temp = xmalloc (1 + strlen (name) + strlen ("index"));
323 sprintf (temp, "%sindex", name);
324 define_user_command (temp, gen_index, 0);
325 defindex (name, code);
326 free (temp);
329 /* Set up predefined indices. */
330 void
331 init_indices (void)
333 int i;
335 /* Create the default data structures. */
337 /* Initialize data space. */
338 if (!the_indices)
340 the_indices = xmalloc ((1 + defined_indices) * sizeof (INDEX_ELT *));
341 the_indices[defined_indices] = NULL;
343 name_index_alist = xmalloc ((1 + defined_indices)
344 * sizeof (INDEX_ALIST *));
345 name_index_alist[defined_indices] = NULL;
348 /* If there were existing indices, get rid of them now. */
349 for (i = 0; i < defined_indices; i++)
351 if (name_index_alist[i])
352 { /* Suppose we're called with two input files, and the first
353 does a @synindex pg cp. Then, when we get here to start
354 the second file, the "pg" element won't get freed by
355 undefindex (because it's pointing to "cp"). So free it
356 here; otherwise, when we try to define the pg index again
357 just below, it will still point to cp. */
358 undefindex (name_index_alist[i]->name);
360 /* undefindex sets all this to null in some cases. */
361 if (name_index_alist[i])
363 free (name_index_alist[i]->name);
364 free (name_index_alist[i]);
365 name_index_alist[i] = NULL;
370 /* Add the default indices. */
371 top_defindex ("cp", 0); /* cp is the only non-code index. */
372 top_defindex ("fn", 1);
373 top_defindex ("ky", 1);
374 top_defindex ("pg", 1);
375 top_defindex ("tp", 1);
376 top_defindex ("vr", 1);
379 /* Given an index name, return the offset in the_indices of this index,
380 or -1 if there is no such index. */
381 static int
382 translate_index (char *name)
384 INDEX_ALIST *which = find_index (name);
386 if (which)
387 return which->read_index;
388 else
389 return -1;
392 /* Return the index list which belongs to NAME. */
393 INDEX_ELT *
394 index_list (char *name)
396 int which = translate_index (name);
397 if (which < 0)
398 return (INDEX_ELT *) -1;
399 else
400 return the_indices[which];
403 /* Define a new index command. Arg is name of index. */
404 static void
405 gen_defindex (int code)
407 char *name;
408 get_rest_of_line (0, &name);
410 if (find_index (name))
412 line_error (_("Index `%s' already exists"), name);
414 else
416 char *temp = xmalloc (strlen (name) + sizeof ("index"));
417 sprintf (temp, "%sindex", name);
418 define_user_command (temp, gen_index, 0);
419 defindex (name, code);
420 free (temp);
423 free (name);
426 void
427 cm_defindex (void)
429 gen_defindex (0);
432 void
433 cm_defcodeindex (void)
435 gen_defindex (1);
438 /* Expects 2 args, on the same line. Both are index abbreviations.
439 Make the first one be a synonym for the second one, i.e. make the
440 first one have the same index as the second one. */
441 void
442 cm_synindex (void)
444 int source, target;
445 char *abbrev1, *abbrev2;
447 skip_whitespace ();
448 get_until_in_line (0, " ", &abbrev1);
449 target = find_index_offset (abbrev1);
450 skip_whitespace ();
451 get_until_in_line (0, " ", &abbrev2);
452 source = find_index_offset (abbrev2);
453 if (source < 0 || target < 0)
455 line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
456 abbrev1, abbrev2);
458 else
460 if (xml && !docbook)
461 xml_synindex (abbrev1, abbrev2);
462 else
463 name_index_alist[target]->write_index
464 = name_index_alist[source]->write_index;
467 free (abbrev1);
468 free (abbrev2);
471 void
472 cm_pindex (void) /* Pinhead index. */
474 index_add_arg ("pg");
477 void
478 cm_vindex (void) /* Variable index. */
480 index_add_arg ("vr");
483 void
484 cm_kindex (void) /* Key index. */
486 index_add_arg ("ky");
489 void
490 cm_cindex (void) /* Concept index. */
492 index_add_arg ("cp");
495 void
496 cm_findex (void) /* Function index. */
498 index_add_arg ("fn");
501 void
502 cm_tindex (void) /* Data Type index. */
504 index_add_arg ("tp");
508 index_element_compare (const void *element1, const void *element2)
510 INDEX_ELT **elt1 = (INDEX_ELT **) element1;
511 INDEX_ELT **elt2 = (INDEX_ELT **) element2;
513 return index_compare_fn ((*elt1)->entry, (*elt2)->entry);
516 /* Force all index entries to be unique. */
517 static void
518 make_index_entries_unique (INDEX_ELT **array, int count)
520 int i, j;
521 INDEX_ELT **copy;
522 int counter = 1;
524 copy = xmalloc ((1 + count) * sizeof (INDEX_ELT *));
526 for (i = 0, j = 0; i < count; i++)
528 if (i == (count - 1)
529 || array[i]->node != array[i + 1]->node
530 || !STREQ (array[i]->entry, array[i + 1]->entry))
531 copy[j++] = array[i];
532 else
534 free (array[i]->entry);
535 free (array[i]->entry_text);
536 free (array[i]);
539 copy[j] = NULL;
541 /* Now COPY contains only unique entries. Duplicated entries in the
542 original array have been freed. Replace the current array with
543 the copy, fixing the NEXT pointers. */
544 for (i = 0; copy[i]; i++)
546 copy[i]->next = copy[i + 1];
548 /* Fix entry names which are the same. They point to different nodes,
549 so we make the entry name unique. */
550 if (copy[i+1]
551 && STREQ (copy[i]->entry, copy[i + 1]->entry)
552 && !html)
554 char *new_entry_name;
556 new_entry_name = xmalloc (10 + strlen (copy[i]->entry));
557 sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
558 free (copy[i]->entry);
559 copy[i]->entry = new_entry_name;
560 counter++;
562 else
563 counter = 1;
565 array[i] = copy[i];
567 array[i] = NULL;
569 /* Free the storage used only by COPY. */
570 free (copy);
574 /* Sort the index passed in INDEX, returning an array of pointers to
575 elements. The array is terminated with a NULL pointer. */
577 static INDEX_ELT **
578 sort_index (INDEX_ELT *index)
580 INDEX_ELT **array;
581 INDEX_ELT *temp;
582 int count = 0;
583 int save_line_number = line_number;
584 char *save_input_filename = input_filename;
585 int save_html = html;
587 /* Pretend we are in non-HTML mode, for the purpose of getting the
588 expanded index entry that lacks any markup and other HTML escape
589 characters which could produce a wrong sort order. */
590 /* fixme: html: this still causes some markup, such as non-ASCII
591 characters @AE{} etc., to sort incorrectly. */
592 html = 0;
594 for (temp = index, count = 0; temp; temp = temp->next, count++)
596 /* We have the length, now we can allocate an array. */
597 array = xmalloc ((count + 1) * sizeof (INDEX_ELT *));
599 for (temp = index, count = 0; temp; temp = temp->next, count++)
601 /* Allocate new memory for the return array, since parts of the
602 original INDEX get freed. Otherwise, if the document calls
603 @printindex twice on the same index, with duplicate entries,
604 we'll have garbage the second time. There are cleaner ways to
605 deal, but this will suffice for now. */
606 array[count] = xmalloc (sizeof (INDEX_ELT));
607 *(array[count]) = *(temp); /* struct assignment, hope it's ok */
609 /* Adjust next pointers to use the new memory. */
610 if (count > 0)
611 array[count-1]->next = array[count];
613 /* Set line number and input filename to the source line for this
614 index entry, as this expansion finds any errors. */
615 line_number = array[count]->defining_line;
616 input_filename = array[count]->defining_file;
618 /* If this particular entry should be printed as a "code" index,
619 then expand it as @code{entry}, i.e., as in fixed-width font. */
620 array[count]->entry = expansion (temp->entry_text, array[count]->code);
622 array[count] = NULL; /* terminate the array. */
624 line_number = save_line_number;
625 input_filename = save_input_filename;
626 html = save_html;
628 #ifdef HAVE_STRCOLL
629 /* This is not perfect. We should set (then restore) the locale to the
630 documentlanguage, so strcoll operates according to the document's
631 locale, not the user's. For now, I'm just going to assume that
632 those few new documents which use @documentlanguage will be
633 processed in the appropriate locale. In any case, don't use
634 strcoll in the C (aka POSIX) locale, that is the ASCII ordering. */
635 if (language_code != en)
637 char *lang_env = getenv ("LANG");
638 if (lang_env && !STREQ (lang_env, "C") && !STREQ (lang_env, "POSIX"))
639 index_compare_fn = strcoll;
641 #endif /* HAVE_STRCOLL */
643 /* Sort the array. */
644 qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
646 /* Remove duplicate entries. */
647 make_index_entries_unique (array, count);
649 /* Replace the original index with the sorted one, in case the
650 document wants to print it again. If the index wasn't empty. */
651 if (index)
652 *index = **array;
654 return array;
657 static void
658 insert_index_output_line_no (int line_number, int output_line_number_len)
660 int last_column;
661 int str_size = output_line_number_len + strlen (_("(line )"))
662 + sizeof (NULL);
663 char *out_line_no_str = (char *) xmalloc (str_size + 1);
665 /* Do not translate ``(line NNN)'' below for !no_headers case (Info output),
666 because it's something like the ``* Menu'' strings. For plaintext output
667 it should be translated though. */
668 sprintf (out_line_no_str,
669 no_headers ? _("(line %*d)") : "(line %*d)",
670 output_line_number_len, line_number);
673 int i = output_paragraph_offset;
674 while (0 < i && output_paragraph[i-1] != '\n')
675 i--;
676 last_column = output_paragraph_offset - i;
679 if (last_column + strlen (out_line_no_str) > fill_column)
681 insert ('\n');
682 last_column = 0;
685 while (last_column + strlen (out_line_no_str) < fill_column)
687 insert (' ');
688 last_column++;
691 insert_string (out_line_no_str);
692 insert ('\n');
694 free (out_line_no_str);
697 /* Nonzero means that we are in the middle of printing an index. */
698 int printing_index = 0;
700 /* Takes one arg, a short name of an index to print.
701 Outputs a menu of the sorted elements of the index. */
702 void
703 cm_printindex (void)
705 char *index_name;
706 get_rest_of_line (0, &index_name);
708 /* get_rest_of_line increments the line number by one,
709 so to make warnings/errors point to the correct line,
710 we decrement the line_number again. */
711 if (!handling_delayed_writes)
712 line_number--;
714 if (xml && !docbook)
716 xml_insert_element (PRINTINDEX, START);
717 insert_string (index_name);
718 xml_insert_element (PRINTINDEX, END);
720 else if (!handling_delayed_writes)
722 int command_len = sizeof ("@ ") + strlen (command) + strlen (index_name);
723 char *index_command = xmalloc (command_len + 1);
725 close_paragraph ();
726 if (docbook)
727 xml_begin_index ();
729 sprintf (index_command, "@%s %s", command, index_name);
730 register_delayed_write (index_command);
731 free (index_command);
733 else
735 int item;
736 INDEX_ELT *index;
737 INDEX_ELT *last_index = 0;
738 INDEX_ELT **array;
739 unsigned line_length;
740 char *line;
741 int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
742 int saved_filling_enabled = filling_enabled;
743 int saved_line_number = line_number;
744 char *saved_input_filename = input_filename;
745 unsigned output_line_number_len;
747 index = index_list (index_name);
748 if (index == (INDEX_ELT *)-1)
750 line_error (_("Unknown index `%s' in @printindex"), index_name);
751 free (index_name);
752 return;
755 /* Do this before sorting, so execute_string is in the good environment */
756 if (xml && docbook)
757 xml_begin_index ();
759 /* Do this before sorting, so execute_string in index_element_compare
760 will give the same results as when we actually print. */
761 printing_index = 1;
762 filling_enabled = 0;
763 inhibit_paragraph_indentation = 1;
764 xml_sort_index = 1;
765 array = sort_index (index);
766 xml_sort_index = 0;
767 close_paragraph ();
768 if (html)
769 add_html_block_elt_args ("<ul class=\"index-%s\" compact>",
770 index_name);
771 else if (!no_headers && !docbook)
772 { /* Info. Add magic cookie for info readers (to treat this
773 menu differently), and the usual start-of-menu. */
774 add_char ('\0');
775 add_word ("\010[index");
776 add_char ('\0');
777 add_word ("\010]\n");
778 add_word ("* Menu:\n\n");
781 me_inhibit_expansion++;
783 /* This will probably be enough. */
784 line_length = 100;
785 line = xmalloc (line_length);
788 char *max_output_line_number = (char *) xmalloc (25 * sizeof (char));
790 if (no_headers)
791 sprintf (max_output_line_number, "%d", output_line_number);
792 else
794 INDEX_ELT *tmp_entry = index;
795 unsigned tmp = 0;
796 for (tmp_entry = index; tmp_entry; tmp_entry = tmp_entry->next)
797 tmp = tmp_entry->output_line > tmp ? tmp_entry->output_line : tmp;
798 sprintf (max_output_line_number, "%d", tmp);
801 output_line_number_len = strlen (max_output_line_number);
802 free (max_output_line_number);
805 for (item = 0; (index = array[item]); item++)
807 /* A pathological document might have an index entry outside of any
808 node. Don't crash; try using the section name instead. */
809 char *index_node = index->node;
811 line_number = index->defining_line;
812 input_filename = index->defining_file;
814 if ((!index_node || !*index_node) && html)
815 index_node = toc_find_section_of_node (index_node);
817 if (!index_node || !*index_node)
819 line_error (_("Entry for index `%s' outside of any node"),
820 index_name);
821 if (html || !no_headers)
822 index_node = (char *) _("(outside of any node)");
825 if (html)
827 /* For HTML, we need to expand and HTML-escape the
828 original entry text, at the same time. Consider
829 @cindex J@"urgen. We want J&uuml;urgen. We can't
830 expand and then escape since we'll end up with
831 J&amp;uuml;rgen. We can't escape and then expand
832 because then `expansion' will see J@&quot;urgen, and
833 @&quot;urgen is not a command. */
834 char *html_entry =
835 maybe_escaped_expansion (index->entry_text, index->code, 1);
837 add_html_block_elt_args ("\n<li><a href=\"%s#index-",
838 (splitting && index->output_file) ? index->output_file : "");
839 add_escaped_anchor_name (index->entry_text, 0);
840 add_word_args ("-%d\">%s</a>: ", index->entry_number,
841 html_entry);
842 free (html_entry);
844 add_word ("<a href=\"");
845 if (index->node && *index->node)
847 /* Ensure any non-macros in the node name are expanded. */
848 char *expanded_index;
850 in_fixed_width_font++;
851 expanded_index = expansion (index_node, 0);
852 in_fixed_width_font--;
853 add_anchor_name (expanded_index, 1);
854 expanded_index = escape_string (expanded_index);
855 add_word_args ("\">%s</a>", expanded_index);
856 free (expanded_index);
858 else if (STREQ (index_node, _("(outside of any node)")))
860 add_anchor_name (index_node, 1);
861 add_word_args ("\">%s</a>", index_node);
863 else
864 /* If we use the section instead of the (missing) node, then
865 index_node already includes all we need except the #. */
866 add_word_args ("#%s</a>", index_node);
868 add_html_block_elt ("</li>");
870 else if (xml && docbook)
872 /* In the DocBook case, the expanded index entry is not
873 good for us, since it was expanded for non-DocBook mode
874 inside sort_index. So we send the original entry text
875 to be used with execute_string. */
876 xml_insert_indexentry (index->entry_text, index_node);
878 else
880 unsigned new_length = strlen (index->entry);
882 if (new_length < 50) /* minimum length used below */
883 new_length = 50;
884 new_length += strlen (index_node) + 7; /* * : .\n\0 */
886 if (new_length > line_length)
888 line_length = new_length;
889 line = xrealloc (line, line_length);
891 /* Print the entry, nicely formatted. We've already
892 expanded any commands in index->entry, including any
893 implicit @code. Thus, can't call execute_string, since
894 @@ has turned into @. */
895 if (!no_headers)
897 sprintf (line, "* %-37s ", index->entry);
898 line[2 + strlen (index->entry)] = ':';
899 insert_string (line);
900 /* Make sure any non-macros in the node name are expanded. */
901 in_fixed_width_font++;
902 execute_string ("%s. ", index_node);
903 insert_index_output_line_no (index->output_line,
904 output_line_number_len);
905 in_fixed_width_font--;
907 else
909 /* With --no-headers, the @node lines are gone, so
910 there's little sense in referring to them in the
911 index. Instead, output the number or name of the
912 section that corresponds to that node. */
913 sprintf (line, "%-*s ", number_sections ? 46 : 1, index->entry);
914 line[strlen (index->entry)] = ':';
915 insert_string (line);
917 if (strlen (index->section) > 0)
918 { /* We got your number. */
919 insert_string ((char *) _("See "));
920 insert_string (index->section);
922 else
923 { /* Sigh, index in an @unnumbered. :-\ */
924 insert_string ("\n ");
925 insert_string ((char *) _("See "));
926 insert_string ("``");
927 insert_string (expansion (index->section_name, 0));
928 insert_string ("''");
931 insert_string (". ");
932 insert_index_output_line_no (index->output_line,
933 output_line_number_len);
937 /* Prevent `output_paragraph' from growing to the size of the
938 whole index. */
939 flush_output ();
940 last_index = index;
943 free (line);
945 me_inhibit_expansion--;
946 printing_index = 0;
948 close_single_paragraph ();
949 filling_enabled = saved_filling_enabled;
950 inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
951 input_filename = saved_input_filename;
952 line_number = saved_line_number;
954 if (html)
955 add_html_block_elt ("</ul>");
956 else if (xml && docbook)
957 xml_end_index ();
960 free (index_name);
961 /* Re-increment the line number, because get_rest_of_line
962 left us looking at the next line after the command. */
963 line_number++;