source: trunk/third/texinfo/makeinfo/index.c @ 18945

Revision 18945, 25.8 KB checked in by amb, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18944, which included commits to RCS files with non-trunk default branches.
Line 
1/* index.c -- indexing for Texinfo.
2   $Id: index.c,v 1.1.1.2 2003-02-28 17:44:47 amb Exp $
3
4   Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software Foundation,
18   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20#include "system.h"
21#include "index.h"
22#include "lang.h"
23#include "macro.h"
24#include "toc.h"
25#include "xml.h"
26
27/* An index element... */
28typedef struct index_elt
29{
30  struct index_elt *next;
31  char *entry;                  /* The index entry itself, after expansion. */
32  char *entry_text;             /* The original, non-expanded entry text. */
33  char *node;                   /* The node from whence it came. */
34  int code;                     /* Nonzero means add `@code{...}' when
35                                   printing this element. */
36  int defining_line;            /* Line number where this entry was written. */
37  char *defining_file;          /* Source file for defining_line. */
38} INDEX_ELT;
39
40
41/* A list of short-names for each index.
42   There are two indices into the the_indices array.
43   * read_index is the index that points to the list of index
44     entries that we will find if we ask for the list of entries for
45     this name.
46   * write_index is the index that points to the list of index entries
47     that we will add new entries to.
48
49   Initially, read_index and write_index are the same, but the
50   @syncodeindex and @synindex commands can change the list we add
51   entries to.
52
53   For example, after the commands
54     @cindex foo
55     @defindex ii
56     @synindex cp ii
57     @cindex bar
58
59   the cp index will contain the entry `foo', and the new ii
60   index will contain the entry `bar'.  This is consistent with the
61   way texinfo.tex handles the same situation.
62
63   In addition, for each index, it is remembered whether that index is
64   a code index or not.  Code indices have @code{} inserted around the
65   first word when they are printed with printindex. */
66typedef struct
67{
68  char *name;
69  int read_index;   /* index entries for `name' */
70  int write_index;  /* store index entries here, @synindex can change it */
71  int code;
72} INDEX_ALIST;
73
74INDEX_ALIST **name_index_alist = NULL;
75
76/* An array of pointers.  Each one is for a different index.  The
77   "synindex" command changes which array slot is pointed to by a
78   given "index". */
79INDEX_ELT **the_indices = NULL;
80
81/* The number of defined indices. */
82int defined_indices = 0;
83
84/* Stuff for defining commands on the fly. */
85COMMAND **user_command_array = NULL;
86int user_command_array_len = 0;
87
88/* How to compare index entries for sorting.  May be set to strcoll.  */
89int (*index_compare_fn) () = strcasecmp;
90
91/* Find which element in the known list of indices has this name.
92   Returns -1 if NAME isn't found. */
93static int
94find_index_offset (name)
95     char *name;
96{
97  int i;
98  for (i = 0; i < defined_indices; i++)
99    if (name_index_alist[i] && STREQ (name, name_index_alist[i]->name))
100      return i;
101  return -1;
102}
103
104/* Return a pointer to the entry of (name . index) for this name.
105   Return NULL if the index doesn't exist. */
106INDEX_ALIST *
107find_index (name)
108     char *name;
109{
110  int offset = find_index_offset (name);
111  if (offset > -1)
112    return name_index_alist[offset];
113  else
114    return NULL;
115}
116
117/* User-defined commands, which happens only from user-defined indexes.
118   Used to initialize the builtin indices, too.  */
119void
120define_user_command (name, proc, needs_braces_p)
121     char *name;
122     COMMAND_FUNCTION *proc;
123     int needs_braces_p;
124{
125  int slot = user_command_array_len;
126  user_command_array_len++;
127
128  if (!user_command_array)
129    user_command_array = xmalloc (1 * sizeof (COMMAND *));
130
131  user_command_array = xrealloc (user_command_array,
132                            (1 + user_command_array_len) * sizeof (COMMAND *));
133
134  user_command_array[slot] = xmalloc (sizeof (COMMAND));
135  user_command_array[slot]->name = xstrdup (name);
136  user_command_array[slot]->proc = proc;
137  user_command_array[slot]->argument_in_braces = needs_braces_p;
138}
139
140/* Please release me, let me go... */
141static void
142free_index (index)
143     INDEX_ELT *index;
144{
145  INDEX_ELT *temp;
146
147  while ((temp = index))
148    {
149      free (temp->entry);
150      free (temp->entry_text);
151      /* Do not free the node, because we already freed the tag table,
152         which freed all the node names.  */
153      /* free (temp->node); */
154      index = index->next;
155      free (temp);
156    }
157}
158
159/* Flush an index by name.  This will delete the list of entries that
160   would be written by a @printindex command for this index. */
161static void
162undefindex (name)
163     char *name;
164{
165  int i;
166  int which = find_index_offset (name);
167
168  /* The index might have already been freed if this was the target of
169     an @synindex.  */
170  if (which < 0 || !name_index_alist[which])
171    return;
172
173  i = name_index_alist[which]->read_index;
174
175  free_index (the_indices[i]);
176  the_indices[i] = NULL;
177
178  free (name_index_alist[which]->name);
179  free (name_index_alist[which]);
180  name_index_alist[which] = NULL;
181}
182
183/* Add the arguments to the current index command to the index NAME.
184   html fixxme generate specific html anchor */
185static void
186index_add_arg (name)
187     char *name;
188{
189  int which;
190  char *index_entry;
191  INDEX_ALIST *tem;
192
193  tem = find_index (name);
194
195  which = tem ? tem->write_index : -1;
196
197  if (macro_expansion_output_stream && !executing_string)
198    append_to_expansion_output (input_text_offset + 1);
199
200  get_rest_of_line (0, &index_entry);
201  ignore_blank_line ();
202
203  if (macro_expansion_output_stream && !executing_string)
204    {
205      char *index_line = xmalloc (strlen (index_entry) + 2);
206      sprintf (index_line, "%s\n", index_entry);
207      me_execute_string_keep_state (index_line, NULL);
208      free (index_line);
209    }
210
211  if (which < 0)
212    {
213      line_error (_("Unknown index `%s'"), name);
214      free (index_entry);
215    }
216  else
217    {
218      INDEX_ELT *new = xmalloc (sizeof (INDEX_ELT));
219      new->next = the_indices[which];
220      new->entry_text = index_entry;
221      new->entry = NULL;
222      new->node = current_node ? current_node : xstrdup ("");
223      new->code = tem->code;
224      new->defining_line = line_number - 1;
225      /* We need to make a copy since input_filename may point to
226         something that goes away, for example, inside a macro.
227         (see the findexerr test).  */
228      new->defining_file = xstrdup (input_filename);
229      the_indices[which] = new;
230#if 0
231      /* The index breaks if there are colons in the entry.
232         -- This is true, but it's too painful to force changing index
233         entries to use `colon', and too confusing for users.  The real
234         fix is to change Info support to support arbitrary characters
235         in node names, and we're not ready to do that.  --karl,
236         19mar02.  */
237      if (strchr (new->entry_text, ':'))
238        warning (_("Info cannot handle `:' in index entry `%s'"),
239                 new->entry_text);
240#endif
241    }
242  if (xml)
243    xml_insert_indexterm (index_entry, name);
244}
245
246/* The function which user defined index commands call. */
247static void
248gen_index ()
249{
250  char *name = xstrdup (command);
251  if (strlen (name) >= strlen ("index"))
252    name[strlen (name) - strlen ("index")] = 0;
253  index_add_arg (name);
254  free (name);
255}
256
257/* Define an index known as NAME.  We assign the slot number.
258   If CODE is nonzero, make this a code index. */
259static void
260defindex (name, code)
261     char *name;
262     int code;
263{
264  int i, slot;
265
266  /* If it already exists, flush it. */
267  undefindex (name);
268
269  /* Try to find an empty slot. */
270  slot = -1;
271  for (i = 0; i < defined_indices; i++)
272    if (!name_index_alist[i])
273      {
274        slot = i;
275        break;
276      }
277
278  if (slot < 0)
279    { /* No such luck.  Make space for another index. */
280      slot = defined_indices;
281      defined_indices++;
282
283      name_index_alist = (INDEX_ALIST **)
284        xrealloc (name_index_alist, (1 + defined_indices)
285                                    * sizeof (INDEX_ALIST *));
286      the_indices = (INDEX_ELT **)
287        xrealloc (the_indices, (1 + defined_indices) * sizeof (INDEX_ELT *));
288    }
289
290  /* We have a slot.  Start assigning. */
291  name_index_alist[slot] = xmalloc (sizeof (INDEX_ALIST));
292  name_index_alist[slot]->name = xstrdup (name);
293  name_index_alist[slot]->read_index = slot;
294  name_index_alist[slot]->write_index = slot;
295  name_index_alist[slot]->code = code;
296
297  the_indices[slot] = NULL;
298}
299
300/* Define an index NAME, implicitly @code if CODE is nonzero.  */
301static void
302top_defindex (name, code)
303     char *name;
304     int code;
305{
306  char *temp;
307
308  temp = xmalloc (1 + strlen (name) + strlen ("index"));
309  sprintf (temp, "%sindex", name);
310  define_user_command (temp, gen_index, 0);
311  defindex (name, code);
312  free (temp);
313}
314
315/* Set up predefined indices.  */
316void
317init_indices ()
318{
319  int i;
320
321  /* Create the default data structures. */
322
323  /* Initialize data space. */
324  if (!the_indices)
325    {
326      the_indices = xmalloc ((1 + defined_indices) * sizeof (INDEX_ELT *));
327      the_indices[defined_indices] = NULL;
328
329      name_index_alist = xmalloc ((1 + defined_indices)
330                                  * sizeof (INDEX_ALIST *));
331      name_index_alist[defined_indices] = NULL;
332    }
333
334  /* If there were existing indices, get rid of them now. */
335  for (i = 0; i < defined_indices; i++)
336    {
337      if (name_index_alist[i])
338        { /* Suppose we're called with two input files, and the first
339             does a @synindex pg cp.  Then, when we get here to start
340             the second file, the "pg" element won't get freed by
341             undefindex (because it's pointing to "cp").  So free it
342             here; otherwise, when we try to define the pg index again
343             just below, it will still point to cp.  */
344          undefindex (name_index_alist[i]->name);
345          free (name_index_alist[i]->name);
346          free (name_index_alist[i]);
347          name_index_alist[i] = NULL;
348        }
349    }
350
351  /* Add the default indices. */
352  top_defindex ("cp", 0);           /* cp is the only non-code index.  */
353  top_defindex ("fn", 1);
354  top_defindex ("ky", 1);
355  top_defindex ("pg", 1);
356  top_defindex ("tp", 1);
357  top_defindex ("vr", 1);
358}
359
360/* Given an index name, return the offset in the_indices of this index,
361   or -1 if there is no such index. */
362int
363translate_index (name)
364     char *name;
365{
366  INDEX_ALIST *which = find_index (name);
367
368  if (which)
369    return which->read_index;
370  else
371    return -1;
372}
373
374/* Return the index list which belongs to NAME. */
375INDEX_ELT *
376index_list (name)
377     char *name;
378{
379  int which = translate_index (name);
380  if (which < 0)
381    return (INDEX_ELT *) -1;
382  else
383    return the_indices[which];
384}
385
386/* Define a new index command.  Arg is name of index. */
387static void
388gen_defindex (code)
389     int code;
390{
391  char *name;
392  get_rest_of_line (0, &name);
393
394  if (find_index (name))
395    {
396      line_error (_("Index `%s' already exists"), name);
397    }
398  else
399    {
400      char *temp = xmalloc (strlen (name) + sizeof ("index"));
401      sprintf (temp, "%sindex", name);
402      define_user_command (temp, gen_index, 0);
403      defindex (name, code);
404      free (temp);
405    }
406
407  free (name);
408}
409
410void
411cm_defindex ()
412{
413  gen_defindex (0);
414}
415
416void
417cm_defcodeindex ()
418{
419  gen_defindex (1);
420}
421
422/* Expects 2 args, on the same line.  Both are index abbreviations.
423   Make the first one be a synonym for the second one, i.e. make the
424   first one have the same index as the second one. */
425void
426cm_synindex ()
427{
428  int source, target;
429  char *abbrev1, *abbrev2;
430
431  skip_whitespace ();
432  get_until_in_line (0, " ", &abbrev1);
433  target = find_index_offset (abbrev1);
434  skip_whitespace ();
435  get_until_in_line (0, " ", &abbrev2);
436  source = find_index_offset (abbrev2);
437  if (source < 0 || target < 0)
438    {
439      line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
440                  abbrev1, abbrev2);
441    }
442  else
443    {
444      name_index_alist[target]->write_index
445        = name_index_alist[source]->write_index;
446    }
447
448  free (abbrev1);
449  free (abbrev2);
450}
451
452void
453cm_pindex ()                    /* Pinhead index. */
454{
455  index_add_arg ("pg");
456}
457
458void
459cm_vindex ()                    /* Variable index. */
460{
461  index_add_arg ("vr");
462}
463
464void
465cm_kindex ()                    /* Key index. */
466{
467  index_add_arg ("ky");
468}
469
470void
471cm_cindex ()                    /* Concept index. */
472{
473  index_add_arg ("cp");
474}
475
476void
477cm_findex ()                    /* Function index. */
478{
479  index_add_arg ("fn");
480}
481
482void
483cm_tindex ()                    /* Data Type index. */
484{
485  index_add_arg ("tp");
486}
487
488int
489index_element_compare (element1, element2)
490     INDEX_ELT **element1, **element2;
491{
492  return index_compare_fn ((*element1)->entry, (*element2)->entry);
493}
494
495/* Force all index entries to be unique. */
496void
497make_index_entries_unique (array, count)
498     INDEX_ELT **array;
499     int count;
500{
501  int i, j;
502  INDEX_ELT **copy;
503  int counter = 1;
504
505  copy = xmalloc ((1 + count) * sizeof (INDEX_ELT *));
506
507  for (i = 0, j = 0; i < count; i++)
508    {
509      if (i == (count - 1)
510          || array[i]->node != array[i + 1]->node
511          || !STREQ (array[i]->entry, array[i + 1]->entry))
512        copy[j++] = array[i];
513      else
514        {
515          free (array[i]->entry);
516          free (array[i]->entry_text);
517          free (array[i]);
518        }
519    }
520  copy[j] = NULL;
521
522  /* Now COPY contains only unique entries.  Duplicated entries in the
523     original array have been freed.  Replace the current array with
524     the copy, fixing the NEXT pointers. */
525  for (i = 0; copy[i]; i++)
526    {
527      copy[i]->next = copy[i + 1];
528
529      /* Fix entry names which are the same.  They point to different nodes,
530         so we make the entry name unique. */
531      if (copy[i+1]
532          && STREQ (copy[i]->entry, copy[i + 1]->entry)
533          && !html)
534        {
535          char *new_entry_name;
536
537          new_entry_name = xmalloc (10 + strlen (copy[i]->entry));
538          sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
539          free (copy[i]->entry);
540          copy[i]->entry = new_entry_name;
541          counter++;
542        }
543      else
544        counter = 1;
545
546      array[i] = copy[i];
547    }
548  array[i] = NULL;
549
550  /* Free the storage used only by COPY. */
551  free (copy);
552}
553
554/* Sort the index passed in INDEX, returning an array of
555   pointers to elements.  The array is terminated with a NULL
556   pointer.  We call qsort because it's supposed to be fast.
557   I think this looks bad. */
558INDEX_ELT **
559sort_index (index)
560     INDEX_ELT *index;
561{
562  INDEX_ELT **array;
563  INDEX_ELT *temp = index;
564  int count = 0;
565  int save_line_number = line_number;
566  char *save_input_filename = input_filename;
567  int save_html = html;
568
569  /* Pretend we are in non-HTML mode, for the purpose of getting the
570     expanded index entry that lacks any markup and other HTML escape
571     characters which could produce a wrong sort order.  */
572  /* fixme: html: this still causes some markup, such as non-ASCII
573     characters @AE{} etc., to sort incorrectly.  */
574  html = 0;
575
576  while (temp)
577    {
578      count++;
579      temp = temp->next;
580    }
581
582  /* We have the length.  Make an array. */
583
584  array = xmalloc ((count + 1) * sizeof (INDEX_ELT *));
585  count = 0;
586  temp = index;
587
588  while (temp)
589    {
590      array[count++] = temp;
591
592      /* Set line number and input filename to the source line for this
593         index entry, as this expansion finds any errors.  */
594      line_number = array[count - 1]->defining_line;
595      input_filename = array[count - 1]->defining_file;
596
597      /* If this particular entry should be printed as a "code" index,
598         then expand it as @code{entry}, i.e. as in fixed-width font.  */
599      array[count-1]->entry = expansion (temp->entry_text,
600                                         array[count-1]->code);
601
602      temp = temp->next;
603    }
604  array[count] = NULL;    /* terminate the array. */
605  line_number = save_line_number;
606  input_filename = save_input_filename;
607  html = save_html;
608
609#ifdef HAVE_STRCOLL
610  /* This is not perfect.  We should set (then restore) the locale to the
611     documentlanguage, so strcoll operates according to the document's
612     locale, not the user's.  For now, I'm just going to assume that
613     those few new documents which use @documentlanguage will be
614     processed in the appropriate locale.  In any case, don't use
615     strcoll in the C (aka POSIX) locale, that is the ASCII ordering.  */
616  if (language_code != en)
617    {
618      char *lang_env = getenv ("LANG");
619      if (lang_env && !STREQ (lang_env, "C") && !STREQ (lang_env, "POSIX"))
620        index_compare_fn = strcoll;
621    }
622#endif /* HAVE_STRCOLL */   
623
624  /* Sort the array. */
625  qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
626  make_index_entries_unique (array, count);
627  return array;
628}
629
630/* Nonzero means that we are in the middle of printing an index. */
631int printing_index = 0;
632
633/* Takes one arg, a short name of an index to print.
634   Outputs a menu of the sorted elements of the index. */
635void
636cm_printindex ()
637{
638  if (xml && !docbook)
639    {
640      char *index_name;
641      get_rest_of_line (0, &index_name);
642      xml_insert_element (PRINTINDEX, START);
643      insert_string (index_name);
644      xml_insert_element (PRINTINDEX, END);
645    }
646  else
647    {
648      int item;
649      INDEX_ELT *index;
650      INDEX_ELT *last_index = 0;
651      INDEX_ELT **array;
652      char *index_name;
653      unsigned line_length;
654      char *line;
655      int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
656      int saved_filling_enabled = filling_enabled;
657      int saved_line_number = line_number;
658      char *saved_input_filename = input_filename;
659
660      close_paragraph ();
661      get_rest_of_line (0, &index_name);
662
663      index = index_list (index_name);
664      if (index == (INDEX_ELT *)-1)
665        {
666          line_error (_("Unknown index `%s' in @printindex"), index_name);
667          free (index_name);
668          return;
669        }
670     
671      /* Do this before sorting, so execute_string is in the good environment */
672      if (xml && docbook)
673        xml_begin_index ();
674     
675      /* Do this before sorting, so execute_string in index_element_compare
676         will give the same results as when we actually print.  */
677      printing_index = 1;
678      filling_enabled = 0;
679      inhibit_paragraph_indentation = 1;
680      xml_sort_index = 1;
681      array = sort_index (index);
682      xml_sort_index = 0;
683      close_paragraph ();
684      if (html)
685        add_word_args ("<ul class=\"index-%s\" compact>", index_name);
686      else if (!no_headers && !docbook)
687        add_word ("* Menu:\n\n");
688     
689      me_inhibit_expansion++;
690     
691      /* This will probably be enough.  */
692      line_length = 100;
693      line = xmalloc (line_length);
694     
695      for (item = 0; (index = array[item]); item++)
696        {
697          /* A pathological document might have an index entry outside of any
698             node.  Don't crash; try using the section name instead.  */
699          char *index_node = index->node;
700         
701          line_number = index->defining_line;
702          input_filename = index->defining_file;
703         
704          if ((!index_node || !*index_node) && html)
705            index_node = toc_find_section_of_node (index_node);
706         
707          if (!index_node || !*index_node)
708            {
709              line_error (_("Entry for index `%s' outside of any node"),
710                          index_name);
711              if (html || !no_headers)
712                index_node = _("(outside of any node)");
713            }
714         
715          if (html)
716            /* fixme: html: we should use specific index anchors pointing
717           to the actual location of the indexed position (but then we
718           have to find something to wrap the anchor around). */
719            {
720              if (last_index
721                  && STREQ (last_index->entry_text, index->entry_text))
722                add_word (", ");  /* Don't repeat the previous entry. */
723              else
724                {
725                  /* In the HTML case, the expanded index entry is not
726                     good for us, since it was expanded for non-HTML mode
727                     inside sort_index.  So we need to HTML-escape and
728                     expand the original entry text here.  */
729                  char *escaped_entry = xstrdup (index->entry_text);
730                  char *expanded_entry;
731                 
732                  /* expansion() doesn't HTML-escape the argument, so need
733                     to do it separately.  */
734                  escaped_entry = escape_string (escaped_entry);
735                  expanded_entry = expansion (escaped_entry, index->code);
736                  add_word_args ("\n<li>%s: ", expanded_entry);
737                  free (escaped_entry);
738                  free (expanded_entry);
739                }
740              add_word ("<a href=\"");
741              if (index->node && *index->node)
742                {
743                  /* Make sure any non-macros in the node name are expanded.  */
744                  in_fixed_width_font++;
745                  index_node = expansion (index_node, 0);
746                  in_fixed_width_font--;
747                  add_anchor_name (index_node, 1);
748                  add_word_args ("\">%s</a>", index_node);
749                  free (index_node);
750                }
751              else if (STREQ (index_node, _("(outside of any node)")))
752                {
753                  add_anchor_name (index_node, 1);
754                  add_word_args ("\">%s</a>", index_node);
755                }
756              else
757                /* If we use the section instead of the (missing) node, then
758                   index_node already includes all we need except the #.  */
759                add_word_args ("#%s</a>", index_node);
760            }
761          else if (xml && docbook)
762            {
763              /* In the DocBook case, the expanded index entry is not
764                 good for us, since it was expanded for non-DocBook mode
765                 inside sort_index.  So we send the original entry text
766                 to be used with execute_string.  */
767              xml_insert_indexentry (index->entry_text, index_node);
768            }
769          else
770            {
771              unsigned new_length = strlen (index->entry);
772             
773              if (new_length < 50) /* minimum length used below */
774                new_length = 50;
775              new_length += strlen (index_node) + 7; /* * : .\n\0 */
776             
777              if (new_length > line_length)
778                {
779                  line_length = new_length;
780                  line = xrealloc (line, line_length);
781                }
782              /* Print the entry, nicely formatted.  We've already
783                 expanded any commands in index->entry, including any
784                 implicit @code.  Thus, can't call execute_string, since
785                 @@ has turned into @. */
786              if (!no_headers)
787                {
788                  sprintf (line, "* %-37s  ", index->entry);
789                  line[2 + strlen (index->entry)] = ':';
790                  insert_string (line);
791                  /* Make sure any non-macros in the node name are expanded.  */
792                  in_fixed_width_font++;
793                  execute_string ("%s.\n", index_node);
794                  in_fixed_width_font--;
795                }
796              else
797                {
798                  /* With --no-headers, the @node lines are gone, so
799                     there's little sense in referring to them in the
800                     index.  Instead, output the number or name of the
801                     section that corresponds to that node.  */
802                  char *section_name = toc_find_section_of_node (index_node);
803                 
804                  sprintf (line, "%-*s ", number_sections ? 50 : 1, index->entry);
805                  line[strlen (index->entry)] = ':';
806                  insert_string (line);
807                  if (section_name)
808                    {
809                      int idx = 0;
810                      unsigned ref_len = strlen (section_name) + 30;
811                     
812                      if (ref_len > line_length)
813                        {
814                          line_length = ref_len;
815                          line = xrealloc (line, line_length);
816                        }
817                     
818                      if (number_sections)
819                        {
820                          while (section_name[idx]
821                                 && (isdigit (section_name[idx])
822                                     || (idx && section_name[idx] == '.')))
823                            idx++;
824                        }
825                      if (idx)
826                        sprintf (line, " See %.*s.\n", idx, section_name);
827                      else
828                        sprintf (line, "\n          See ``%s''.\n", section_name);
829                      insert_string (line);
830                    }
831                  else
832                    {
833                      insert_string (" "); /* force a blank */
834                      execute_string ("See node %s.\n", index_node);
835                    }
836                }
837            }
838         
839          /* Prevent `output_paragraph' from growing to the size of the
840             whole index.  */
841          flush_output ();
842          last_index = index;
843        }
844
845      free (line);
846      free (index_name);
847     
848      me_inhibit_expansion--;
849     
850      printing_index = 0;
851      free (array);
852      close_single_paragraph ();
853      filling_enabled = saved_filling_enabled;
854      inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
855      input_filename = saved_input_filename;
856      line_number = saved_line_number;
857     
858      if (html)
859        add_word ("</ul>");
860      else if (xml && docbook)
861        xml_end_index ();
862    }
863}
Note: See TracBrowser for help on using the repository browser.