
#include "sr_linda.h"

struct tuple_msg_type
{
    int type;
    char mask[20];
    char hanger[128];
    int aggreg_size;
    int tuple_size;
    char aggreg_data[AG_MAX];
};

struct tuple_msg_type tuple_channel;

struct space_q
{
    struct space_q *next;
    char mask[20];
    char hanger[128];
    int aggreg_size;
    int tuple_size;
    char aggreg_data[AG_MAX];
} *head_avl_nodeq, *tuple_space[256], *space_tails[256], *head;

struct wait_queue
{
    int id;
    int type;
    char mask[20];
    char hanger[128];
    struct wait_queue *next;
} *head_avl_waitq, *wait_head, *wait_tail;

struct globals
{
    int aglen;
    int *size_ptr;
} global;



tm()
{

    int tmsg, id, ln, i;
    struct tuple_msg_type *tcp;

    wait_tail = NULL; 
    wait_head = NULL;
    head_avl_waitq = NULL;
    for (i = 0; i < 256; i++)
    {
	tuple_space[i] = NULL;
	space_tails[i] = NULL;
    }
    head_avl_nodeq = NULL;
    tmsg = -1;
    id = -1;
    tcp =  NULL;
    p4_recv(&tmsg, &id, &tcp, &ln);
    bcopy(tcp,&tuple_channel,ln);

    while (tuple_channel.type != END)
    {
	p4_dprintfl(99,"tm: servicing reqtype=%d from id=%d mask=%s\n",
		    tuple_channel.type,id,tuple_channel.mask);
	if ((tuple_channel.type == RD) || (tuple_channel.type == IN))
	    serve_in_or_rd(id, tuple_channel.type);
	else if (tuple_channel.type == OUT)
	{
	    if (qcheck() == 0)
	    {
		drop_in(ln);
	    }
	}
	tmsg = -1;
	id = -1;
	tcp = NULL;
	p4_dprintfl(88,"tm: recving\n");
	p4_recv(&tmsg, &id, &tcp, &ln);
	bcopy(tcp,&tuple_channel,ln);
    }
}


qcheck()
{
    char *p, *pout, *pin;
    int i, tln, qid, found, mismatch, found_in, hold_type;
    char buffer[80], tmpmask[80], tempin[80], outtok[80], intok[80], outbuf[80];
    struct wait_queue *wait_node, *pred, *saveq;

    pred = wait_head;
    wait_node = wait_head;
    found_in = 0;
    found = 0;
    while (wait_node != NULL)
    {
	qid = wait_node->id;
	p4_dprintfl(99,"matching waitnode=%d waithanger=%s tuplehanger=%s\n",
		    wait_node->id,wait_node->hanger,tuple_channel.hanger);
	/* cannot get 2 INs from one tuple */
	if (!found_in  ||  wait_node->type != IN)  
	{
	    if (match(tuple_channel.hanger,wait_node->hanger,wait_node->mask))
	    {
	        found = 1;
	        p4_dprintfl(99,"qcheck matched on node with id=%d\n",wait_node->id);
	    }
	}
	if (found)
	{
	    saveq = wait_node;
	    hold_type = wait_node->type;

	    tuple_channel.type = hold_type;
	    tln = tuple_channel.tuple_size;
	    p4_send(tuple_channel.type, qid, &tuple_channel, tln);

	    if (wait_node == wait_head)
	    {
		wait_head = wait_node->next;
		pred = wait_node;
		wait_node = wait_node->next;
		if (wait_head == NULL)
		    wait_tail = wait_head;
	    }
	    else if (wait_node == wait_tail)
	    {
		pred->next = NULL;
		wait_tail = pred;
		pred = wait_node;
		wait_node = NULL;
	    }
	    else
	    {
		pred->next = wait_node->next;
		pred = wait_node;
		wait_node = wait_node->next;
	    }
	    p4_dprintfl(99,"servrdin: found one for %d             ; dequeued  him ; wait_head=%d\n",
			qid,wait_head);

	    if (hold_type == IN)
		found_in = 1;
	    found = 0;

	    saveq->next = head_avl_waitq;
	    head_avl_waitq = saveq;
	}
	else
	{
	    p4_dprintfl(99,"qcheck failed match on node with id=%d\n",wait_node->id);
	    pred = wait_node;
	    wait_node = wait_node->next;
	    found = 0;
	}
    }				/* end while2 */

    return (found_in);
}				/* end checkq */

