/*
 * $RCSfile: ptcp.c,v $
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1996,1994  Arizona Board of Regents
 */

#include <stdio.h>
#include <time.h>
#include "xkernel.h"

/* #define XK_ETC "../../../etc" */
#define PSDIR "../../simulator/etc"
#define CSX33DIR "/cs/x33/simulator/etc"

char *PsDir=PSDIR;

#define TCP_TRACE

/* --- Dummy stuff for include file */
struct tcphdr   {int i;};
struct tcpiphdr {int i;};
struct inpcb    {int i;};
typedef u_int tcp_seq;

#define TCPT_NTIMERS 4
#include "tcp_var.h"

#include "tcp_trace.h"
/* VENKAT: Increased all these array sizes */
#define MAX_NUM_PACKETS 100000
#define MAX_NUM_EVENTS  650000
#define ARRAY_SIZE      100000

#define INIT_COMP(min,max,avg)  min=1000000,max=0,avg=0
#define DO_COMP(t2,t1,min,max,avg)	\
  { int d;				\
    d = t2 - t1;			\
    if (d < min) min = d;		\
    if (d > max) max = d;		\
    avg += d;				\
  }

typedef struct {
  int   seq;
  int   len;
  int   ack;
  unsigned long   time; /* VENKAT */
  short flags;
  short sid;
} RcvTraceType;

typedef struct {
  int   time; 
  int   seq;
  int   time_rcvd_ack;
  int   len;
  short flags;
  short sid;
} SndTraceType;

TcpTrace       	*Traces;
long		Nt; /* VENKAT */
RcvTraceType  	RcvTraces[MAX_NUM_PACKETS];
SndTraceType    SndTraces[MAX_NUM_PACKETS];
struct tcpstat	TcpStat;
int		StatSize;
int		Total_bytes_sent, Total_bytes_rcvd;
long 		Test_time; /* VENKAT */
char		buf[5000];
int		PageNum=0;
int             Sids[256], SidCnt=0, SidsUse[256];
int             SidUse=-1;

#define ADD_ENTRY(a,i,t,v) \
  if ((v) != a[i-1][1]) {  \
    a[i][0] = t;           \
    a[i][1] = a[i-1][1];   \
    i++;                   \
    a[i][0] = t;           \
    a[i++][1] = (v);       \
  }

#define ADD_ENTRY_CHOP(a,i,t,av,m) { \
  int v;                             \
  v = (av) > m ? m : (av);           \
  if ((v) != a[i-1][1]) {            \
    a[i][0] = t;                     \
    a[i][1] = a[i-1][1];             \
    i++;                             \
    a[i][0] = t;                     \
    a[i++][1] = (v);                 \
  }                                  \
}

#define ADD_ENTRY_ALWAYS(a,i,t,v) { \
  a[i][0] = t;                      \
  a[i][1] = a[i-1][1];              \
  i++;                              \
  a[i][0] = t;                      \
  a[i++][1] = (v);                  \
}

char TimeArray[300], array[300], str[100];
char *Filename="trace.data", DataName[100], Path[200], RemoteName[200];

#define IS_ACK(x)       (x & 0x10)
#define IS_PUSH(x)      (x & 0x08)
#define IS_URG(x)       (x & 0x20)
#define IS_RST(x)       (x & 0x04)
#define IS_SYN(x)       (x & 0x02)
#define IS_FIN(x)       (x & 0x01)
#define IS_ROPT(x)	(x & 0x100)

#define E_BLOCK 	0x1000
#define E_AWAKE 	0x2000
#define E_TO_REXMT	0x4000
#define E_TO_PERSIST	0x8000
#define E_TO_KEEP	0x10000
#define E_TO_2MSL	0x20000
#define E_PUSH		0x40000
#define E_SND		0x80000
#define E_ACK		0x10
#define E_BADSUM	0x200
#define E_ROPT		0x100
#define E_RCV		0x400
#define E_PUSHF		0x08
#define E_URG		0x20
#define E_RST		0x04
#define E_SYN		0x02
#define E_FIN		0x01
#define E_DROP		0x100000
#define E_FTO		0x200000
#define E_STO		0x400000
#define E_OACK		0x800000
#define E_WS		0x1000000
#define E_RCWND		0x2000000
#define E_RTO		0x4000000
#define E_INTER0	0x8000000
#define E_INTER1	0x10000000
#define E_SPIKESUP	0x20000000

#define F_LOST		0x1
#define F_RESEND	0x2

int   LostPacketsSntTime[500], LostPacketsSntTimeN=0;
int   NumPacketsSent=0, NumPacketsRcvd=0;

int   Seq[ARRAY_SIZE][2], SeqN=0, MaxSeq=0;
int   Rtt[ARRAY_SIZE][2], RttN=0, MaxRtt=0;
int   To[ARRAY_SIZE][2], ToN=0;
int   Artt[ARRAY_SIZE][2], ArttN=0, Arttn=4;
int   Drtt[ARRAY_SIZE][2], DrttN=0;
int   Dartt[ARRAY_SIZE][2], DarttN=0;
int   Dirtt[ARRAY_SIZE][2], DirttN=0;
int   Prate[ARRAY_SIZE], PrateN=0;
int   BufSize[3*ARRAY_SIZE][2], BufSizeN=0;
int   Cbit[ARRAY_SIZE][2], CbitN=0, MaxWin=0;
int   Awin[ARRAY_SIZE][2], AwinN=0;
int   Cwin[ARRAY_SIZE][2], CwinN=0;
int   Thrs[ARRAY_SIZE][2], ThrsN=0;
int   EventA[120000][2], EventN=0;
int   Lrate[ARRAY_SIZE][2], LrateN=0, MaxRate=0, Lraten=12;
int   FixMaxRate=100000000, FixMaxWin=10000000;
int   FixRateTic=0, FixWinTic=0;
int   Lrate2[ARRAY_SIZE][2], Lrate2N=0, Lrate2n=50;
int   Lrate3[ARRAY_SIZE][2], Lrate3N=0;
float Lrate3n=1.0;
int   Grate[ARRAY_SIZE][2], GrateN=0;
int   Cwrate[ARRAY_SIZE][2], CwrateN=0;
int   Vactual[ARRAY_SIZE][2], VactualN=0, Vmax=0;
int   Vpred[ARRAY_SIZE][2], VpredN=0;
int   Vtop[ARRAY_SIZE][2], VtopN=0;
int   Vbot[ARRAY_SIZE][2], VbotN=0;
int   Vexp_nseg=0, Vtop_nseg=0, Vbot_nseg=0, VegasFlags=0;
int   Lost[1000][2], LostN=0;
int   LostGroups[200][2], LostGroupsN=0, LossMode=0;
int   State[2000][2], StateN=0, LState=-1;
int   NotLost[1000][2], NotLostN=0;
int   Psnt[2000][2], Prcv[2000][2], PsntN=0, PrcvN=0;
int   Closs[ARRAY_SIZE][2], Gloss[ARRAY_SIZE][2];
int   ClossN=0, GlossN=0, MaxLoss=0;
int   BlockN=0, AwakeN=0, RexmtN=0, PersistN=0, KeepN=0, MslN=0, PushN=0;
int   SndN=0, AckN=0, BadsumN=0, RoptN=0, PushfN=0, UrgN=0, RstN=0;
int   SynN=0, FinN=0, DropN=0, FtoN=0, StoN=0, RcvN=0, OackN=0;
int   WsN=0, RcwndN=0, RtoN=0, InterN=0, SpikesupN=0;
int   ZeroFun[2][2], LostCnt=0, LostBcnt=0;
int   LastSndTime=0, ToTimeSum=0;
int   Strip_beg_time=0, Strip_end_time=4000;
long  Run_time; /* VENKAT */
int   Read_np_lost;
int   PlotLostSntTimeBars=1, LastAckTime=0;
float Aylen=1.5, Axpos=1.0, Axlen=6.3, X0=1.0, Y0=10.4;
int   MaxBit=0, MaxAwin=0, MaxCwin=0, AvgNpit=0, NumStrips=1, MaxBufSize=0;
int   MaxThrs=0;
char  *DbFile=NULL;
int   GoalNpit, BegTime=0, PageCnt=1, PageFlag=0, DbFlag=0, BigFlag=0;
int   FixMaxRateFlag=0, FixMaxWinFlag=0;
int   FixRateTicFlag=0, FixWinTicFlag=0;
long   RateBegTime=0, FirstSeq=0;
int   Min, Max, Auto1Flag, Auto2Flag;
int   LastPkLost=-2, PkLostRuns[1000], PkLostCnt=0;
int   RttMin=100000000, RttMax=0, RttSum=0, RttCnt=0, RttLast=0, RttMaxTime=0;
int   RttHisto[125], RttHistoFlag=0;
long   WinScale=0, LastPred=-1; /* VENKAT */
char  PageName[50], *RttHistoFile=NULL;
char  *Note=NULL;
FILE  *Fout, *Fcom;

float PrintHeader(), PlotVegas(), PlotRate(), PlotWin(), PlotBuf();
float PlotLoss(), PlotRtt(), PlotDeltaRtt(), PlotACDeltaRtt();
float PlotDirDeltaRtt(), PlotSeq();

char  *PlotTypeArray[] = {"rate", "vegas", "win", "buf", "loss",
			  "rtt", "drtt", "acdrtt", "ddrtt", "seq", NULL};
float (*PlotFunArray[])() = {PlotRate, PlotVegas, PlotWin, PlotBuf, PlotLoss,
			     PlotRtt, PlotDeltaRtt, PlotACDeltaRtt,
			     PlotDirDeltaRtt, PlotSeq};
int   timer2event[] = {E_TO_REXMT, E_TO_PERSIST, E_TO_KEEP, E_TO_2MSL};

int   fix_time_flag = 1;

char  Sbuf[4000], *OpenType="w", *OutFilename="trace.ps";
int   Slen, Ntics=0;
int   Xtime=5000, Xtics=500;
int   Xbeg=0, Xend=1000000;
int   PutHeaderFlag=0, PutShowPageFlag=0, ScaleFlag=0, JournalFlag=0;
int   ShowEvents=1;
int   NumPlotTypes=1, NumGraphs=0;

#ifndef xFree
void xFree(a) char *a; {}
#endif

void xAssertPrint(s, n) char *s; int n; {}

unsigned long getTime(char *cp, int defs)
{
  unsigned long d=0, dc=1, t, s=defs;

  sscanf(cp, "%ld", &t);
  while(isdigit(*cp))
    cp++;
  if (*cp == '.')
    while (isdigit(*cp))
      d = d*10 + (*cp++ - '0'), dc *= 10;
  if (*cp == 'm' && *(cp+1) != 'i')
    s = 1000;
  else if (*cp == 'u')
    s = 1;
  else if (*cp == 's')
    s = 1000000;
  else if (*cp == 'm'  &&  *(cp+1) == 'i')
    s = 60000000;
  t = t*s + d*s/dc;
  return t;
}

