produce_frozen_state (const char *name)
{
  FILE *file;
  int h;
  symbol *sym;
  const builtin *bp;

  if (file = fopen (name, O_BINARY ? "wb" : "w"), !file)
    {
      M4ERROR ((warning_status, errno, name));
      return;
    }

  /* Write a recognizable header.  */

  xfprintf (file, "# This is a frozen state file generated by %s\n",
	   PACKAGE_STRING);
  xfprintf (file, "V1\n");

  /* Dump quote delimiters.  */

  if (strcmp (lquote.string, DEF_LQUOTE) || strcmp (rquote.string, DEF_RQUOTE))
    {
      xfprintf (file, "Q%d,%d\n", (int) lquote.length, (int) rquote.length);
      fputs (lquote.string, file);
      fputs (rquote.string, file);
      fputc ('\n', file);
    }

  /* Dump comment delimiters.  */

  if (strcmp (bcomm.string, DEF_BCOMM) || strcmp (ecomm.string, DEF_ECOMM))
    {
      xfprintf (file, "C%d,%d\n", (int) bcomm.length, (int) ecomm.length);
      fputs (bcomm.string, file);
      fputs (ecomm.string, file);
      fputc ('\n', file);
    }

  /* Dump all symbols.  */

  for (h = 0; h < hash_table_size; h++)
    {

      /* Process all entries in one bucket, from the last to the first.
	 This order ensures that, at reload time, pushdef's will be
	 executed with the oldest definitions first.  */

      symtab[h] = reverse_symbol_list (symtab[h]);
      for (sym = symtab[h]; sym; sym = SYMBOL_NEXT (sym))
	{
	  switch (SYMBOL_TYPE (sym))
	    {
	    case TOKEN_TEXT:
	      xfprintf (file, "T%d,%d\n",
			(int) strlen (SYMBOL_NAME (sym)),
			(int) strlen (SYMBOL_TEXT (sym)));
	      fputs (SYMBOL_NAME (sym), file);
	      fputs (SYMBOL_TEXT (sym), file);
	      fputc ('\n', file);
	      break;

	    case TOKEN_FUNC:
	      bp = find_builtin_by_addr (SYMBOL_FUNC (sym));
	      if (bp == NULL)
		{
		  M4ERROR ((warning_status, 0, "\
INTERNAL ERROR: builtin not found in builtin table!"));
		  abort ();
		}
	      xfprintf (file, "F%d,%d\n",
			(int) strlen (SYMBOL_NAME (sym)),
			(int) strlen (bp->name));
	      fputs (SYMBOL_NAME (sym), file);
	      fputs (bp->name, file);
	      fputc ('\n', file);
	      break;

	    case TOKEN_VOID:
	      /* Ignore placeholder tokens that exist due to traceon.  */
	      break;

	    default:
	      M4ERROR ((warning_status, 0, "\
INTERNAL ERROR: bad token data type in freeze_one_symbol ()"));
	      abort ();
	      break;
	    }
	}

      /* Reverse the bucket once more, putting it back as it was.  */

      symtab[h] = reverse_symbol_list (symtab[h]);
    }

  /* Let diversions be issued from output.c module, its cleaner to have this
     piece of code there.  */

  freeze_diversions (file);

  /* All done.  */

  fputs ("# End of frozen state file\n", file);
  if (close_stream (file) != 0)
    M4ERROR ((EXIT_FAILURE, errno, "unable to create frozen state"));
}
Unknown