1998-09-12  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (add_char): Undo incorrect replacement of
	strncpy with memcpy.  If the line being refilled includes nothing
	but the indentation and the word being added, do NOT add an extra
	newline.

1998-09-07  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (maybe_update_execution_strings): Only
	reallocate TEXT if the existing storage is too small, otherwise
	leave TEXT alone.
	(replace_with_expansion): Call maybe_update_execution_strings to
	reallocate input_text if we are executing_string, since storage
	for execution_string is assumed to be large enough to hold every
	possible string.
	(me_execute_string): xstrdup the argument, so callees could freely
	relocate it as needed.

1998-09-06  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (replace_with_expansion): Don't remember
	macro-expansion pointers if we are executing_string.

1998-09-05  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (maybe_update_execution_strings): New
	function, updates an entry in execution_strings[] array when
	input_text is relocated by replace_with_expansion.
	(replace_with_expansion): Call it.

	* info/filesys.c (info_suffixes): Put the empty suffix last in the
	list, so that `foo.info' is found before `foo', if both exist.

1998-09-04  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (expand_macro): If a macro is called with
	too many arguments, return NULL and print the line number where
	the call begins.
	(execute_macro): If expand_macro returns NULL, return
	immediately.

1998-08-28  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c (cm_uref, cm_email): Use get_xref_token to
	gather arguments.
	(get_xref_token): Keep track of input line number when expanding
	xref arguments.

1998-08-16  Eli Zaretskii  <eliz@is.elta.co.il>

	* info/indices.c (info_index_apropos): In the *Apropos* menu,
	print the label first, then the Info file name and the node name.
	(apropos_in_all_indices): Scan each Info file only once, thus
	avoiding multiple identical entries in the *Apropos* menu.  Free
	xstrdup'ed buffer, to avoid leeking memory.

1998-06-26  Eli Zaretskii  <eliz@is.elta.co.il>

	* makeinfo/makeinfo.c: (only_macro_expansion): New variable,
	suppresses all expansions except macros.
	(replace_with_expansion): New function, replaces a portion of
	input text with its expansion.  Avoids moving the text around if
	we are positive it will expand into itself.  If the length of the
	expanded text is the same as the length of the original text, just
	replaces the original text without moving the rest.  Resyncs the
	remembered text pointers with the realloc'ed input_text, when it
	is realloc'ed.
	(reader_loop): When only_macro_expansion is non-zero, only handle
	macros, but leave the rest of input intact.
	(read_command): Now returns an int, zero means no known command or
	macro is found after the prefix character; all callers changed.
	Support operation under non-zero only_macro_expansion.
	(cm_node): Expand only the macros in the @node line.  Allocate and
	generate the macro-expanded @node line in one swell whoop.
	(glean_node_from_menu): Expand macros in menu entries.
	(get_xref_token): A new argument EXPAND, when non-zero, means
	expand macros in the entire brace-delimited argument before
	looking for the next comma; all callers changed.
	(expansion): Save and restore additional state variables important
	for output generation machinery.  Disable indentation and filling
	during the recursive expansion, so that the output buffer offset
	is not invalidated by filling.
	(me_execute_string_keep_state): New function, calls
	me_execute_string, but saves and restores state variables
	important for output generation, so that -E doesn't change the
	generated Info output.
	(index_add_arg, cm_footnote): Call me_execute_string_keep_state.
	(expand_macro): New function, returns the macro expansion as a
	malloc'ed string.
	(execute_macro): Call expand_macro.
	(me_execute_string): Avoid memory leak by freeing input_filename.
	(get_until_in_braces, replace_with_expansion, add_char,
	cm_footnote, cm_macro, cm_unmacro, get_brace_args,
	extract_colon_unit): Use the faster memcpy/memmove instead of
	strncpy.