/*-------------------------  main  -------------------------
*/
main (argc, argv)
  int  argc;
  char *argv[];
{
  static char  *plotTypes[10], *cp;
  int   i, j, k, n, ns, kinc, inc, osCnt=0;
  float x, y, z;
  FILE  *fin, *fout;

  printf("Running ptcp\n");

  /* --- process arguments */
  k = 1;
  if (!strcmp(argv[k], "-h")) {
    printf("USAGE: pttt [-h] [<trace-file>]\n");
    exit(0);
  }

  for (j=0,k=1; k<argc-1; k++) {
    if (!strcmp(argv[k], "-t"))
      fix_time_flag = 0;
    else if (!strcmp(argv[k], "-pn"))
      PageFlag = 1;
    else if (!strncmp(argv[k], "-db=", 4)) {
      DbFlag = 1;
      DbFile = argv[k]+4;
    }
    else if (!strncmp(argv[k], "-sid=", 5)) {
      sscanf(argv[k]+5, "%d", &SidUse);
      SidsUse[SidUse] = 1;
    }
    else if (!strncmp(argv[k], "-xtime=", 7))
      Xtime = getTime(argv[k]+7, 1000)/1000;
      /* sscanf(argv[k]+7, "%d", &Xtime); */
    else if (!strncmp(argv[k], "-xbeg=", 6))
      Xbeg = getTime(argv[k]+6, 1000)/1000;
    else if (!strncmp(argv[k], "-xend=", 6))
      Xend = getTime(argv[k]+6, 1000)/1000;
    else if (!strncmp(argv[k], "-maxTime=", 9))
      Xend = getTime(argv[k]+9, 1000)/1000;
    else if (!strcmp(argv[k], "-journal")) {
      JournalFlag = 1;
      Axpos = 0.6;
      Axlen = 8.0;
    }
    else if (!strcmp(argv[k], "-noEvents"))
      ShowEvents = 0;
    else if (!strncmp(argv[k], "-journal=", 9)) {
      JournalFlag = 1;
      Axpos = 0.6;
      Axlen = 8.0;
      sscanf(argv[k]+9, "%d", &NumGraphs);
    }
    else if (!strncmp(argv[k], "-xtics=", 7))
      Xtics = getTime(argv[k]+7, 1000)/1000;
      /* sscanf(argv[k]+7, "%d", &Xtics); */
    else if (!strcmp(argv[k], "-header"))
      PutHeaderFlag = 1;
    else if (!strcmp(argv[k], "-scale"))
      ScaleFlag = 1;
    else if (!strcmp(argv[k], "-allplot"))
      PutHeaderFlag = PutShowPageFlag = 1;
    else if (!strcmp(argv[k], "-n"))
      Note = argv[++k];
    else if (!strcmp(argv[k], "-a"))
      OpenType = "a";
    else if (!strcmp(argv[k], "-o"))
      OutFilename = argv[++k];
    else if (!strcmp(argv[k], "-tail"))
      PutShowPageFlag = 1;
    else if (!strcmp(argv[k], "-big")) {
      BigFlag = 1;
      Axpos = 0.7;
      Axlen = 3.2;
      Aylen = 1.5;
    }
    else if (!strncmp(argv[k], "-arn=", 5)) {
      sscanf(argv[k]+5, "%d", &Lraten);
    }
    else if (!strncmp(argv[k], "-arn2=", 6)) {
      sscanf(argv[k]+6, "%d", &Lrate2n);
    }
    else if (!strncmp(argv[k], "-arn3=", 6)) {
      sscanf(argv[k]+6, "%f", &Lrate3n);
    }
    else if (!strcmp(argv[k], "-rh")) {
      RttHistoFlag = 1;
      RttHistoFile = argv[++k];
    }
    else if (!strncmp(argv[k], "-maxRate=", 9)) {
      sscanf(argv[k]+9, "%d", &FixMaxRate);
      FixMaxRateFlag = 1;
    }
    else if (!strncmp(argv[k], "-rateTic=", 9)) {
      sscanf(argv[k]+9, "%d", &FixRateTic);
      FixRateTicFlag = 1;
    }
    else if (!strncmp(argv[k], "-maxWin=", 8)) {
      sscanf(argv[k]+8, "%d", &FixMaxWin);
      FixMaxWinFlag = 1;
    }
    else if (!strncmp(argv[k], "-winTic=", 8)) {
      sscanf(argv[k]+8, "%d", &FixWinTic);
      FixWinTicFlag = 1;
    }
    else if (*argv[k] != '-')
      plotTypes[j++] = argv[k];
    else if (!strcmp(argv[k], "-auto1")) {
      PageFlag = 1;
      Auto1Flag = 1;
    }
    else if (!strcmp(argv[k], "-auto2")) {
      PageFlag = 1;
      Auto2Flag = 1;
      if ((fin=fopen("trace.page", "r")) != NULL) {
	cp = buf;
	while ((i=fgetc(fin)) != EOF)
	  *cp++ = (char) i;
	*cp = '\0';
	sscanf(buf, "%d", &PageCnt);
	fclose(fin);
      }
    }
  }
  if (j == 0) 
    plotTypes[0] = "win";
  else
    NumPlotTypes = j;
  if (JournalFlag) {
    if (NumGraphs == 0)
      Y0 = NumPlotTypes*2.1;
    else
      Y0 = NumGraphs*2.1;
  }

/*   if ((Fcom = fopen(argv[k], "r")) == NULL) { */
/*     fprintf(stderr,"ERROR: Could not open command file %s\n", argv[k]); */
/*     exit(1); */
/*   } */
/*   k++; */

  Filename = argv[argc-1];

  if (strcmp(Filename, "-")) {
    for (k=strlen(Filename)-1; k>=0 && Filename[k]!='/'; k--)
      ;
    k++;
    if (k >= 3) 
      strcpy(DataName, &Filename[k-3]);
    else 
      strcpy(DataName, &Filename[k]);
    strcpy(RemoteName, &Filename[k+3]);
  }
  else
    k = 0;

  if (k == 0)
    strcpy(Path, "./");
  else
    strncpy(Path, Filename, k);

  if (strcmp(Filename, "-")) {
    for (k=strlen(Filename)-4; k>=0 && Filename[k]!='.'; k--)
      ;
    k++, cp = PageName;
    while (Filename[k] != '.'  &&  Filename[k] != '\0')
      *cp++ = Filename[k++];
    *cp = '\0';
  }
  else
    strcpy(PageName, "stdin");

  if (BigFlag) {
    X0 = 0.7;
    Y0 = 5.2;
  }
  x = X0, y = Y0;
  if (Auto2Flag)
    Fout = fopen(OutFilename, "a");
  else if (PutHeaderFlag)
    InitPsFile();
  else
    Fout = fopen(OutFilename, OpenType);

  /* --- Read trace data */
  ReadTraceData();

  /* --- Process all of the trace events */
  ProcessEvents();

/*  if (BigFlag) {
    X0 = 0.7;
    Y0 = 5.2;
  }
  x = X0, y = Y0;
  if (Auto2Flag) 
    Fout = fopen(OutFilename, "a");
  else if (PutHeaderFlag)
    InitPsFile();
  else
    Fout = fopen(OutFilename, OpenType);
*/
  if (PutHeaderFlag)
    BeginPage(x, y);

/*   PrintLostPackets(); */
  if (PutHeaderFlag)
    y = PrintHeader(x, y);
  else
    PrintHeader(x, -1.0);

  /* --- Do strips! */
  for (ns=1; ns<=NumStrips; ns++) {

    kinc = 1;
    strcpy(TimeArray, "[ ");
    if (BigFlag) {
      for (k=1; k<=Ntics; k++) {
	sprintf(TimeArray+strlen(TimeArray), "(%.1f) ", 
		Xbeg/1000.0 + (ns-1)*Xtime/1000.0 + k*Xtics/1000.0);
      }
    }
    else {
      for (k=1; k<=Ntics; k++) {
	sprintf(TimeArray+strlen(TimeArray), "(%.1f) ", 
		Xbeg/1000.0 + (ns-1)*Xtime/1000.0 + k*Xtics/1000.0);
      }
    }
    strcat(TimeArray, "]");
    if (BigFlag) {
      Strip_beg_time = Xbeg + (ns - 1)*Xtime/2;
      Strip_end_time = Strip_beg_time + Xtime/2;
      fprintf(Fout, "/xfix { %d sub %d div } def\n", Strip_beg_time, Xtics);
    }
    else {
      Strip_beg_time = Xbeg + (ns - 1)*Xtime;
      Strip_end_time = Strip_beg_time + Xtime;
      fprintf(Fout, "/xfix { %d sub %d div } def\n", Strip_beg_time, Xtics);
    }
      
    if (Strip_beg_time + 1000 > Xend)
      break;
    for (j=0; j<NumPlotTypes; j++) {
      fprintf(Fout, "%%\n%% y = %0.2f\n%%\n", y);
      for (k=0; PlotTypeArray[k]!=NULL; k++)
	if (!strcmp(plotTypes[j], PlotTypeArray[k])) {
	  if (BigFlag && ((++osCnt)%2 == 0))
	    y = PlotFunArray[k](y, 0.7, 0);
	  else
	    y = PlotFunArray[k](y, 0.3, 0);
	}
      y -= 0.25;

      /* --- Show lost groups */
      if (!JournalFlag && ShowEvents) {
        fprintf(Fout, "%%\n%% Begin Loss Groups\n%%\n");
        for (k=0; k<LostGroupsN; k++) {
	  LostGroups[k][1] = Max+(Max-Min)*0.15;
	  if (k%2 == 1) {
	    PlotFunEr(0, 2, &LostGroups[k-1][0], 4, "%d %d\n",
		      "3 0.8 plotStraightLines\n", 1);
	  }
        }
      }

      /* --- Packets acking more */
      if (ShowEvents && AckN > 0) PlotEvent(E_ACK, 7, Min*1.0, "Black");
      /* --- Packets acking old */
      if (ShowEvents && OackN > 0) PlotEvent(E_OACK, 9, Min*1.0, "Black");
      /* --- Packets with PUSH bit set Events */
      if (ShowEvents && PushfN > 0) PlotEvent(E_PUSHF, 10, 1.0*Min, "Black");
      /* --- Packets with URG bit set */
      if (ShowEvents && UrgN > 0 && !JournalFlag)
	PlotEvent(E_URG, 10, 1.0*Min, "Black");
      /* --- Packets with RST bit set */
      if (ShowEvents && RstN > 0 && !JournalFlag)
	PlotEvent(E_RST, 11, 1.0*Min, "Black");
      /* --- Packets with SYN bit set */
      if (ShowEvents && SynN > 0 && !JournalFlag)
	PlotEvent(E_SYN, 11, 1.0*Min, "Black");
      /* --- Packets with FIN bit set */
      if (ShowEvents && FinN > 0 && !JournalFlag)
	PlotEvent(E_FIN, 11, 1.0*Min, "Black");
      /* --- Packets with data */
      if (ShowEvents && RcvN > 0) PlotEvent(E_RCV, 8, 1.0*Min, "Black");
      /* --- Kbyte Numbers */
      sprintf(str, "0 %f 6 plotNum\n", Min+(Max-Min)*0.03);
      if (PrcvN > 0 && !JournalFlag)
	PlotFun(0, PrcvN, Prcv, 100, "%d %d\n", str, 0);
      
      /* --- Send Events */
      if (ShowEvents && SndN > 0) PlotEvent(E_SND, 7, Max*1.0, "Black");
      /* --- Spike suppression events */
      if (ShowEvents && SpikesupN > 0 && !JournalFlag)
	PlotEvent(E_SPIKESUP, 13, Max*1.0, "Black");
      /* --- Push Block Events */
/*    if (ShowEvents && BlockN > 0 && !JournalFlag)
	PlotEvent(E_BLOCK, 12, Max*1.0, "Black"); */
      /* --- Push Awake Events */
/*    if (ShowEvents && AwakeN > 0 && !JournalFlag)
	PlotEvent(E_AWAKE, 13, Max*1.0, "Black"); */
      /* --- Packet Numbers */
      sprintf(str, "0 %f 6 plotNum\n", Max+(Max-Min)*0.03);
      if (PsntN > 0) PlotFun(0, PsntN, Psnt, 100, "%d %d\n", str, 0);
      
      /* --- Timeout REXMT Events */
      if (RexmtN > 0) PlotEvent(E_TO_REXMT, 4, Max+(Max-Min)*0.15, "Timeout");
      /* --- Timeout PERSIST Events */
      if (ShowEvents && PersistN > 0 && !JournalFlag)
	PlotEvent(E_TO_PERSIST, 1, Max+(Max-Min)*0.15, "Black");
      /* --- Timeout KEEP Events */
      if (ShowEvents && KeepN > 0 && !JournalFlag)
	PlotEvent(E_TO_KEEP, 2, Max+(Max-Min)*0.15, "Black");
      /* --- Timeout 2MSL Events */
      if (ShowEvents && MslN > 0 && !JournalFlag)
	PlotEvent(E_TO_2MSL, 3, Max+(Max-Min)*0.15, "Black");
      /* --- Reduce exp increase of timeout */
      if (ShowEvents && RtoN > 0 && !JournalFlag)
	PlotEvent(E_RTO, 6, Max+(Max-Min)*0.15, "Black");
      /* --- Fast timer Events */
      if (FtoN > 0 && !JournalFlag)
        PlotEvent(E_FTO, 3, Max+(Max-Min)*0.10, "Black");
      /* --- Slow timer Events */
      if (StoN > 0) PlotEvent(E_STO, 6, Max+(Max-Min)*0.10, "Black");
      /* --- Worry resend packet Events */
      if (ShowEvents && WsN > 0 && !JournalFlag)
	PlotEvent(E_WS, 2, Max+(Max-Min)*0.10, "Black");
      /* --- Reduce cong window Events */
      if (ShowEvents && RcwndN > 0 && !JournalFlag)
	PlotEvent(E_RCWND, 0, Max+(Max-Min)*0.10, "Black");
      /* --- Bad checksum Events */
      if (ShowEvents && BadsumN > 0 && !JournalFlag)
	PlotEvent(E_BADSUM, 5, Max+(Max-Min)*0.10, "Black");
      /* --- Interval times (used for cong control */
      if (!strcmp(plotTypes[j], "vegas") && InterN > 0) {
/*      PlotEvent(E_INTER0, 7, Min+(Max-Min)*0.4, "Black"); */
        PlotEvent(E_INTER0, 7, Max-(Max-Min)*0.4, "Black");
/*      PlotEvent(E_INTER1, 0, Min+(Max-Min)*0.4, "Black"); */
        PlotEvent(E_INTER1, 7, Max-(Max-Min)*0.4, "Black");
      }      
    }
  }

  if (PutShowPageFlag)
    EndPage();
  if (Fout != NULL &&  PutShowPageFlag)
    fprintf(Fout, "end\n");
  fclose(Fout);
  if (Auto1Flag || Auto2Flag) {
    if ((fout = fopen("trace.page", "w")) != NULL) {
      fprintf(fout, "%d\n", PageCnt);
      fclose(fout);
    }
  }

} /* End of main  .............................................*/