drop_in(ln)
int ln;
{


    struct space_q *temp_node, *space_node;
    struct space_q *alloc_space_q();
    int i, hashnum;
    char key[20];

    stok(key, tuple_channel.hanger);
    hashnum = thash(key);

    if (tuple_space[hashnum] == NULL)
    {
	space_node = alloc_space_q(ln);
	bcopy(tuple_channel.mask, space_node->mask, ln - sizeof(tuple_channel.type));
	space_node->next = NULL;
	tuple_space[hashnum] = space_node;
	space_tails[hashnum] = space_node;
    }
    else
    {
	space_node = alloc_space_q(ln);
	bcopy(tuple_channel.mask, space_node->mask, ln - sizeof(tuple_channel.type));
	space_node->next = NULL;
	space_tails[hashnum]->next = space_node;
	space_tails[hashnum] = space_node;
    }

}				/* end drop_in */

serve_in_or_rd(id, type)
int id, type;
{
    int rc;
    char *p;
    struct space_q *space_node, *pred;
    struct wait_queue *wait_node, *alloc_wait_q();
    struct aggregate *agnode;
    int stok();
    int tln, aglen, integer, cnt, found, mismatch, tokint, i, j;
    int *dchr, *achr, *schr;
    int hashnum;
    char *char_ptr;
    char outbuf[80];
    char temp[80];
    char intok[80], tmpmask[80], key[80], tokchr[80];
    char *pchr, *pout, *pin, *template, *hanger, *mask;


    found = 0;

    stok(key, tuple_channel.hanger);

    hashnum = thash(key);

    pred = tuple_space[hashnum];
    space_node = tuple_space[hashnum];
    while ((!found) && (space_node != NULL))
    {
	if (match(space_node->hanger, tuple_channel.hanger, tuple_channel.mask))
	{
	    found = 1;
	}
	else
	{
	    pred = space_node;
	    space_node = space_node->next;
	}
    }				/* end while inner */
    if (found)
    {
	p4_dprintfl(99,"servrdin: found tuple for id=%d reqtype=%d\n",id,type);
	if (type == IN)
	{
	    p4_dprintfl(10,"servrdin: unhooking for id=%d an in\n",id);
	    if (space_node == tuple_space[hashnum])
		tuple_space[hashnum] = space_node->next;
	    else if (space_node->next == NULL)
	    {
		pred->next = NULL;
		space_tails[hashnum] = pred;
	    }
	    else
		pred->next = space_node->next;

	}			/* end if type == IN */
	bcopy(space_node->mask, tuple_channel.mask, space_node->tuple_size);
	p4_send(tuple_channel.type, id, &tuple_channel, space_node->tuple_size);
	if (type == IN)
	{
	    p4_shfree(space_node);
	}
    }
    else
    {
	p4_dprintfl(99,"servrdin: did not find tuple for id=%d ; queueing him ; wait_head=%d mask=%s\n",
		    id,wait_head,tuple_channel.mask);

	wait_node = alloc_wait_q();
	/* may need to do COPY here */
	wait_node->id = id;
	wait_node->type = tuple_channel.type;
	strcpy(wait_node->mask, tuple_channel.mask);
	strcpy(wait_node->hanger, tuple_channel.hanger);
	wait_node->next = NULL;
	if (wait_head == NULL)
	{
	    wait_tail = wait_node;
	    wait_head = wait_node;
	}
	else
	{
	    wait_tail->next = wait_node;
	    wait_tail = wait_node;
	}
    }
}