*** info/indices.c~2	Sat May 23 13:54:12 1998
--- info/indices.c	Sun Aug 16 18:44:18 1998
*************** apropos_in_all_indices (search_string, i
*** 495,505 ****
--- 495,507 ----
        REFERENCE **this_index, *this_item;
        NODE *this_node;
        FILE_BUFFER *this_fb;
+       int dir_node_duplicated = 0;
  
        this_item = dir_menu[dir_index];
  
        if (!this_item->filename)
          {
+ 	  dir_node_duplicated = 1;
            if (dir_node->parent)
              this_item->filename = xstrdup (dir_node->parent);
            else
*************** apropos_in_all_indices (search_string, i
*** 515,521 ****
          this_node = info_get_node (this_item->label, "Top");
  
        if (!this_node)
!         continue;
  
        /* Get the file buffer associated with this node. */
        {
--- 517,527 ----
          this_node = info_get_node (this_item->label, "Top");
  
        if (!this_node)
! 	{
! 	  if (dir_node_duplicated)
! 	    free (this_item->filename);
! 	  continue;
! 	}
  
        /* Get the file buffer associated with this node. */
        {
*************** apropos_in_all_indices (search_string, i
*** 527,532 ****
--- 533,551 ----
  
          this_fb = info_find_file (files_name);
  
+ 	/* If we already scanned this file, don't do that again.
+ 	   In addition to being faster, this also avoids having
+ 	   multiple identical entries in the *Apropos* menu.  */
+ 	for (i = 0; i < dir_index; i++)
+ 	  if (FILENAME_CMP (this_fb->filename, dir_menu[i]->filename) == 0)
+ 	    break;
+ 	if (i < dir_index)
+ 	  {
+ 	    if (dir_node_duplicated)
+ 	      free (this_item->filename);
+ 	    continue;
+ 	  }
+ 
          if (this_fb && inform)
            message_in_echo_area (_("Scanning indices of \"%s\"..."), files_name);
  
*************** DECLARE_INFO_COMMAND (info_index_apropos
*** 651,660 ****
            for (i = 0; apropos_list[i]; i++)
              {
                int len;
!               sprintf (line_buffer, "* (%s)%s::",
                         apropos_list[i]->filename, apropos_list[i]->nodename);
-               len = pad_to (36, line_buffer);
-               sprintf (line_buffer + len, "%s", apropos_list[i]->label);
                printf_to_message_buffer ("%s\n", line_buffer);
              }
            free (line_buffer);
--- 670,683 ----
            for (i = 0; apropos_list[i]; i++)
              {
                int len;
! 	      /* The label might be identical to that of another index
! 		 entry in another Info file.  Therefore, we make the file
! 		 name part of the menu entry, to make them all distinct.  */
!               sprintf (line_buffer, "* %s [%s]: ",
! 		       apropos_list[i]->label, apropos_list[i]->filename);
!               len = pad_to (40, line_buffer);
!               sprintf (line_buffer + len, "(%s)%s.",
                         apropos_list[i]->filename, apropos_list[i]->nodename);
                printf_to_message_buffer ("%s\n", line_buffer);
              }
            free (line_buffer);
*** info/filesys.c~3	Sat Sep  5 12:36:30 1998
--- info/filesys.c	Sat Sep  5 12:37:02 1998
*************** typedef struct
*** 36,42 ****
  } COMPRESSION_ALIST;
  
  static char *info_suffixes[] = {
-   "",
    ".info",
    "-info",
    "/index",
--- 36,41 ----
*************** static char *info_suffixes[] = {
*** 46,51 ****
--- 45,51 ----
    ".in",        /* for .inz, .igz etc. */
    ".i",
  #endif
+   "",
    (char *)NULL
  };
  
*** djgpp/README.~	Fri May 22 18:53:16 1998
--- djgpp/README	Sat Jul 11 16:06:16 1998
***************
*** 16,21 ****
--- 16,23 ----
        - a DJGPP port of Bash;
        - a port of GNU Sed;
        - ginstall and rm from the Fileutils package;
+       - DJGPP ports of Fileutils, Diffutils, and Grep (only if you
+         need to reconfigure the source distribution);
        - etags (from the Emacs distribution) and mkid (from ID-utils)
          if you need the TAGS and ID targets of the Makefile's.
  
***************
*** 135,141 ****
  	      Printing Texinfo documentation with TeX.
  
        * texindex: (texinfo)Format with tex/texindex.	
! 	      Sorting Texinfo index files automaically.
  
        * makeinfo: (texinfo)makeinfo options.
  	      Translate Texinfo source into Info, plain ASCII, or HTML.
--- 137,143 ----
  	      Printing Texinfo documentation with TeX.
  
        * texindex: (texinfo)Format with tex/texindex.	
! 	      Sorting Texinfo index files automatically.
  
        * makeinfo: (texinfo)makeinfo options.
  	      Translate Texinfo source into Info, plain ASCII, or HTML.
***************
*** 275,281 ****
  	  grab the output.  When this option is given, the screen
  	  colors defined by the `INFO_COLORS' environment variable and
  	  the visible-bell feature will be disabled, because stdio
! 	  functions don't support neiher color text nor inverting
  	  screen colors.  This improvement was suggested and
  	  originally implemented by Hans-Bernhard Broeker
  	  <Broeker@physik.rwth-aachen.de>.
--- 277,283 ----
  	  grab the output.  When this option is given, the screen
  	  colors defined by the `INFO_COLORS' environment variable and
  	  the visible-bell feature will be disabled, because stdio
! 	  functions don't support neither color text nor inverting
  	  screen colors.  This improvement was suggested and
  	  originally implemented by Hans-Bernhard Broeker
  	  <Broeker@physik.rwth-aachen.de>.
***************
*** 346,351 ****
--- 348,374 ----
     forget to edit the indirect file table in the main Info file and
     change the sub-file filenames there too!
  
+    An alternative for those packages which have more than 99 Info
+    sub-files is to generate them from the Texinfo sources and force
+    Makeinfo to produce files without the .iNN extensions, like this:
+ 
+ 	        makeinfo -o foo foo.txi
+ 
+    This causes Makeinfo to generate file names like foo-1, foo-2,
+    etc., which leave more place for the numeric index.  If necessary,
+    Makeinfo will automatically remove characters from the end of the
+    argument to `-o'.  For example, "-o texinfo" produces files
+    texinf-1, ..., texin-10, ..., texi-100, etc. on platforms which
+    only support 8+3 file names.
+ 
+    Saying "@setfilename foo" near the beginning of the Texinfo source
+    file is another way of forcing Makeinfo to produce files without
+    the .iNN extensions.
+ 
+    Using Makeinfo to produce files whose names are "compression-ready"
+    is more convenient, since you don't need to edit the the indirect
+    file table to reflect the changes in file names.
+ 
     On platforms which support long filenames, the usual Info behavior
     of appending `.gz' or `.Z' to the original filename also works;
     this is done *before* Info checks the above butchered names.
***************
*** 384,390 ****
     whose name follows the `>' character.
  
     If INFO_PRINT_COMMAND is not defined, the DJGPP port will use
!    ">PRN" as the default, which causes it print to the local priner
     device, PRN.
  
  6. Bug Reports
--- 407,413 ----
     whose name follows the `>' character.
  
     If INFO_PRINT_COMMAND is not defined, the DJGPP port will use
!    ">PRN" as the default, which causes it to print to the local printer
     device, PRN.
  
  6. Bug Reports
*** makeinfo/makeinfo.c~3	Fri Jun 26 14:17:38 1998
--- makeinfo/makeinfo.c	Sat Sep 12 17:49:12 1998
*************** void forget_itext (), me_append_before_t
*** 159,164 ****
--- 159,165 ----
  void append_to_expansion_output (), write_region_to_macro_output ();
  void maybe_write_itext (), me_execute_string ();
  void me_execute_string_keep_state ();
+ void maybe_update_execution_strings ();
  #endif /* HAVE_MACROS */
  
  
*************** replace_with_expansion (from, to)
*** 1868,1874 ****
    if (xp_len != raw_len)
      {
        new_len = from + xp_len + size_of_input_text - *to + 1;
!       input_text = xrealloc (input_text, new_len);
        memmove (input_text + from + xp_len,
  	       input_text + *to, size_of_input_text - *to + 1);
        
--- 1869,1885 ----
    if (xp_len != raw_len)
      {
        new_len = from + xp_len + size_of_input_text - *to + 1;
!       if (executing_string)
! 	{
! 	  /* If we are in execute_string, we might need to update
! 	     the relevant element in the execution_strings[] array,
! 	     since it could have to be relocated from under our
! 	     feet. (input_text is reallocated here as well, if needed.)  */
! 	  maybe_update_execution_strings (&input_text, new_len);
! 	}
!       /* Don't bother to realloc if we have enough space.  */
!       else if (new_len > raw_len)
! 	input_text = xrealloc (input_text, new_len);
        memmove (input_text + from + xp_len,
  	       input_text + *to, size_of_input_text - *to + 1);
        
*************** replace_with_expansion (from, to)
*** 1880,1888 ****
  
  #if defined (HAVE_MACROS)
    /* Synchronize the macro-expansion pointers with our new input_text.  */
!   if (input_text != old_input)
!     forget_itext (old_input);
!   remember_itext (input_text, from);
  #endif
  }
  
--- 1891,1902 ----
  
  #if defined (HAVE_MACROS)
    /* Synchronize the macro-expansion pointers with our new input_text.  */
!   if (macro_expansion_output_stream && !executing_string)
!     {
!       if (input_text != old_input)
! 	forget_itext (old_input);
!       remember_itext (input_text, from);
!     }
  #endif
  }
  
*************** get_until_in_line (expand, match, string
*** 1912,1926 ****
       Otherwise, the `,' separating the macro args A and B is taken as
       the node argument separator, so the node name is `@foo{A'.  This
       expansion is only necessary on the first call, since we expand the
!      whole line then.
!      
!      Furthermore, if we're executing a string, don't do it -- we'll end
!      up shrinking the execution string which is currently aliased to
!      `input_text', so it might get moved, and not updated in the
!      `execution_strings' array.  This happens when processing the
!      (synthetic) Overview-Footnotes node in the Texinfo manual.  */
  
!   if (expand && !executing_string && !me_executing_string)
      {
        replace_with_expansion (input_text_offset, &limit);
      }
--- 1926,1934 ----
       Otherwise, the `,' separating the macro args A and B is taken as
       the node argument separator, so the node name is `@foo{A'.  This
       expansion is only necessary on the first call, since we expand the
!      whole line then.  */
  
!   if (expand)
      {
        replace_with_expansion (input_text_offset, &limit);
      }
*************** add_char (character)
*** 2883,2889 ****
                          while (temp && whitespace (output_paragraph[temp - 1]))
                            temp--;
  
!                         output_paragraph[temp++] = '\n';
  
                          /* We have correctly broken the line where we want
                             to.  What we don't want is spaces following where
--- 2891,2905 ----
                          while (temp && whitespace (output_paragraph[temp - 1]))
                            temp--;
  
! 			/* If we went back all the way to the newline of the
! 			   preceding line, it probably means that the word we
! 			   are adding is itself wider than the space that
! 			   indentation and the fill_column let us use.  In
! 			   that case, do NOT insert another newline, since it
! 			   won't help.  Just indent to current_indent and
! 			   leave it alone, since that's the most we can do.  */
! 			if (temp && output_paragraph[temp - 1] != '\n')
! 			  output_paragraph[temp++] = '\n';
  
                          /* We have correctly broken the line where we want
                             to.  What we don't want is spaces following where
*************** add_char (character)
*** 2907,2913 ****
                            if (t1 != temp)
                              {
                                adjust_braces_following (temp, (- (t1 - temp)));
!                               memcpy ((char *) &output_paragraph[temp],
                                         (char *) &output_paragraph[t1],
                                         (output_paragraph_offset - t1));
                                output_paragraph_offset -= (t1 - temp);
--- 2923,2929 ----
                            if (t1 != temp)
                              {
                                adjust_braces_following (temp, (- (t1 - temp)));
!                               strncpy ((char *) &output_paragraph[temp],
                                         (char *) &output_paragraph[t1],
                                         (output_paragraph_offset - t1));
                                output_paragraph_offset -= (t1 - temp);
*************** get_xref_token (expand)
*** 5802,5810 ****
    char *string;
  
  #if defined (HAVE_MACROS)
!   if (expand && !executing_string && !me_executing_string)
      {
        int old_offset = input_text_offset;
  
        get_until_in_braces ("}", &string);
        if (curchar () == '}')	/* as opposed to end of text */
--- 5818,5827 ----
    char *string;
  
  #if defined (HAVE_MACROS)
!   if (expand)
      {
        int old_offset = input_text_offset;
+       int old_lineno = line_number;
  
        get_until_in_braces ("}", &string);
        if (curchar () == '}')	/* as opposed to end of text */
*************** get_xref_token (expand)
*** 5814,5819 ****
--- 5831,5837 ----
  	  int limit = input_text_offset;
  
  	  input_text_offset = old_offset;
+ 	  line_number = old_lineno;
  	  only_macro_expansion++;
  	  replace_with_expansion (input_text_offset, &limit);
  	  only_macro_expansion--;
*************** void
*** 5965,6007 ****
  cm_uref (arg, start_pos, end_pos)
       int arg, start_pos, end_pos;
  {
!   if (arg == END)
      {
!       char *comma;
!       char *arg = (char *) &output_paragraph[start_pos];
! 
!       output_paragraph[end_pos] = 0;
!       output_column -= end_pos - start_pos;
!       output_paragraph_offset = start_pos;
  
!       arg = xstrdup (arg);
!       comma = strchr (arg, ','); /* let's hope for no commas in the url  */
!       if (comma)
!         {
!           *comma = 0;
!           /* Ignore spaces at beginning of second arg.  */
!           for (comma++; isspace (*comma); comma++)
!             ;
!           add_word (comma);
!           add_char (' ');
!           add_char ('(');
!           add_word (arg);
!           add_char (')');
!         }
        else
!         {
!           extern int printing_index;
!           
!           if (!printing_index)
!             add_char ('`');
!             
!           add_word (arg);
!           
!           if (!printing_index)
!             add_char ('\'');
!         }
!       free (arg);
!    }
  }
  
  /* An email reference.  */
--- 5983,6004 ----
  cm_uref (arg, start_pos, end_pos)
       int arg, start_pos, end_pos;
  {
!   if (arg == START)
      {
!       extern int printing_index;
!       char *url  = get_xref_token (1);
!       char *desc = get_xref_token (0);
  
!       if (*desc)
! 	execute_string ("%s (%s)", desc, url);
        else
! 	execute_string ("%s%s%s",
! 			printing_index ? "" : "`",
! 			url,
! 			printing_index ? "" : "\'");
!       if (url) free (url);
!       if (desc) free (desc);
!     }
  }
  
  /* An email reference.  */
*************** void
*** 6009,6037 ****
  cm_email (arg, start_pos, end_pos)
       int arg, start_pos, end_pos;
  {
!   if (arg == END)
      {
!       char *comma;
!       char *arg = (char *) &output_paragraph[start_pos];
! 
!       output_paragraph[end_pos] = 0;
!       output_column -= end_pos - start_pos;
!       output_paragraph_offset = start_pos;
  
!       arg = xstrdup (arg);
!       comma = strchr (arg, ',');
!       if (comma)
!         {
!           *comma = 0;
!           for (comma++; isspace (*comma); comma++)
!             ;
!           add_word (comma);
!           add_char (' ');
!         }
!       add_char ('<');
!       add_word (arg);
!       add_char ('>');
!       free (arg);
      }
  }
  
--- 6006,6019 ----
  cm_email (arg, start_pos, end_pos)
       int arg, start_pos, end_pos;
  {
!   if (arg == START)
      {
!       char *addr = get_xref_token (1);
!       char *name = get_xref_token (0);
  
!       execute_string ("%s%s<%s>", name, *name ? " "  : "", addr);
!       if (addr) free (addr);
!       if (name) free (name);
      }
  }
  
*************** get_execution_string (initial_size)
*** 6699,6704 ****
--- 6681,6721 ----
    return (es);
  }
  
+ /* Given a pointer to TEXT and its desired length NEW_LEN, find TEXT's
+    entry in the execution_strings[] array and change the .STRING and
+    .SIZE members of that entry as appropriate.  */
+ void
+ maybe_update_execution_strings (text, new_len)
+      char **text;
+      unsigned new_len;
+ {
+   register int i = 0;
+ 
+   if (execution_strings)
+     {
+       for (i = 0; i < execution_strings_index; i++)
+         if (execution_strings[i] && (execution_strings[i]->in_use == 1) &&
+ 	    execution_strings[i]->string == *text)
+           {
+ 	    /* Don't ever shrink the string storage in execution_strings[]!
+ 	       execute_string assumes that it is always big enough to store
+ 	       every possible execution_string, and will break if that's
+ 	       not true.  So we only enlarge the string storage if the
+ 	       current size isn't big enough.  */
+ 	    if (execution_strings[i]->size < new_len)
+ 	      {
+ 		execution_strings[i]->string =
+ 		  *text = (char *)xrealloc (*text, new_len + 1);
+ 		execution_strings[i]->size = new_len + 1;
+ 	      }
+ 	    return;
+           }
+     }
+   /* We should *never* end up here, since if we are inside
+      execute_string, TEXT is always in execution_strings[].  */
+   abort ();
+ }
+ 
  /* Execute the string produced by formatting the ARGs with FORMAT.  This
     is like submitting a new file with @include. */
  void
*************** expand_macro (def)
*** 9027,9032 ****
--- 9044,9050 ----
    char **arglist;
    int num_args;
    char *execution_string = (char *)NULL;
+   int start_line = line_number;
  
    /* Find out how many arguments this macro definition takes. */
    num_args = array_len (def->arglist);
*************** expand_macro (def)
*** 9037,9044 ****
    if (num_args < array_len (arglist))
      {
        free_array (arglist);
!       line_error (_("Macro `%s' called with too many args"), def->name);
!       return;
      }
  
    if (def->body)
--- 9055,9063 ----
    if (num_args < array_len (arglist))
      {
        free_array (arglist);
!       line_error (_("Macro `%s' called on line %d with too many args"),
! 		  def->name, start_line);
!       return execution_string;
      }
  
    if (def->body)
*************** execute_macro (def)
*** 9059,9064 ****
--- 9078,9085 ----
      me_append_before_this_command ();
  
    execution_string = expand_macro (def);
+   if (!execution_string)
+     return;
  
    if (def->body)
      {
*************** me_execute_string (execution_string)
*** 9429,9442 ****
  {
    pushfile ();
    input_text_offset = 0;
!   input_text = execution_string;
    input_filename = xstrdup (input_filename);
    size_of_input_text = strlen (execution_string);
  
!   remember_itext (execution_string, 0);
  
    me_executing_string++;
    reader_loop ();
    free (input_filename);
    popfile ();
    me_executing_string--;
--- 9450,9465 ----
  {
    pushfile ();
    input_text_offset = 0;
!   /* The following xstrdup is so we can relocate input_text at will.  */
!   input_text = xstrdup (execution_string);
    input_filename = xstrdup (input_filename);
    size_of_input_text = strlen (execution_string);
  
!   remember_itext (input_text, 0);
  
    me_executing_string++;
    reader_loop ();
+   free (input_text);
    free (input_filename);
    popfile ();
    me_executing_string--;
