ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/contrib/gauge/Model/ppshow.c

This is ppshow.c in view mode; [Download] [Up]

#if (!defined(lint) && !defined(SABER)) 
static char *rcsid = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Model/RCS/ppshow.c,v 1.11 1992/04/17 21:10:38 mei Exp $";
#endif

/*AERO_MESG*/
/********************************************************/
/* FILE: ppshow.c                                       */
/********************************************************/

#include <errno.h>
#include <stdio.h>
#include <strings.h>
#include <math.h>
#include <setjmp.h>
#include <sys/param.h>

#ifdef HISTOGRAM
#include <Xsw/Xsw.h>
#include <Xsw/Help.h>
#include <X11/Shell.h>
#endif /* HISTOGRAM */

#if defined(symmetry)
#define MAXFLOAT HUGE
#endif
#if defined(sun4) || defined(iris)
#include <values.h>
#endif

#include "ppshowP.h"

#ifdef HISTOGRAM
#include <Gauge/Viewer.h>
#endif

char *checkmalloc(/* size,procname */);

static jmp_buf ErrorEnv;

/** used in cmp_bar,cmp_node,sort_bar **/ 
int CmpNode; 
Widget view;

/** used in sort_bars,subset - This variable is used to prevent
a resort of the data when a subset is being created **/

static making_subset = 0;

typedef struct CollectArgStruct{
    float max, min, total;
    float mean, sd;
    int items;
    Histo *histo;
}CollectArg;

/********************************************************/
/* NAME : find_node                                     */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
#ifdef HISTOGRAM
find_node(label,node,mode) 
     char *label;
     int node,mode;
{
  if (mode == UTILIZATION || mode == IDLE_TIME || 
                        mode == MSG_COUNT || mode == COMM_VOLUME)
    sscanf(label,"Processor %d",&node);
  return node;
}

/********************************************************/
/* Name : collect_from_internal                         */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
double collect_from_internal(pPtr,nPtr,mode,curr_snap_no)
     Procedure *pPtr; 
     void *nPtr;
     String mode;
     int curr_snap_no;
{
  double bar_value();
  double value = 0;
  int clause, goal;
  Clause *cPtr; /* calling procedure */

  for(clause = 0; clause < pPtr->size; clause++) {
    cPtr = pPtr->clauses+clause;
    for (goal = 0 ; goal < cPtr->body_goals; goal++)
      if (!(cPtr->calls[goal]->visible))
	value += bar_value((void *) cPtr->calls[goal],nPtr,mode,curr_snap_no);
  }
  return value;
}

/********************************************************/
/* Name : bar_value                                     */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
double bar_value(pPtr,nPtr,mode,curr_snap_no)
     void *pPtr, *nPtr;
     String mode;
     int curr_snap_no;
{
double value = 0.0;
ProcedureProfileData *procdataPtr; 
NodeStats *nsPtr;

switch (*mode) {
  case VTIME:
    procdataPtr= lookup_procsnapprof((Procedure *) pPtr,
                       curr_snap_no,((Node *) nPtr)->node_no); 
    value=(NO_PROC_DATA(procdataPtr)) ? 0 :
        collect_from_internal((Procedure *) pPtr,nPtr,mode,curr_snap_no)+ 
                       procdataPtr->cost.total;
    break;
  case VFREQ:
    procdataPtr= lookup_procsnapprof((Procedure *) pPtr,
                       curr_snap_no,((Node *) nPtr)->node_no); 
    value=(NO_PROC_DATA(procdataPtr) ? 0 : procdataPtr->counts.use);
    break;
  case VIDLE:
    procdataPtr= lookup_procsnapprof((Procedure *) pPtr,
                       curr_snap_no,((Node *) nPtr)->node_no); 
    value=(NO_PROC_DATA(procdataPtr)) ? 0 :
         collect_from_internal((Procedure *) pPtr,nPtr,mode,curr_snap_no)+
                        procdataPtr->cost.idle;
    break;
  case VMSGCNTS:
    nsPtr=((Node *) nPtr)->stats+curr_snap_no; 
    value=(NO_PROC_DATA(procdataPtr)) ? 0 : 
         SEND_CNT(nsPtr)+ RCV_CNT(nsPtr);
    break;
  case VMSGVOL:
    nsPtr=((Node *) nPtr)->stats+curr_snap_no; 
    value=(NO_PROC_DATA(procdataPtr)) ? 0 :
         (SEND_VOL(nsPtr)+ RCV_VOL(nsPtr)) / 1024.;
    break;
  default:
    value = 0;
  }
  return value;
}

/********************************************************/
/* Name : Help                                          */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
static void Help(w,hPtr,call)
     Widget w;
     Histo *hPtr;
     XPointer call;
{
XswHelpShow(hPtr->help,hPtr->help_key,XswGetShell(w),XswRight);
}

/********************************************************/
/* Name : ViewChanged                                   */
/* Content : for callback calls to update the screen    */
/*   with new data. This is where the refresh take place*/ 
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
ViewChanged(w, client_data, call_data)
     Widget w;
     XtPointer client_data;
     XtPointer call_data;
{
  Histo *hPtr = (Histo *) client_data;
  View *vPtr = (View *) call_data;
  char *str;
  VType type;
  StringList view;
  char wname[64], iname[64];
  CurrStats *csPtr;
  type = vPtr->type; /* ByNodes, ByProcedures, or ThreeD */
  view = vPtr->data;

  switch (*(view[0])) {
  case VTIME:
    sprintf(TextBuffer,GLOBAL_FMT,
	    hPtr->info.mins,hPtr->info.secs,hPtr->info.msecs,
	    hPtr->info.reductions,hPtr->info.suspensions);
    hPtr->help_key = "Time";
    break;
  case VFREQ:
    sprintf(TextBuffer,GLOBAL_FMT,
        hPtr->info.mins,hPtr->info.secs,hPtr->info.msecs,
        hPtr->info.reductions,hPtr->info.suspensions);
    hPtr->help_key = "Freq";
    break;
  case VIDLE:
    sprintf(TextBuffer,GLOBAL_FMT,
        hPtr->info.mins,hPtr->info.secs,hPtr->info.msecs,
        hPtr->info.reductions,hPtr->info.suspensions);
    if ((view[1] != NULL) && *(view[1]) == VTIME)
      hPtr->help_key = "TimeBreakdown";
    else
      hPtr->help_key = "Idle";
    break;
  case VMSGCNTS:
    csPtr= &(hPtr->currstats); 
    sprintf(TextBuffer,COMM_FMT,"message counts",
        SEND_CNT(csPtr),
        RCV_CNT(csPtr),
        SEND_CNT(csPtr)+RCV_CNT(csPtr));
    hPtr->help_key = "MsgCnts";
    break;
  case VMSGVOL:
    csPtr= &(hPtr->currstats); 
    sprintf(TextBuffer,COMM_FMT,"communication volume in KBytes",
        SEND_VOL(csPtr)/1024,
        RCV_VOL(csPtr)/1024,
       	SEND_VOL(csPtr)/1024+RCV_VOL(csPtr)/1024);
    hPtr->help_key = "MsgVol";
    break;
  default: ;
  }

  sprintf(wname,"Gauge profile of %s%s", 
	  hPtr->filename,hPtr->subset ? " (Subset)" : "");
  strcpy(iname,wname);
  XswSetWMNames(w,wname,iname);

  /* First time here? */
  if (hPtr->view == NULL)
    return;
  else 
    XswViewerSetText(hPtr->view,TextBuffer);
}