struct space_q *
alloc_space_q(t_ln)
int t_ln;
{
    struct space_q *node;

    node = (struct space_q *) p4_shmalloc(t_ln);
    if (node == NULL)
	printf("Failed malloc in node\n");

    return (node);
}

struct wait_queue *
alloc_wait_q()
{
    struct wait_queue *node;

    if ((node = head_avl_waitq) == NULL)
    {
	node = (struct wait_queue *) p4_shmalloc(sizeof(struct wait_queue));
	if (node == NULL)
	    printf("Failed malloc in wait\n");
    }

    else
    {
	head_avl_waitq = node->next;
    }

    return (node);
}


out(tuple_mask,va_alist)
char tuple_mask[80];
va_dcl
{
    va_list tuple_list;
    char *p;
    int type, tln, integer, id;
    int *a;
    char *char_ptr;
    char temp[80];
    char hanger[128];
    char *s;


    type = OUT;
    global.aglen = 1;

    tuple_channel.aggreg_size = 0;
    tuple_channel.aggreg_data[0] = '0';
    va_start(tuple_list);
    strcpy(tuple_channel.mask, tuple_mask);
    parse(tuple_mask, type, hanger, tuple_list);
    va_end(tuple_list);

    strcpy(tuple_channel.hanger, hanger);
    tuple_channel.type = OUT;
    id = p4_get_my_id();
    tln = sizeof(tuple_channel.aggreg_size) + sizeof(tuple_channel.type) + sizeof(tuple_channel.mask) + sizeof(tuple_channel.hanger) + sizeof(tuple_channel.tuple_size) + global.aglen;

    tuple_channel.tuple_size = tln;
    p4_sendr(tuple_channel.type, 1, &tuple_channel, tln);
    return(0);
}				/* end out */


in(tuple_mask,va_alist)
char tuple_mask[80];
va_dcl
{
    va_list tuple_list;
    char *p;
    struct space_q *space_node, *pred;
    int stok();
    int dum, tln, id, ln, integer, cnt, found, mismatch, tokint;
    int *int_ptr, *dchr, *achr, *schr;
    char *char_ptr;
    char outbuf[80], template[128];
    char temp[80];
    char intok[80], outtok[80], tokchr[80];
    char *pchr, *pout, *pin;
    int tmsg, rc, n, type, fromid;
    struct tuple_msg_type *tcp;

    type = IN;
    va_start(tuple_list);
    strcpy(tuple_channel.mask, tuple_mask);
    parse(tuple_mask, type, template, tuple_list);
    va_end(tuple_list);

    strcpy(tuple_channel.hanger, template);
    tuple_channel.type = type;
    tln = tuple_channel.tuple_size = sizeof(tuple_channel);
    p4_dprintfl(50,"in: sending a msg to 1\n");
    p4_send(tuple_channel.type, 1, &tuple_channel, tln);
    p4_dprintfl(50,"in: sent a msg to 1\n");
    id = p4_get_my_id();
    tmsg = -1;
    fromid = -1;
    tcp = NULL;
    p4_dprintfl(50,"in: recving a msg\n");
    p4_recv(&tmsg, &fromid, &tcp, &ln);
    p4_dprintfl(50,"in: recved a msg from %d\n",fromid);
    if (tmsg == END)
    {
	rc = END;
    }
    else
    {
	bcopy(tcp,&tuple_channel,ln);
	instantiate(tuple_mask, template, tuple_channel.hanger);
	rc = 0;
    }
    return(rc);
}


