Exemplo n.º 1
0
Arquivo: srv.c Projeto: 99years/plan9
void
walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fid*, void*), void *arg)
{
	int i;
	char *e;

	if(r->fid == r->newfid && r->ifcall.nwname > 1){
		respond(r, "lib9p: unused documented feature not implemented");
		return;
	}

	if(r->fid != r->newfid){
		r->newfid->qid = r->fid->qid;
		if(clone && (e = clone(r->fid, r->newfid, arg))){
			respond(r, e);
			return;
		}
	}

	e = nil;
	for(i=0; i<r->ifcall.nwname; i++){
		if(e = walk1(r->newfid, r->ifcall.wname[i], arg))
			break;
		r->ofcall.wqid[i] = r->newfid->qid;
	}

	r->ofcall.nwqid = i;
	if(e && i==0)
		respond(r, e);
	else
		respond(r, nil);
}
Exemplo n.º 2
0
/*
** Name: walk1	- Post-order walk
**
** Description:
**      This is a recursive implementation of the post-order walk of
**	algorithm 3 described in the reference.  It has been made re-entrant.
**
** Inputs:
**      tnode                           The tree to walk
**	hh				Depth in tree
**	control				Control structure
**
** Outputs:
**      control                         May be changed in various ways
**	Returns:
**	    Pointer to a parallel tree
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	06-may-86 (jeff)
**          adapted from walk1() in jutil!fmttree.c in 4.0
**      17-Aug-2010 (horda03) b124274
**          If tree to be displayed in segments, at the maximum
**          depth if the node contains a child mark the node
**          as a new segment (don't descend into the children
**          that will be done when the new segment is displayed).
*/
static PARATREE *
walk1( PTR tnode, i4  hh, ULD_CONTROL *control )
{
    register PARATREE   *l;
    register PARATREE   *r;
    register PARATREE	*p;
    i4			h;
    i4			place;
    PTR			t;
    PTR                 lson, rson;
 
    h = hh;
    t = tnode;
 
    if (t == (PTR) NULL)
	return (NULL);
 
    /* Allocate a node for the parallel tree */
    if (control->pti >= PTMX || h >= MAXH)
	return (NULL);
 
    p = control->ptp + control->pti++;

    lson = (*control->lson)(t);
    rson = (*control->rson)(t);

    if ( h && (h == control->max_level) && (lson || rson) )
    {
       p->new_root = ++(*control->num_segments);
       control->segments [ p->new_root - 1] = t;

       l = r = NULL;
    }
    else
    {
       p->new_root = 0;
 
       /*
       ** Walk the left and right subtrees of the users tree and
       ** attach the corresponding nodes of the parallel tree.
       */
       l = p->lf = walk1(lson, h + 1, control);
       r = p->rt = walk1(rson, h + 1, control);
    }
 
    /* The rest is pretty much identical to the reference */
    if (l == (PARATREE *) NULL && r == (PARATREE *) NULL)  /* a leaf node */
    {
	place = control->next_pos[h];
    }
    else if (l == (PARATREE *) NULL)
    {
	place = r->x - 1;
    }
    else if (r == (PARATREE *) NULL)
    {
	place = l->x + 1;
    }
    else 
    {
	place = (l->x + r->x) / 2;
    }
 
    if ((int) control->modifier[h] < (int) (control->next_pos[h] - place))
	   control->modifier[h] = control->next_pos[h] - place;
 
    if (l == (PARATREE *) NULL && r == (PARATREE *) NULL)
	p->x = place;
    else 
	p->x = place + control->modifier[h];
 
    control->next_pos[h] = p->x + 2;
    p->modifier = control->modifier[h];
    control->maxh = max(h, control->maxh);
 
    return (p);
}
Exemplo n.º 3
0
/*{
** Name: uld_prtree	- Format and print a tree
**
** Description:
**      This function formats and prints a tree, with help from caller-
**	supplied functions.  The algorithm was adapted by Bob Kooi from
**		Wetherell, C. and Shannon, A., "Tidy Drawings of Trees,"
**		IEEE Transactions on Software Engineering, Vol. SE-5, No. 5
**		September, 1979
**
**	Later mods made it re-entrant so it could run as part of a server.
**
**	EXAMPLE:
**		suppose you have a tree made out of nodes of type tnode:
**
**		struct tnode
**		{
**			i4		data1;
**			i4		data2;
**			struct tnode	*left;
**			struct tnode	*right;
**		}
**
**		where Root is a pointer to the root.  you must provide
**		three routines, call them leftson, rightson and printnode:
**
**		PTR
**		leftson(t)
**		PTR	    t;
**		{
**			return ((PTR) ((struct tnode *) t)->left);
**		}
**
**		PTR
**		rightson(t)
**		PTR	    t;
**		{
**			return ((PTR) ((struct tnode *) t)->right);
**		}
**
**		VOID 
**		printnode(t, control)
**		PTR	    t;
**		PTR	    control;
**		{
**			struct tnode	*node = (struct tnode *) t;
**
**			uld_prnode(control, "*****");
**			TRformat(uld_tr_callback, (i4 *)0,
**			    global_buffer, sizeof(global_buffer),
**			    "* %d *",
**			    node->data1);
**			uld_prnode(control, global_buffer);
**			TRformat(uld_tr_callback, (i4 *)0,
**			    global_buffer, sizeof(global_buffer),
**			    %d*",
**			    node->data2, node->data1);
**			uld_prnode(control, global_buffer);
**			uld_prnode(control, "*****");
**		}
**
**
**		then the call:
**
**		uld_prtree(0, (PTR) Root, printnode, leftson, rightson, 8, 5);
**
**		would print a tree where each node is 8 characters wide
**		by 5 characters long and would contain data1 on the first
**		line, data2 and data1 on the second line with a border of
**		stars.
**
**		a sample output might be:
 
                                        *****
                                        * 7 *
                                        *3 7*
                                        *****
 
                         /                              \
                        *****                           *****
                        * 4 *                           * 3 *
                        *3 4*                           *3 3*
                        *****                           *****
 
                 /              \                /              \
                *****           *****           *****           *****
                * 3 *           * 1 *           * 2 *           * 1 *
                *3 3*           *3 1*           *3 2*           *3 1*
                *****           *****           *****           *****
 
         /              \                /              \
        *****           *****           *****           *****
        * 2 *           * 1 *           * 1 *           * 1 *
        *3 2*           *3 1*           *3 1*           *3 1*
        *****           *****           *****           *****
 
 /              \
*****           *****
* 1 *           * 1 *
*3 1*           *3 1*
*****           *****
 
 
**
** Parts of a tree that exceed the manifest constants are not printed
** but should not otherwise cause difficulty (supposedly).
**
**
** the main difference between this and the reference is that here a
** "parallel" tree is built to hold the info (x,modifier) that, in the
** reference, is held in the nodes of the tree being printed.
** this means that the user need not plan for this routine but can
** easily add it in later. this is almost imperative when the user
** is working with variable size nodes in his tree.
**
** Inputs:
**      root                            Pointer to the root of the tree
**	printnode			Pointer to function to format a node
**	leftson				Pointer to function to find left son
**	rightson			Pointer to function to find right son
**	indent				Indent scale factor (number of spaces
**					to indent for each horizontal level)
**	lbl				Lines between levels (should at least
**					equal the maximum number of lines that
**					the user would ever print for a node
**					to ensure an evenly spaced tree)
**      facility                        facility ID of caller
**
** Outputs:
**      None
**	Returns:
**	    None
**	Exceptions:
**	    none
**
** Side Effects:
**	    none
**
** History:
**	06-may-86 (jeff)
**          Adapted from fmttree() in jutil!fmttree.c in 4.0
**	24-mar-87 (daved)
**	    set exclusive semaphore so that large static structures
**	    for the control struct are single threaded.
**	18-Jun-87 (DaveS)
**	    Modified to get memory from ULM instead of using statics.
**	    SCF semaphore removed since we no longer need it.
**	04-nov-87 (thurston)
**          On ulm_startup() call, I made the block size almost as large as the
**          pool since all that this routine does is create a pool, start a
**          stream, and allocate one L*A*R*G*E piece out of it.  (Wouldn't this
**          be better served by SCU_MALLOC directly???
**	08-feb-89 (jrb)
**	    Fixed calls to ule_format which made no sense at all.
**	21-may-89 (jrb)
**	    Updated for new ule_format interface.
**	22-sep-1992 (bryanp)
**	    Pass an err_code argument to ule_format. It demands one.
**	7-oct-2004 (thaju02)
**	    Change memleft to SIZE_TYPE.
**	19-Aug-2009 (kibro01) b122509
**	    Add new uld_prtree_x function which allows an extra sc930-tracing
**	    parameter to uld_prtree
**      17-Aug-2010 (horda03) b124274
**          Allow Trees to be printed in connected segments to aid readability.
*/
VOID
uld_prtree_x( i4 flags, PTR root, VOID (*printnode)(), PTR (*leftson)(), PTR (*rightson)(),
	    i4  indent, i4  lbl, i4  facility, PTR sc930_trace )
{
    register i4         i;
    register PARATREE	*pnode;
    ULD_CONTROL		control;
    ULD_STORAGE		*storage = 0;
    ULM_RCB		ulm_rcb;
    SIZE_TYPE		memleft;
    STATUS		status;
    i4		err_code;
    i4          max_nodes;
    ULD_PARAM   *uld_param = 0;
    
 
    control.facility = facility;
    ulm_rcb.ulm_facility = DB_ULF_ID;
    ulm_rcb.ulm_sizepool = sizeof(ULD_STORAGE) + 1024;
    ulm_rcb.ulm_blocksize = sizeof(ULD_STORAGE) + 128;
    memleft = sizeof(ULD_STORAGE) + 1024;
    ulm_rcb.ulm_memleft	    = &memleft;
 
    /* create a memory pool */
    status = ulm_startup(&ulm_rcb);
    if (status != E_DB_OK)
    {
	 (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	 (VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	 return;
    }

    /* open the private memory stream and allocate ULD_STORAGE */
    ulm_rcb.ulm_flags = ULM_PRIVATE_STREAM | ULM_OPEN_AND_PALLOC;
    ulm_rcb.ulm_psize	    = sizeof (ULD_STORAGE);
    ulm_rcb.ulm_streamid_p = NULL;
    if ((status = ulm_openstream(&ulm_rcb)) != E_DB_OK)
    {
	 (VOID) ule_format(ulm_rcb.ulm_error.err_code, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	(VOID) ule_format(E_UL0201_ULM_FAILED, (CL_ERR_DESC *)NULL,
		  ULE_LOG, NULL, (char *)NULL, (i4)0, (i4 *)NULL,
		  &err_code, 0);
	return;
    }
 
    storage   		    = (ULD_STORAGE *)ulm_rcb.ulm_pptr;
 
    control.lbl = lbl + 1;
    control.isf = indent;
    control.pti = 0;
    control.ptp = storage->pts;
    control.ncmx = indent * 2;
    control.first = 0;
 
    if (flags & ULD_FLAG_OUT_SEG)
    {
       uld_param = (ULD_PARAM *) root;

       root = uld_param->root;

       control.max_level = uld_param->control->max_level;
       control.segments  = uld_param->control->segments;
       control.num_segments = uld_param->control->num_segments;
    }
    else if (flags & ULD_FLAG_SEGMENTS)
    {
       control.segments = storage->segments;
       control.num_segments = &storage->num_segments;
       storage->num_segments = 0;

       max_nodes = 132 / control.ncmx;

       for (i = 1; i < sizeof(nodes_per_level)/sizeof(i4); i++)
       {
          if (max_nodes < nodes_per_level [i]) break;
       }

       control.max_level = i - 1;
    }
    else
       control.max_level = 0;

    for (i = PMX + 1; i--; )
	control.pbuf[i] = &(storage->pbf[i][0]);
 
    control.modifier = storage->mod;
    control.next_pos = storage->ned;
 
    /* Initialize line buffers */
    control.bmax = PMX;
    prflsh(1, &control, NULL);
 
    /* Initialize arrays */
    for (i = MAXH; i--; )
    {
	control.next_pos[i] = '\1';
	control.modifier[i] = '\0';
    }
 
    /* Initialize the function pointers */
    control.lson = leftson;
    control.rson = rightson;
    control.pnod = printnode;
 
    /* Do the first post-order walk */
    control.maxh = -1;
    pnode = walk1(root, 0, &control);

    if (uld_param)
    {
       pnode->new_root = uld_param->root_num;
    }
 
    /* Do the second pre-order walk */
    control.modfsum = 0;
    walk2(pnode, &control);
 
    /* For each level, print out the nodes at that level */
    control.type = ROOT;
    for (i = 0; i <= control.maxh; i++)
    {
	walk3(root, pnode, 0, i, &control);
	prflsh(0, &control, sc930_trace);
    }

    if ( !uld_param  && control.max_level)
    {
       ULD_PARAM u_root;

       u_root.control = &control;

       for (i = 0; i < *control.num_segments; i++ )
       {
           u_root.root = control.segments [i];

           u_root.root_num = i + 1;

           uld_prtree_x( ULD_FLAG_OUT_SEG, (PTR) &u_root, printnode, leftson, rightson, indent, -lbl, facility, sc930_trace );
       }
    }
 
    /* if we got any memory, return it */
    if (storage)
       ulm_shutdown(&ulm_rcb);
}