/********************************************************/
/* Name : cmp_bar                                       */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
cmp_bar(bar1,bar2)
     ListElement *bar1,*bar2;
{
  double tmp;
  if (CmpNode == UNSORT)
    return ((Procedure *) bar1->pointer)->id -
      ((Procedure *) bar2->pointer)->id;
  else {
    tmp = XswViewerRowValue(view, bar2) - XswViewerRowValue(view, bar1);
    return tmp > 0 ? 1 : tmp < 0 ? -1 : 0;
  }
}

/********************************************************/
/* Name : cmp_node                                      */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
cmp_node(node1,node2)
     ListElement *node1, *node2;
{
  double tmp;
  if (CmpNode == SORT) {
    tmp = XswViewerColumnValue(view, node2) - 
      XswViewerColumnValue(view, node1);
    return tmp > 0 ? 1 : tmp < 0 ? -1 : 0;
  }
  else
    return ((Node *) node1->pointer)->node_no -
      ((Node *) node2->pointer)->node_no;
}

/********************************************************/
/* Name : sort_bars                                     */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
sort_bars(w, client_data, call_data)
     Widget w;
     XtPointer call_data, client_data;
{
  Histo *hPtr = (Histo *) client_data;
  int order = (int) XawToggleGetCurrent(w);

  if (making_subset) return;

  if (order != 0) {
    CmpNode = order;
    view = hPtr->view;
    
    if (XswViewerViewType(hPtr->view) == ByNodes)
      qsort((char *) (hPtr->vnodes),hPtr->curr.node_cnt,sizeof(ListElement),cmp_node);
    else 
      qsort((char *)(hPtr->procs),hPtr->curr.procedure_cnt,sizeof(ListElement),cmp_bar);
    hPtr->curr.order = order;
    XswViewerUpdateView(hPtr->view);
  }
}

/********************************************************/
/* Name : collect_stats                                 */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
void collect_stats(pPtr, nPtr, name, dPtr, curr_snap_no)
  void *pPtr, *nPtr;
  char *name;
  CollectArg *dPtr;
  int curr_snap_no;

{
  Widget view = dPtr->histo->view;
  double value;

  if (XswViewerIsBucket(view))
    value = XswViewerBucketValue(view,pPtr);
  else 
    switch (XswViewerViewType(view)) {
    case ByNodes:
      value = XswViewerColumnValue(view,nPtr);
      break;
    case ByProcedures:
      value = XswViewerRowValue(view,pPtr);
      break;
    case Bucket3D:
      value = XswViewerRowValue(view,pPtr);
      break;
    case ThreeD:
      value = bar_value(pPtr,nPtr,name,curr_snap_no);
    }/* switch */

  (dPtr->items)++;
  dPtr->min = value < dPtr->min ? value : dPtr->min;
  dPtr->max = value > dPtr->max ? value : dPtr->max;
  dPtr->total += value;
  dPtr->sd += value * value;
}

/********************************************************/
/* Name : show_information                              */
/* Content :                                            */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
show_information(w, hPtr, call_data)
     Widget w;
     Histo *hPtr;
     XtPointer call_data;
{
  char format[128];
  sprintf(TextBuffer,"\nCounter file: %s\n",hPtr->filename);
  sprintf(format,"Architectural parameters: %s\n\n",
                              hPtr->nodes[0].machine);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Total number of nodes: %d \n",
                              hPtr->info.node_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Current number of nodes: %d\n\n",
                              hPtr->curr.node_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Number of procedures: %d\n",
                              hPtr->info.procedure_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Current number of procedures: %d\n\n",
                              hPtr->curr.procedure_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Number of modules: %d\n",
                              hPtr->info.module_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Current number of modules: %d\n\n",
                              hPtr->curr.module_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  sprintf(format,"Number of snapshots: %d\n",
                              hPtr->info.snap_cnt);
  strncat(TextBuffer,format,FMT_SIZE);
  XswPopupBox(hPtr->view,"Profile Information",TextBuffer);

}

/********************************************************/
/* Name : SelectSnap                                    */
/* Content : update the snapshot number for the main    */
/*  display's widget and then update the view           */
/* Date : 2/1992                                        */
/********************************************************/
/*ARGSUSED*/
void SelectSnap(Snap_no,hPtr)
int Snap_no;
Histo *hPtr;
{
String label;
 
    XswViewerSetZptr(hPtr->view,Snap_no);
    XswViewerUpdateView(hPtr->view);
}

/********************************************************/
/* Name: get_showsnap                                   */
/* Content: organize all the snapshot name into a table */
/* Date: 2/1992                                         */
/********************************************************/
/*ARGSUSED*/
void 
get_showsnap(hPtr,list)
Histo *hPtr;
String *list;
{
int i;

if(hPtr->info.snap_cnt > LIST_MAX){
    sprintf(TextBuffer,"snap number of [%d] is bigger than the maximum allowed",hPtr->info.snap_cnt);
    GaugeError("get_showsnap",TextBuffer);
}/*if*/
 
for(i=0;i<hPtr->info.snap_cnt;i++) {
  sprintf(item_buffer,"%s [%d]",hPtr->info.snap[i].name,i);
  list[i]=XtNewString(item_buffer);
  }
list[i]=NULL;
}