parse(tuple_mask, type, buffer, tuple_list)
char *tuple_mask, *buffer;
int type;
va_list tuple_list;
{
    char *mask_ptr;
    struct space_q *space_node, *pred;
    int stok();
    int dum, tln, id, ln, integer, size, cnt, found, mismatch, tokint;
    int *int_ptr, *dchr, *achr, *a, *schr;
    char *char_ptr;
    char outbuf[80];
    char temp[80];
    char intok[80], outtok[80], tokchr[80];
    char *pchr, *pout, *pin;
    double flt;
    double *flt_ptr;
    int rc, n;

    if (tuple_mask[1] == 's')
    {
	char_ptr = va_arg(tuple_list, char *);
	sprintf(buffer, "%s ", char_ptr);
    }
    else
    {
	integer = va_arg(tuple_list, int);
	sprintf(buffer, "%d ", integer);
    }
    for (mask_ptr = tuple_mask + 2; *mask_ptr; mask_ptr++)
    {
	if (*mask_ptr == '%')
	    switch (mask_ptr[1])
	    {
	    case 's':
		char_ptr = va_arg(tuple_list, char *);
		sprintf(temp, "%s ", char_ptr);
		strcat(buffer, temp);
		break;

	    case 'd':
		integer = va_arg(tuple_list, int);
		sprintf(temp, "%d ", integer);
		strcat(buffer, temp);
		break;

	    case 'f':
		flt = va_arg(tuple_list, double);
		printf("parse pre-spr f: %f g: %g\n", flt, flt);
		sprintf(temp, "%f ", flt);
		printf("parse rec %s\n", temp);
		strcat(buffer, temp);
		break;
	    }
	else if (*mask_ptr == '?')
	    switch (mask_ptr[1])
	    {
	    case 'd':
		int_ptr = va_arg(tuple_list, int *);
		/* need to try %p here */
		sprintf(temp, "%d ", int_ptr);
		strcat(buffer, temp);
		break;

	    case 's':
		char_ptr = va_arg(tuple_list, char *);
		sprintf(temp, "%d ", char_ptr);
		strcat(buffer, temp);
		break;

	    case 'f':
		flt_ptr = va_arg(tuple_list, double *);
		sprintf(temp, "%d ", flt_ptr);
		strcat(buffer, temp);
		break;
	    }
	else if (*mask_ptr == ':')
	{
	    if (type == OUT)
	    {
		switch (mask_ptr[1])
		{

		case 'd':
		    int_ptr = va_arg(tuple_list, int *);
		    size = va_arg(tuple_list, int);
		    global.aglen = sizeof(int) * size;

		    tuple_channel.aggreg_size = size;

		    bcopy(int_ptr, tuple_channel.aggreg_data, global.aglen);
		    sprintf(temp, "%d ", int_ptr);
		    strcat(buffer, temp);
		    break;

		case 's':
		    char_ptr = va_arg(tuple_list, char *);
		    size = va_arg(tuple_list, int);
		    global.aglen = sizeof(char) * size;

		    tuple_channel.aggreg_size = size;

		    bcopy(char_ptr, tuple_channel.aggreg_data, global.aglen);
		    sprintf(temp, "%d ", char_ptr);
		    strcat(buffer, temp);
		    break;

		case 'f':
		    flt_ptr = va_arg(tuple_list, double *);
		    size = va_arg(tuple_list, int);
		    global.aglen = sizeof(double) * size;

		    tuple_channel.aggreg_size = size;

		    bcopy(flt_ptr, tuple_channel.aggreg_data, global.aglen);
		    sprintf(temp, "%d ", flt_ptr);
		    strcat(buffer, temp);
		    break;
		}
	    }			/* end if type = out */
	    else
	    {
		switch (mask_ptr[1])
		{
		case 'd':
		    int_ptr = va_arg(tuple_list, int *);
		    global.size_ptr = va_arg(tuple_list, int *);

		    sprintf(temp, "%d ", int_ptr);
		    break;
		case 's':
		    char_ptr = va_arg(tuple_list, char *);
		    global.size_ptr = va_arg(tuple_list, int *);

		    sprintf(temp, "%d ", char_ptr);
		    break;
		case 'f':
		    flt_ptr = va_arg(tuple_list, double *);
		    global.size_ptr = va_arg(tuple_list, int *);

		    sprintf(temp, "%d ", flt_ptr);
		    break;
		}
		tuple_channel.aggreg_size = 0;
		tuple_channel.aggreg_data[0] = '0';
		strcat(buffer, temp);

	    }			/* end if type not out */
	}			/* end else if mask_ptr = : */

    }
}

