Mac binaries
[jabaws.git] / website / archive / binaries / mac / src / fasta34 / p2_workcomp.c
diff --git a/website/archive/binaries/mac/src/fasta34/p2_workcomp.c b/website/archive/binaries/mac/src/fasta34/p2_workcomp.c
new file mode 100644 (file)
index 0000000..0600b6c
--- /dev/null
@@ -0,0 +1,1230 @@
+
+/* copyright (c) 1996, 1997, 1998, 1999 William R. Pearson and the
+   U. of Virginia */
+
+/* $Name: fa_34_26_5 $ - $Id: p2_workcomp.c,v 1.49 2007/01/02 17:24:36 wrp Exp $ */
+
+/* This version is modifed to read all files, query and database,
+   through the manager process. Workers will now receive their
+   database from the manager, rather than reading it themselves.  This
+   cuts down considerably on NFS traffic, simplifies searches of
+   multiple files, and allows use of clusters of slave nodes that do
+   not have NFS access */
+
+/* September, 1994 - this version has been modified to do two kinds of
+   searches, a general library search, or list of library sequences search.
+   The latter would be used to generate optimized scores for fasta and
+   to produce alignments */
+
+/* modified July, 2002, to provide query shuffle */
+
+/* modified October, 2005, to support struct a_res_str a_res -
+   coordinates of alignment in aa0[], aa1[].  Future modifications
+   will cause do_walign to be run only once - subsequent calls for
+   seqc[0,1] can be filled using a_res, by adding a_res to the
+   struct sqs2 array.
+
+   19-March-2006 - modifications to call do_walign() only once, and
+   use the resulting a_res structure for subsequent calls to calc_id,
+   calcons, calcons_a, have been implemented.  Also, the -V option is
+   now valid with the parallel programs.
+
+   31-May-2006 - some functions (e.g. dropfs and dropff do not store
+   complete information in a_res - thus they cannot use this shortcut
+   (yet).
+
+*/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef PVM_SRC
+#include "pvm3.h"
+#endif
+
+#ifdef MPI_SRC
+#include "mpi.h"
+#endif
+
+/*
+#define PvmDataDefault 0
+#define PvmTaskDefault 0
+*/
+#include "msg.h"
+#include "defs.h"
+#include "param.h"
+#include "w_mw.h"
+#include "structs.h"
+
+#ifdef MPI_SRC
+#define XTERNAL
+#endif
+#include "upam.h"
+#include "uascii.h"
+
+#ifdef PVM_SRC
+int worker, mytid;
+int nnodes, pinums[MAXNOD];
+#endif
+
+#include "drop_func.h"
+
+extern void alloc_pam (int d1, int d2, struct pstruct *ppst); /* allocate ppst->pam12,pam12x */
+extern int **alloc_pam2p (int len, int nsq); 
+extern void w_init ();
+extern void irand(int);
+extern void revcomp(unsigned char *, int, int *);
+
+
+
+extern void initseq(char **seqc0, char **seqc0a, char **seqc1, char **seqca, int seqsiz);
+extern void freeseq(char **seqc0, char **seqc0a, char **seqc1, char **seqca);
+
+void send_bestr(int, int, struct comstr *, int, int);
+void send_bestr2(int, struct comstr2 *, int);
+void send_code(int, char *, int);
+
+extern void get_param (struct pstruct *ppst, char *pstring2, char *pstring3);
+extern void update_param(struct qmng_str *qm_msg, struct mngmsg *m_msg,
+                        struct pstruct *ppst);
+extern int shuffle(unsigned char *, unsigned char *, int);
+extern int wshuffle(unsigned char *, unsigned char *, int, int, int *);
+
+extern char err_str[];
+
+/* local function declarations */
+void free_ares(struct sqs2 *, int itt, int *, int walign_cnt, int worker);
+
+
+
+void w_abort (p, p1)
+char *p, *p1;
+{
+    fprintf (stderr, " %s %s\n", p, p1);
+#ifdef PVM_SRC
+    pvm_exit();
+    exit (1);
+#endif
+#ifdef MPI_SRC
+  MPI_Abort(MPI_COMM_WORLD,1);
+#endif
+}
+
+#ifdef PVM_SRC
+main ()
+#endif
+#ifdef MPI_SRC
+void
+workcomp(int worker)
+#endif
+{
+  unsigned char *aa0[6], *aa1s, *aa0s; /* Query and library sequences */
+  struct mngmsg m_msg; /* start message from manager to worker 1 */
+  struct qmng_str qm_msg; /* updated for each query */
+  int last_msg_b[10];  /* last set of numbers */
+  struct sqs2 *seqpt;          /* sequence pointers for chunk */
+  int seqbuf_n,seqbuf_s;       /* number of sequences, length of sequences */
+  int max_sql;                 /* maximum number of sequences/node */
+  int *n1_arr;                 /* array of sequence lengths in buffer */
+  int *m_seqnm_arr;            /* array of sequence numbers in buffer */
+  int *aa1i_arr;               /* array of offsets into the buffer */
+  unsigned char *seq_buf;      /* space for sequence data */
+  int ntx;
+  int nsq;                     /* effective alphabet size */
+  long curtype = ONETYPE;      /* current send message type */
+  int ieven=0;                 /* flag for window shuffle */
+  int cur_n0;
+  int n1, n1over;              /* length of query, library sequences */
+  struct comstr bestr[BFR+1];  /* best structures */
+  struct comstr2 bestr2[BFR2+1];       /* best structures */
+  struct a_struct aln, *aln_dp;
+  int qres_bufsize;            /* results buffer size */
+  int bestcnt = 0;             /* how many best structures are full */
+  char gstring2[MAX_STR];              /* parameter string for manager */
+  char gstring3[MAX_STR];              /* parameter string for manager */
+  struct pstruct pst;          /* parameter structure */
+  struct rstruct rst, qrst, rrst;      /* results structure */
+  void *f_str[6], *qf_str;
+  int sw_score;
+  int lcnt, count, seqnm;      /* counters */
+  int *walign_done[2], walign_cnt[2];  /* index of current valid a_res in seqpt */
+  int have_walign;
+  int *tres;                   /* allocated storage for seqpt[].a_res[].res */
+  int lend;                    /*global library sequence number information */
+  int lsn;                     /* library sequence number */
+  struct stage2_str *liblist=NULL;     /* list of sequences to search */
+  int i, j;            /* my turn to send sequence descriptions */
+  char libstr[21];
+  char errstr[128];
+  int itt=0;
+  int bufid;
+  char *seqc0, *seqc0a, *seqc1, *seqca;
+  char *seqc, *seqc_buff;
+  int seqc_buff_cnt, seqc_buff_len, seqc_flag;
+  int maxc, lc, nc, nident, ngap, aln_code_n;
+  float percent, gpercent;
+  int old_shuffle=0;   /* did a qshuffle last time */
+  int hosttid=0;
+  char worker_str[5];
+
+#ifdef MPI_SRC
+  MPI_Status mpi_status;
+#endif
+  
+#ifdef PVM_SRC
+  mytid = pvm_mytid();
+  hosttid = pvm_parent();
+#endif
+
+  w_init();    /* sets up default sascii, hsq, sq */
+
+  /* Allocate space for the query sequence */
+  if ((aa0[0] = (unsigned char *) malloc ((MAXTST+2+SEQ_PAD)*sizeof (char))) == NULL) {
+    w_abort ("Unable to allocate sequence array[0] - exiting!","");
+  }
+  *aa0[0]='\0';
+  aa0[0]++;
+
+  /* initial messages set up various parameter structures:
+
+     STARTTYPE0: &nnodes
+                pinums
+                &m_msg
+
+     STARTTYPE1  &pst
+
+     STARTTYPE2         pam12
+     STARTTYPE3         pam12x
+  */
+
+#ifdef PVM_SRC
+#ifdef ROUTE_DIRECT
+  pvm_setopt(PvmRoute,PvmRouteDirect);
+#endif
+  /* get number of nodes, pinums */
+  bufid = pvm_recv(hosttid,STARTTYPE0);
+  pvm_upkint(&nnodes,1,1);
+  pvm_upkint(pinums,nnodes,1);
+  pvm_upkbyte((char *)&m_msg,(int)sizeof(m_msg),1);
+  worker = tidtonode(mytid);
+  pvm_freebuf(bufid);
+#endif
+
+  sprintf(worker_str,"@%d",worker);
+
+#ifdef MPI_SRC
+  MPI_Recv(&m_msg,sizeof(m_msg),MPI_BYTE,hosttid,STARTTYPE0,MPI_COMM_WORLD,
+          &mpi_status);
+#endif
+
+  /* the aln structure needs some information from m_msg0.aln */
+  memcpy(&aln,&m_msg.aln,sizeof(struct a_struct));
+
+  /*
+  fprintf(stderr,"d1: %d d2: %d\n",m_msg.pamd1,m_msg.pamd2);
+  */
+
+  /* get pst params */
+#ifdef PVM_SRC
+  bufid = pvm_recv(hosttid,STARTTYPE1);
+  pvm_upkbyte((char *)&pst,(int)sizeof(pst),1);
+  /* 31t nsq = pst.nsq; */
+  pvm_upkbyte((char *)pascii,(int)sizeof(aascii),1);
+  pvm_freebuf(bufid);
+#endif
+#ifdef MPI_SRC
+  MPI_Recv(&pst,(int)sizeof(pst),MPI_BYTE,hosttid,STARTTYPE1,MPI_COMM_WORLD,
+          &mpi_status);
+
+  MPI_Recv(pascii,(int)sizeof(aascii)/sizeof(int),MPI_INT,hosttid,STARTTYPE1,MPI_COMM_WORLD,
+          &mpi_status);
+#endif
+
+  if (pst.ext_sq_set) { nsq = pst.nsqx;}
+  else { nsq = pst.nsq;}
+
+  aa0[5] = aa0[4] = aa0[3] = aa0[2] = aa0[1] = aa0[0];
+  if (m_msg.qframe == 2) {
+    if ((aa0[1]=(unsigned char *)malloc((MAXTST+2)*sizeof (char)))==NULL)
+      w_abort ("Unable to allocate sequence[1] array - exiting!","");
+    *aa0[1]='\0';
+    aa0[1]++;
+  }
+
+  if ((aa1s=(unsigned char *)malloc((m_msg.max_tot+1)*sizeof (char)))==NULL)
+      w_abort ("Unable to allocate shuffled library sequence", "");
+  *aa1s=0;
+  aa1s++;
+
+  irand(0);    /* necessary for shuffled sequences */
+
+  /* this function allocates pam12, pam12x
+     assigns pst.pam[0][0]=pam12, pst.pam[1][0] = pam12x
+     and sets up the correct pst.pam[0][0][0] pointers */
+
+  alloc_pam(m_msg.pamd1,m_msg.pamd2,&pst);
+
+#ifdef PVM_SRC
+  bufid = pvm_recv(hosttid,STARTTYPE2);
+  pvm_upkint(pam12,m_msg.pamd1*m_msg.pamd2,1);
+  pvm_freebuf(bufid);
+
+  bufid = pvm_recv(hosttid,STARTTYPE3);
+  pvm_upkint(pam12x,m_msg.pamd1*m_msg.pamd2,1);
+  pvm_freebuf(bufid);
+#endif  
+
+#ifdef DEBUG
+  if (worker==FIRSTNODE) {
+    fprintf(stderr,"ext?: %d\tnsq: %d\tnsqx: %d\n",pst.ext_sq_set,pst.nsq, pst.nsqx);
+    for (i=1; i<5; i++) {
+      for (j=1; j <= i; j++) fprintf(stderr," %c,%c:%2d",pst.sq[i],pst.sq[j],pst.pam2[0][i][j]);
+      fprintf(stderr,"\n");
+    }
+    for (i=pst.nsq+1; i<pst.nsq+5; i++) {
+      for (j=pst.nsq+1; j <= i; j++) fprintf(stderr," %c,%c:%2d",pst.sqx[i],pst.sqx[j],pst.pam2[0][i][j]);
+      fprintf(stderr,"\n");
+    }
+
+    for (i=1; i<5; i++) {
+      for (j=1; j <= i; j++) fprintf(stderr," %c,%c:%2d",pst.sqx[i],pst.sqx[j],pst.pam2[1][i][j]);
+      fprintf(stderr,"\n");
+    }
+    for (i=pst.nsq+1; i<pst.nsq+5; i++) {
+      for (j=pst.nsq+1; j <= i; j++) fprintf(stderr," %c,%c:%2d",pst.sqx[i],pst.sqx[j],pst.pam2[1][i][j]);
+      fprintf(stderr,"\n");
+    }
+  }
+#endif
+
+#ifdef MPI_SRC
+  MPI_Recv(pam12,m_msg.pamd1*m_msg.pamd2,MPI_INT,hosttid,STARTTYPE2,
+          MPI_COMM_WORLD,&mpi_status);
+
+  MPI_Recv(pam12x,m_msg.pamd1*m_msg.pamd2,MPI_INT,hosttid,STARTTYPE3,
+          MPI_COMM_WORLD,&mpi_status);
+#endif
+
+/*
+  We have the PAM matrices - get the library sequences
+*/
+
+  /* Allocate space for the sequences */
+  max_sql = MAXSQL/2;
+
+  if ((seqpt=(struct sqs2 *)calloc(max_sql,sizeof(struct sqs2)))==NULL)
+    w_abort("cannot allocate seqpt(sqs2)","");
+
+  if ((n1_arr=(int *)calloc(m_msg.pbuf_siz+1,sizeof(int)))==NULL)
+    w_abort("cannot allocate n1_arr","");
+
+  if ((aa1i_arr=(int *)calloc(m_msg.pbuf_siz+1,sizeof(int)))==NULL)
+    w_abort("cannot allocate n1_arr","");
+
+  if ((m_seqnm_arr=(int *)calloc(m_msg.pbuf_siz+1,sizeof(int)))==NULL)
+    w_abort("cannot allocate m_seqnm_arr","");
+
+/*****************************************************************/
+/* This section gets all the database sequences from the manager */
+/*****************************************************************/
+
+  lcnt = 0;
+  while (1) {
+#ifdef PVM_SRC
+    /* get the number of sequences, sequence lengths */
+    bufid = pvm_recv(hosttid,STARTTYPE4);
+    pvm_upkint(&seqbuf_n,1,1); /* number of sequences */
+    pvm_upkint(&seqbuf_s,1,1); /* size of sequence buffer */
+    pvm_upkint(n1_arr,seqbuf_n,1);     /* length of each sequence in buffer */
+    pvm_upkint(aa1i_arr,seqbuf_n,1);    /* indexes for each sequence */
+    pvm_upkint(m_seqnm_arr,seqbuf_n,1);        /* number of each library sequence */
+    pvm_freebuf(bufid);
+#endif
+#ifdef MPI_SRC
+    MPI_Recv(&seqbuf_n,1,MPI_INT,hosttid,STARTTYPE4,MPI_COMM_WORLD,
+            &mpi_status);
+    MPI_Recv(&seqbuf_s,1,MPI_INT,hosttid,STARTTYPE4,MPI_COMM_WORLD,
+            &mpi_status);
+    MPI_Recv(n1_arr,seqbuf_n,MPI_INT,hosttid,STARTTYPE4,MPI_COMM_WORLD,
+            &mpi_status);
+    MPI_Recv(aa1i_arr,seqbuf_n,MPI_INT,hosttid,STARTTYPE4,MPI_COMM_WORLD,
+            &mpi_status);
+    MPI_Recv(m_seqnm_arr,seqbuf_n,MPI_INT,hosttid,STARTTYPE4,MPI_COMM_WORLD,
+            &mpi_status);
+#endif
+
+    if (seqbuf_n <= 0) break;
+#ifdef DEBUG    
+    /*
+    fprintf(stderr,"[%d] seqbuf_n: %d seqbuf_s: %d\n",
+           worker,seqbuf_n,seqbuf_s);
+    fprintf(stderr,"[%d] lcnt: %d n1: %d seqnm %d\n",
+           worker,0,n1_arr[0],m_seqnm_arr[0]);
+    fprintf(stderr,"[%d] lcnt: %d n1: %d seqnm %d\n",
+           worker,1,n1_arr[1],m_seqnm_arr[1]);
+    */
+#endif
+
+    /* allocate space for sequences */
+    if ((seq_buf = (unsigned char *)calloc((size_t)seqbuf_s+1,sizeof(char)))
+       ==NULL) {
+      w_abort("cannot allocate tmp_seq","");
+    }
+    seq_buf++; /* leave a '\0' at the start */
+
+    /* get the sequence buffer */
+#ifdef PVM_SRC
+    bufid = pvm_recv(hosttid,STARTTYPE5);
+    pvm_upkbyte((char *)seq_buf,seqbuf_s,1);
+    pvm_freebuf(bufid);
+#endif  
+#ifdef MPI_SRC
+    MPI_Recv(seq_buf,seqbuf_s,MPI_BYTE,hosttid,STARTTYPE5,MPI_COMM_WORLD,
+            &mpi_status);
+#endif
+
+    /* now we have everything  - update the pointers */
+    if (lcnt+seqbuf_n >= max_sql) {
+      max_sql += max(MAXSQL/2,seqbuf_n);
+      if ((seqpt=(struct sqs2 *)realloc(seqpt,max_sql*sizeof(struct sqs2)))
+         ==NULL)
+       w_abort("cannot allocate seqpt(sqs2)","");
+    }
+
+    /* convert from offsets to pointers into buffer */
+    /* ntx = 0; */
+    for (i=0; i<seqbuf_n; i++,lcnt++) {
+      seqpt[lcnt].n1 = n1_arr[i];
+      seqpt[lcnt].m_seqnm = m_seqnm_arr[i];
+      seqpt[lcnt].aa1 = &seq_buf[aa1i_arr[i]];
+      /*      ntx += n1_arr[i]+1 + SEQ_PAD */
+
+#ifdef DEBUG
+      /* must have null's at both ends of sequence */
+      if (seqpt[lcnt].aa1[-1]!= '\0') {
+       fprintf(stderr,"Missing null at start: %d %d\n",
+               lcnt,seqpt[lcnt].aa1[-1]);
+       seqpt[lcnt].aa1[-1]='\0';
+      }
+      if (seqpt[lcnt].aa1[seqpt[lcnt].n1]!= '\0') {
+       fprintf(stderr,"Missing null at end: %d %d\n",
+               lcnt,seqpt[lcnt].aa1[seqpt[lcnt].n1]);
+       seqpt[lcnt].aa1[seqpt[lcnt].n1]='\0';
+      }
+#endif
+    }
+  }
+  /* all done - lcnt has the total number of library sequences */
+
+#ifdef DEBUG
+  if (lcnt > 0)
+    for (i=0; i<10; i++) {
+      for (j=0; j<10; j++) libstr[j]=pst.sq[seqpt[i].aa1[j]];
+      libstr[10]='\0';
+      fprintf(stderr,"[%d] n1: %d seqnm: %d aa1: %s\n",
+             worker,seqpt[i].n1,seqpt[i].m_seqnm,libstr);
+    }
+#endif
+
+  /* send back the number of descriptions received */
+
+#ifdef PVM_SRC
+  pvm_initsend(PvmDataRaw);
+  pvm_pkint(&lcnt,1,1);
+  pvm_send(hosttid,STARTTYPE0);
+#endif
+#ifdef MPI_SRC
+/*  p4_dprintf(" have %d descriptions to send\n",lcnt); */
+  MPI_Send(&lcnt,1,MPI_INT,hosttid,STARTTYPE0,MPI_COMM_WORLD);
+#endif  
+
+/*****************************************************************/
+/* Library reads are finished, get ready to do searches          */
+/*****************************************************************/
+
+  /* get last set of numbers */
+#ifdef PVM_SRC
+  bufid = pvm_recv(hosttid,STARTTYPE0);
+  pvm_upkint(last_msg_b,2,1);
+  pvm_freebuf(bufid);
+#endif
+#ifdef MPI_SRC
+  MPI_Recv(last_msg_b, 2, MPI_INT, hosttid, STARTTYPE0, MPI_COMM_WORLD,
+            &mpi_status);
+#endif
+  m_msg.nbr_seq = last_msg_b[0];
+  qres_bufsize = last_msg_b[1];
+
+#ifdef DEBUG
+#ifdef PVM_SRC
+  fprintf(stderr,"[%d] have nbr_seq %d qres_bufsize %d\n",worker,
+            m_msg.nbr_seq, qres_bufsize);
+#endif
+#ifdef MPI_SRC
+  /*  p4_dprintf("[%d] have nbr_seq %d qres_bufsize %d\n",worker,
+            m_msg.nbr_seq, qres_bufsize);
+  */;
+#endif
+#endif  
+  /* If self search, receive sequence numbering data */
+  if (m_msg.self) {
+#ifdef PVM_SRC
+    bufid = pvm_recv(hosttid,STARTTYPE1);
+    pvm_upkint(&lend,1,1);
+    pvm_freebuf(bufid);
+#endif
+#ifdef MPI_SRC
+    MPI_Recv(&lend,1,MPI_INT,hosttid,STARTTYPE1,MPI_COMM_WORLD,&mpi_status);
+#endif
+  }
+  
+  /* allocate space for a_res flag array */
+
+  if ((walign_done[0] = (int *)calloc(lcnt,sizeof(int)))==NULL) {
+    w_abort("cannot allocate walign_done");
+  }
+  walign_cnt[0]=0;
+
+  if ((walign_done[1] = (int *)calloc(lcnt,sizeof(int)))==NULL) {
+    w_abort("cannot allocate walign_done");
+  }
+  walign_cnt[1]=0;
+
+  /* was commented in for only FASTX/TFASTX, but do it always to
+     simplify */
+  aainit(pst.tr_type, pst.debug_lib);
+  pst.maxlen = m_msg.maxn;
+
+/*****************************************************************/
+/* Main search loop, which calles do_work() repeatedly           */
+/*****************************************************************/
+
+  cur_n0 = 0;
+  while (1)  {
+/*
+#ifdef DEBUG
+#ifdef PVM_SRC
+    fprintf(stderr," W: %d waiting MSEQTYPE\n",worker);
+#endif
+#ifdef MPI_SRC
+    p4_dprintf(" W: %d waiting MSEQTYPE\n",worker);
+#endif
+#endif
+*/
+
+/*****************************************************************/
+/* Wait for a query sequence from the manager                    */
+/*****************************************************************/
+
+#ifdef PVM_SRC
+    bufid = pvm_recv(hosttid,MSEQTYPE);
+    pvm_upkbyte((char *)&qm_msg,sizeof(qm_msg),1);
+#endif
+#ifdef MPI_SRC
+    MPI_Recv(&qm_msg,sizeof(struct mngmsg),MPI_BYTE,hosttid,MSEQTYPE,
+            MPI_COMM_WORLD,&mpi_status);
+#endif
+#ifdef DEBUG
+    fprintf(stderr,"[%d] have MSEQTYPE n0: %d s_func: %d slist: %d qf: %d\n",
+           worker,qm_msg.n0,qm_msg.s_func,qm_msg.slist,qm_msg.qshuffle);
+#endif
+
+/*****************************************************************/
+/* New query sequence indicated by qm_msg.slist=0                */
+/*****************************************************************/
+
+    if (qm_msg.n0 > 0 && qm_msg.slist == 0) {
+
+      if (cur_n0 > 0) {
+
+/*****************************************************************/
+/*    free everything associated with previous search            */
+/*****************************************************************/
+
+       close_work (aa0[0], cur_n0, &pst, &f_str[0]);  
+       free_ares(seqpt, 0, walign_done[0], walign_cnt[0], worker);
+       walign_cnt[0] = 0;
+       if (m_msg.ann_flg) free(m_msg.aa0a);
+
+
+       if (m_msg.qframe == 2) {
+         close_work(aa0[1], cur_n0, &pst, &f_str[1]);
+         free_ares(seqpt, 1, walign_done[1], walign_cnt[1], worker);
+         walign_cnt[1] = 0;
+       }
+       if (old_shuffle) {
+         close_work(aa0s,cur_n0, &pst, &qf_str);
+         aa0s--;
+         free(aa0s);
+         old_shuffle = 0;
+       }
+       if (pst.pam_pssm) {
+         free_pam2p(pst.pam2p[0]);
+         free_pam2p(pst.pam2p[1]);
+       }
+      }
+
+/*****************************************************************/
+/*    Start allocating things for the next search                */
+/*****************************************************************/
+
+      pst.pam_pssm = qm_msg.pam_pssm;
+      cur_n0 = qm_msg.n0;
+      if (m_msg.ann_flg) {
+       if ((m_msg.aa0a = calloc(qm_msg.n0+1,sizeof(char)))==NULL) {
+         w_abort(" cannot allocate aa0a");
+       }
+      }
+
+/*****************************************************************/
+/*    Get the next query sequence                                */
+/*****************************************************************/
+
+#ifdef PVM_SRC
+      pvm_upkbyte((char *)aa0[0],qm_msg.n0+1+SEQ_PAD,1);
+      if (m_msg.ann_flg) {
+       pvm_upkbyte((char *)m_msg.aa0a,qm_msg.n0+1,1);
+      }
+#endif
+#ifdef MPI_SRC
+      MPI_Recv(aa0[0],qm_msg.n0+1+SEQ_PAD,MPI_BYTE,hosttid,
+              MSEQTYPE1,MPI_COMM_WORLD, &mpi_status);
+      if (m_msg.ann_flg) {
+       MPI_Recv(m_msg.aa0a,qm_msg.n0+1,MPI_BYTE,hosttid,
+                MSEQTYPE2,MPI_COMM_WORLD, &mpi_status);
+      }
+#endif
+
+#ifdef DEBUG
+      /* must have null's at both ends of sequence */
+      if (aa0[0][-1]!= '\0') {
+       fprintf(stderr,"Missing null at start: %s %d\n",
+               qm_msg.libstr,aa0[0][-1]);
+       aa0[0][-1]='\0';
+      }
+      if (aa0[0][qm_msg.n0]!= '\0') {
+       fprintf(stderr,"Missing null at end: %s %d\n",
+               qm_msg.libstr,aa0[0][qm_msg.n0]);
+       aa0[qm_msg.n0]='\0';
+      }
+
+      /* This discovers most reasons for core dumps */
+      if (pst.debug_lib)
+       for (j=0; j<qm_msg.n0; j++)
+         if (aa0[0][j]>pst.nsq) {
+           fprintf(stderr,
+                   "seq: %s residue[%d/%d] %d range (%d)\n",
+                   qm_msg.libstr,j,qm_msg.n0,aa0[0][j],pst.nsq);
+           aa0[0][j]=0;
+           qm_msg.n0=j-1;
+           break;
+         }
+#endif
+      update_params(&qm_msg,&m_msg,&pst);
+    }
+
+/*****************************************************************/
+/*    End of free()'s/ initialization for new sequence           */
+/*****************************************************************/
+
+#ifdef PVM_SRC
+    pvm_freebuf(bufid);
+#endif
+
+    if (qm_msg.n0 == -1) {
+
+/*****************************************************************/
+/*   All done with searches                                      */
+/*****************************************************************/
+/*    printf(" %d: got n0 == -1\n",worker); */
+      break;
+    }
+
+    /*    p4_dprintf(" W:%d n0:%d slist:%d s_func:%d (%d)\n",worker,qm_msg.n0,qm_msg.slist,qm_msg.s_func,qres_bufsize); */
+
+/*****************************************************************/
+/*   if qm_msg.slist > 0, search specific sequences, to be sent  */
+/*****************************************************************/
+
+    if (qm_msg.slist > 0) {  /* list search, not library search */
+      if (liblist != NULL) free(liblist);
+
+      /* get the list of sequences */
+      if ((liblist=(struct stage2_str *)
+          calloc(qm_msg.slist,sizeof(struct stage2_str)))==NULL) {
+         sprintf(errstr,"sequence list %d",qm_msg.slist);
+         w_abort (errstr, "");
+       }
+
+#ifdef PVM_SRC
+      bufid = pvm_recv(hosttid,LISTTYPE);
+      pvm_upkbyte((char *)liblist,qm_msg.slist*sizeof(struct stage2_str),1);
+      pvm_freebuf(bufid);
+#endif
+#ifdef MPI_SRC
+      MPI_Recv(liblist,qm_msg.slist*sizeof(struct stage2_str),MPI_BYTE,
+              hosttid,LISTTYPE,MPI_COMM_WORLD, &mpi_status);
+#endif
+    }
+
+/*****************************************************************/
+/* have list of sequences to be compared/aligned                 */
+/*****************************************************************/
+
+    /* Initial stuff */
+    if (qm_msg.slist == 0) {
+/*****************************************************************/
+/* New query - set up matrices and init_work()                   */
+/*****************************************************************/
+#ifdef DEBUG
+/*
+      fprintf(stderr,"n1: %d\t",qm_msg.n0);
+      for (i=0; i<10; i++) fprintf(stderr,"%c",nt[aa0[0][i]]);
+      fprintf(stderr,"\n");
+*/
+#endif
+      if (pst.pam_pssm) {
+       pst.pam2p[0] = alloc_pam2p(qm_msg.n0,nsq);
+       pst.pam2p[1] = alloc_pam2p(qm_msg.n0,nsq);
+      }
+
+      init_work (aa0[0], qm_msg.n0, &pst, &f_str[0]);
+      f_str[5]=f_str[4]=f_str[3]=f_str[2]=f_str[1]=f_str[0];
+
+      if (qm_msg.qshuffle) {
+       if ((aa0s=(unsigned char *)malloc((qm_msg.n0+2)*sizeof (char)))==NULL)
+         w_abort ("Unable to allocate aa0s array - exiting!","");
+       *aa0s='\0';
+       aa0s++;
+
+       memcpy(aa0s,aa0[0],qm_msg.n0+1);
+       qshuffle(aa0s,qm_msg.n0,qm_msg.nm0);
+#ifdef DEBUG
+       fprintf(stderr,"[%d] shuffle: %d\n",worker,qm_msg.n0);
+       fputs("   ",stderr);
+       for (i=0; i<5; i++) {fprintf(stderr,"%c",pst.sq[aa0s[i]]);}
+       fputc('\n',stderr);
+#endif
+
+       init_work (aa0s, qm_msg.n0, &pst, &qf_str);
+       old_shuffle=1;
+      }
+
+      if (m_msg.qframe == 2) {
+       memcpy(aa0[1],aa0[0],qm_msg.n0+1);
+       revcomp(aa0[1],qm_msg.n0,&pst.c_nt[0]);
+       init_work (aa0[1], qm_msg.n0, &pst, &f_str[1]);
+      }
+#ifdef DEBUG
+/*
+       fprintf(stderr,"[%d] init_work qf: %d nf: %d\n",worker,m_msg.qframe,m_msg.nframe);
+*/
+#endif
+    }
+
+/*****************************************************************/
+/* Finished with initialization,                                 */
+/* start doing comparisons or alignments                         */
+/*****************************************************************/
+
+    bestcnt = 0;
+    if (qm_msg.slist == 0) {   /* library search */
+
+/*****************************************************************/
+/* Start library search                                          */
+/*****************************************************************/
+
+      for (count=0; count < lcnt; count++) {
+
+       for (itt=m_msg.revcomp; itt<=m_msg.nitt1; itt++) {
+
+         rst.score[0] = rst.score[1] = rst.score[2] = 0;
+         if (m_msg.self) {
+           lsn = lend + count;
+           if ((qm_msg.seqnm > lsn) && (((qm_msg.seqnm + lsn) % 2) != 0)) {
+             do_work (aa0[itt], qm_msg.n0,seqpt[count].aa1, seqpt[count].n1,
+                      itt, &pst, f_str[itt], 0, &rst);
+           }
+           else if ((qm_msg.seqnm <= lsn) && (((qm_msg.seqnm+lsn)%2) == 0)) {
+             do_work (aa0[itt], qm_msg.n0, seqpt[count].aa1, seqpt[count].n1, 
+                      itt, &pst, f_str[itt], 0, &rst);
+           }
+           else continue;
+         }
+         else {
+           do_work (aa0[itt], qm_msg.n0, seqpt[count].aa1, seqpt[count].n1,
+                    itt, &pst, f_str[itt], 0, &rst);
+           if (qm_msg.qshuffle) {
+             do_work (aa0s, qm_msg.n0, seqpt[count].aa1, seqpt[count].n1,
+                    itt, &pst, qf_str, 1, &qrst);
+           }
+         }
+#ifdef DEBUG
+/*
+         if (count < 10 || (count % 200 == 199)) {
+           fprintf(stderr,"[node %d] itt:%d/%d (%d) %3d %3d %3d - %d/%d\n",
+                   worker,itt,m_msg.nitt1,count,
+                   rst.score[0],rst.score[1],rst.score[2],
+                   seqpt[count].m_seqnm,seqpt[count].n1);
+         }
+*/
+#endif
+         sw_score = -1;
+
+         bestr[bestcnt].seqnm  = count;
+         bestr[bestcnt].m_seqnm  = seqpt[count].m_seqnm;
+         bestr[bestcnt].score[0] = rst.score[0];
+         bestr[bestcnt].score[1] = rst.score[1];
+         bestr[bestcnt].score[2] = rst.score[2];
+         bestr[bestcnt].escore = rst.escore;
+         bestr[bestcnt].segnum = rst.segnum;
+         bestr[bestcnt].seglen = rst.seglen;
+         bestr[bestcnt].frame = itt;
+         bestr[bestcnt].comp = rst.comp;
+         bestr[bestcnt].H = rst.H;
+
+         bestr[bestcnt].qr_score = qrst.score[pst.score_ix];
+         bestr[bestcnt].qr_escore = qrst.escore;
+
+         if (pst.zsflag >= 10) {
+           if (pst.zs_win > 0) 
+             wshuffle(seqpt[count].aa1, aa1s,seqpt[count].n1,pst.zs_win,&ieven);
+           else 
+             shuffle(seqpt[count].aa1, aa1s,seqpt[count].n1);
+
+           do_work(aa0[itt],qm_msg.n0,aa1s,seqpt[count].n1,itt, &pst, 
+                   f_str[itt], 0, &rst);
+           bestr[bestcnt].r_score = rst.score[pst.score_ix];
+         }
+
+         bestcnt++;
+         if (bestcnt >= qres_bufsize) {
+#ifdef DEBUG
+           fprintf(stderr," worker: %d sending %d results\n",worker,qres_bufsize);
+#endif
+           send_bestr(hosttid,curtype,bestr,qres_bufsize,bestcnt);
+           bestcnt = 0;
+         }
+       }
+      }        /* END - for count loop */
+      send_bestr(hosttid, curtype, bestr,qres_bufsize, (bestcnt | FINISHED));
+    }
+
+/*****************************************************************/
+/* End of library search section                                 */
+/*****************************************************************/
+
+/*****************************************************************/
+/* Do do_opt() from list   s_func=DO_CALC_FLG                    */
+/*****************************************************************/
+
+    else if (qm_msg.s_func== DO_CALC_FLG) {  /* qm_msg.slist > 0 */
+
+      bestcnt = 0;
+      for (count=0; count < qm_msg.slist; count++) {
+       rst.score[0] = rst.score[1] = rst.score[2] = 0;
+       itt = liblist[count].frame;
+       seqnm = bestr2[bestcnt].seqnm  = liblist[count].seqnm;
+       bestr2[bestcnt].m_seqnm = seqpt[seqnm].m_seqnm;
+
+       do_opt (aa0[itt], qm_msg.n0, seqpt[seqnm].aa1,
+                seqpt[seqnm].n1, itt,
+                &pst, f_str[itt], &rst);
+
+       bestr2[bestcnt].score[0] = rst.score[0];
+       bestr2[bestcnt].score[1] = rst.score[1];
+       bestr2[bestcnt].score[2] = rst.score[2];
+       bestr2[bestcnt].escore = rst.escore;
+       bestr2[bestcnt].segnum = rst.segnum;
+       bestr2[bestcnt].seglen = rst.seglen;
+       bestr2[bestcnt].aln_code_n = 0;
+       bestcnt++;
+
+       if (bestcnt >= BFR2) {
+         send_bestr2(hosttid,bestr2,bestcnt);
+         bestcnt = 0;
+       }
+      }        /* END - for count loop */
+
+      send_bestr2(hosttid,bestr2,(bestcnt|FINISHED));
+    }
+
+/*****************************************************************/
+/* s_func=DO_OPT_FLG                                             */
+/*                                                               */
+/* from list:                                                    */
+/* if (m_msg.stages > 1) do_opt()                                */
+/* do_walign()                                                   */
+/* calc_id or calc_code, no calcons                              */
+/*****************************************************************/
+
+    /* s_func == 1 means do_opt if necessary */
+    else if (qm_msg.s_func== DO_OPT_FLG) {  /* qm_msg.slist > 0 */
+#ifdef DEBUG
+      fprintf(stderr," [%d] starting s_func:1 slist: %d\n",
+             worker,qm_msg.slist);
+#endif
+      /* get the buffer once - re-use it for the entire slist */
+      if (m_msg.show_code == SHOW_CODE_ALIGN) {
+       seqc_buff_len = (BFR2+5)*256;
+       seqc = seqc_buff = (char *)calloc(seqc_buff_len,sizeof(char));
+       seqc_buff_cnt = 0;
+       if (seqc_buff == NULL) {
+         seqc_buff_cnt = seqc_buff_len = 0;
+       }
+      }
+
+      bestcnt = 0;
+      for (count=0; count < qm_msg.slist; count++) {
+       rst.score[0] = rst.score[1] = rst.score[2] = 0;
+       itt = liblist[count].frame;
+       seqnm = liblist[count].seqnm;
+
+       bestr2[bestcnt].seqnm  = seqnm;
+       bestr2[bestcnt].m_seqnm = seqpt[seqnm].m_seqnm;
+       if (m_msg.stages > 1) {
+         do_opt (aa0[itt], qm_msg.n0, seqpt[seqnm].aa1,
+                 seqpt[seqnm].n1, itt,
+                 &pst, f_str[itt], &rst);
+
+         bestr2[bestcnt].score[0] = rst.score[0];
+         bestr2[bestcnt].score[1] = rst.score[1];
+         bestr2[bestcnt].score[2] = rst.score[2];
+       }
+
+       if (m_msg.markx & MX_M9SUMM) {
+#ifdef DEBUG
+         fprintf(stderr," [%d] starting do_walign seqnm: %d n1: %d\n",
+                 worker,seqnm,seqpt[seqnm].n1);
+#endif
+         aln_dp = &bestr2[bestcnt].aln_d;
+         memcpy(aln_dp, &aln,sizeof(struct a_struct));
+
+         sw_score = do_walign(aa0[itt], qm_msg.n0,
+                              seqpt[seqnm].aa1, seqpt[seqnm].n1,
+                              itt, &pst, f_str[itt],
+                              &seqpt[seqnm].a_res[itt],
+                              &have_walign);
+         seqpt[seqnm].sw_score[itt] = sw_score;
+
+         /* the a_res[itt] provided by do_walign is re-used - so it
+            must be copied to a valid location */
+
+         if (have_walign) {
+           if ((tres = calloc(seqpt[seqnm].a_res[itt].nres+1,sizeof(int)))==NULL) {
+             w_abort(" cannot allocate tres");
+           }
+           else {
+             memcpy(tres,seqpt[seqnm].a_res[itt].res,sizeof(int)*seqpt[seqnm].a_res[itt].nres);
+             seqpt[seqnm].a_res[itt].res = tres;
+             /*
+               fprintf(stderr, " [%d] saving %d:%d[%d]:%o\n", worker, 
+               walign_cnt[itt],seqnm,itt, seqpt[seqnm].a_res[itt].res);
+             */
+             if (walign_cnt[itt] < lcnt) walign_done[itt][walign_cnt[itt]++] = seqnm;
+             else w_abort(" walign_cnt overrun");
+             seqpt[seqnm].walign_dflg[itt] = 1;
+           }
+         }
+         aln_func_vals(itt, aln_dp);
+
+#ifdef DEBUG
+         fprintf(stderr," [%d] starting calc_id sw_score: %d\n",
+                 worker,sw_score);
+         fprintf(stderr,"bi: %d seqc_buff_cnt: %d - seqc_buff_len: %d\n",
+                 bestcnt, seqc_buff_cnt, seqc_buff_len);
+#endif
+         aln_code_n = 0;       /* must be set in case no seqc_code */
+         if (m_msg.show_code == SHOW_CODE_ALIGN) {
+           if (seqc_buff_cnt < seqc_buff_len - 256) {
+             lc=calc_code(aa0[itt],qm_msg.n0,
+                          seqpt[seqnm].aa1, seqpt[seqnm].n1,
+                          aln_dp,seqpt[seqnm].a_res[itt],pst,
+                          seqc,seqc_buff_len-seqc_buff_cnt-10,
+                          f_str[itt]);
+             aln_code_n = strlen(seqc);
+             seqc_buff_cnt += aln_code_n + 1;
+/*
+             fprintf(stderr,"%d:%d:%d: %d/%d - [%d] %s\n",
+                     worker,seqnm,bestcnt,aln_code_n,seqc_buff_cnt, seqc-seqc_buff,seqc);
+*/
+             seqc += aln_code_n;
+             *seqc++ = '\0';
+           }
+         }
+         else {
+           lc=calc_id(aa0[itt],qm_msg.n0,
+                      seqpt[seqnm].aa1, seqpt[seqnm].n1,
+                      aln_dp,seqpt[seqnm].a_res[itt],pst,f_str[itt]);
+         }
+
+         nident = aln_dp->nident;
+         aln_dp->a_len = lc;
+
+         if (lc > 0) percent = (100.0*(float)nident)/(float)lc;
+         else percent = 0.0;
+
+         ngap = aln_dp->ngap_q + aln_dp->ngap_l;
+#ifndef SHOWSIM
+         if (lc-ngap > 0) gpercent = (100.0*(float)nident)/(float)(lc-ngap);
+#else
+         if (lc > 0) gpercent =(100.0*(float)aln_dp->nsim)/(float)lc;
+#endif
+         else gpercent = -1.0;
+
+         bestr2[bestcnt].sw_score = sw_score;
+         bestr2[bestcnt].percent = percent;
+         bestr2[bestcnt].gpercent = gpercent;
+         bestr2[bestcnt].aln_code_n = aln_code_n;
+       }
+       bestcnt++;
+
+       if (bestcnt >= BFR2) {
+         send_bestr2(hosttid,bestr2,bestcnt);
+         if (m_msg.show_code == SHOW_CODE_ALIGN) {
+           send_code(hosttid,seqc_buff,seqc_buff_cnt);
+           memset(seqc_buff,0,seqc_buff_len);
+           seqc = seqc_buff;
+           seqc_buff_cnt = 0;
+         }
+         bestcnt = 0;
+       }
+      }        /* END - for count loop */
+
+      send_bestr2(hosttid,bestr2,(bestcnt|FINISHED));
+      if (m_msg.show_code == SHOW_CODE_ALIGN) {
+       send_code(hosttid,seqc_buff,seqc_buff_cnt);
+       if (seqc_buff) free(seqc_buff);
+      }
+    }
+    /* get alignments */
+
+/*****************************************************************/
+/* s_list >                                                      */
+/* s_func=DO_ALIGN_FLG                                           */
+/*                                                               */
+/* from list:                                                    */
+/* do_walign() if not done already                               */ 
+/* calcons()                                                     */
+/*****************************************************************/
+
+    else if (qm_msg.s_func==DO_ALIGN_FLG) {
+      for (count=0; count < qm_msg.slist; count++) {
+       itt = liblist[count].frame;
+       seqnm = liblist[count].seqnm;
+/*
+       fprintf(stderr,"worker: %d; %s, frame: %d\n",worker,qm_msg.libstr,itt);
+*/
+       if (!seqpt[seqnm].walign_dflg[itt]) {
+         seqpt[seqnm].sw_score[itt] = 
+           sw_score = do_walign (aa0[itt], qm_msg.n0,seqpt[seqnm].aa1,
+                                 seqpt[seqnm].n1, itt,
+                                 &pst, f_str[itt],
+                                 &seqpt[seqnm].a_res[itt],
+                                 &have_walign);
+       }
+       else {
+         sw_score = seqpt[seqnm].sw_score[itt];
+         pre_cons(seqpt[seqnm].aa1,seqpt[seqnm].n1,itt,f_str[itt]);
+       }
+
+       aln_func_vals(itt, &aln);
+
+       if (aln.showall==1)
+         maxc = seqpt[seqnm].a_res[itt].nres + max(seqpt[seqnm].a_res[itt].min0,seqpt[seqnm].a_res[itt].min1)+
+           max((qm_msg.n0-seqpt[seqnm].a_res[itt].max0),
+               (seqpt[seqnm].n1-seqpt[seqnm].a_res[itt].max1))+4;
+       else  maxc = seqpt[seqnm].a_res[itt].nres + 4*aln.llen+4;
+
+       initseq(&seqc0, &seqc0a, &seqc1, &seqca, maxc);
+
+       if (!m_msg.ann_flg) {
+         nc=calcons(aa0[itt],qm_msg.n0,
+                  seqpt[seqnm].aa1, seqpt[seqnm].n1,
+                  &lc,&aln,seqpt[seqnm].a_res[itt],pst,
+                  seqc0,seqc1,seqca,f_str[itt]);
+         memset(seqc0a,' ',nc);
+         seqc0a[nc]='\0';
+       }
+       else {
+         nc=calcons_a(aa0[itt],m_msg.aa0a,qm_msg.n0,
+                      seqpt[seqnm].aa1, seqpt[seqnm].n1,
+                      &lc,&aln,seqpt[seqnm].a_res[itt],pst,
+                      seqc0,seqc0a,seqc1,seqca,
+                      m_msg.ann_arr,f_str[itt]);
+       }
+
+       /*
+       fprintf(stderr,"[%d] nident: %d nsim: %d lc: %d\n",aln.nident, aln.nsim, lc);
+       */
+
+       maxc = max(strlen(seqc0),strlen(seqc1))+1;
+       nident = aln.nident;
+       percent = (100.0*(float)nident)/(float)lc;
+       ngap = aln.ngap_q+aln.ngap_l;
+#ifndef SHOWSIM
+       if (lc-ngap > 0) gpercent = (100.0*(float)nident)/(float)(lc-ngap);
+#else
+       if (lc > 0) gpercent = (100.0*(float)aln.nsim)/(float)lc;
+#endif
+       else gpercent = -1.0;
+
+#ifdef PVM_SRC
+       pvm_initsend(PvmDataRaw);
+       pvm_pkint(&nc,1,1);
+       pvm_pkint(&lc,1,1);
+       pvm_pkint(&maxc,1,1);
+       pvm_pkfloat(&percent,1,1);
+       pvm_pkfloat(&gpercent,1,1);
+       pvm_pkint(&sw_score,1,1);
+       pvm_pkbyte((char *)&aln,sizeof(struct a_struct),1);
+       pvm_send(hosttid,ALN1TYPE);
+#ifdef DEBUG
+       fprintf(stderr,"[%d] ALN1TYPE sent: %d\n",worker,qm_msg.n0);
+#endif
+       pvm_initsend(PvmDataRaw);
+       pvm_pkbyte(seqc0,maxc,1);
+       if (m_msg.ann_flg) pvm_pkbyte(seqc0a,maxc,1);
+       pvm_pkbyte(seqc1,maxc,1);
+       pvm_pkbyte(seqca,maxc,1);
+       pvm_send(hosttid,ALN2TYPE);
+#endif
+#ifdef MPI_SRC
+       last_msg_b[0]=nc;
+       last_msg_b[1]=lc;
+       last_msg_b[2]=maxc;
+       last_msg_b[3]=sw_score;
+       MPI_Send(last_msg_b,4,MPI_INT,hosttid,ALN1TYPE,MPI_COMM_WORLD);
+       MPI_Send(&percent,1,MPI_FLOAT,hosttid,ALN2TYPE,MPI_COMM_WORLD);
+       MPI_Send(&gpercent,1,MPI_FLOAT,hosttid,ALN2TYPE,MPI_COMM_WORLD);
+
+/*     p4_dprintf("[%d] sending aln\n",worker); */
+       MPI_Send(&aln,sizeof(struct a_struct),MPI_BYTE,hosttid,
+                ALN3TYPE,MPI_COMM_WORLD);
+
+       MPI_Send(seqc0,maxc,MPI_BYTE,hosttid,ALN2TYPE,MPI_COMM_WORLD);
+       if (m_msg.ann_flg) MPI_Send(seqc0a,maxc,MPI_BYTE,hosttid,ALN2TYPE,MPI_COMM_WORLD);
+       MPI_Send(seqc1,maxc,MPI_BYTE,hosttid,ALN3TYPE,MPI_COMM_WORLD);
+       MPI_Send(seqca,maxc,MPI_BYTE,hosttid,ALN3TYPE,MPI_COMM_WORLD);
+#endif
+       freeseq(&seqc0,&seqc0a,&seqc1,&seqca);
+      }        
+    }
+    
+/* send back parameter settings */
+    if (worker==FIRSTWORK && qm_msg.slist==0) {
+      get_param(&pst, gstring2,gstring3);
+#ifdef PVM_SRC
+      pvm_initsend(PvmDataRaw);
+      pvm_pkbyte(gstring2,sizeof(gstring2),1);
+      pvm_pkbyte(gstring3,sizeof(gstring3),1);
+      pvm_send(hosttid,PARAMTYPE);
+#endif
+#ifdef MPI_SRC
+      MPI_Send(gstring2,sizeof(gstring2),MPI_BYTE,
+              hosttid,PARAMTYPE,MPI_COMM_WORLD);
+      MPI_Send(gstring3,sizeof(gstring3),MPI_BYTE,
+              hosttid,PARAMTYPE,MPI_COMM_WORLD);
+#endif
+    }
+    
+    if (qm_msg.slist==0) {
+      if (curtype == ONETYPE) curtype = TWOTYPE;
+      else curtype = ONETYPE;
+    }
+  }        /* END - while (1) loop */
+#ifdef PVM_SRC
+  pvm_exit();
+#endif
+#ifdef MPI_SRC
+/*  MPI_Finalize(); */
+#endif
+}
+
+void
+send_bestr(int hosttid, int curtype, 
+          struct comstr *bestr, int buf_size, int lastcnt) {
+
+  bestr[buf_size].seqnm = lastcnt;
+#ifdef PVM_SRC
+  pvm_initsend(PvmDataRaw);
+  pvm_pkbyte((char *)&bestr[0],sizeof(struct comstr)*(buf_size+1),1);
+  pvm_send(hosttid,curtype);
+#endif
+#ifdef MPI_SRC
+  MPI_Send(bestr,sizeof(struct comstr)*(buf_size+1),MPI_BYTE,
+          hosttid,curtype,MPI_COMM_WORLD);
+#endif
+}
+
+void
+send_bestr2(int hosttid, struct comstr2 *bestr2,
+           int lastcnt)
+{
+  bestr2[BFR2].seqnm = lastcnt;
+#ifdef PVM_SRC
+  pvm_initsend(PvmDataRaw);
+  pvm_pkbyte((char *)&bestr2[0],sizeof(struct comstr2)*(BFR2+1),1);
+  pvm_send(hosttid,LISTRTYPE);
+#endif
+#ifdef MPI_SRC
+  MPI_Send(&bestr2[0],sizeof(struct comstr2)*(BFR2+1),MPI_BYTE,
+          hosttid,LISTRTYPE,MPI_COMM_WORLD);
+#endif
+}
+
+void
+send_code(int hosttid, char *seqc_buff, int seqc_buff_len) {
+
+#ifdef PVM_SRC
+  pvm_initsend(PvmDataRaw);
+  pvm_pkint(&seqc_buff_len,1,1);
+  if (seqc_buff_len > 0) pvm_pkbyte(seqc_buff,seqc_buff_len,1);
+  pvm_send(hosttid,CODERTYPE);
+#endif
+#ifdef MPI_SRC
+  MPI_Send(&seqc_buff_len,1,MPI_INT,
+          hosttid,CODERTYPE,MPI_COMM_WORLD);
+  if (seqc_buff_len>0) MPI_Send(seqc_buff,seqc_buff_len,MPI_BYTE,
+                              hosttid,CODERTYPE,MPI_COMM_WORLD);
+#endif
+}
+
+#ifdef PVM_SRC
+int tidtonode(tid)
+     int tid;
+{
+  int i;
+  for (i=FIRSTNODE; i< nnodes; i++) if (tid==pinums[i]) return i;
+  fprintf(stderr," cannot find tid %d\n",tid);
+  return -1;
+}
+#endif
+
+void
+free_ares(struct sqs2 *seqpt, int itt, int *walign_done, int walign_cnt, int worker) {
+
+  int i, seqnm;
+
+  for (i=0; i< walign_cnt; i++) {
+    seqnm = walign_done[i];
+    walign_done[i]=0;
+    if (seqpt[seqnm].walign_dflg[itt]) {
+      if (seqpt[seqnm].a_res[itt].nres > 0 ) {
+       /*
+       fprintf(stderr, "[%d] freeing %d:%d[%d]:%o\n",
+               worker,i,seqnm,itt,seqpt[seqnm].a_res[itt].res);
+       */
+       seqpt[seqnm].a_res[itt].nres = 0;
+       free(seqpt[seqnm].a_res[itt].res);
+      }
+    }
+    else {
+      w_abort(" have walign_done but no walign_dflag");
+    }
+    seqpt[seqnm].walign_dflg[itt] = 0;
+  }
+}