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); }
/* ** 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); }
/*{ ** 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); }