instantiate(tuple_mask, template, hanger, va_alist)
    char *tuple_mask, *template, *hanger;
    va_dcl
{
    va_list tuple_list;
    char *mask_ptr;
    struct space_q *space_node, *pred;
    int stok();
    int dum, tln, id, ln, integer, cnt, found, mismatch, tokint;
    int *int_ptr, *dchr, *achr;
    char *char_ptr, *schr;
    char outbuf[80];
    char temp[80];
    char template_tok[80], hanger_tok[80], tokchr[80];
    char *pchr, *pout, *pin;
    int *generic_ptr;
    int rc, n;
    double tokflt, *flt_ptr;

    pin = template;
    pout = hanger;
    for (mask_ptr = tuple_mask + 2, stok(template_tok, pin), stok(hanger_tok, pout); *mask_ptr; mask_ptr += 2)
    {
	pout = pout + strlen(hanger_tok) + 1;
	pin = pin + strlen(template_tok) + 1;
	stok(template_tok, pin);
	stok(hanger_tok, pout);
	if (*mask_ptr == '%')
	    continue;
	else if (*mask_ptr == '?')

	    switch (mask_ptr[1])
	    {
	    case 's':
		sscanf(template_tok, "%d", &generic_ptr);
		sscanf(hanger_tok, "%s", tokchr);
		char_ptr = (char *) generic_ptr;
		strcpy(char_ptr, tokchr);
		break;

	    case 'd':
		sscanf(template_tok, "%d", &generic_ptr);
		sscanf(hanger_tok, "%d", &tokint);
		int_ptr = (int *) generic_ptr;
		*int_ptr = tokint;
		break;

	    case 'f':
		sscanf(template_tok, "%d", &generic_ptr);
		sscanf(hanger_tok, "%lf", &tokflt);
		flt_ptr = (double *) generic_ptr;
		*flt_ptr = tokflt;
		break;
	    }
	else if (*mask_ptr == ':')
	    switch (mask_ptr[1])
	    {
	    case 'd':
		sscanf(template_tok, "%d", &generic_ptr);
		int_ptr = (int *) generic_ptr;
		tln = sizeof(int) * tuple_channel.aggreg_size;
		bcopy(tuple_channel.aggreg_data, int_ptr, tln);
		*global.size_ptr = tuple_channel.aggreg_size;

		break;
	    case 's':
		sscanf(template_tok, "%d", &generic_ptr);
		char_ptr = (char *) generic_ptr;
		tln = sizeof(char) * tuple_channel.aggreg_size;
		bcopy(tuple_channel.aggreg_data, char_ptr, tln);
		*global.size_ptr = tuple_channel.aggreg_size;

		break;
	    case 'f':
		sscanf(template_tok, "%d", &generic_ptr);
		flt_ptr = (double *) generic_ptr;
		tln = sizeof(double) * tuple_channel.aggreg_size;
		bcopy(tuple_channel.aggreg_data, flt_ptr, tln);
		*global.size_ptr = tuple_channel.aggreg_size;

		break;
	    }

    }				/* end for */

}				/* end instantiate */