GetMaxMin (array, inc, count, amin, amax)

  int *array, inc, count, *amin, *amax;
{
  int min, max, k, *ip;

  ip = array;
  min = max = *ip;
  for (k=0; k<count; k++) {
    if (*ip < min)
      min = *ip;
    if (*ip > max)
      max = *ip;
    ip += inc;
  }
  *amin = min;
  *amax = max;
}

SetGraph (ydec, aymin, aymax, rnd, ytic, inc, mtics, xtit, ytit, fixstr, fixv)
  
  float ydec;
  int   *aymin, *aymax, rnd, ytic, inc, mtics, fixv;
  char  *xtit, *ytit, *fixstr;
{
  char str[100];
  int i, j, k, ymin, ymax;

  ymin = *aymin, ymax = *aymax;
  if (ydec != 0.0)
    fprintf(Fout, "yy %f sub dup /aypos exch def .25 sub /yy exch def \n", 
	    ydec);
  fprintf(Fout, "%s\n", TimeArray);
  if (abs(ymin)%rnd != 0) {
    if (ymin > 0)
      ymin = ymin + (rnd - ymin%rnd);
    else
      ymin = -(abs(ymin) + (rnd - abs(ymin)%rnd));
  }
  if (abs(ymax)%rnd != 0) {
    if (ymax > 0)
      ymax = ymax + (rnd - ymax%rnd);
    else
      ymax = -(abs(ymax) + (rnd - abs(ymax)%rnd));
  }
  i = ytic;
  while ((ymax-ymin)/i > mtics)
    i += inc;
  if (ymax%i != 0)
    ymax = ymax + (i - ymax%i);
  for(k=ymax; k>ymin; k-=i)
    ;
  ymin = k;
  *aymin = ymin, *aymax = ymax;

  fprintf(Fout, "1 setlinewidth\n");
  strcpy(array, "[ ");
  for (k=ymin+i; k<=ymax; k+=i)
    sprintf(array+strlen(array), "(%d) ", k);
  strcat(array, "]");
  fprintf(Fout, "%s\n", array);
  fprintf(Fout, "(%s)\n(%s)\naxes\n1\n1\ngrid\n", xtit, ytit);
  if (ymin == 0)
    sprintf(str, "/yfix { %s %d div } def\n", fixstr, i);
  else
    sprintf(str, "/yfix { %d sub %s %d div } def\n", ymin, fixstr, i);

  fprintf(Fout, str, fixv);
  return i;
}


PlotFun(kbeg, kend, array, narray, dformat, pformat, inter)

  int  kbeg, kend, *array, narray, inter;
  char *dformat, *pformat;
{
  int   k, c=0, y, x0, y0, y1, ftime=1, xv, yv;

  fprintf(Fout, "beginFunction\n");
  for (k=kbeg; k<kend; k++) {
    xv = *(array + k*2);
    if (ftime  &&  xv >= Strip_beg_time) {
      ftime = 0;
      if (inter  &&  k > 0) {
	x0 = *(array + (k-1)*2);
	y0 = *(array + (k-1)*2 + 1);
	y1 = *(array + k*2 + 1);
	y = y0 + (Strip_beg_time-x0)*(y1-y0)/(xv-x0);
	fprintf(Fout, dformat, Strip_beg_time, y);
      }
    }
    if (xv > Strip_end_time) {
      if (inter  &&  k > kbeg  &&  (x0=*(array + (k-1)*2)) < Strip_end_time) {
	y0 = *(array + (k-1)*2 + 1);
	y1 = *(array + k*2 + 1);
	y = y0 + (Strip_end_time-x0)*(y1-y0)/(xv-x0);
	fprintf(Fout, dformat, Strip_end_time, y);
      }
      break;
    }
    if (xv >= Strip_beg_time) {
      yv = *(array + k*2 + 1);
      fprintf(Fout, dformat, xv, yv);
      c++;
      if (c%1200 == 0) {
	fprintf(Fout, "endFunction\n");
        fprintf(Fout, pformat);
        fprintf(Fout, "beginFunction\n");
      }
      else if (c%200 == 0)
        fprintf(Fout, "endFunctionInter\n");
    }
  }
  fprintf(Fout, "endFunction\n");
  fprintf(Fout, pformat);
  return 0;
}

PlotFunEr(kbeg, kend, array, narray, dformat, pformat, inter)
int  kbeg, kend, *array, narray, inter;
char *dformat, *pformat;
{
  PlotFunErDo(kbeg, kend, array, narray, dformat, pformat, inter, "");
  return 0;
}

PlotFunErSwap(kbeg, kend, array, narray, dformat, pformat, inter)
int  kbeg, kend, *array, narray, inter;
char *dformat, *pformat;
{
  PlotFunErDo(kbeg, kend, array, narray, dformat, pformat, inter, "Swap");
  return 0;
}

PlotFunErDo(kbeg, kend, array, narray, dformat, pformat, inter, str)
int  kbeg, kend, *array, narray, inter;
char *dformat, *pformat, *str;
{
  int   k, c=0, y, x0, y0, y1, ftime=1, xv, xv0, xv1, yv, yv0=-3, yv1=-1;

  fprintf(Fout, "begin%sFunction\n", str);
  for (k=kbeg; k<kend; k++) {
    xv = *(array + k*2);
    if (ftime  &&  xv >= Strip_beg_time) {
      ftime = 0;
      if (inter  &&  (kbeg == 0  ||  k > kbeg)) {
	if (k > 0) {
	  x0 = *(array + (k-1)*2);
	  y0 = *(array + (k-1)*2 + 1);
	  y1 = *(array + k*2 + 1);
	  y = y0 + (Strip_beg_time-x0)*(y1-y0)/(xv-x0);
	  fprintf(Fout, dformat, Strip_beg_time, y);
	  xv0 = xv1 = Strip_beg_time;
	  yv0 = yv1 = y;
	}
	else {
	  xv0 = xv1 = xv, yv0 = yv1 = *(array + k*2 + 1);
	  fprintf(Fout, dformat, xv0, yv0);
	}
      }
      else {
	xv0 = xv1 = xv, yv0 = yv1 = *(array + k*2 + 1);
	fprintf(Fout, dformat, xv0, yv0);
      }
    }
    if (xv > Strip_end_time) {
      fprintf(Fout, dformat, xv1, yv1);
      if (inter  &&  k > kbeg  &&  (x0=*(array + (k-1)*2)) < Strip_end_time) {
	y0 = *(array + (k-1)*2 + 1);
	y1 = *(array + k*2 + 1);
	y = y0 + (Strip_end_time-x0)*(y1-y0)/(xv-x0);
	fprintf(Fout, dformat, Strip_end_time, y);
	xv1 = Strip_end_time, yv1 = y;
      }
      break;
    }
    if (xv >= Strip_beg_time) {
      if ((yv = *(array + k*2 + 1)) == yv1  &&  yv0 == yv1) 
	xv1 = xv, yv1 = yv;
      else {
	fprintf(Fout, dformat, xv1, yv1);
	yv0 = yv1;
	xv1 = xv, yv1 = yv;
	c++;
        if (c%1200 == 0) {
          fprintf(Fout, "end%sFunction\n", str);
          fprintf(Fout, pformat);
          fprintf(Fout, "begin%sFunction\n", str);
        }
        else if (c%300 == 0)
          fprintf(Fout, "endFunctionInter\n");
      }
    }
  }
  fprintf(Fout, dformat, xv1, yv1);
  fprintf(Fout, "end%sFunction\n", str);
  fprintf(Fout, pformat);
  return 0;
}

PlotEvent(event, symbol, yval, color)
int   event, symbol;
float yval;
char  *color;
{
  char str[30];
  int  i=0, k, t;

  if (yval ==  ((int) yval)) 
    sprintf(str, "%d", (int)yval);
  else {
    sprintf(str, "%f", yval);
    k = strlen(str) - 1;
    while (str[k] == '0')
      k--;
    str[k+1] = '\0';
  }

  fprintf(Fout, "beginFunction\n");
  for (k=0; k<EventN; k++) {
    if ((t=EventA[k][0]) > Strip_end_time)
      continue;
    if (t >= Strip_beg_time) {
      if (EventA[k][1] & event) {
	fprintf(Fout, "%d %s\n", EventA[k][0], str);
	if (++i%1200 == 0) {
	  fprintf(Fout, "endFunction\n");
          fprintf(Fout, "%d %s plotSymbolsC\n", symbol, color);
          fprintf(Fout, "beginFunction\n");
        }
        else if (i%200 == 0)
          fprintf(Fout, "endFunctionInter\n");
      }
    }
  }
  fprintf(Fout, "endFunction\n");
  if (i > 0)
    fprintf(Fout, "%d %s plotSymbolsC\n", symbol, color);
}

PlotBars(array, kend)

  int   *array, kend;
{
  int  i=0, k, t;

  fprintf(Fout, "beginFunction\n");
  for (k=0; k<kend; k++) {
    if ((t=array[k]) > Strip_end_time)
      break;
    if (t >= Strip_beg_time) {
      fprintf(Fout, "%d 0\n", array[k]);
      if (++i%1200 == 0) {
	fprintf(Fout, "endFunction\n");
        fprintf(Fout, "VerticalBars plotVBarsC\n");
        fprintf(Fout, "beginFunction\n");
      }
      else if (i%200 == 0)
        fprintf(Fout, "endFunctionInter\n");
    }
  }
  fprintf(Fout, "endFunction\n");
  if (i > 0)
    fprintf(Fout, "VerticalBars plotVBarsC\n");
}


/*-------------------------  PrintLostPackets  -------------------------
*/
PrintLostPackets ()

{
  int        i, j, k;
  static int beg_lost=0, num_lost_printed=0;

  fprintf(Fout, "%%\n%%   Lost Packets\n%%\n");
  /* --- Print packets lost */
  if (LostCnt-num_lost_printed > 0) {
    if (LostCnt-num_lost_printed > 80) 
      i = 80;
    else
      i = LostCnt-num_lost_printed;
    fprintf(Fout, "/y 10.2 in def\n/x axpos axlen add in 10 add def\n");
    fprintf(Fout, "/ye y %d sub 4 sub def\n", (i+1)*8);
    fprintf(Fout, "8 HBfont\n");
    fprintf(Fout, "1 setlinewidth x 2 sub y 10 add moveto\n");
    fprintf(Fout, "(Packets Lost) stringwidth pop 2 add x add dup\n");
    fprintf(Fout, "y 10 add lineto\n");
    fprintf(Fout, "ye lineto x 2 sub ye lineto\n");
    fprintf(Fout, "closepath stroke\n");
    fprintf(Fout, "(Packets Lost) showit\n");
    fprintf(Fout, "8 Cfont ( pn  NPIT) showit \n");
    for (k=beg_lost,j=0; k<NumPacketsSent; k++) {
      if (SndTraces[k].time_rcvd_ack <= 0) {
	fprintf(Fout, "(%4d  %2d) showit\n", k, Prate[k]);
	if (++j == i) 
	  break;
      }
    }
    num_lost_printed += i;
    beg_lost = k + 1;
  }
  
} /* End of PrintLostPackets  .............................................*/