/********************************************************/
/* Name: get_snap_no                                    */
/* Content: organize all the snapshot name into a table */
/* Date: 2/1992                                         */
/********************************************************/
/*ARGSUSED*/
int 
get_snap_no(string)
String string;
{
int i;

  sscanf(string,"%*s [%d]",&i);
  return i;
}

/********************************************************/
/* Name : print_statistics                              */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
show_statistics(w, client_data, call_data)
     Widget w;
     XtPointer call_data, client_data;
{

  Histo *hPtr = (Histo *) client_data;
  CollectArg data;
  char box_string[512];

  data.min = MAXFLOAT;
  data.max = data.total = data.mean = data.sd = data.items = 0;
  data.histo = hPtr;

  XswViewerMapSelectedRows(hPtr->view, collect_stats, &data);
  
  data.mean = data.total / data.items;
  data.sd =
    (data.items == 1) ? 0.0 :
      sqrt((data.sd - data.mean*data.total) / (data.items - 1.0));
  sprintf(box_string,"\
Items:              %14d\n\
Mean:               %14.6g\n\
Standard Deviation: %14.6g\n\
Minimum:            %14.6g\n\
Maximum:            %14.6g\n\
Total:              %14.6g",
	  data.items, data.mean,data.sd,
	  data.min,data.max,data.total);
  XswPopupBox(hPtr->view, "Statistics",box_string);
}

/********************************************************/
/* Name : collect_usage_stats                           */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
void collect_usage_stats(pPtr, nPtr, name, sPtr, curr_snap_no)
     Procedure *pPtr;
     Node *nPtr;
     char *name;
     UsageStats *sPtr;
     int curr_snap_no;
{
  int clause;
  int node = nPtr->node_no;
  ProcedureProfileData *psPtr;
  ClauseProfileData *clsPtr;
  
  psPtr=lookup_procsnapprof(pPtr,curr_snap_no,node);
  if(NO_PROC_DATA(psPtr)) {
     sprintf(TextBuffer,
        "Node[%d] Snap[%d]'s procedure profile data not available",
             node,curr_snap_no);
     GaugeWarning("collect_usage_stats",TextBuffer);
     return;
  }/*if*/

  sPtr->suspends += psPtr->counts.suspend;
  sPtr->cost += psPtr->cost.total;
  sPtr->display = node;
  sPtr->nodes += 1;

  if (pPtr->type == FOREIGN_PROCEDURE)
    sPtr->counts[0].use += psPtr->counts.use;
  else {
    for (clause = 0; clause < pPtr->size; clause++) {

      clsPtr=lookup_clausnapprof(pPtr,clause,curr_snap_no,node);
      if(NO_CLAUSE_DATA(clsPtr)) {
         sprintf(TextBuffer,
            "Node[%d] Snap[%d] Clause[%d]'s profile data not available",
                node,curr_snap_no,clause);
         GaugeWarning("collect_usage_stats",TextBuffer);
         continue;
      }/*if*/

      sPtr->counts[clause].use += clsPtr->counts.use;
      sPtr->counts[clause].commit += clsPtr->counts.commit;
      sPtr->counts[clause].failure += clsPtr->counts.failure;
    }/*for*/
  }/*if-else*/
}

/********************************************************/
/* Name : show_usage_data                               */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
show_usage_data(w,client_data, call_data)
 Widget w;
     XtPointer call_data, client_data;
{
  Histo *hPtr = (Histo *) client_data;
  char box_string[FMT_SIZE];
  char format[128];
  Procedure *pPtr;
  UsageStats data;
  int i, clause, length,selected;
  Boolean *selections;
  int total_used = 0, total_commit = 0, total_failure = 0;

  XswViewerSelectedRows(hPtr->view,OR,&selections,&length);
  for (selected = 0, i = 0; i < length ; i++)
    if (selections[i] == True) {
      pPtr = (Procedure *) hPtr->procs[i].pointer;
      if (selected++ == 1) {
	Free(selections);
	XswPopupBox(hPtr->view,"Usage Data",
		    "\n  More than one procedure selected  \n\n");
	return;
      }
    }/*if*/

  Free(selections);
  if (selected == 0) {
    XswPopupBox(hPtr->view,"Usage Data","\n\n  No bars selected  \n\n");
    return;
  }/*if*/

  data.proc = pPtr;
  data.nodes = data.suspends = 0;
  data.cost = 0.0;
  data.counts =
    (struct s_clausecounts *) calloc(pPtr->size,sizeof(struct s_clausecounts));

  XswViewerMapSelections(hPtr->view, collect_usage_stats, &data);

  if (data.nodes == hPtr->info.node_cnt) {
    sprintf(box_string,"Usage data for %s on all nodes",pPtr->name);
  } else if (data.nodes == 1)
    sprintf(box_string,"Usage data for %s on node %d",
	    pPtr->name,data.display);
  else
    sprintf(box_string,"Usage data for %s on %d nodes",
	    data.proc->name, data.nodes);

  if (pPtr->type == FOREIGN_PROCEDURE) {
    sprintf(format,"\n Foreign defined kernel\n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," Number of uses:      %d\n",data.counts[0].use);
    strncat(box_string,format,FMT_SIZE);
    if (data.counts[0].use) {
      sprintf(format," Mean execution time: %-10.3f\n\n",
	      data.cost/data.counts[0].use);
      strncat(box_string,format,FMT_SIZE);
    } else {
      sprintf(format," Mean execution time: 0.0\n\n");
      strncat(box_string,format,FMT_SIZE);
    }
  } else {
    sprintf(format,"\n Number of implications:  %d\n",pPtr->size);
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," Number of suspends: %d\n\n",data.suspends);
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," +-------------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," | Implication #  |   Used   | Commits  | Failures | \n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," +-------------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
    for (clause = 0; clause < pPtr->size; clause++) {
      sprintf(format," | Implication %2d | %8d | %8d | %8d | \n", clause+1,
	      data.counts[clause].use,
	      data.counts[clause].commit,
	      data.counts[clause].failure);
      strncat(box_string,format,FMT_SIZE);
      total_used += data.counts[clause].use,
      total_commit += data.counts[clause].commit;
      total_failure += data.counts[clause].failure;
    }
    sprintf(format," +=================================================+ \n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," | Procedure      | %8d | %8d | %8d | \n",
	    total_used, total_commit, total_failure);
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," +-------------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
  }
  *(box_string + FMT_SIZE - 1) = '\0';
  Free(data.counts);
  XswPopupBox(hPtr->view,"Usage Data",box_string);
}