rd(tuple_mask,va_alist)
char tuple_mask[80];
va_dcl
{
    va_list tuple_list;
    char *p;
    struct space_q *space_node, *pred;
    int stok();
    int dum, tln, id, ln, integer, cnt, found, mismatch, tokint;
    int *int_ptr, *dchr, *achr, *schr;
    char *char_ptr, template[128];
    char outbuf[80];
    char temp[80];
    char template_tok[80], outtok[80], tokchr[80];
    char *pchr, *pout, *pin;
    int tmsg, rc, n, type, fromid;
    struct tuple_msg_type *tcp;

    type = RD;
    va_start(tuple_list);
    strcpy(tuple_channel.mask, tuple_mask);
    parse(tuple_mask, type, template, tuple_list);
    va_end(tuple_list);
    strcpy(tuple_channel.hanger, template);
    tuple_channel.type = RD;
    id = p4_get_my_id();
    tln = sizeof(tuple_channel);
    tuple_channel.tuple_size = sizeof(tuple_channel);
    p4_send(tuple_channel.type, 1, &tuple_channel, tln);
    tmsg = -1;
    fromid = -1;
    tcp = NULL;
    p4_recv(&tmsg, &fromid, &tcp, &ln);
    if (tmsg == END)
    {
	rc = END;
    }
    else
    {
	rc = 0;
	bcopy(tcp,&tuple_channel,ln);
	instantiate(tuple_mask, template, tuple_channel.hanger);
    }
    return(rc);
}



int 
stok(tok, source)
char *tok, *source;
{
    int i;

    for (i = 0; (source[i] != ' ') && (source[i] != '\0'); i++)
	tok[i] = source[i];
    tok[i] = '\0';
    if (source[i] == '\0')
	return (1);
    else
	return (0);
}


sr_linda_end()
{

    struct tuple_msg_type tuple_channel, *tcp;
    int i, ln, numslaves, tmsg, id;

    p4_dprintfl(99,"entering sr_linda_end\n");
    strcpy(tuple_channel.hanger, "endstring");
    strcpy(tuple_channel.mask, "%end");
    tuple_channel.type = END;
    numslaves = p4_num_total_ids() - 2;   /* skip me and tm */
    for (i=0; i < numslaves; i++)
    {
	p4_send(tuple_channel.type, i+2, &tuple_channel, sizeof(tuple_channel));
	tmsg = -1;
	id = -1;
	tcp =  NULL;
	p4_recv(&tmsg, &id, &tcp, &ln);
    }

    /* then I can tell tm to terminate */
    p4_send(tuple_channel.type, 1, &tuple_channel, sizeof(tuple_channel));
    p4_dprintfl(99,"calling wait_for_end\n");
    p4_wait_for_end();
    p4_dprintfl(99,"exiting sr_linda_end\n");
}

int t[256] =
{1,87,49,12,176,178,102,166,121,193,6,84,249,230,44,163,14,197,213,
 181,161,85,218,80,64,239,24,226,236,142,38,200,110,177,104,103,141,
 253,255,50,77,101,81,18,45,96,31,222,25,107,190,70,86,237,240,34,
 72,242,20,214,244,227,149,235,97,234,57,22,60,250,82,175,208,5,127,
 100,111,62,135,248,174,169,211,58,66,154,106,195,245,171,17,187,182,
 179,0,243,132,56,148,75,128,133,158,100,130,126,91,13,153,246,216,
 219,119,68,223,78,83,88,201,00,122,11,92,32,136,114,52,10,138,30,48,
 183,156,35,61,26,143,74,251,94,129,162,63,152,170,7,115,167,241,206,
 3,150,55,59,151,220,90,53,23,131,125,173,15,238,79,95,89,16,105,137,
 225,224,217,160,37,123,118,73,2,157,46,116,9,145,134,228,207,212,202,
 215,69,229,27,188,67,124,168,252,42,4,29,108,21,247,19,205,39,203,
 233,40,186,147,198,192,155,33,164,191,98,204,165,180,117,76,140,36,
 210,172,41,54,159,8,185,232,113,196,231,47,146,120,51,65,28,144,254,
 221,93,189,194,139,112,43,71,109,184,209};

thash(word)
    char word[80];

{
    int h;
    int i;

    h = 0;
    for (i = 1; word[i] != '\0'; i++)
    {
	h = t[h ^ word[i]];
	/* printf("%d ",h); */
    }
    return (h);

}