/*-------------------------  InitPsFile  -------------------------
*/
InitPsFile ()
{
  char *cp, com[500], *getenv(), buf[4096], *dirs[10];
  int j, k=0, n, ng=NumPlotTypes, dirsN=0;
  FILE *fin;

  if ((cp = getenv("GRAPH_PS")) != NULL)
    dirs[dirsN++] = cp;
  if ((cp = getenv("XNETSIM_UTIL_DIR")) != NULL)
    dirs[dirsN++] = cp;
  if ((cp = getenv("XNETSIM_DIR")) != NULL)
    dirs[dirsN++] = cp;
  dirs[dirsN++] = ".";
  dirs[dirsN++] = PSDIR;
  dirs[dirsN++] = CSX33DIR;

  for (j=0; j<dirsN; j++) {
    sprintf(com, "%s/graph.ps", dirs[j]);
    if ((fin = fopen(com, "r")) != NULL )
      break;
  }
  if (fin == NULL ) {
    printf("ERROR: Could not open file: %s\n", "graph.ps");
    exit(1);
  }

  Fout = fopen(OutFilename, "w");
  if (Fout == NULL) {
    printf("ERROR: Could not open output file: %s\n", OutFilename);
    exit(2);
  }
  if (JournalFlag) {
    n = fread(buf, 1, 4096, fin);
    for (cp=buf, k=j=0; k<n && j<3; k++,cp++) {
      if (*cp == '\n')
        j++;
    }
    if (NumGraphs > 0)
      ng = NumGraphs;
    fwrite("%!PS-Adobe-2.0 EPSF-1.2\n", 1, 24, Fout);
    fwrite("%%DocumentFonts: Courier Helvetica Helvetica-Bold\n", 1, 50, Fout);
    sprintf(com, "%%%%BoundingBox: 0 0 %5d %5d\n", 550, ng*121);
    fwrite(com, 1, 31, Fout);
    fwrite(cp, 1, n-k, Fout);
  }
  while ((n=fread(buf, 1, 4096, fin)) > 0)
    fwrite(buf, 1, n, Fout);
  fclose(fin);
  fprintf(Fout, "%%\n%%   Initializations\n%%\n"); 
  if (JournalFlag)
    fprintf(Fout, ".85 .80 scale\n");
  fprintf(Fout, "/showit { x y moveto show y 8 sub /y exch def } def\n");
  fprintf(Fout, "/showit1 { x y moveto show } def\n");
  fprintf(Fout, "/showit2 { x 2.25 in add y moveto show } def\n");
  fprintf(Fout, 
	  "/showit3 { x 4.5 in add y moveto show y 8 sub /y exch def } def\n");
  fprintf(Fout, "/EndPage { showpage } def\n");
  fprintf(Fout, "/BeginPage { dup in 72 div dup /yy exch def /aypos0 exch def\n");
  fprintf(Fout, "  /y exch in def /x exch in def\n");
  fprintf(Fout, "  /aypos aypos0 def /yy aypos0 def } def\n");
  fprintf(Fout, "/checkEOP { yy exch sub .3 lt \n");
  fprintf(Fout, "  { EndPage %.3f %.3f BeginPage } if } def\n", X0, Y0);

  /* --- Init graphs */
  fprintf(Fout, "/axpos %f def\n", Axpos);
  fprintf(Fout, "/axlen %f def\n", Axlen);
  fprintf(Fout, "/aylen %f def\n", Aylen);


} /* End of InitPsFile  .............................................*/


/*-------------------------  BeginPage  -------------------------
*/
BeginPage (x, y)

float x, y;
{

  fprintf(Fout, "%%\n%%   Begin Page\n%%\n");
  if (ScaleFlag)
    fprintf(Fout, "1 .8 scale  0 2.3 in translate\n");
  if (PageFlag)
    fprintf(Fout, "%%%%Page: %s %d\n", PageName, PageCnt);

  if (BigFlag) {
    fprintf(Fout, "1.75 1.75 scale\n");
    fprintf(Fout, "%f in 72 div dup /yy exch def /aypos0 exch def\n", 
	    y);
    fprintf(Fout, "8 Cfont /x %f in def /y %f in def\n", x, y);
    fprintf(Fout, "/aypos aypos0 def /yy aypos0 def\n");
    fprintf(Fout, "8 HBfont ");
    if (Note != NULL)
      fprintf(Fout, ".3 in 5.8 in moveto (%s) show\n", Note);
    fprintf(Fout, "(%s) dup stringwidth pop 4.3 in exch sub \n", DataName);
    fprintf(Fout, "  5.8 in moveto show\n");
    fprintf(Fout, "6 HBfont (  %d) show\n", PageCnt++);
  }
  else {
    fprintf(Fout, "%f in 72 div dup /yy exch def /aypos0 exch def\n", 
	    y);
    fprintf(Fout, "8 Cfont /x %f in def /y %f in def\n", x, y);
    fprintf(Fout, "/aypos aypos0 def /yy aypos0 def\n");
    if (!JournalFlag) {
      fprintf(Fout, "12 HBfont ");
      if (Note != NULL)
        fprintf(Fout, "35 758 moveto (%s) show\n", Note);
      fprintf(Fout, "(%s) dup stringwidth pop 575 exch sub 758 moveto show\n", 
	      DataName);
      fprintf(Fout, "10 HBfont (  %d) show\n", PageCnt++);
    }
  }
  fprintf(Fout, "%%   End of Begin Page\n");

} /* End of BeginPage  .............................................*/


/*-------------------------  EndPage  -------------------------
*/
EndPage ()
{
  fprintf(Fout, "showpage\n");

} /* End of EndPage  .............................................*/


/*-------------------------  PrintHeader  -------------------------
*/
float PrintHeader (x, y)

float x, y;
{
  char fname[200], line[200], str[100], *cp, *pt="ttcp", *cpt;
  int  id, i, j, k, lk;
  int smin, smax, rmin, rmax;
  int savg=0, ravg=0; 
  int  numPack=0, numKBdup=0, numBadsum=0, numDrop=0;
  int  numRxmt=0, numPersist=0, numKeep=0, num2msl=0, numKB=0;
  int  ntpl=-1, tplc=0, tpl[500], version=0;
  long trkb=985; /* VENKAT */
  int  numDiff=0, numDup=0, numOOO=0, numBytes=0;
  int  bufsize=50, rttCnt=0;
  FILE *fin=NULL, *fout;

  if (BigFlag)
    return y;

  trkb = Total_bytes_sent/1024.0;
  for (cp=Filename+strlen(Filename)-4; *cp!='.' &&  cp>=Filename; cp--)
    ;
  cp++;
  if (!strncmp(cp, "ttcp.", 5))
    pt = "ttcp", version=0;
  else if (!strncmp(cp, "rtcp.", 5))
    pt = "rtcp", version=1;
  else if (!strncmp(cp, "rtcp4.", 6))
    pt = "rtcp4", version=4;
  else if (!strncmp(cp, "vtcp1.", 6))
    pt = "vtcp", version=1;
  else if (!strncmp(cp, "vtcp5.", 6))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "vtcp2.", 6))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "vtcp7.", 6))
    pt = "vtcp", version=7;
  else if (!strncmp(cp, "mvtcp.", 6))
    pt = "mvtcp", version=7;
  else if (!strncmp(cp, "vtcp.", 5))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "artcp.", 6))
    pt = "artcp", version=2;
  else if (!strncmp(cp, "avtcp.", 6))
    pt = "avtcp", version=105;
  else if (!strncmp(cp, "vtcp10.", 7))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "vtcp20.", 7))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "vtcp40.", 7))
    pt = "vtcp", version=5;
  else if (!strncmp(cp, "rtcp5.", 6))
    pt = "rtcp", version=1;
  else if (!strncmp(cp, "rtcp2.", 6))
    pt = "rtcp", version=1;
  else if (!strncmp(cp, "rtcp10.", 7))
    pt = "rtcp", version=1;
  else if (!strncmp(cp, "rtcp20.", 7))
    pt = "rtcp", version=1;
  else if (!strncmp(cp, "rtcp40.", 7))
    pt = "rtcp", version=1;

  for (cp=Filename+strlen(Filename)-2; *cp!='.' &&  cp>=Filename; cp--)
    ;
  cp++;
  printf("id_string: %s\n", cp); 
  if (sscanf(cp, "%d", &id) == 1) {
    printf("id: %d\n", id); 
    strcpy(fname, Path);
    strncat(fname, RemoteName, 12);
    strcat(fname, "+NIH");
    printf("NIH file: %s\n", fname);    
    if ((fin=fopen(fname, "r")) == NULL) {
      strcpy(fname + strlen(fname)-4, "+COL"); 
      printf("COL file: %s\n", fname);
      fin = fopen(fname, "r");
    }
    if (fin == NULL) 
      printf("*** Could not access server data\n");
    else {
      for (k=0; k<=id; k++) {
	while (GetLine(fin, line) != EOF  &&  
	       strncmp(line, "*** I am the server", 19))
	  ;
      }
      while (GetLine(fin, line) != EOF  &&  
	     strncmp(line, "*** I am the server", 19)) {
	if (!strncmp(line, "*** buffer size: ", 17)) 
	  sscanf(line+17, "%d", &bufsize);
	else if (!strncmp(line, "NTPL ", 5))
	  sscanf(line+5, "%d", &ntpl);
	else if (!strncmp(line, "TPL ", 4))
	  sscanf(line+4, "%d", &tpl[tplc++]);
	else if (!strncmp(line, "DISP ", 5))
	  sscanf(line+5, "%d", &numDiff);
	else if (!strncmp(line, "DUPP ", 5))
	  sscanf(line+5, "%d", &numDup);
	else if (!strncmp(line, "POOO ", 5))
	  sscanf(line+5, "%d", &numOOO);
	else if (!strncmp(line, "UKB ", 4))
	  sscanf(line+4, "%d", &numBytes);
	else if (!strncmp(line, "TRKB ", 5))
	  sscanf(line+4, "%d", &trkb);
      }
    }
    printf("+ Number of test packets lost: %4d\n", ntpl);
    printf("  Distinct  packets received:  %4d\n", numDiff);
    printf("  Duplicate packets received:  %4d\n", numDup);
    printf("  KB on non-duplicate packets: %4d\n", numBytes);
    printf("  Unique KB rcvd by test ulp:  %4d\n", trkb);
  }

  fprintf(Fout, "%%\n%%   Header\n%%\n");
  INIT_COMP(smin,smax,savg);
  INIT_COMP(rmin,rmax,ravg);
  printf("***********************\n");
  for (k=1; k<NumPacketsSent; k++) {
/*    printf("%d: time %d\n ",k-1,SndTraces[k-1].time);*/
    if (SndTraces[k].time_rcvd_ack > 0) {
      DO_COMP(SndTraces[k].time_rcvd_ack, SndTraces[k].time,
	      rmin, rmax, ravg);
      rttCnt++;
    }
/*    printf("%d: time %d\n ",k-1,SndTraces[k-1].time);*/
    DO_COMP(SndTraces[k].time,SndTraces[k-1].time,smin,smax,savg);
/*    printf("%ld: time: %ld time0:%ld smin: %d smax:%d savg:%lu\n",k,SndTraces[k].time,SndTraces[k-1].time,smin,smax,savg);*/
  }

  if (!JournalFlag) {
    if (y > 0.0)
      fprintf(Fout, "8 Cfont /x %f in def /y %f in def\n", x, y);
    else 
      fprintf(Fout, "8 Cfont /x %f in def /yy yy 0.25 sub def /y yy in def\n",
	      x);
    fprintf(Fout, "(Test Date: %s) showit\n", TimeArray);
  }
  if (Slen != 0) {
    cp = Sbuf;
    i = 0;
    while (*cp != '\0') {
      cpt = str;
      while (*cp != '\n'  &&  *cp != '\0')
	*cpt++ = *cp++;
      *cpt = '\0';
      if (*cp != '\0')
	cp++;
      if (!JournalFlag)
        fprintf(Fout, "(%s) showit\n", str);
      i++;
    }
    if (RexmtN > 0) {
      printf("avg timeout: %d\n", ToTimeSum/RexmtN);
      if (!JournalFlag) fprintf(Fout, "(avg timeout: %d) showit\n", ToTimeSum/RexmtN);
    }

    if (!JournalFlag) {
      fprintf(Fout, "(exp_nseg:%d, top_nseg:%d, bot_nseg:%d) showit\n", 
	      Vexp_nseg, Vtop_nseg, Vbot_nseg);
      fprintf(Fout, "(Flags: ");
      if (VegasFlags & 0x1)
        fprintf(Fout, "EXP_INC_SLOW ");
      if (VegasFlags & 0x2)
        fprintf(Fout, "SPIKE_PREV ");
      if (VegasFlags & 0x4)
        fprintf(Fout, "CONG_DETECT ");
      if (VegasFlags & 0x8)
        fprintf(Fout, "PREDICT ");
      if (VegasFlags & 0x100)
        fprintf(Fout, "INC_EVERY_OTHER ");
      fprintf(Fout, ") showit\n");
      i += 3;
      fprintf(Fout, "/yy yy %.3f sub def\n", i*8.0/72.0);
      y -= i*8.0/72.0; 
/*    fprintf(Fout, "/yy %.3f def\n", y); */
    }
    return y;
  }

  if (!JournalFlag) {
    printf("Total Bytes sent %d\n",Total_bytes_sent);
    fprintf(Fout, 
      "(Number of Kbytes sent: %5d (in %d packets, avg pkt size: %d)) showit\n",
	    Total_bytes_sent/1024, NumPacketsSent, 
	    Total_bytes_sent/NumPacketsSent);
    fprintf(Fout, 
            "(Number of bytes rcvd:  %5d) showit\n", 
	    Total_bytes_rcvd);
    fprintf(Fout, "(Time for test:         %4lds %dms) showit1\n", 
	    (LastAckTime-RateBegTime)/1000, (LastAckTime-RateBegTime)%1000);
    fprintf(Fout, "(Running avg size: %d, %d) showit3\n", Lraten, Lrate2n);
    fprintf(Fout, "currentpoint /yyc exch def /xxc exch def\n");
    fprintf(Fout, "(S KB/S:  %.1f   T KB/S: %.1f) showit1 \n", 
	   (Total_bytes_sent/1024.0)/((LastAckTime-RateBegTime)/1000.0),
	    (trkb)/((LastAckTime-RateBegTime)/1000.));
    fprintf(Fout, "(Packets resent by worry: %d) showit3\n", WsN);
    fprintf(Fout, "( ) showit\n");
    y -= 6.0*8.0/72.0;

    if (NumPacketsSent > 1) {
      /* venkat: commented out stuff here */
      fprintf(Fout, 
    "(Lost %d packets out of %d packets sent (%d%% lost, ~%d Kbytes)) showit\n",
	      LostCnt, NumPacketsSent, LostCnt*100/(NumPacketsSent-1),
	      LostBcnt/1024);
/*      fprintf(Fout, */
/*             "(Transmition delta times, Min: %4d, Max: %4d, Ave: %4lu) showit\n",*/
/*	      smin, smax, savg/(NumPacketsSent-1));*/
      if (RttCnt > 0)
	{
/*        fprintf(Fout, */
/* "(Round trip times,        Min: %4d, Max: %4d, Ave: %4lu  (%ld, %ldms)) showit\n",*/
/*	        RttMin, RttMax, RttSum/RttCnt, RttCnt, RttMaxTime);
 */
	}
      else if (rttCnt > 0) {
/*        fprintf(Fout, */
/*	    "(Round trip times,        Min: %4ld, Max: %4ld, Ave: %4ld) showit\n",*/
/*	        rmin, rmax, ravg/rttCnt);*/
      }
      fprintf(Fout, "(ON RECEIVER SIDE) showit3\n");
/*       fprintf(Fout, "( ) showit\n"); */
      y -= 4.0*8.0/72.0;
    }    

    fprintf(Fout, "(Packets w/bad cksum:        %4d) showit1\n", 
	    TcpStat.tcps_rcvbadsum);
    fprintf(Fout, "(Packets retransmited: %4d) showit2\n",
	    TcpStat.tcps_sndrexmitpack);
    fprintf(Fout, "(packets rcvd:      %4d) showit3\n", numPack);
    fprintf(Fout, "(Packets w/bad off or short: %4d) showit1\n",
	    TcpStat.tcps_rcvbadoff + TcpStat.tcps_rcvshort);
    fprintf(Fout, "(KB retransmitted:     %4d) showit2\n", 
	    TcpStat.tcps_sndrexmitbyte/1024);
    fprintf(Fout, "(dup packets rcvd:  %4d) showit3\n", numDup);
    fprintf(Fout, "(RXMT    timeout:            %4d) showit1\n", 
	    TcpStat.tcps_rexmttimeo);
    fprintf(Fout, "(Dup packets rcvd:     %4d) showit2\n", 
	    TcpStat.tcps_rcvduppack);
    fprintf(Fout, "(KB in dup packets: %4d) showit3\n", numKBdup);
    fprintf(Fout, "(PERSIST timeout:            %4d) showit1\n", 
	    TcpStat.tcps_persisttimeo);
    fprintf(Fout, "(Dup KB rcvd:          %4d) showit2\n", 
	    TcpStat.tcps_rcvdupbyte/1024);
    fprintf(Fout, "(Packets w/badsum:  %4d) showit3\n", numBadsum);
    fprintf(Fout, "(KEEP    timeout:            %4d) showit1\n", 
	    TcpStat.tcps_keeptimeo);
    fprintf(Fout, "(Out of order packets: %4d) showit2\n", 
	    TcpStat.tcps_rcvoopack);
    fprintf(Fout, "(Packets dropped:   %4d) showit3\n", numDrop);
    fprintf(Fout, "(                                ) showit1\n");
    fprintf(Fout, "(                          ) showit2\n");
/*  fprintf(Fout, "(RXMT:%-3d PERSIST:%-3d KEEP:%-3d 2MSL:%-3d) showit3\n",  */
/*          numRxmt, numPersist, numKeep, num2msl); */

/*   x = ((float) AvgNpit)/CntNpit; */
/*   fprintf(Fout, "8 Cfont\n"); */
/*   fprintf(Fout,  */
/* 	     "xxc yyc moveto ((%.1f ave NPIT, implies %.1f Kbs/PIT)) show\n", */
/* 	     x, ((float) Total_bytes_sent)/(LastAckTime)/x); */

    y -= 6.0*8.0/72.0;
    fprintf(Fout, "/yy %f def\n", y);
  }
  
  /* --- Rtt Histo info */
  if (RttHistoFlag  &&  RttHistoFile != NULL) {
    int n=0;
    strcpy(fname, "./"); /* VENKAT */
    strcat(fname, RttHistoFile);
    if ((fout=fopen(fname, "a")) == NULL) {
      printf("ERROR: Could not open rtt database file: %s\n", fname);
      return y;
    }
    cp = TimeArray;
    lk = 0;
    fprintf(fout, "\n%c%c%c  %c%c%c %c%c %c%c %c%c%c%c%c\n", cp[0], cp[1],
	    cp[2], cp[4], cp[5], cp[6], cp[8], cp[9], cp[22], cp[23],
	    cp[11], cp[12], cp[13], cp[14], cp[15]);
    for (k=0; k<100; k++) {
      n += RttHisto[k];
      if (RttHisto[k] == 0) {
	if (lk >= 0)
	  continue;
	else
	  lk = k;
      }
      else {
	if (lk >= 0) {
	  fprintf(fout, "%4d-%4d  %4d\n", lk*10, (k)*10, 0);
	  lk = -1;
	}
	fprintf(fout, "%4d-%4d  %4d\n", k*10, (k+1)*10, RttHisto[k]);
      }
    }
    fprintf(fout, "Count: %d\n", n);
    fclose(fout);
  }
    

  /* --- Enter data into database */
  if (!DbFlag)
    return y;
  strcpy(fname, "./");
  strcat(fname, DbFile);
  if ((fout=fopen(fname, "a")) == NULL) {
    printf("ERROR: Could not open database file: %s\n", fname);
    return y;
  }
  cp = TimeArray;
  fprintf(fout, "%%\n+++++\n%%\n");
  fprintf(fout, "Protocol: %s\n", pt);
  fprintf(fout, "Type: %d\n", version);
  fprintf(fout, "buf size: %d\n", bufsize);
  fprintf(fout, "Path: %c%c\n", DataName[0], DataName[1]);
  fprintf(fout, "Date: %c%c%c %c%c %c%c\n", cp[4], cp[5], cp[6],
	  cp[8], cp[9], cp[22], cp[23]);
  fprintf(fout, "Dow: %c%c%c\n", cp[0], cp[1], cp[2]);
  fprintf(fout, "Time: %c%c%c%c%c\n", cp[11], cp[12], cp[13], cp[14], cp[15]);
  fprintf(fout, "KB sent: %d\n", Total_bytes_sent/1024);
  fprintf(fout, "KB rcvd: %d\n", numKB);
  fprintf(fout, "T KB rcvd: %d\n", trkb);
  fprintf(fout, "KB lost: %d\n", Total_bytes_sent/1024-numKB);
  fprintf(fout, "%% lost: %.1f\n", 
	  100.*(Total_bytes_sent-numKB*1024.)/Total_bytes_sent);
  fprintf(fout, "pk sent: %d\n", NumPacketsSent);
  fprintf(fout, "pk rcvd: %d\n", numPack);
  /* --- TODO */
  fprintf(fout, "pk lost: %d\n", LostCnt);