/********************************************************/
/* Name : user_program                                  */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
Procedure *user_program(pPtr)
     Procedure *pPtr;
{
  while (!(pPtr->visible))
    pPtr = pPtr->callers->clause_ptr->proc_ptr;
  return pPtr;
}

/********************************************************/
/* Name : show_call_data                                */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
show_call_data(w, client_data, call_data)
     Widget w;
     XtPointer call_data, client_data;
{
  char box_string[FMT_SIZE+1];
  char format[256];
  int uses = 0;
  Procedure *pPtr;
  RGraph *ctemp;
  UsageStats data;
  Boolean *node_selections, *program_selections;
  int length, i, node;
  int programs_selected = 0;
  int nodes_selected = 0;
  Histo *hPtr = (Histo *) client_data;
  ProcedureProfileData *psPtr;
  ClauseProfileData *csPtr;
  Clause *cPtr;
  int curr_snap_no;

  XswViewerGetZptr(hPtr->view,&curr_snap_no); 
  XswViewerSelectedRows(hPtr->view,OR,&program_selections,&length);
  for (i = 0; i < length ; i++)
    if (program_selections[i] == True) {
      pPtr = (Procedure *) hPtr->procs[i].pointer;
      if (programs_selected++ == 1) {
	Free(program_selections);
	XswPopupBox(hPtr->view,"Call Data",
		    "\n  More than one program selected  \n\n");
	return;
      }
    }

  Free(program_selections);
  if (programs_selected == 0) {
    XswPopupBox(hPtr->view,"Call Data","\n\n  No program selected  \n\n");
    return;
  }

  XswViewerSelectedColumns(hPtr->view,OR,&node_selections,&length);
  for (i = 0; i < length ; i++) 
    if (node_selections[i] == True)
      {
	node = i;
	nodes_selected++;
        psPtr=lookup_procsnapprof(pPtr,curr_snap_no,i);
        if(NO_PROC_DATA(psPtr)) {
          sprintf(TextBuffer,
             "Node[%d] Snap[%d]'s procerue profile data not available",
                 i,curr_snap_no);
          GaugeWarning("show_call_data",TextBuffer);
          continue;
        }/*if*/
	uses += psPtr->counts.use;
      }

  if (nodes_selected == hPtr->info.node_cnt)
    sprintf(box_string,"Call data for %s on all nodes",pPtr->name);
  else if (nodes_selected == 1)
    sprintf(box_string,"Call data for %s on node %d",pPtr->name,node);
  else
    sprintf(box_string,"Call data for %s on %d nodes",
                                           pPtr->name,nodes_selected);
  
  if (pPtr->callers == (RGraph *) NULL) {
    sprintf(format,"\n\n  Root procedure  \n\n");
    strncat(box_string,format,FMT_SIZE);
    XswPopupBox(hPtr->view,"Call Data",box_string);
  } else {
    sprintf(format,"\n Type of procedure:  %s\n",
	    pPtr->type == FOREIGN_PROCEDURE ? "Foreign" :
	    pPtr->type == PCN_PARALLEL ? "PCN" : "PCN");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," Total uses: %d\n\n",uses);
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," +-------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," |      Called by       |  Usage   | Percent | \n");
    strncat(box_string,format,FMT_SIZE);
    sprintf(format," +-------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
    for (ctemp = pPtr->callers; ctemp != (RGraph *) NULL; ctemp=ctemp->next) {
      int used = 0, i;
      for (i = 0 ; i < length ; i++) {
        cPtr=ctemp->clause_ptr;
	if (node_selections[i] == True) {
          csPtr=lookup_clausnapprof2(cPtr,curr_snap_no,i);
          if(NO_CLAUSE_DATA(csPtr)) {
            sprintf(TextBuffer,
             "Node[%d] Snap[%d]'s profile data not available",
                 i,curr_snap_no);
            GaugeWarning("show_call_data",TextBuffer);
            continue;
            } else used += csPtr->counts.commit;
        } /*if*/
      } /* for */

      sprintf(format," | %-20s | %8d |  %5.1f  | \n",
          user_program(cPtr->proc_ptr)->name,used,
               (uses == 0) ? 0.0 : (used*100.0)/uses);
      strncat(box_string,format,FMT_SIZE);
    }
    sprintf(format," +-------------------------------------------+ \n");
    strncat(box_string,format,FMT_SIZE);
    XswPopupBox(hPtr->view, "Call Data",box_string);
  }
  Free(node_selections);
}

/********************************************************/
/* Name : build_bars                                    */
/* Content : link up the procedure list for the hPtr    */
/* Date : OLD routines                                  */
/********************************************************/
char *build_bars(procname,proc,bar)
     char *procname;
     Procedure *proc;
     char *bar;
{
  ListElement *lst = (ListElement *) bar;
  if (proc->visible) {
    lst->pointer = (void *) proc;
    lst->label = (char *)
      checkmalloc(strlen(proc->mod_ptr->name)+strlen(procname)+2,"build_bars");
    /*
    sprintf(((ListElement *) bar)->label,"%s:%s",proc->mod_ptr->name,procname);
    */
    sprintf(((ListElement *) bar)->label,"%s",procname);
    return (char *) (++lst);
  }
  else return bar;
}

#endif /* Histogram */