match(template, hanger, mask)
char *template, *hanger, *mask;
{
    int i, k, j, count;
    int flag = 1;

    count = 0;
    k = 0;
    j = 0;
    for (i = 0; (*(mask + i) != '\0') && flag; i += 2)
    {
	if (*(mask + i) == '%')
	{
	    for (; (*template != ' ') || (*hanger != ' '); template++, hanger++)
	    {
		if (*template != *hanger)
		{
		    flag = 0;
		    p4_dprintfl(88,"matchfailed i=%d template=%c hanger=%c\n",i,*template,*hanger);
		    break;
		}
	    }
	}
	else
	{

	    for (; *template != ' '; template++);
	    for (; *hanger != ' '; hanger++);
	}
	template++;
	hanger++;
    }
    return (flag);
}

eval(tuple_mask,proc_name_char) 
char tuple_mask[]; 
char proc_name_char[];
{
    out("%s%s","$livetuple$",proc_name_char);
    return(0);
}

sr_linda_init(ac, av, functions_table)
int *ac;
char **av;
struct linda_eval_table functions_table[];
{
    int i, done, found;
    int (*int_func_ptr) (); 
    char proc_name_char[64];

    for (i=0; functions_table[i].ptr != NULL; i++)
    {
	sr_linda_functions_table[i].ptr = functions_table[i].ptr;
	strcpy(sr_linda_functions_table[i].name,functions_table[i].name);
    }
    sr_linda_functions_table[i].ptr = NULL;  /* mark end of the table */

    p4_initenv(ac, av);
    p4_create_procgroup();
    if (p4_get_my_id() != 0)
    {
	if (p4_get_my_id() == 1)
	{
	    p4_dprintfl(99,"sr_linda_init: calling tm\n");
	    tm();
	    p4_dprintfl(99,"sr_linda_init: exiting tm\n");
	}
	else
	{
	    p4_dprintfl(99,"entering not done loop\n");
	    done = in("%s?s","$livetuple$",proc_name_char);
	    while (!done)
	    {
		found = 0;
		for (i=0; !found && sr_linda_functions_table[i].ptr != NULL; i++)
		{
		    if (strcmp(proc_name_char,sr_linda_functions_table[i].name) == 0)
		    {
			found = 1;
			int_func_ptr = sr_linda_functions_table[i].ptr;
			break;
		    }
		}
		if (!found)
		{
		    p4_dprintf("unknown procedure=%s\n",proc_name_char);
		    p4_error("work: attempting to execute unknown procedure",0);
		}
		(*int_func_ptr)(); 
		done = in("%s?s","$livetuple$",proc_name_char);
	    }
	    p4_dprintfl(99,"past not done loop\n");
	    tuple_channel.type = END;
	    p4_send(tuple_channel.type, 0, &tuple_channel, sizeof(tuple_channel));
	}
	p4_wait_for_end();
	p4_dprintfl(99,"past wait_for_end\n");
	exit(0);
    }
}

slave()
{
    int i, done, found;
    int (*int_func_ptr) (); 
    char proc_name_char[64];

    if (p4_get_my_id() == 1)
    {
	p4_dprintfl(99,"slave: calling tm\n");
	tm();
	p4_dprintfl(99,"slave: exiting tm\n");
    }
    else
    {
	p4_dprintfl(99,"entering not done loop\n");
	done = in("%s?s","$livetuple$",proc_name_char);
	while (!done)
	{
	    found = 0;
	    for (i=0; !found && sr_linda_functions_table[i].ptr != NULL; i++)
	    {
		if (strcmp(proc_name_char,sr_linda_functions_table[i].name) == 0)
		{
		    found = 1;
		    int_func_ptr = sr_linda_functions_table[i].ptr;
		    break;
		}
	    }
	    if (!found)
	    {
		p4_dprintf("unknown procedure=%s\n",proc_name_char);
		p4_error("work: attempting to execute unknown procedure",0);
	    }
	    (*int_func_ptr)(); 
	    done = in("%s?s","$livetuple$",proc_name_char);
	}
	p4_dprintfl(99,"past not done loop\n");
	tuple_channel.type = END;
	p4_send(tuple_channel.type, 0, &tuple_channel, sizeof(tuple_channel));
    }
}