/*   fprintf(fout, "ack lost: %d\n", LostCnt - (NumPacketsSent-numDiff)); */
/*   fprintf(fout, "lost runs: "); */
/*   j = 0; */
/*   for (k=1; k<NumPacketsSent; k++) */
/*     if (PkLostRuns[k] > 0) { */
/*       if (++j > 6) { */
/* 	j = 0; */
/* 	fprintf(fout, "\nlost runs: "); */
/*       } */
/*       fprintf(fout, "%d %d  ", k, PkLostRuns[k]); */
/*     } */
/*   fprintf(fout, "\n"); */
/*   fprintf(fout, "dup pk: %d\n", numDup); */
/*   fprintf(fout, "dup ack: %d\n", DupN); */
/*   fprintf(fout, "nc pk: %d\n", numOOO); */
/*   fprintf(fout, "ooo ack: %d\n", RackoN); */
/*   fprintf(fout, "timeouts: %d\n", ToN); */
/*   fprintf(fout, "min rtt: %d\n", rmin); */
/*   fprintf(fout, "max rtt: %d\n", rmax); */
/*   fprintf(fout, "avg rtt: %d\n", ravg/(NumPacketsSent-1)); */
  fprintf(fout, "pk resent: %d\n", TcpStat.tcps_sndrexmitpack);
  fprintf(fout, "pk worry resent: %d\n", WsN);
  fprintf(fout, "timeouts: %d\n", TcpStat.tcps_rexmttimeo);
  if (RexmtN > 0) 
    fprintf(fout, "avg timeout: %d\n", ToTimeSum/RexmtN);
  fprintf(fout, "test pk lost: %d\n", 0);
  fprintf(fout, "S KB/S: %.1f\n",  
	  (((Total_bytes_sent+511.)/1024.)/(LastAckTime/1000.)));
  fprintf(fout, "T KB/S: %.1f\n",  
	  ((trkb)/(LastAckTime/1000.)));
  fclose(fout);
  return y;


} /* End of PrintHeader  .............................................*/


/*-------------------------  PlotRate  -------------------------
*/
float PlotRate (y, ydec, plotLostSntTimeBars)

float y, ydec;  /* 0.2 */
int   plotLostSntTimeBars;
{
  int zero=0;

  fprintf(Fout, "%%\n%%   Plot Rate\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec);
  }
  
  Min = 0, Max = MaxRate;
  if (FixMaxRateFlag)
    Max = FixMaxRate;
  if (FixRateTicFlag)
    SetGraph(ydec+Aylen, &zero, &Max, FixRateTic, FixRateTic, FixRateTic,
             11, "Time in seconds", "Sending KB/S", " ", 0);
  else
    SetGraph(ydec+Aylen, &zero, &Max, 20, 20, 20, 11, "Time in seconds",
	     "Sending  KB/S", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Big local send rate */
/*   fprintf(Fout, "[2] 0 setdash\n");  */
  PlotFunEr(1, Lrate3N, Lrate3, 10000, "%d %d\n",
	    "2.0 AvgRate plotStraightLinesC\n", 1);
/*   fprintf(Fout, "[] 0 setdash\n");  */
  /* --- Global send rate */
/*   PlotFunEr(1, GrateN, Grate, 10000, "%d %d\n", */
/* 	    "1.5 0.5 plotStraightLines\n", 1); */
  /* --- Local send rate */
  PlotFunEr(1, LrateN, Lrate, 10000, "%d %d\n",
	    "0.5 Black plotStraightLinesC\n", 1);
  /* --- Predicted by control window */
/*   fprintf(Fout, "[2] 0 setdash\n"); */
/*  PlotFunEr(1, CwrateN, Cwrate, 10000, "%d %d\n", */
/* 	    "0 0 plotStraightLines\n", 1); */
/*   fprintf(Fout, "[] 0 setdash\n"); */

  return y;

} /* End of PlotRate  .............................................*/


/*-------------------------  PlotVegas  -------------------------
*/
float PlotVegas (y, ydec, plotLostSntTimeBars)

float y, ydec;  /* 0.2 */
int   plotLostSntTimeBars;
{
  int zero=0;

  fprintf(Fout, "%%\n%%   Plot Vegas\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec);
  }
  
  Min = 0, Max = Vmax;
  SetGraph(ydec+Aylen, &zero, &Max, 20, 20, 20, 11, "Time in seconds",
	   "CAM KB/S", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);

  PlotFunEr(1, VpredN, Vpred, 10000, "%d %d\n",
	    "2.0 ExpectedTp plotStraightLinesC\n", 1);

  PlotFunEr(1, VactualN, Vactual, 10000, "%d %d\n",
	    "1 ActualTp plotStraightLinesC\n", 1);

  fprintf(Fout, "%[2] 0 setdash\n"); 
  if (VtopN > 0) 
    PlotFunEr(1, VtopN, Vtop, 10000, "%d %d\n",
	      "%%0 0 plotStraightLines\n", 1);
  if (VbotN > 0)
    PlotFunErSwap(1, VbotN, Vbot, 10000, "%d %d\n",
                  "%%0 0 plotStraightLines\nAlphaBeta plotArea\n", 1);
  fprintf(Fout, "%%[] 0 setdash\n");

  return y;

} /* End of PlotVegas  .............................................*/


/*-------------------------  PlotWin  -------------------------
*/
float PlotWin (y, ydec, plotLostSntTimeBars)

float y, ydec;
int   plotLostSntTimeBars;
{
  int   zero=0, j;
  float x;

  fprintf(Fout, "%%\n%%   Plot Npit\n%%\n");

  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec);
  }
  j = MaxWin/1024;
  if (j < 64)
    j = 70;
  j = (j + 9)/10;
  
  Min = -10, Max = j*10;
  if (FixMaxWinFlag)
    Max = FixMaxWin;

  if (FixWinTicFlag)
    SetGraph(Aylen+ydec, &Min, &Max, FixWinTic, FixWinTic, FixWinTic, 10,
             "Time in seconds", "KB", " ", 0);
  else
    SetGraph(Aylen+ydec, &Min, &Max, 10, 5, 5, 10, "Time in seconds",
	     "KB", " ", 0);
  /* --- Average CBIT  TODO */