/********************************************************/
/* Name : read_histogram                                */
/* Content : call the read_counter_files to retrieve    */
/*   profile data from the external file and then calc. */
/*   static values for currstats (for HISTOGRAM only -  */
/*   call build_bars to linkup all the procedures with  */
/*   Histo->procs)                                      */
/* Calls : build_bars(for all procedures)               */
/* Date : OLD routines                                  */
/********************************************************/
read_histogram(file,hPtr)
     FILE *file;
     Histo *hPtr;
{
int node;
Node *nPtr;
NodeStats *nsPtr;

  read_counters_file(hPtr,file);

/* into the viewer widget 2/24 hui
  if(curr_snap_no == LAST)  
    curr_snap_no=(hPtr->info.snap_cnt -1);
*/

#ifdef HISTOGRAM
  hPtr->vnodes = (ListElement *) 
    checkmalloc(sizeof(ListElement) * (hPtr->info.node_cnt+1),
      "read_histogram");
#endif /* HISTOGRAM */

  hPtr->curr.node_cnt = hPtr->info.node_cnt;
  hPtr->curr.procedure_cnt = hPtr->info.procedure_cnt;
  hPtr->curr.module_cnt = hPtr->info.module_cnt;
  hPtr->curr.snap_cnt = hPtr->info.snap_cnt;

                  /* specifically for the total node_cnt */
  for (node = 0 ; node < hPtr->info.node_cnt ; node++) {
    nPtr=hPtr->nodes+node;
    if(hPtr->info.snap_cnt -1 >= 0)
       nsPtr=nPtr->stats + hPtr->info.snap_cnt-1;/* the last snapshot */ 

#ifdef HISTOGRAM
    hPtr->vnodes[node].pointer = nPtr;
    sprintf(nPtr->bar.label,"%d",node);
    hPtr->vnodes[node].label = nPtr->bar.label;
#endif /* HISTOGRAM */

/* currstats <- sum on all node's stat */
    if( (hPtr->info.snap_cnt-1 < 0) || nsPtr->used == FALSE ) {
#ifdef MEIDEBBUG
      sprintf(TextBuffer,
        "No stats data for node[%d] snap_no[%d]",node,hPtr->info.snap_cnt-1);
      GaugeWarning("read_histogram",TextBuffer);
#endif
      continue;
    }/*if*/

    hPtr->currstats.send_small += nsPtr->send_small;
    hPtr->currstats.send_big += nsPtr->send_big;
    hPtr->currstats.send_length += nsPtr->send_length;
    hPtr->currstats.rcv_small += nsPtr->rcv_small;
    hPtr->currstats.rcv_big += nsPtr->rcv_big;
    hPtr->currstats.rcv_length += nsPtr->rcv_length;
  }

/* just the last nodes' */
  nPtr=hPtr->nodes+hPtr->info.node_cnt-1;
  nsPtr=nPtr->stats+hPtr->info.snap_cnt-1;
  hPtr->currstats.gc_count = nsPtr->gc_count;
  hPtr->currstats.gc_mins = nsPtr->gc_mins;
  hPtr->currstats.gc_secs = nsPtr->gc_secs;
  hPtr->currstats.gc_msecs = nsPtr->gc_msecs;

#ifdef HISTOGRAM
  hPtr->procs = (ListElement *)
    checkmalloc(sizeof(ListElement)*(hPtr->info.procedure_cnt+1)
      ,"read_histogram");
  map_procedures(hPtr->modules,build_bars,(char *) hPtr->procs);
  hPtr->procs[hPtr->info.procedure_cnt].label = NULL;
  hPtr->vnodes[hPtr->info.node_cnt].label = NULL;
#endif /* HISTOGRAM */

}

/********************************************************/
/* Name: print_procedure                                */
/* Content : */
/* Date : OLD routines                                  */
/********************************************************/
/* ARGSUSED */
print_procedure(procname,proc,dummy)
     char *procname;
     Procedure *proc;
     char *dummy;
{
  printf("Procedure %s:%s\n",procname,proc->mod_ptr->name);
}

/********************************************************/
/* Name: free_module,free_procedure,free_snaptable      */
/* Name: free_snaptablerow, free_snaptablelist          */
/* Name: */
/* Name: */
/* Content : utility routines to free the allocated     */
/*   data structure                                     */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
free_module(name,module,pass)
     char *name;
     Module *module;
     char *pass;
{
  Free(module->name);
  free_table(module->procedures);
  free_snaptable(module->snaptable);
  Free(module);
}

free_snaptable(snaptable)
TableHeader *snaptable;
{
   if(snaptable != (TableHeader *) NULL) {
     free_snaptablerow(snaptable->data_ptr); /* free the body */
     Free(snaptable); /* free the header */
   }
}

free_snaptablerow(ptr)
SnapTableEntry *ptr;
{
   if(ptr != (SnapTableEntry *) NULL) {
     if(ptr->next_node_list != (SnapTableEntry *) NULL)
        free_snaptablerow(ptr->next_node_list);
     free_snaptablelist(ptr->next_snap_entry);
     Free(ptr);
   }
}

free_snaptablelist(ptr)
SnapTableEntry *ptr;
{
   if(ptr != (SnapTableEntry *) NULL) {
      free_snaptablelist(ptr->next_snap_entry);
      Free(ptr);
   }
}

/*ARGSUSED*/
free_procedure(proc_name,pPtr,hPtr)
     char *proc_name;
     Procedure *pPtr;
     char *hPtr;
{
  RGraph *ctemp, *ctemp1;

  if(pPtr != (Procedure *) NULL) {
    Free(pPtr->name);
    free_procprofile(pPtr->procpernode);
    for(ctemp = pPtr->callers; ctemp != (RGraph *) NULL ; ctemp = ctemp1) {
      ctemp1 = ctemp->next;
      Free(ctemp);
    } /*for*/
    Free(pPtr->total);
    free_clause(pPtr);
    Free(pPtr);
  } /*if*/
}

free_procprofile(psPtr)
TableHeader *psPtr;
{
  if(psPtr != (TableHeader *) NULL) {
               /* the profile data body */
    free_procdataentry(psPtr->data_ptr); 
               /* the profile data header */
    Free(psPtr); 
  }
}

free_procdataentry(pPtr)
ProcedureProfileData *pPtr;
{
  if(pPtr != (ProcedureProfileData *) NULL ) {
    free_procdataentry(pPtr->next);
    Free(pPtr);
  }
}

free_clause(pPtr)
Procedure *pPtr;
{
 int i;

  if(pPtr != (Procedure *) NULL) {
    for (i = 0 ; i < pPtr->size ; i++) {
      if (pPtr->type != FOREIGN_PROCEDURE) {
        if (pPtr->clauses[i].foreigns != NULL)
                 Free(pPtr->clauses[i].foreigns);
        if (pPtr->clauses[i].calls != NULL)
                 Free(pPtr->clauses[i].calls);
      } /*if*/
    } /*for*/
   /* clause data is allocated in set of size=pPtr->size */
    free_clauseprofile(pPtr->clauses->claupernode->data_ptr); /* the profile data body */
    for(i=0;i<pPtr->size && pPtr->clauses+i != NULL;i++)
      Free(pPtr->clauses+i); /* the profile data headers */
   } /*if !NULL*/
}

