/************************************************/
/* UtilHist.c - Simple utility for extracting 	*/
/* the processor element (PE) utilitizations	*/
/* results from the summaries.dat file to make	*/
/* a bar-chart histogram plot-file.		*/
/*						*/
/* Assumes you are in the directory where you 	*/
/* ran a simulation.  To use, run this utilhist */
/* utility.  It reads your "netinfo" file to 	*/
/* find the name-ID-numbers of your PE's, and 	*/
/* then it reads your summaries.dat file to 	*/
/* produce a plot-file called, "utils.dat".	*/
/* Then run XGRAPH on utils.dat.		*/
/* Example:					*/
/*	utilhist				*/
/*	xgraph utils.dat			*/
/*						*/
/* To compile this program:			*/
/*	gcc utilhist.c -o utilhist		*/
/************************************************/

#include <stdio.h>
#include <strings.h>

FILE *infile, *outfile;


/**********************************************/
/* Data structure to hold PE name-ID's.       */
/**********************************************/
struct wordpair	    
 {
  char *name, *value;
  struct wordpair *nxt;
 } *nameIDs=0;


/**********************************************/
/* Routine to get a new line from input file. */
/**********************************************/
void read_line( char *line )
{
 int i=0;
 do  line[i++] = getc(infile); 
 while ((!feof(infile)) && (line[i-1]!=10));
 line[i-1] = '\0';
}


/**************************************************/
/* Routine to add a name-value pair to word-list. */
/**************************************************/
void add_word( char *name, char *value )
{
 struct wordpair *tmppt;

 tmppt = (struct wordpair *)malloc(sizeof(struct wordpair));
 tmppt->name = strdup(name);
 tmppt->value = strdup(value);
 tmppt->nxt = nameIDs;
 nameIDs = tmppt;
}



/**************************************************/
/* Routine to find a named value.		  */
/**************************************************/
char *find_entry( char *name )
{
 struct wordpair *tmppt;

 tmppt = nameIDs;
 while ((tmppt!=0) && (strcmp(tmppt->name,name)!=0))
  tmppt = tmppt->nxt;
 if (tmppt==0) return 0; else return tmppt->value;
}


/*.......................................................................
  .     NEXT_WORD - accepts a line of text, and returns with the        .
  . next word in that text in the second parameter, the original line   .
  . is shortened from the beginning so that the word is removed.        .
  . If the line encountered is empty, then the word returned will be    .
  . empty. NEXTWORD parses on arbitrary delimiters. 			.
  .......................................................................*/
void Next_Word( char *line, char *word, char *delim )
{
 int i=0, j=0, k=0, m=0, flag=1;

 /* Eat away preceding garbage */
 while ((line[i]!='\0') && (flag))
  {
   j = 0;
   while ((delim[j]!='\0') && (line[i]!=delim[j])) j = j + 1;
   if (line[i]==delim[j]) { k = k + 1;  i = i + 1; }
   else  flag = 0;
  }

 /* Copy the word until the next delimiter. */
 while ((line[i]!='\0') && (!flag))
  {
   word[m] = line[i];
   m = m + 1;  i = i + 1;
   if (line[i]!='\0')
    {
     j = 0;
     while ((delim[j]!='\0') && (line[i]!=delim[j])) j = j + 1;
     if (line[i]==delim[j]) flag = 1;
    }
  }

 /* Shorten line. */
 j = 0;
 while (line[i]!='\0')
  { line[j] = line[i];  j = j + 1;  i = i + 1; }

 /* Terminate the char-strings. */
 line[j] = '\0';
 word[m] = '\0';
}




/********************************************************/
/* Main - Open files, scan them, and produce output.	*/
/********************************************************/

main()
{
 char line[1000], word[500], name[500], *ID;
 int flag=0, NPEs=0;

 /* First get the processor name - ID numbers. */
 infile = fopen("netinfo","r");
 if (infile == 0) 
  {printf("ERROR: Cannot open netinfo.\n"); exit(0);}

 /* Scan the netinfo file for name-ID numbers. */
 read_line( line );
 while ((!feof(infile)) && (flag<2))
  {
   Next_Word( line, word, " 	");
   if (strcmp(word,"Sim>")==0) flag++; else
   if (strlen(word)>0)
    {
     Next_Word( line, name, " 	");
     add_word( name, word );	NPEs++;
    }
   read_line( line );
  }
 fclose(infile);


 /* Now scan summaries.dat for processor utilizations. */

 infile = fopen("summaries.dat","r");
 if (infile == 0) 
  {printf("ERROR: Cannot open summaries.dat.\n"); exit(0);}

 /* Open output file and write graph titles, etc.. */
 outfile = fopen("utils.dat","w");
 if (infile == 0) 
  {printf("ERROR: Cannot open utils.dat for writing.\n"); exit(0);}

 /* Bar graph.  Set bar thickness. */ 
 fprintf(outfile,"thickness=%f\n", 25.0 / (1.0 + 0.1 * (float)NPEs) );  
 fprintf(outfile,"title = Processor Utilizations\n");
 fprintf(outfile,"title_x = Processor Element\n");
 fprintf(outfile,"title_y = Utilization (%c)\n", 37);

 /*******************************************************/
 /* Expect summaries.dat to have the following format: 	*/
 /* 	/pe2: Utilization = 0.06 %			*/
 /*	/pe4: Utilization = 0.06 %			*/
 /* Or, an older alternate format:			*/
 /*	----- Summary from PE 1  ---------		*/
 /* 	PE Utilization = 60.0 %				*/
 /*******************************************************/

 read_line( line );
 while (!feof(infile))
  {
   if ((strstr(line,"Utilization =")!=0) &&
       (strstr(line,"Avg. Processor Utilization")==0))
    {
     Next_Word( line, name, " 	:");
     Next_Word( line, word, " 	:=");
     Next_Word( line, word, " 	:=");

     /* Find the entry. */
     ID = find_entry( name );

     if (ID==0) printf("ERROR: Could not find device '%s'\n", name);
     else
      {
	fprintf(outfile,"%s	0\n", ID);
	fprintf(outfile,"%s	%s\n", ID, word);
	fprintf(outfile,"next\n");
      }
    }
   else
   if (strstr(line,"-------------- Summary from PE")!=0)
    {
     Next_Word( line, name, " 	-");	/* Summary */
     Next_Word( line, name, " 	");	/* from */
     Next_Word( line, name, " 	");	/* PE */
     Next_Word( line, name, " 	-");
     read_line( line );
     Next_Word( line, word, " 	");	/* PE */
     Next_Word( line, word, " 	=");	/* Utilization */
     Next_Word( line, word, " 	=");	
     fprintf(outfile,"%s	0\n", name);
     fprintf(outfile,"%s	%s\n", name, word);
     fprintf(outfile,"next\n");
    }
   read_line( line );
  }
 fclose(infile);
 fclose(outfile);

 printf("\nTo plot PE-Utilizations:\n  xgraph utils.dat\n\n");
}