/*   x = ((float) AvgNpit)/CntNpit; */
/*   fprintf(Fout, "%f yfix yinc mul ypos add /y exch def \n", x); */
/*   fprintf(Fout, "xpos 1 add ypos 1 add moveto\n"); */
/*   fprintf(Fout, "xpos 1 add y lineto xpos axlen in add y lineto\n"); */
/*   fprintf(Fout, "xpos axlen in add ypos 1 add lineto closepath \n"); */
/*   fprintf(Fout, "0.98 setgray fill 0 setgray\n"); */
/*   fprintf(Fout, "1 1 grid\n"); */
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Awin data */
   PlotFun(0, AwinN, Awin, 10000, "%d %d\n", "3 SendWin plotStraightLinesC\n",1);
  /* --- Cwin data */
  PlotFun(0, CwinN, Cwin, 10000, "%d %d\n", "3 CongWin plotStraightLinesC\n",1);
  /* --- Thrs data */
  fprintf(Fout, "[3] 0 setdash\n");
  PlotFun(0, ThrsN, Thrs, 10000, "%d %d\n", "2 ThreshWin plotStraightLinesC\n",
          1);
  fprintf(Fout, "[] 0 setdash\n");
  /* --- Current CBIT data */
  PlotFunEr(0, CbitN, Cbit, 10000, "%d %d\n", "1 CurWin plotStraightLinesC\n",
            1);
  return y;

} /* End of PlotWin  .............................................*/


/*-------------------------  PlotSeq  ------------------------- */
float PlotSeq (y, ydec, plotLostSntTimeBars)

float y, ydec;
int   plotLostSntTimeBars;
{
  int   zero=0, j;
  float x;

  fprintf(Fout, "%%\n%%   Plot Seq\n%%\n");

  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec);
  }
  j = MaxSeq/1024;
  j = (j + 9)/10;

  Min = 0, Max = j*10;
/*  if (FixMaxWinFlag)
    Max = FixMaxWin;
*/

/*  if (FixWinTicFlag)
    SetGraph(Aylen+ydec, &Min, &Max, FixWinTic, FixWinTic, FixWinTic, 10,
             "Time in seconds", "KB", " ", 0);
  else
*/    SetGraph(Aylen+ydec, &Min, &Max, 100, 100, 100, 100, "Time in seconds",
             "Sequence Number (KB)", " ", 0);
/*  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
*/
  /* --- Seq data */
  PlotFun(0, SeqN, Seq, 10000, "%d %d\n", "7 plotSymbols\n",1);
  return y;

} /* End of PlotSeq  .............................................*/

/*-------------------------  PlotBuf  ------------------------- */
float PlotBuf (y, ydec, plotLostSntTimeBars)