free_clauseprofile(csPtr)
ClauseProfileData *csPtr;
{
 if(csPtr != (ClauseProfileData *) NULL) {
    free_clauseprofile(csPtr->next);
    Free(csPtr);
 }
}

free_nodes(hPtr)
Histo *hPtr;
{
int i;

  if(hPtr != (Histo *) NULL) {
     for(i=0;i<hPtr->info.node_cnt;i++)
        Free(hPtr->nodes[i].machine);
     Free(hPtr->nodes->stats);
     Free(hPtr->nodes);
  }
}

#ifdef HISTOGRAM

#ifdef STAND_ALONE
static int window_count = 1;
#endif

/********************************************************/
/* Name :  */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
static void
DestroySubset(w, hPtr, call_data)
     Widget w;
     Histo *hPtr;
     XtPointer call_data;
{
#ifdef STAND_ALONE
  if (--window_count == 0)
    exit(0);
#endif
  Free(hPtr->vnodes);
  Free(hPtr->procs);
  Free(hPtr);
}

/*ARGSUSED*/
static void
DestroyGauge(w, hPtr, call_data)
     Widget w;
     Histo *hPtr;
     XtPointer call_data;
{
  int i;

#ifdef STAND_ALONE
  if (--window_count == 0)
    exit(0);
#endif
  Free(hPtr->title);
  Free(hPtr->filename);

  (void) map_procedures(hPtr->modules,free_procedure,(char *) hPtr);
  (void) map_table(hPtr->modules,free_module,(char *) hPtr);
  free_table(hPtr->modules);
  free_nodes(hPtr);
  Free(hPtr->vnodes);
  for (i = 0 ; i < hPtr->info.procedure_cnt ; i++)
    Free(hPtr->procs[i].label);
  Free(hPtr->procs);
  Free(hPtr);
}

#define SUBSET 0
#define DELETE 1

/*ARGSUSED*/
SubsetButton(w, hPtr, call_data)
     Widget w;
     Histo *hPtr;
     XtPointer call_data;
{
  Widget subset();

  XswWidgetTool("GaugeSubsetDisplay",subset(shell, hPtr, SUBSET), shell);
}

/*ARGSUSED*/
DeleteButton(w, hPtr, call_data)
     Widget w;
     Histo *hPtr;
     XtPointer call_data;
{
  Widget subset();

  XswWidgetTool("GaugeSubsetDisplay",subset(shell, hPtr, DELETE), shell);
}

/********************************************************/
/* Name : subset                                        */
/* Content :  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
Widget subset(parent, hPtr, op)
     Widget parent;
     Histo *hPtr;
     int op;
{
  Histo *hPtr1 = (Histo *) checkmalloc(sizeof(Histo),"subset");
  int i, j, length;
  Boolean *selected;
  int sense = (op == SUBSET) ? True : False;
 
  *hPtr1 = *hPtr;
  hPtr1->subset = True;
  hPtr1->view = (Widget) NULL;


  if (op == DELETE) {
    hPtr1->curr.procedure_cnt = XswViewerSelectedRows(hPtr->view,AND,&selected,&length);
    hPtr1->curr.procedure_cnt = length - hPtr1->curr.procedure_cnt;
    if (hPtr1->curr.procedure_cnt == 0) {
      XtFree(selected);
      Free(hPtr1);
      GaugeWarning("subset","Attempting to delete all programs");
      return (Widget) NULL;
    }
  } else 
    hPtr1->curr.procedure_cnt = XswViewerSelectedRows(hPtr->view,OR,&selected,&length);

  hPtr1->procs = (ListElement *)
    checkmalloc(sizeof(ListElement)*(hPtr1->curr.procedure_cnt + 1),"subset");

  for (j = 0, i = 0; i < length; i++) 
    if (selected[i] == sense) 
      hPtr1->procs[j++] = hPtr->procs[i];

  hPtr1->procs[j].label = NULL;
  XtFree(selected);

  if (op == DELETE) {
    hPtr1->curr.node_cnt = XswViewerSelectedColumns(hPtr->view,AND,&selected,&length);
    hPtr1->curr.node_cnt = length - hPtr1->curr.node_cnt;
    if (hPtr1->curr.node_cnt == 0) {
      XtFree(selected);
      Free(hPtr1);
      GaugeWarning("subset","Attempting to delete all nodes");
      return (Widget) NULL;
    }
 }
  else
    hPtr1->curr.node_cnt = XswViewerSelectedColumns(hPtr->view,OR,&selected,&length);
  hPtr1->vnodes = (ListElement *)
    checkmalloc(sizeof(ListElement)*(hPtr1->curr.node_cnt + 1),"subset");
  for (j = 0, i = 0 ; i < length ; i++)
    if (selected[i] == sense) 
      hPtr1->vnodes[j++] = hPtr->vnodes[i];
  hPtr1->vnodes[j].label = NULL;
  XtFree(selected);

  XswRegisterCallback("Statistics",show_statistics,hPtr1);
  XswRegisterCallback("Usage",show_usage_data,hPtr1);
  XswRegisterCallback("Calls",show_call_data,hPtr1);
  XswRegisterCallback("Sort",sort_bars,hPtr1);
  XswRegisterCallback("Subset",SubsetButton,hPtr1);
  XswRegisterCallback("Delete",DeleteButton,hPtr1);
  XswRegisterCallback("Help",Help,hPtr1);
  XswRegisterCallback("ViewChanged", ViewChanged,hPtr1);
  XswRegisterCallback("ProfileInfo", show_information,hPtr1);
  /* Register destroy callback */

  making_subset = 1;
  CreateGauge(&(hPtr1->view), parent, hPtr1, hPtr1->vnodes,
	      hPtr1->procs, bar_value, hPtr->view);
  making_subset = 0;
  XswViewerSetText(hPtr1->view,TextBuffer);

  XtAddCallback(XtParent(hPtr1->view), XtNdestroyCallback, DestroySubset,hPtr1);

#ifdef STAND_ALONE
  window_count++;
