void xProfileStage(char *stage_name)
{
	char *low, *high, *filename;
	struct gmon_file *gf;
	size_t len;

	if( !xProfFlag )
		return;
	xProfilingOff();
	low = kaffe_memory_samples->ms_low;
	high = kaffe_memory_samples->ms_high +
		(extraProfileCount * HISTFRACTION);
	KTHREAD(suspendall)();
	len = strlen(kaffe_gmon_filename) +
		(stage_name ? strlen(stage_name) + 1 : 0) +
		1;
	if( (filename = (char *)KMALLOC(len)) )
	{
		sprintf(filename,
			"%s%s%s",
			kaffe_gmon_filename,
			stage_name ? "." : "",
			stage_name ? stage_name : "");
		/* Create and write out the gmon file */
		if( (gf = createGmonFile(filename)) )
		{
			struct profiler_gmon_file pgf;
			
			/* Initialize the profiler_gmon_files state */
			pgf.pgf_stage = stage_name;
			pgf.pgf_file = gf;
			/* Write out the samples */
			pgf.pgf_record =
				writeGmonRecord(gf,
						GRA_Type, GMON_TAG_TIME_HIST,
						GRA_LowPC, low,
						GRA_HighPC, high,
						GRA_DONE);
			/* The low/high might be aligned by writeGmonRecord */
			low = gf->gf_low;
			high = gf->gf_high;
			walkMemorySamples(kaffe_memory_samples,
					  low,
					  high -
					  (extraProfileCount * HISTFRACTION),
					  &pgf,
					  profilerSampleWalker);
			if( pgf.pgf_file )
			{
				/* Dump out the call graph data */
				writeCallGraph(kaffe_call_graph, pgf.pgf_file);
				deleteGmonFile(pgf.pgf_file);
			}
			else
			{
				resetMemorySamples(kaffe_memory_samples);
			}
		}
		else
		{
			fprintf(stderr,
				"XProf Notice: Cannot create gmon file %s\n",
				filename);
			KFREE(filename);
			resetMemorySamples(kaffe_memory_samples);
		}
	}
	else
	{
		fprintf(stderr,
			"XProf Notice: Not enough memory to write "
			"profiling data\n");
		resetMemorySamples(kaffe_memory_samples);
	}
	resetCallGraph(kaffe_call_graph);
	xProfilingOn();
	KTHREAD(unsuspendall)();
}
/*
 * A walker function for walkMemorySamples.  This does a little more than
 * the one provided by the gmon code since it will create a new gmon file
 * if theres a large gap in observed memory.
 */
static int profilerSampleWalker(void *handle, char *addr,
				short *bins, size_t size)
{
	struct profiler_gmon_file *pgf = handle;
	struct gmon_file *gf = pgf->pgf_file;
	int retval = 0;

	/* Check if we need to dump these samples in another file */
	if( (addr - gf->gf_addr) > SAMPLE_GUTTER_THRESHOLD )
	{
		char *filename, *old_high;
		size_t len;

		old_high = gf->gf_high;
		/* Rewrite the old record with the new high address */
		writeGmonRecord(gf,
				GRA_Rewrite, pgf->pgf_record,
				GRA_Type, GMON_TAG_TIME_HIST,
				GRA_LowPC, gf->gf_low,
				GRA_HighPC, gf->gf_addr,
				GRA_DONE);
		writeCallGraph(kaffe_call_graph, gf);
		/* Close down the file */
		deleteGmonFile(gf);
		pgf->pgf_file = 0;
		gf = 0;

		/*
		 * Make up the filename for the new file, we'll just use the
		 * starting address for this range to make it unique
		 */
		len = strlen(kaffe_gmon_filename) +
			1 + /* `.' */
			2 + (sizeof(void *) * 2) + /* `0x...' */
			(pgf->pgf_stage ? strlen(pgf->pgf_stage) + 1 : 0) +
			1;
		if( (filename = (char *)KMALLOC(len)) )
		{
			/* Construct the new file name */
			sprintf(filename,
				"%s.%p%s%s",
				kaffe_gmon_filename,
				addr,
				pgf->pgf_stage ? "." : "",
				pgf->pgf_stage ? pgf->pgf_stage : "");
			if( (pgf->pgf_file = createGmonFile(filename)) )
			{
				gf = pgf->pgf_file;
				/* Write out another hist record */
				pgf->pgf_record = writeGmonRecord(
					gf,
					GRA_Type, GMON_TAG_TIME_HIST,
					GRA_LowPC, addr,
					GRA_HighPC, old_high,
					GRA_DONE);
			}
		}
	}
	if( gf )
	{
		/* Let the gmon walker do its thing */
		retval = gmonSampleWalker(gf, addr, bins, size);
	}
	memset(bins, 0, size * sizeof(short));
	return( retval );
}
void 
write_htmlFnctPages::writePage(void) 
{
  // most of the informations can be write only if the function has a body !

  dataDrawerListIterator   p;         // browse the list
  string                fnctName;     // name of the function

  
  // Browse list one function for time
  p = dataBL->begin();
  while (p != dataBL->end()) {
    dataB = *p;
    p++;
    
    fData = dataB->getFnctData();
    
    cout << "Generating html page for function " 
	 << (fnctName = fData->getName()) << "...\n";

    htmlpage.open((HTMLfilesRegister::htmlFile(*fData)).c_str());

    // begin of the page
    pageTitle = fnctName ;
    writeHead();
    writeIndex();
    
    htmlpage << "<br><br>\n";
    if (fnctName != "")
      htmlpage << "This is the page of the function " 
	       << fnctName << ".<br><br>\n";

    htmlpage << *fData
	     << "<br><l><br>\n\n";
    
    if (fData->hasBody()) {
      
      writePageIndex();
      
      // write body graph
      if (!noBodyGraph) {
	htmlpage << "<A name=\"bodyGraph\">\n";
	writeSectionTitle("Graph of the body");
	writeBodyGraph();
      }
      
      // write CFG
      if (!noCFG) {
	htmlpage << "<A name=\"CFG\">\n";
	writeSectionTitle("Control flow graph");
	writeCFG();
      }

      // write stmt stat
      if (!noStmtStat) {
	htmlpage << "<A name=\"stmtStatistics\">\n";
	writeSectionTitle("Statements statistics");
	htmlpage << *(dataB->getStmtNumData());
      }
      
      // write decl list
      if ( (!noDeclsList) && (dataB->hasDeclsList()) ) {
	htmlpage << "<A name=\"declsList\">\n";
	writeSectionTitle("Declarations into the function");
	htmlpage << *(dataB->getDeclsList());
      }
      
      // write var used
      if ( (!noVarUsed) && (dataB->hasVarUsedList()) ) {
	htmlpage << "<A name=\"varUsedList\">\n";
	writeSectionTitle("Variables used by the function");
	htmlpage << *(dataB->getVarUsedList());
      }

      // write exprs list
      if ( (!noExprsList) && (dataB->hasExprsList()) ) {
	htmlpage << "<A name=\"exprsList\">\n";
	writeSectionTitle("List of the expressions");
	htmlpage << *(dataB->getExprsList());
      }
      
      // write expr stat
      if (!noExprStat) {
	htmlpage << "<A name=\"exprStatistics\">\n";
	writeSectionTitle("Expression statistics");
	htmlpage << *(dataB->getExprNumData());
      }
      
      // write call graph
      if (!noCallGraph) {
	htmlpage << "<A name=\"callGraph\">\n";
	writeSectionTitle("Call graph");
	writeCallGraph();
      }

    }   

    // end of the page
    writeIndex();
    writeFoot();
    htmlpage.close();
  }

  return;
}