For the following Texinfo file,

  \input texinfo
  @setfilename foo.info

  @ifinfo
  @node Top, concept index, (dir), (dir)
  @top
  @end ifinfo

  Some text here.

  @cindex foo-concept
  @findex foo-function

  @defindex xx
  @synindex cp xx
  @synindex fn xx

  Some more text here.

  @cindex bar-concept
  @findex bar-function

  @ifinfo
  @menu
  * concept index::               
  * function index::              
  * xx index::                    
  @end menu
  @end ifinfo

  @node concept index, function index, Top, Top
  @chapter concept index

  @printindex cp

  @node function index, xx index, concept index, Top
  @chapter function index

  @printindex fn

  @node xx index,  , function index, Top
  @chapter xx index

  @printindex xx

  @bye

TeX creates three indices with the contents

  concept index
    foo-concept

  function index
    foo-function

  xx index 
    bar-concept
    bar-function

but makeinfo version 1.64 (from texinfo-3.7) creates three indices 
with the contents:

  concept index
    bar-concept
    bar-function

  function index
    bar-function

  xx index
    bar-function

Here is a patch that will cause makeinfo to behave more like
TeX/texinfo.tex.  It is relative to the versionof makeinfo distributed
with texinfo 3.9.

Tue Nov 12 22:20:22 1996  John Eaton  <jwe@bevo.che.wisc.edu>

	* makeinfo.c (INDEX_ALIST): Use two indices, read_index and
	write_index, instead of just one.
	(find_index_offset): If a match is found, return index to the
	current INDEX_ALIST struct, not the index pointing to the list of
	index entries.
	(translate_index): Return read_index from the matching
	INDEX_ALIST.
	(undefindex): Delete the list of index elements pointed to by
	read_index from the INDEX_ALIST that matches name.
	(defindex): Initialize read_index and write_index.
	(index_add_arg): Add entries to the list pointed to by write_index
	from the INDEX_ALIST matching name.
	(index_append): Delete unused function.
	(cm_synindex): Don't merge indcies, just make the write_index for
	redirectee the same as the write_index for redirector.

diff -cNr texinfo-3.9/makeinfo/makeinfo.c texinfo-3.9.local/makeinfo/makeinfo.c
*** texinfo-3.9/makeinfo/makeinfo.c	Fri Oct  4 13:20:54 1996
--- texinfo-3.9.local/makeinfo/makeinfo.c	Thu Nov  7 13:12:59 1996
***************
*** 7472,7485 ****
    int defining_line;		/* Line number where this entry was written. */
  } INDEX_ELT;
  
! /* A list of short-names for each index, and the index to that index in our
!    index array, the_indices.  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 index;
    int code;
  } INDEX_ALIST;
  
--- 7472,7511 ----
    int defining_line;		/* Line number where this entry was written. */
  } 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 xx
!      @synindex cp xx
!      @cindex bar
! 
!    the cp index will contain the entry `foo', and the new xx
!    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;
  
***************
*** 7544,7550 ****
    for (i = 0; i < defined_indices; i++)
      if (name_index_alist[i] &&
  	strcmp (name, name_index_alist[i]->name) == 0)
!       return (name_index_alist[i]->index);
    return (-1);
  }
  
--- 7570,7577 ----
    for (i = 0; i < defined_indices; i++)
      if (name_index_alist[i] &&
  	strcmp (name, name_index_alist[i]->name) == 0)
!       return i;
! 
    return (-1);
  }
  
***************
*** 7570,7576 ****
    INDEX_ALIST *which = find_index (name);
  
    if (which)
!     return (which->index);
    else
      return (-1);
  }
--- 7597,7603 ----
    INDEX_ALIST *which = find_index (name);
  
    if (which)
!     return (which->read_index);
    else
      return (-1);
  }
***************
*** 7603,7609 ****
      }
  }
  
! /* Flush an index by name. */
  void
  undefindex (name)
       char *name;
--- 7630,7637 ----
      }
  }
  
! /* Flush an index by name.  This will delete the list of entries that
!    would be written by a @printindex command for this index. */
  void
  undefindex (name)
       char *name;
***************
*** 7614,7620 ****
    if (which < 0)
      return;
  
!   i = name_index_alist[which]->index;
  
    free_index (the_indices[i]);
    the_indices[i] = (INDEX_ELT *) NULL;
--- 7642,7648 ----
    if (which < 0)
      return;
  
!   i = name_index_alist[which]->read_index;
  
    free_index (the_indices[i]);
    the_indices[i] = (INDEX_ELT *) NULL;
***************
*** 7662,7668 ****
    /* We have a slot.  Start assigning. */
    name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
    name_index_alist[slot]->name = strdup (name);
!   name_index_alist[slot]->index = slot;
    name_index_alist[slot]->code = code;
  
    the_indices[slot] = (INDEX_ELT *) NULL;
--- 7690,7697 ----
    /* We have a slot.  Start assigning. */
    name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
    name_index_alist[slot]->name = strdup (name);
!   name_index_alist[slot]->read_index = slot;
!   name_index_alist[slot]->write_index = slot;
    name_index_alist[slot]->code = code;
  
    the_indices[slot] = (INDEX_ELT *) NULL;
***************
*** 7679,7685 ****
  
    tem = find_index (name);
  
!   which = tem ? tem->index : -1;
  
  #if defined (HAVE_MACROS)
    if (macro_expansion_output_stream)
--- 7708,7714 ----
  
    tem = find_index (name);
  
!   which = tem ? tem->write_index : -1;
  
  #if defined (HAVE_MACROS)
    if (macro_expansion_output_stream)
***************
*** 7782,7803 ****
      }
  }
  
- /* Append LIST2 to LIST1.  Return the head of the list. */
- INDEX_ELT *
- index_append (head, tail)
-      INDEX_ELT *head, *tail;
- {
-   register INDEX_ELT *t_head = head;
- 
-   if (!t_head)
-     return (tail);
- 
-   while (t_head->next)
-     t_head = t_head->next;
-   t_head->next = tail;
-   return (head);
- }
- 
  /* Expects 2 args, on the same line.  Both are index abbreviations.
     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. */
--- 7811,7816 ----
***************
*** 7821,7842 ****
      }
    else
      {
!       /* I think that we should let the user make indices synonymous to
!          each other without any lossage of info.  This means that one can
!          say @synindex cp dt anywhere in the file, and things that used to
!          be in cp will go into dt. */
!       INDEX_ELT *i1 = the_indices[redirectee], *i2 = the_indices[redirector];
! 
!       if (i1 || i2)
! 	{
! 	  if (i1)
! 	    the_indices[redirectee] = index_append (i1, i2);
! 	  else
! 	    the_indices[redirectee] = index_append (i2, i1);
! 	}
! 
!       name_index_alist[redirectee]->index =
! 	name_index_alist[redirector]->index;
      }
  }
  
--- 7834,7841 ----
      }
    else
      {
!       name_index_alist[redirectee]->write_index =
! 	name_index_alist[redirector]->write_index;
      }
  }
  