#endif

  return XtParent(hPtr1->view);
}

#endif /* HISTOGRAM */

/********************************************************/
/* Name :  */
/* Content : utility routine  */
/* Date : OLD routines                                  */
/********************************************************/
#include <sys/types.h>
#include <sys/stat.h>

FILE *open_counter_file(filename)
     char *filename;
{
  struct stat buf;
  int fds[2];			/* 0=reading, 1=writing */
  int status;
  extern char *sys_errlist[];

  /*  Check that file exists and is readable before doing anything else */

  if ( access(filename, 4) != 0)
  {
    sprintf(TextBuffer,"Unable to open counter file %s",filename);
    GaugeError("open_counter_file",TextBuffer);
  }
#ifdef DONT_INCLUDE
  /*
   * Steve Tuecke, 11/25/92
   * This was what was originally used instead of the above
   * call to access().
   * The call to access() seems to be more portable, since
   * it doesn't require the S_IROTH values, etc.
   */
  if  (stat(filename, &buf) )  {
    sprintf(TextBuffer,"Unable to open counter file %s",filename);
    GaugeError("open_counter_file",TextBuffer);
  }/* if */

  if  ( !(buf.st_mode & S_IROTH) )
    if  ( !(buf.st_mode & S_IRGRP) || (buf.st_gid != getgid()) )
      if  ( !(buf.st_mode & S_IRUSR) || (buf.st_uid != getuid()) )  {
	sprintf(TextBuffer,"Cannot read counter file %s\n%s",
		filename,sys_errlist[errno]);
	GaugeError("open_counter_file",TextBuffer);
      }
#endif

  if (strlen(filename) > 2 && ! strcmp(filename + strlen(filename) - 2,".Z")) {
    
    /*  Set-up pipe and fork. */
    if  ( pipe( fds ) )  {
      sprintf(TextBuffer,"Cannot run zcat:%s",sys_errlist[errno]);
      GaugeError("open_counter_file",TextBuffer);
    }
    status = fork();

    if  ( status < 0 )  {
      sprintf(TextBuffer,"Cannot fork zcat:%s",sys_errlist[errno]);
      GaugeError("open_counter_file",TextBuffer);
    } else if (status) {	/* parent */
      close(fds[1]);
      return fdopen(fds[0],"r");
    }
    else {			/* child  */
      status = dup2( fds[1], 1 );
      status = execlp( "zcat", "zcat", filename, (char *) 0);
      sprintf(TextBuffer,"Cannot exec zcat:%s",sys_errlist[errno]);
      GaugeError("open_counter_file",TextBuffer);
    }
  } else
    return fopen(filename,"r");
}

/********************************************************/
/* Name : ppshow                                        */
/* Content : to allocate the space for profile data and */
/*   calls read_histogram to bring in the data          */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
Widget ppshow(parent,filename,flag)
     Widget parent;
     char *filename;
     int flag;
{
  char *execution_time(), *print_time();
  FILE *ifile = stdin;
  FILE *ofile = stdout;
  extern double atof();
  Histo *hPtr;

  if (setjmp(ErrorEnv) != 0) 
    return (Widget) NULL;

  hPtr = (Histo *) checkmalloc(sizeof(Histo),"ppshow");

  ModeFlag = flag;
  hPtr->filename = checkmalloc(strlen(filename)+1,"ppshow");
  strcpy(hPtr->filename,filename);

#ifdef HISTOGRAM
  hPtr->subset = False;
  hPtr->title =
      checkmalloc(sizeof("Multiprocessor Pefformance Analysis Tool")+1,"ppshow");
  strcpy(hPtr->title,"Multiprocessor Performance Analysis Tool");
#endif /* HISTOGRAM */

  if ((ifile = open_counter_file(filename)) == (FILE *) NULL) {
    sprintf(TextBuffer,"Unable to open counter file %s",filename);
    GaugeError("ppshow",TextBuffer);
  }

#ifdef HISTOGRAM
  hPtr->view = parent;
#endif

  read_histogram(ifile,hPtr);
  fclose(ifile);

/* 2/92 hui : don't want this to show 
  sprintf(TextBuffer,"\n  Processing counter file: %s  \n\n",filename);
  sprintf(TextBuffer+strlen(TextBuffer),"  Parameter values:\n");
  sprintf(TextBuffer+strlen(TextBuffer),
    "    Inst Cost = (%f,%f)\n    Suspend= %f\n\n",
      hPtr->architecture->parameters.classtype[0],
         hPtr->architecture->parameters.classtype[1],
	    hPtr->architecture->parameters.suspend);
  sprintf(TextBuffer+strlen(TextBuffer),
    "  Processing data from %d processors\n\n", hPtr->info.node_cnt);
  inform_user(hPtr,TextBuffer);
*/

  switch (flag)
    {
    case WRITE:
      (void) map_procedures(hPtr->modules,execution_time,(char *) hPtr); 
      output_times(hPtr,ofile,print_time); /*just last snapshot*/ 
      return (Widget) NULL;
    case CALIBRATE:
      output_calibration(hPtr,ofile); 
      return (Widget) NULL;
#ifdef HISTOGRAM
    case DISPLAY:
      (void) map_procedures(hPtr->modules,execution_time,(char *) hPtr); 

      XswRegisterCallback("Statistics",show_statistics,hPtr);
      XswRegisterCallback("Usage",show_usage_data,hPtr);
      XswRegisterCallback("Calls",show_call_data,hPtr);
      XswRegisterCallback("Sort",sort_bars,hPtr);
      XswRegisterCallback("Subset",SubsetButton,hPtr);
      XswRegisterCallback("Delete",DeleteButton,hPtr);
      XswRegisterCallback("Help",Help,hPtr);
      XswRegisterCallback("ViewChanged", ViewChanged,hPtr);
      XswRegisterCallback("ProfileInfo", show_information,hPtr);

      hPtr->view = NULL; /* Let ChangeView know we are just starting */
      CreateGauge(&(hPtr->view), parent, hPtr, hPtr->vnodes,
		  hPtr->procs, bar_value, NULL);
      XswViewerSetText(hPtr->view,TextBuffer);

      hPtr->help = XtCreatePopupShell(
                           "gaugeHelp",
                           helpWidgetClass,
                           XtParent(hPtr->view),
			   NULL, 0);

      XtAddCallback(XtParent(hPtr->view), XtNdestroyCallback, DestroyGauge, hPtr);

      return XtParent(hPtr->view);
#endif
    default:
      break;
    }
}