float y, ydec;
int   plotLostSntTimeBars;
{
  int zero=0;

  fprintf(Fout, "%%\n%%   Plot Queue\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 
  
  Min = 0; Max = MaxBufSize*1.1;
  SetGraph(ydec+Aylen, &zero, &Max, 10, 5, 5, 6, "Time in seconds", 
	       "Buffer Size in KB", " ", 0); 
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Queue Count data */
  PlotFunEr(0, BufSizeN, BufSize, 10000, "%d %d\n",  
	    "1 0 plotStraightLines\n", 1); 
  return y;

} /* End of PlotBuf  .............................................*/


/*-------------------------  PlotLoss  -------------------------
*/
float PlotLoss (y, ydec, plotLostSntTimeBars)

float y, ydec;
int   plotLostSntTimeBars;
{
  int zero=0, j;

  fprintf(Fout, "%%\n%%   Plot Loss\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 

  j = LostBcnt/1024;

  Min = 0, Max = j;
  SetGraph(ydec+Aylen, &zero, &Max, 10, 5, 5, 6, "Time in seconds",
	   "KB Dropped", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Global loss */
  PlotFunEr(0, GlossN, Gloss, 10000, "%d %d\n", "2 0.4 plotStraightLines\n",
	    1);
  return y;

} /* End of PlotLoss  .............................................*/


/*-------------------------  PlotRtt  -------------------------
*/
float PlotRtt (y, ydec, plotLostSntTimeBars)

float y, ydec;
int  plotLostSntTimeBars;
{
  int zero=0;

  fprintf(Fout, "%%\n%%   Plot Rtt\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 

  Min = 0, Max = MaxRtt;
  SetGraph(ydec+Aylen, &zero, &Max, 20, 20, 20, 6, "Time in seconds", 
	   "RTT in msecs", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Running average round trip times */
  PlotFunEr(0, ArttN, Artt, 10000, "%d %d\n", "2 0.5 plotStraightLines\n", 
	    1);
  /* --- Round trip times */
  fprintf(Fout, "[1] 0 setdash\n");
  PlotFunEr(0, ToN, To, 10000, "%d %d\n", "0 0 plotStraightLines\n", 1);
  fprintf(Fout, "[] 0 setdash\n");
  PlotFunEr(0, RttN, Rtt, 10000, "%d %d\n", "0.5 0 plotStraightLines\n", 1);
  return y;

} /* End of PlotRtt  .............................................*/


/*-------------------------  PlotDeltaRtt  -------------------------
*/
float PlotDeltaRtt (y, ydec, plotLostSntTimeBars)

  float y, ydec;
  int   plotLostSntTimeBars;
{
  fprintf(Fout, "%%\n%%   Plot Delta Rtt\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 

  GetMaxMin(&Drtt[0][1], 2, DrttN, &Min, &Max);
  SetGraph(ydec+Aylen, &Min, &Max, 10, 10, 10, 11, "Time in seconds",
	   "Delta RTT", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Delta rtt */
  PlotFunEr(0, DrttN, Drtt, 10000, "%d %d\n",
	  "0.5 0 plotStraightLines\n", 1);
  return y;

} /* End of PlotDeltaRtt  .............................................*/


/*-------------------------  PlotACDeltaRtt  -------------------------
*/
float PlotACDeltaRtt (y, ydec, plotLostSntTimeBars)

  float y, ydec;
  int   plotLostSntTimeBars;
{
  fprintf(Fout, "%%\n%%   Plot AC Delta Rtt\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 

  GetMaxMin(&Dartt[0][1], 2, DarttN, &Min, &Max);
  SetGraph(ydec+Aylen, &Min, &Max, 10, 10, 10, 11, "Time in seconds",
	   "A C Delta RTT", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Average current Delta RTT */
  PlotFunEr(0, DarttN, Dartt, 10000, "%d %d\n", "0.5 0 plotStraightLines\n",1);
  return y;

} /* End of PlotACDeltaRtt  .............................................*/


/*-------------------------  PlotDirDeltaRtt  -------------------------
*/
float PlotDirDeltaRtt (y, ydec, plotLostSntTimeBars)

float y, ydec;
int   plotLostSntTimeBars;
{
  fprintf(Fout, "%%\n%%   Plot Dir Delta Rtt\n%%\n");
  y -= Aylen + ydec;
  if (y < 0.3) {
    EndPage();
    BeginPage(X0, Y0);
    y = Y0 - (Aylen + ydec); 
  } 

  GetMaxMin(&Dirtt[0][1], 2, DirttN, &Min, &Max);
  SetGraph(ydec+Aylen, &Min, &Max, 10, 10, 10, 11, "Time in seconds",
	   "Dir Delta RTT", " ", 0);
  if (plotLostSntTimeBars || PlotLostSntTimeBars)
    PlotBars(LostPacketsSntTime, LostPacketsSntTimeN);
  /* --- Dir Delta rtt */
  PlotFunEr(0, DirttN, Dirtt, 10000, "%d %d\n",
	  "0.5 0 plotStraightLines\n", 1);
  return y;

} /* End of PlotDirDeltaRtt  .............................................*/


/*-------------------------  ReadTraceData  -------------------------
*/
ReadTraceData ()

{
  long  i, j, k, n;
  int  len, rtt, ack_time, lrtt=0, dir=0, sum=0, rate;
  int  max_beg_seq_sent=-1, max_seq_sent=-1;
  int  seq, ack, flg, opt_len, win, last_time, flags;
  int  dup_cnt=0, dup_bytes=0, lost_cnt=0, lost_bytes=0;
  long post_len;
  dthdr fileHdr;
  char buf[5000];
  FILE *fin;
  dttracemapentry *trace_map;
  long post_off;

  /* cant use stdin because I have fseeks */
/*  if (!strcmp(Filename, "-"))
    fin = stdin;
  else */

  if ((fin = fopen(Filename, "r")) == NULL) {
    fprintf(stderr, "ERROR: Could not open trace file %s\n", Filename);
    exit(1);
  }

  fread((char *)&fileHdr, sizeof(dthdr), 1, fin);
  post_off = dtPostAmbleLocation(&fileHdr);

  /* go to the postamble location */
  fseek(fin, post_off, 0);

  fread((char *)&post_len, sizeof(int), 1, fin);
  fread((char *)&Test_time, sizeof(long), 1, fin);
  fread((char *)&Total_bytes_sent, sizeof(int), 1, fin);
  fread((char *)&Total_bytes_rcvd, sizeof(int), 1, fin);
  fread((char *)&Run_time, sizeof(long), 1, fin);
  fread((char *)&Read_np_lost, sizeof(int), 1, fin);
  fread((char *)&Slen, sizeof(int), 1, fin);
  if (Slen > 0) 
    fread(Sbuf, Slen, 1, fin);
  fread((char *)&StatSize, sizeof(long), 1, fin);
  if (StatSize > 0) {
    fread(buf, StatSize, 1, fin);
    bcopy(buf, (char *)&TcpStat, sizeof(struct tcpstat));
  }

  trace_map = dtGetTraceMap(&fileHdr);
  if (! trace_map) {
    printf("Error getting the map of the trace file\n");
    exit(-1);
  }

  for (i=j=0; j<fileHdr.numberBuffers; j++)
    i += trace_map[j].size + 1024;
  Traces = (TcpTrace *) malloc(i + 1024);
/*
  if (trace_map[0].size > MAX_NUM_EVENTS*sizeof(TcpTrace)) {
    printf("Trace data size (%d) is larger than trace buffer size (%d)\n",
	   trace_map[0].size, MAX_NUM_EVENTS*sizeof(TcpTrace));
    exit(-1);
  }
*/

  Nt = 0;
  for (j=0; j<fileHdr.numberBuffers; j++) {
    fseek(fin, trace_map[j].seek, 0);
    /* read the trace data */
    fread(&Traces[Nt], 1, trace_map[j].size, fin);
    Nt += trace_map[j].size/sizeof(TcpTrace);
  }
  fclose(fin);

  /* --- Process Trace Data */

  Cbit[CbitN][0] = 0;
  Cbit[CbitN++][1] = 0;
  BufSize[BufSizeN][0] = 0;
  BufSize[BufSizeN++][1] = 0;
  Awin[AwinN][0] = 0;
  Awin[AwinN++][1] = 0;
  Cwin[CwinN][0] = 0;
  Cwin[CwinN++][1] = 0;
  Cwrate[CwrateN][0] = 0;
  Cwrate[CwrateN++][1] = 0;
/*   Vactual[VactualN][0] = 0; */
/*   Vactual[VactualN++][1] = 0; */
/*   Vpred[VpredN][0] = 0; */
/*   Vpred[VpredN++][1] = 0; */
  Thrs[ThrsN][0] = 0;
  Thrs[ThrsN++][1] = 0;
  Gloss[GlossN][0] = 0;
  Gloss[GlossN++][1] = 0;
  /* TODO */
  Closs[ClossN][0] = 0;
  Closs[ClossN++][1] = 0;
  Grate[GrateN][0] = 0;
  Grate[GrateN++][1] = 0;

  /* --- Get beginning time */
  for (k=0; k<Nt; k++)
    if (Traces[k].event == TCP_EVENT_OTHER9) {
      if (Traces[k].data == 6)
        WinScale = Traces[k].time;
    }
    else if (Traces[k].event == TCP_EVENT_OPEN  &&  SidsUse[Traces[k].event]) {
      RateBegTime = Traces[k].time - 2;
      break;
    }
    else if (Traces[k].event == TCP_EVENT_PUSH) {
      RateBegTime = Traces[k].time - 2;
      break;
    }
  if (fix_time_flag) {
    BegTime = RateBegTime;
    RateBegTime = -1;
  }

  /* --- Get first seq */
  for (k=0; k<Nt; k++)
    if (Traces[k].event == TCP_EVENT_OUT1) {
      FirstSeq = Traces[k].time;
      break;
    }

  /* --- Reset times and process snd and rcv events */
  for (k=0; k<Nt; k++)
    if ((i=Traces[k].event) == TCP_EVENT_IN  ||  i == TCP_EVENT_OUT  ||
        i == TCP_EVENT_FAST_TO  ||  i == TCP_EVENT_SLOW_TO  ||
        i == TCP_EVENT_TIMER  ||  i == TCP_EVENT_OPEN  ||
        i == TCP_EVENT_PUSH  ||  i == TCP_EVENT_PUSHA ||
        i == TCP_EVENT_CTL_PUSH) {

      if (Sids[Traces[k].sid] == 0)
        Sids[Traces[k].sid] = 1, SidCnt++;
      Traces[k].time -= BegTime;
    } 

  printf("\nNumber of sid: %d\n", SidCnt);
  for (k=i=0; k<255; k++)
    if (Sids[k] != 0) {
      printf("%3d ", k);
      if (++i >= 19)
        printf("\n"), i=0;
    }

  if (SidCnt > 2  &&  SidUse == -1) {
    printf("\nThe trace file contains more than one connection, \n");
    printf("you must use the -sid= command line argument\n\n");
    exit(1);
  }

  for (k=0; k<Nt; k++) {
    if (SidsUse[Traces[k].sid] == 0)
      continue;
    switch (Traces[k].event) { 

    case TCP_EVENT_OUT:
      last_time = Traces[k].time;
      break;
    case TCP_EVENT_DUP:
      break;
    case TCP_EVENT_OUT1:
      /* venkat: added this here */
      if (last_time <= 0)
	last_time = 0;
      SndTraces[NumPacketsSent].time = last_time;
/*      printf("%d: SndTraces %d\n",NumPacketsSent,SndTraces[NumPacketsSent].time);*/
      len = SndTraces[NumPacketsSent].len = Traces[k].data;
      seq = SndTraces[NumPacketsSent].seq = Traces[k].time - FirstSeq;
      Seq[SeqN][0] = last_time;
      Seq[SeqN++][1] = seq/1024;
      if (seq > MaxSeq)
        MaxSeq = seq;
      SndTraces[NumPacketsSent++].flags = 0;
      if (Traces[k-1].event == TCP_EVENT_DUP) {
	int flg=0;
	SndTraces[NumPacketsSent-1].flags |= F_RESEND;
	dup_cnt++;
	dup_bytes += len;
	for (j=NumPacketsSent-2; j>=0; j--) {
/* 	  if (SndTraces[j].flags & F_LOST) */
/* 	    break; */
	  if (SndTraces[j].len == 0)
	    continue;
          if (seq >= SndTraces[j].seq &&
	      seq < SndTraces[j].seq+SndTraces[j].len-24 && len >= 32) {
/*	  if (seq < SndTraces[j].seq+SndTraces[j].len-2-24 &&  
	      seq+len >= SndTraces[j].seq+SndTraces[j].len) { */
	    SndTraces[j].flags |= F_LOST;
	    lost_cnt++;
	    lost_bytes += SndTraces[j].len;
	    flg = 1;
/* 	    break; */
	  }
	  else if (flg && (seq > SndTraces[j].seq))
	    break;
	}
      }
      break;
    case TCP_EVENT_IN:
      last_time = Traces[k].time;
      break; 
    case TCP_EVENT_IN1:
      ack = Traces[k].time - FirstSeq;
      for (j=NumPacketsSent-1; j>=0; j--) {
	if (ack >= (SndTraces[j].seq + SndTraces[j].len)) {
	  if (SndTraces[j].time_rcvd_ack == 0  &&  
	      !(SndTraces[j].flags & F_LOST)) {
	    SndTraces[j].time_rcvd_ack = last_time;
	    /* --- Process rtt */
/* 	    ack_time = last_time; */
/* 	    Rtt[RttN][0] = ack_time; */
/* 	    rtt = ack_time - SndTraces[j].time; */
/* 	    Rtt[RttN++][1] = rtt; */
/* 	    if (MaxRtt < rtt) */
/* 	      MaxRtt = rtt; */
/* 	    if (RttN > 1) { */
/* 	      Drtt[DrttN][0] = ack_time; */
/* 	      Drtt[DrttN++][1] = rtt - Rtt[RttN-2][1]; */

/* 	      i = rtt - Rtt[RttN-2][1]; */
/* 	      Dirtt[DirttN][0] = ack_time; */
/* 	      if (i*dir > 0)  */
/* 		Dirtt[DirttN++][1] = rtt - lrtt; */
/* 	      else { */
/* 		Dirtt[DirttN++][1] = i; */
/* 		dir = i; */
/* 		lrtt = rtt; */
/* 	      } */
/* 	    } */
/* 	    if (RttN >= Arttn) { */
/* 	      for (sum=0,j=RttN-Arttn; j<RttN; j++) */
/* 		sum += Rtt[j][1]; */
/* 	      rate = sum/Arttn; */
/* 	      Artt[ArttN][0] = ack_time; */
/* 	      Artt[ArttN++][1] = sum/Arttn; */

/* 	      sum -= Rtt[RttN-1][1]; */
/* 	      rate = sum/(Arttn-1); */
/* 	      Dartt[DarttN][0] = ack_time; */
/* 	      Dartt[DarttN++][1] = rtt - rate; */
/* 	    } */
	    break;
	  }
	  else if (SndTraces[j].time_rcvd_ack != 0 &&
		   !(SndTraces[j].flags & F_RESEND))
	    break;
	}
      }
      break;
    case TCP_EVENT_SET_TO:
      RttCnt++;
      RttSum += Traces[k].data;
      if (last_time-RttLast > RttMaxTime) 
	RttMaxTime = last_time - RttLast;
      RttLast = last_time;
      if (Traces[k].data > RttMax)
	RttMax = Traces[k].data;
      if (Traces[k].data < RttMin)
	RttMin = Traces[k].data;
      Rtt[RttN][0] = last_time;
      To[ToN][0] = last_time;
      rtt = Traces[k].data;
      if (rtt <= 1000)
	RttHisto[rtt/10]++;
      else if (rtt <= 5000)
	RttHisto[101+(rtt-1001)/200];
      else
	RttHisto[121]++;
      Rtt[RttN++][1] = rtt;
      To[ToN++][1] = Traces[k].time;
      if (MaxRtt < rtt)
	MaxRtt = rtt;
      if (RttN > 1) {
	Drtt[DrttN][0] = last_time;
	Drtt[DrttN++][1] = rtt - Rtt[RttN-2][1];

	i = rtt - Rtt[RttN-2][1];
	Dirtt[DirttN][0] = last_time;
	if (i*dir > 0) 
	  Dirtt[DirttN++][1] = rtt - lrtt;
	else {
	  Dirtt[DirttN++][1] = i;
	  dir = i;
	  lrtt = rtt;
	}
      }
      if (RttN >= Arttn) {
	for (sum=0,j=RttN-Arttn; j<RttN; j++)
	  sum += Rtt[j][1];
	rate = sum/Arttn;
	Artt[ArttN][0] = last_time;
	Artt[ArttN++][1] = sum/Arttn;
	
	sum -= Rtt[RttN-1][1];
	rate = sum/(Arttn-1);
	Dartt[DarttN][0] = last_time;
	Dartt[DarttN++][1] = rtt - rate;
      }
      break;
    default:
      ;
    } 
  } 
    
  for (k=0; k<Nt; k++) {
    if (SidsUse[Traces[k].sid] == 0)
      continue;
    switch (Traces[k].event) {
          
    case TCP_EVENT_IN:
      last_time = Traces[k].time;
      len = Traces[k].data;
      seq = Traces[++k].time;
      opt_len = 0;
      if (IS_ACK(Traces[++k].data))
        ack = Traces[k].time - FirstSeq;
      else
        ack = -1;
      flags = (int)Traces[k].data;
      break;
    case TCP_EVENT_ROPT:
      opt_len = Traces[k].time;
      flags |= 0x100;
      break;
    case TCP_EVENT_IN0: 
      RcvTraces[NumPacketsRcvd].time = last_time;
      RcvTraces[NumPacketsRcvd].seq = seq;
      RcvTraces[NumPacketsRcvd].len = len-opt_len;
      RcvTraces[NumPacketsRcvd].flags = flags;
      RcvTraces[NumPacketsRcvd++].ack = ack;
/*       bytes_rcvd += len-opt_len; */
      break;
    default:
      ;
    } 
  } 
          
  LastAckTime = last_time;

  /* --- Record lost packets */
  for (k=0; k<NumPacketsSent; k++) {
    if (SndTraces[k].flags & F_LOST) {
      LostPacketsSntTime[LostPacketsSntTimeN++] = SndTraces[k].time;
      LostBcnt += SndTraces[k].len;
      LostCnt++;
      ADD_ENTRY(Gloss, GlossN, SndTraces[k].time, LostBcnt/1024);
      if (LastPkLost == k-1)
	PkLostCnt++, LastPkLost++;
      else  {
	PkLostRuns[PkLostCnt]++;
	LastPkLost = k;
	PkLostCnt = 1;
      }
    }
  }
  PkLostRuns[PkLostCnt]++;

  strcpy(TimeArray, ctime((time_t *)&Test_time));
  TimeArray[strlen(TimeArray)-1] = '\0';

} /* End of ReadTraceData  .............................................*/


/*-------------------------  ProcessEvents  -------------------------
*/
ProcessEvents ()

{
  int i, j, k, n, t, minrtt=100000000;
  int p_show=10, last_p_show=0, pn, cur_npit=0, queue_cnt=0, etime;
  int largest_ack=0, last_snt=-1, byte_cnt=0, rtt=6000;
  int sum=0, rate, np_lost=0, loss=0, np=0, ack_time;
  int global_loss=0, current_loss=0, last_time, flags, ack, len;

  ZeroFun[0][0] = 0;
  ZeroFun[0][1] = 0;
  ZeroFun[1][0] = LastAckTime;
  ZeroFun[1][1] = 0;

  Ntics = Xtime/Xtics;
  if (BigFlag && Ntics%2 != 0) {
    Ntics += 1;
    Xtics = Xtime/Ntics;
  }
/*   i = LastAckTime/1000; */
/*   i = i + (5 - i%5); */
/*   NumStrips = i/5; */
  i = LastAckTime + (Xtime - LastAckTime%Xtime);
  NumStrips = i/Xtime;

  p_show = Total_bytes_sent/(NumStrips*10);
  p_show = p_show + (10240 - p_show%10240);
  if (p_show < 10240)
    p_show = 10240;
  last_p_show = p_show;
  if (BigFlag)
    NumStrips *= 2;

  for (k=0; k<NumPacketsRcvd; k++) {
    EventA[EventN][0] = RcvTraces[k].time;
    EventA[EventN][1] = flags = RcvTraces[k].flags;
    if (RcvTraces[k].len > 0) {
      EventA[EventN][1] |= E_RCV;
      RcvN++;
    }
    if (IS_ACK(flags)) {
      if (RcvTraces[k].ack > largest_ack) {
	largest_ack = RcvTraces[k].ack;
	AckN++;
      }
      else {
	OackN++;
	EventA[EventN][1] &= ~E_ACK;
	EventA[EventN][1] |= E_OACK;
      }
    }
    if (IS_ROPT(flags))	RoptN++;
    if (IS_PUSH(flags)) PushfN++;
    if (IS_URG(flags))	UrgN++;
    if (IS_RST(flags))	RstN++;
    if (IS_SYN(flags))	SynN++;
    if (IS_FIN(flags))	FinN++;
    ack = RcvTraces[k].ack;
    if (ack >= last_p_show  &&  IS_ACK(flags)) {
      Prcv[PrcvN][0] = RcvTraces[k].time;
      Prcv[PrcvN++][1] = last_p_show/1024;
      last_p_show += p_show;
    }
    EventN++;
  }

  last_p_show = p_show;
  len = 0;
  for (k=0; k<NumPacketsSent; k++) {
    EventA[EventN][0] = SndTraces[k].time;
    EventA[EventN++][1] |= E_SND;
    SndN++;
    if (SndTraces[k].time & F_RESEND)
      continue;
/*     len += SndTraces[k].len; */
/*     if (len >= last_p_show) { */
    if (SndTraces[k].seq >= last_p_show) {
      Psnt[PsntN][0] = SndTraces[k].time;
      Psnt[PsntN++][1] = last_p_show/1024;
      last_p_show += p_show;
    }
  }

  pn = 0;
  for (k=0; k<Nt; k++) {
    if (SidsUse[Traces[k].sid] == 0)
      continue;
    switch(Traces[k].event) {

    case TCP_EVENT_IN:
      last_time = Traces[k].time;
      break;
    case TCP_EVENT_IN0: 
    case TCP_EVENT_IN1:
      break;
    case TCP_EVENT_BADSUM:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_BADSUM;
      BadsumN++;
      break;
    case TCP_EVENT_DROP:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_DROP;
      DropN++;
      break;
    case TCP_EVENT_OUT:  
      LastSndTime = last_time = Traces[k].time;
      if (LState != Traces[k].data) {
	LState = Traces[k].data;
	State[StateN][0] = last_time;
	State[StateN++][1] = Traces[k].data;
      }
      if (last_time > Cbit[CbitN-1][0]+1 && CbitN > 2) {
        int ii, jj, kk, nn, mmax, mmin;
        ii = jj = CbitN-1;
        mmax = mmin = Cbit[jj][1];
        while (ii > 1  &&  Cbit[jj][0] <= Cbit[ii-1][0]+1) {
          ii--;
          if (Cbit[ii][1] < mmin) mmin = Cbit[ii][1];
/*          if (Cbit[ii][1] > mmax) mmax = Cbit[ii][1]; */
        }
        if (jj - ii > 2) {
          if (mmax - mmin < 5) {
            Cbit[ii][1] = Cbit[ii-1][1];
            Cbit[ii+1][1] = mmax;
            CbitN = ii+2;
          }
          else {
            Cbit[ii][1] = Cbit[ii-1][1];
            Cbit[ii+1][1] = mmin;
            Cbit[ii+2][1] = mmax;
            CbitN = ii+3;
          }
        }
      }
      break;
    case TCP_EVENT_OUT0:
      ADD_ENTRY_CHOP(Awin, AwinN, last_time, (Traces[k].data<<WinScale)/1024,
                     FixMaxWin);
      if (Cwin[CwinN-1][0] >= (last_time-1))
	CwinN -= 2;
      ADD_ENTRY_CHOP(Cwin, CwinN, last_time, (Traces[k+1].data<<WinScale)/1024,
                     FixMaxWin);
/*       ADD_ENTRY(Cwrate, CwrateN, last_time, Traces[k+1].data/rtt); */
      ADD_ENTRY_CHOP(Thrs, ThrsN, last_time, (Traces[k+2].data<<WinScale)/1024,
                     FixMaxWin);
/*       if (BufSize[BufSizeN-1][0] >= (last_time-1)) */
/* 	BufSizeN -= 2; */
      ADD_ENTRY_CHOP(BufSize, BufSizeN, last_time, Traces[k].time/1024,
                     FixMaxWin);
/*
      if (Cbit[CbitN-1][0] >= (last_time-1)  &&
          Cbit[CbitN-1][1] - (Traces[k+1].time-Traces[k+2].time)/1024)
	CbitN -= 2;
*/
     ADD_ENTRY_CHOP(Cbit, CbitN, last_time,
                    (Traces[k+1].time-Traces[k+2].time)/1024, FixMaxWin);
      if (rtt != 6000) {
	if (Cwrate[CwrateN-1][0] >= (last_time-1)  &&  CwrateN > 2)
	  CwrateN -= 2;  /* protect from silly wiggles */
	ADD_ENTRY_CHOP(Cwrate, CwrateN, last_time, (int)
		       ((Traces[k+1].time-Traces[k+2].time)/(1.024*minrtt)),
		       FixMaxWin);
      }
/*      if (MaxWin < (Traces[k].data<<4))               MaxWin = Traces[k].data<<4;
      if (MaxWin < (Traces[k+1].data<<4))       MaxWin = Traces[k+1].data<<4;
      if (MaxWin < (Traces[k+2].data<<4))       MaxWin = Traces[k+2].data<<4;
*/
      if (MaxWin < Traces[k].data)	MaxWin = Traces[k].data;
      if (MaxWin < Traces[k+1].data)	MaxWin = Traces[k+1].data;
      if (MaxWin < Traces[k+2].data)	MaxWin = Traces[k+2].data;
      if (MaxBufSize < Traces[k].time/1024) MaxBufSize = Traces[k].time/1024;
      if (MaxWin < Traces[k+1].time-Traces[k+2].time)	
	MaxWin = Traces[k+1].time-Traces[k+2].time;
      break;
    case TCP_EVENT_DUP:
      break;
    case TCP_EVENT_OUT1:
      byte_cnt += Traces[k].data;
      if (pn > 3) {
	rate = byte_cnt/(last_time-RateBegTime);
	if (rate > FixMaxRate)
	  rate = FixMaxRate;
	if (rate > MaxRate) 
	  MaxRate = rate;
	Grate[GrateN][0] = last_time;
	Grate[GrateN++][1] = rate;
      }
      if (pn >= Lraten+4) {
/* 	for (sum=0,j=pn-Lraten+1; j<=pn; j++) */
	for (sum=0,j=pn; j>pn-Lraten; j--)
	  sum += SndTraces[j].len;
/* 	t = last_time - (SndTraces[pn-Lraten+1].time); */
	t = last_time - (SndTraces[pn-Lraten].time);
	while (t == 0) {
	  sum += SndTraces[j].len;
	  t = last_time - (SndTraces[j--].time);
	}
	rate = sum/t;
	if (rate > FixMaxRate)
	  rate = FixMaxRate;
	if (rate > MaxRate) 
	  MaxRate = rate;
	Lrate[LrateN][0] = last_time;
	Lrate[LrateN++][1] = rate;
      }
      if (pn >= Lraten+4  &&  rtt != 6000) {
	int tt=0, jj, kk;
	for (sum=0,j=pn; (last_time-Lrate3n*rtt)<SndTraces[j].time; j--)
	  sum += SndTraces[j].len;

/* 	t = last_time - (SndTraces[pn-Lraten+1].time); */
	t = last_time - (SndTraces[j].time);
	sum = (sum*rtt*Lrate3n)/(last_time-SndTraces[j].time);
	rate = sum/t;
	if (rate > FixMaxRate)
	  rate = FixMaxRate;
	if (rate > MaxRate) 
	  MaxRate = rate;
	Lrate3[Lrate3N][0] = last_time;
	Lrate3[Lrate3N++][1] = rate;
      }
      if (pn >= Lrate2n+4) {
	for (sum=0,j=pn; j>pn-Lrate2n; j--)
	  sum += SndTraces[j].len;
	t = last_time - (SndTraces[pn-Lrate2n].time);
	while (t == 0) {
	  sum += SndTraces[j].len;
	  t = last_time - (SndTraces[j--].time);
	}
	rate = sum/t;
	if (rate > FixMaxRate)
	  rate = FixMaxRate;
	Lrate2[Lrate2N][0] = last_time;
	Lrate2[Lrate2N++][1] = rate;
      }
      if (SndTraces[pn].flags & F_LOST) {
	if (LossMode == 0) 
	  LostGroups[LostGroupsN++][0] = LastSndTime;
      }
      if (Traces[k-1].event == TCP_EVENT_DUP) {
	if (!(SndTraces[pn].flags & F_LOST)) {
	  if (LossMode > 0) {
	    LossMode--;
	    if (LossMode <= 0) {
	      LostGroups[LostGroupsN++][0] = LastSndTime;
	    }
	  }
	}
      }
      else if (SndTraces[pn].flags & F_LOST)
	LossMode++;
      pn++;
      break;
    case TCP_EVENT_FAST_TO:
      EventA[EventN][0] = Traces[k].time;
      EventA[EventN++][1] |= E_FTO;
      FtoN++;
      break;
    case TCP_EVENT_SLOW_TO:
      EventA[EventN][0] = Traces[k].time;
      EventA[EventN++][1] |= E_STO;
      StoN++;
      break;
    case TCP_EVENT_TIMER:
      EventA[EventN][0] = Traces[k].time;
      EventA[EventN++][1] |= timer2event[Traces[k].data];
      if (Traces[k].data == 0) {
	RexmtN++;
	ToTimeSum += (Traces[k].time - LastSndTime);
      }
      if (Traces[k].data == 1) PersistN++;
      if (Traces[k].data == 2) KeepN++;
      if (Traces[k].data == 3) MslN++;
      break;
    case TCP_EVENT_PUSH:
      if (Traces[k+1].event != TCP_EVENT_PUSHW) {
      EventA[EventN][0] = last_time = Traces[k].time;
	EventA[EventN++][1] |= E_PUSH;
	PushN++;
      }
      break;
    case TCP_EVENT_PUSHW:
      if (Traces[k+1].event != TCP_EVENT_PUSHA) {
	EventA[EventN][0] = last_time;
	EventA[EventN++][1] |= E_BLOCK;
	BlockN++;
      }
      break;
    case TCP_EVENT_PUSHA:
      if (Traces[k+1].event != TCP_EVENT_PUSHW) {
	EventA[EventN][0] = Traces[k].time;
	EventA[EventN++][1] |= E_AWAKE;
	AwakeN++;
      }
      break;
    case TCP_EVENT_ROPT:
    case TCP_EVENT_OPEN:
    case TCP_EVENT_OPEN1:
    case TCP_EVENT_DATA:
    case TCP_EVENT_CTL_PUSH:
    case TCP_EVENT_CTL_NDUP:
    case TCP_EVENT_CTL_SSN:
    case TCP_EVENT_OTHER1:
    case TCP_EVENT_OTHER2:
    case TCP_EVENT_OTHER4:
    case TCP_EVENT_OTHER8:
    case TCP_EVENT_OTHERa:
    case TCP_EVENT_OTHERb:
      break;
    case TCP_EVENT_OTHER9:
      if (Traces[k].data == 6)
        WinScale = Traces[k].time;
      break;
    case TCP_EVENT_OTHER3:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_SPIKESUP;
      SpikesupN++;
      break;
    case TCP_EVENT_OTHER5:
      EventA[EventN][0] = last_time;
      if (Traces[k].data)
	EventA[EventN++][1] |= E_INTER1;
      else
	EventA[EventN++][1] |= E_INTER0;	
      InterN++;
      break;
    case TCP_EVENT_OTHER6:
      if ( 1  /*Traces[k].time < 800*/ ) {
/* 	ADD_ENTRY(Vactual, VactualN, last_time, Traces[k].time); */
/* 	ADD_ENTRY(Vpred, VpredN, last_time, Traces[k].data); */
        if (LastPred > 0  &&  (Traces[k].data > 3*LastPred ||
            Traces[k].time < 0 || 3*Traces[k].data < LastPred))
          break;
        LastPred = Traces[k].data;
	Vactual[VactualN][0] = last_time;
	Vactual[VactualN++][1] = Traces[k].time;
	if (Traces[k].time > Vmax)
	  Vmax = Traces[k].time;
	Vpred[VpredN][0] = last_time;
	Vpred[VpredN++][1] = Traces[k].data;
	if (Traces[k].data > Vmax)
	  Vmax = Traces[k].data;
	if (Vtop_nseg > -1) {
	  Vtop[VtopN][0] = last_time;
	  Vtop[VtopN++][1] = Traces[k].data-(Vtop_nseg*1460)/minrtt;
	}
	if (Vbot_nseg > -1) {
	  Vbot[VbotN][0] = last_time;
	  Vbot[VbotN++][1] = Traces[k].data-(Vbot_nseg*1460)/minrtt;
	}
      }
      break;
    case TCP_EVENT_OTHER7:
      VegasFlags = Traces[k++].data;
      Vexp_nseg = Traces[k++].time;
      Vtop_nseg = Traces[k].time;
      Vbot_nseg = Traces[k].data;
      break;
    case TCP_EVENT_SET_TO:
      rtt = Traces[k].data;
      if (rtt < minrtt)
	minrtt = rtt;
      break;
    case TCP_EVENT_WSND:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_WS;
      WsN++;
      break;
    case TCP_EVENT_RCWND:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_RCWND;
      RcwndN++;
      break;
    case TCP_EVENT_RTO:
      EventA[EventN][0] = last_time;
      EventA[EventN++][1] |= E_RTO;
      RtoN++;
      break;
    default:
      printf("Event: (%d) UNKNOWN EVENT *********\n", Traces[k].event); 
      ;
    }
  }
  Cwin[CwinN][0] = last_time;
  i = Cwin[CwinN-1][1];
  Cwin[CwinN++][1] = i;
  Awin[AwinN][0] = last_time;
  i = Awin[AwinN-1][1];
  Awin[AwinN++][1] = i;
  Thrs[ThrsN][0] = last_time;
  i = Thrs[ThrsN-1][1];
  Thrs[ThrsN++][1] = i;

} /* End of ProcessEvents  .............................................*/

/*-------------------------  GetLine  ------------------------- */
GetLine (fin, line)

FILE *fin;
char *line;
{
  int  i;

  while ((i=fgetc(fin)) != EOF  &&  i != '\n')
    *line++ = (char) i;
  *line = '\0';
  return i;

} /* End of GetLine  .............................................*/

/* 
 * These stub routines are included to avoid linking in msg.c.
 */
void *msgWalkToughNext(cxt, len)
MsgWalk *cxt;
int     *len;
{ fprintf(stderr, "Remove this Stub for msgWalkToughNext !! \n"); exit(-1); }

void msgToughDestroy(n)
MsgNode n;
{ fprintf(stderr, "Remove this Stub for msgToughDestroy!!\n"); exit(-1); }
