#! /usr/bin/perl
use File::Find;

%states = ();

find sub
{
 if ($File::Find::name =~ /\.[ich]$/)
 {
  open (F, "$_") or die "unable to open $_";
  while (<F>)
  {
   chomp;
   if (/STATE_DECL\((.*)\)/)
   {
       if (!/^#\s*define/)
       {
	   $states{$1}="yes";
       }
   }
  }
  close F;
 }
}, "src";

@states = sort keys(%states);

find sub
{
 if ($_ eq "describe_states.txt")
 {
  open F, $_;
  while (<F>)
  {
   chomp;
   /\s*(\S*)\s*(\S*)(\s?)(\S.*)*/;
   if (!defined($states{$1}))
   {
       printf("Warning: described state $1 not used, consider removing it from describe_states.txt\n");
   }
   $descriptions{$1} = $2;
   if ( !($4 eq "") )
   {
       $color_descriptions{$1} = $4;
   }
  }
  close F;
 }
}, "src";

foreach (@states)
{
    if (!defined($descriptions{$_}))
    {
	printf("ERROR: $_ not in a describe_states.txt file\n");
    }
}

open HFILE, ">src/include/mpiallstates.h"
  or die "Unable to open src/include/mpiallstates.h";
print HFILE "/* -*- Mode: C; c-basic-offset:4 ; -*- */\n";
print HFILE "/*\n";
print HFILE " *  (C) 2001 by Argonne National Laboratory.\n";
print HFILE " *      See COPYRIGHT in top-level directory.\n";
print HFILE " */\n";
print HFILE "\n";
print HFILE "/* automatically generated by maint/genstates */\n";
print HFILE "\n";
print HFILE "#ifndef MPIALLSTATES_H\n";
print HFILE "#define MPIALLSTATES_H\n";
print HFILE "\n";
print HFILE "/* Insert all the states to be logged here */\n";
print HFILE "\n";
print HFILE "enum MPID_TIMER_STATE\n";
print HFILE "{\n";
foreach (@states) {
  print HFILE "$_,\n";
}
print HFILE "MPID_NUM_TIMER_STATES\n";
print HFILE "};\n";
print HFILE "\n";
print HFILE "#endif\n";
close HFILE;

open F, ">src/util/logging/common/describe_states.c"
 or die "Unable to open src/util/logging/common/describe_states.c";
print F "/* -*- Mode: C; c-basic-offset:4 ; -*- */\n";
print F "/*\n";
print F " *  (C) 2001 by Argonne National Laboratory.\n";
print F " *      See COPYRIGHT in top-level directory.\n";
print F " */\n";
print F "\n";
print F "/* automatically generated by maint/genstates */\n";
print F "\n";
print F "#include \"mpiimpl.h\"\n";
print F "\n";
print F "/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build\n";
print F "   the MPI routines */\n";
print F "#ifndef MPICH_MPI_FROM_PMPI\n";
print F "\n";
print F "#ifdef HAVE_TIMING\n";
print F "\n";
print F "#if (USE_LOGGING == MPID_LOGGING_RLOG)\n";
print F "\n";
print F "#include <math.h>\n";
print F "\n";
print F "/* utility funcions */\n";
print F "#ifndef RGB\n";
print F "#define RGB(r,g,b)      ((unsigned long)(((unsigned char)(r)|((unsigned short)((unsigned char)(g))<<8))|(((unsigned long)(unsigned char)(b))<<16)))\n";
print F "#endif\n";
print F "\n";
print F "static unsigned long getColorRGB(double fraction, double intensity, unsigned char *r, unsigned char *g, unsigned char *b)\n";
print F "{\n";
print F "    double red, green, blue;\n";
print F "    double dtemp;\n";
print F "\n";
print F "    fraction = fabs(modf(fraction, &dtemp));\n";
print F "    \n";
print F "    if (intensity > 2.0)\n";
print F "	intensity = 2.0;\n";
print F "    if (intensity < 0.0)\n";
print F "	intensity = 0.0;\n";
print F "\n";
print F "    dtemp = 1.0/6.0;\n";
print F "\n";
print F "    if (fraction < 1.0/6.0)\n";
print F "    {\n";
print F "	red = 1.0;\n";
print F "	green = fraction / dtemp;\n";
print F "	blue = 0.0;\n";
print F "    }\n";
print F "    else\n";
print F "    {\n";
print F "	if (fraction < 1.0/3.0)\n";
print F "	{\n";
print F "	    red = 1.0 - ((fraction - dtemp) / dtemp);\n";
print F "	    green = 1.0;\n";
print F "	    blue = 0.0;\n";
print F "	}\n";
print F "	else\n";
print F "	{\n";
print F "	    if (fraction < 0.5)\n";
print F "	    {\n";
print F "		red = 0.0;\n";
print F "		green = 1.0;\n";
print F "		blue = (fraction - (dtemp*2.0)) / dtemp;\n";
print F "	    }\n";
print F "	    else\n";
print F "	    {\n";
print F "		if (fraction < 2.0/3.0)\n";
print F "		{\n";
print F "		    red = 0.0;\n";
print F "		    green = 1.0 - ((fraction - (dtemp*3.0)) / dtemp);\n";
print F "		    blue = 1.0;\n";
print F "		}\n";
print F "		else\n";
print F "		{\n";
print F "		    if (fraction < 5.0/6.0)\n";
print F "		    {\n";
print F "			red = (fraction - (dtemp*4.0)) / dtemp;\n";
print F "			green = 0.0;\n";
print F "			blue = 1.0;\n";
print F "		    }\n";
print F "		    else\n";
print F "		    {\n";
print F "			red = 1.0;\n";
print F "			green = 0.0;\n";
print F "			blue = 1.0 - ((fraction - (dtemp*5.0)) / dtemp);\n";
print F "		    }\n";
print F "		}\n";
print F "	    }\n";
print F "	}\n";
print F "    }\n";
print F "\n";
print F "    if (intensity > 1)\n";
print F "    {\n";
print F "	intensity = intensity - 1.0;\n";
print F "	red = red + ((1.0 - red) * intensity);\n";
print F "	green = green + ((1.0 - green) * intensity);\n";
print F "	blue = blue + ((1.0 - blue) * intensity);\n";
print F "    }\n";
print F "    else\n";
print F "    {\n";
print F "	red = red * intensity;\n";
print F "	green = green * intensity;\n";
print F "	blue = blue * intensity;\n";
print F "    }\n";
print F "\n";
print F "    *r = (unsigned char)(red * 255.0);\n";
print F "    *g = (unsigned char)(green * 255.0);\n";
print F "    *b = (unsigned char)(blue * 255.0);\n";
print F "\n";
print F "    return RGB(*r,*g,*b);\n";
print F "}\n";
print F "\n";
print F "static unsigned long random_color(unsigned char *r, unsigned char *g, unsigned char *b)\n";
print F "{\n";
print F "    double d1, d2;\n";
print F "\n";
print F "    d1 = (double)rand() / (double)RAND_MAX;\n";
print F "    d2 = (double)rand() / (double)RAND_MAX;\n";
print F "\n";
print F "    return getColorRGB(d1, d2 + 0.5, r, g, b);\n";
print F "}\n";
print F "\n";
print F "#define MAX_RANDOM_COLOR_STR 40\n";
print F "static char random_color_str[MAX_RANDOM_COLOR_STR];\n";
print F "static char *get_random_color_str()\n";
print F "{\n";
print F "    unsigned char r,g,b;\n";
print F "    random_color(&r, &g, &b);\n";
print F "    MPIU_Snprintf(random_color_str, MAX_RANDOM_COLOR_STR, \n";
print F "		  \"%3d %3d %3d\", (int)r, (int)g, (int)b);\n";
print F "    return random_color_str;\n";
print F "}\n";
print F "\n";
print F "int MPIR_Describe_timer_states()\n";
print F "{\n";
print F "\n";
while ( ($state, $description) = each %descriptions )
{
  if (defined($color_descriptions{$state}))
  {
    print F "    RLOG_DescribeState(g_pRLOG, $state, \"$description\", \"$color_descriptions{$state}\");\n";
  }
  else
  {
    print F "    RLOG_DescribeState(g_pRLOG, $state, \"$description\", get_random_color_str());\n";
  }
}
print F "    return 0;\n";
print F "}\n";
print F "\n";
print F "#endif /* USE_LOGGING == MPID_LOGGING_RLOG */\n";
print F "#endif /* HAVE_TIMING */\n";
print F "#endif /* MPICH_MPI_FROM_PMPI */\n";