/********************************************************/
/* Name :  */
/* Content : utility  */
/* Date : OLD routines                                  */
/********************************************************/
/*ARGSUSED*/
inform_user(hPtr,str)
     Histo *hPtr;
     char *str;
{
#if (HISTOGRAM)
  if (ModeFlag == DISPLAY)
    XswPopupBox(hPtr->view,"Gauge Information",str);
  else
    printf(str);  
#else
  printf(str);
#endif
}


/********************************************************/
/********************************************************/
/* from hutil.c        (for ppshow only)                */
/********************************************************/
/********************************************************/

     /* from ppshow.c but not really used */
struct cost_parameters Parameters; 

char *checkmalloc(size,procname)
     int size;
     char *procname;
{
  /* char *calloc(); */
  char *ptr = (char *) calloc((unsigned) 1,(unsigned) size);
  if (ptr == NULL) {
    sprintf(TextBuffer,"Malloc failed in %s",procname);
    GaugeError("checkmalloc",TextBuffer);
  } else
    return ptr;
}

GaugeError(procname,str)
     char *procname,*str;
{
sprintf(MessageBuffer,"%s -%s\n",procname,str);
#if (HISTOGRAM)
  if (ModeFlag == DISPLAY) {
    XtWarning(MessageBuffer);
    longjmp(ErrorEnv,1);
  } else {
    printf(MessageBuffer);
    exit(1);
  }
#else
  printf(MessageBuffer);
  exit(1);
#endif
}

GaugeWarning(procname,str)
     char *procname,*str;
{
sprintf(MessageBuffer,"%s -%s\n",procname,str);
#if (HISTOGRAM)
  if (ModeFlag == DISPLAY)
    XtWarning(MessageBuffer);
  else
    printf(MessageBuffer);
#else
  printf(MessageBuffer);
#endif
}


/* ARGSUSED */
load_arch_dbase(hPtr,arch)
     Histo *hPtr;
     struct arch_descriptor *arch;
{
  char buf[256];
  char hostname[MAXHOSTNAMELEN];

  typedef struct {
    String dbase_file;
    String default_arch;
  } ArchData, *ArchDataPtr;

#ifdef HISTOGRAM
  static XtResource arch_resources[] = {
    { "archDbase", "ArchDbase", XtRString, sizeof (String),
	XtOffset(ArchDataPtr, dbase_file), XtRString, 
        "pcn_hosts" },
/* DEFAULT_ARCH_DBASE }, */
    { "archDefault", "ArchDefault", XtRString, sizeof (String),
	XtOffset(ArchDataPtr, default_arch), XtRString, 
	"sun4" },
/* DEFAULT_ARCH }, */
  };
#endif
  ArchData data;
  FILE *fd;

/* data.default_arch = DEFAULT_ARCH; */
/* data.dbase_file = DEFAULT_ARCH_DBASE; */
data.default_arch=(char *) checkmalloc(sizeof("sun4")+1,"load_arch_dbase");
data.dbase_file=(char *) checkmalloc(sizeof("pcn_hosts")+1,"load_arch_dbase");
strcpy(data.default_arch,"sun4");
strcpy(data.dbase_file,"pcn_hosts");

#ifdef HISTOGRAM
  if (ModeFlag == DISPLAY) {
    XtGetApplicationResources(hPtr->view, &data, arch_resources, 
			      XtNumber(arch_resources), NULL, 0);
    data.dbase_file = XswGetLibName(data.dbase_file);
  }
#endif /* HISTOGRAM */

  fd = fopen(data.dbase_file,"r");
  if (fd == NULL) {
    sprintf(TextBuffer,"Could not open architecture parameter file");
    GaugeError("load_arch_dbase",TextBuffer);
    return;
  }

  strcpy(hostname,arch->host_name);

  lookup:
  while (fscanf(fd,"%s",buf) != EOF) {
    if (buf[0] == '+' && buf[1] == '>')
      { /* A reference line */
	fscanf(fd," %s ",buf);
	if (! strncmp(buf,hostname,strlen(buf)) ) {
	  /* Get name of hostype being referenced */
	  fscanf(fd," %s ",hostname);
	  /* Now resolve it */
	  rewind(fd);
	  continue;
	}
      }
    else if  ( (buf[0] == '-' && buf[1] == '-') ||
	      strncmp(buf,hostname,strlen(buf)) )
      fscanf(fd,"%*[^\n]");
    else  {
      int i, tmp;
      union u_bytecode_key key;

      sprintf(TextBuffer+strlen(TextBuffer),
	      "  Using architectural parameters for %s\n\n",buf);

      /* Get byteorder key */
      for (i = 0 ; i < 8 ; i++) {
	fscanf(fd," %2x ",&tmp);
	key.bytes[i] = tmp;
      }
      arch->byte_swapper = decode_byteorder_key(key.timer);

      /* Get the number of clock ticks per second */
      fscanf(fd," %d ",&(arch->ticks_per_second));
      /* Finally, get the instruction parameters */
      if (ModeFlag == CALIBRATE) {
	int i;
	for (i = 0 ; i < INSTR_CLASSES ; i++)
	  arch->parameters.classtype[i] = 1.0;
	arch->parameters.suspend = arch->parameters.copy = 1.0;
	arch->parameters.send_small = arch->parameters.send_big =
	  arch->parameters.send_length = 1.0;
	arch->parameters.rcv_small = arch->parameters.rcv_big =
	  arch->parameters.rcv_length = 1.0;
      } else {
	for (i = 0 ; i < INSTR_CLASSES ; i++) 
	  fscanf(fd," %f ",(arch->parameters.classtype)+i);
	fscanf(fd," %f ",&(arch->parameters.suspend));
      }
      fclose(fd);
      return;
    }
  }

  sprintf(TextBuffer,
	  "Architectural parameters for host:\n    %s\n  are not defined.\n\
  Using parameters for %s instead\n  Use the \"pcnhost\" command to  \n  add\
 this host to the architecture database",
	  arch->host_name,data.default_arch);
  GaugeWarning("load_arch_dbase",TextBuffer);
  rewind(fd);
  strcpy(hostname,data.default_arch);
  goto lookup;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.