Annotation of researchv10no/cmd/twig/path.c, revision 1.1.1.1

1.1       root        1: #include <stdio.h>
                      2: #include "common.h"
                      3: #include "code.h"
                      4: #include "sym.h"
                      5: #include "machine.h"
                      6: 
                      7: /*
                      8:  * Routines to enumerate paths of a tree.  Firt call path_setup to
                      9:  * initialize the internal data structure.  Each component of the
                     10:  * path may be consecutively retrieved by calling path_getsym.
                     11:  */
                     12: 
                     13: /*
                     14:  * For trees, a path is defined to be the sequence of nodes and edges
                     15:  * from the root to a leaf.  A path is represented here as a list of
                     16:  * path components.  Each component is represented by the following
                     17:  * strucutre and may either be a pointer to a node or an integer.
                     18:  * If the integer is i then the next component is the ith child of the
                     19:  * previous component in the list.  For example, "a 3 b 1 c" is a path
                     20:  * for the tree "a(x,y,b(c,k))".  The tag field indicates whether the
                     21:  * component is a node or a branch.
                     22:  *     When the component represents a node then the node field points
                     23:  * the corresponding Node structure.  When the component is a branch then
                     24:  * branch is the index of the current branch followed (1 is leftmost...)
                     25:  * and node is a list of all unexamined children.
                     26:  */
                     27: struct path {
                     28:        int tag;
                     29: #define                P_NODE  0
                     30: #define                P_BRANCH        1
                     31:        int branch;
                     32:        Node *node;
                     33: };
                     34: 
                     35: /*
                     36:  * The path component list is stored in the path array.  Path_length
                     37:  * is the length of the path.  Path_ptr points to the first unread
                     38:  * component of the path component list. (see path_getsym
                     39:  * and path_build for details)
                     40:  */
                     41: struct path path[2*MAXPATH];
                     42: static int path_length;
                     43: static struct path *path_ptr = NULL;
                     44: 
                     45: /*
                     46:  * Given a tree, path_setup updates the path array with the leftmost
                     47:  * of a subtree starting at root.  The leftmost path is produced by
                     48:  * following the leftmost branch of every encountered interior node 
                     49:  * starting at the root.  Note that this routine can be used to layout
                     50:  * the leftmost branch of a subtree into part of the path array and for
                     51:  * initializing the path array with the leftmost path of the whole tree.
                     52:  */
                     53: void
                     54: path_setup(root)
                     55:        Node *root;
                     56: {
                     57:        for(;;) {
                     58:                register struct path *pp = &path[path_length++];
                     59:                Node *ep;
                     60:                assert (root!=NULL);
                     61: 
                     62:                /* Place node in the component list */
                     63:                pp->tag = P_NODE;
                     64:                pp->node = root;
                     65: 
                     66:                /* If leaf encountered exit */
                     67:                if ((ep=root->children)==NULL)
                     68:                        break;
                     69: 
                     70:                /*
                     71:                 * Mark that the left branch (i.e. 1st in our numbering
                     72:                 * scheme) was followed.
                     73:                 */
                     74:                pp = &path[path_length++];
                     75:                pp->tag = P_BRANCH;
                     76:                pp->branch = 1;
                     77:                pp->node = ep->siblings;
                     78:                root = ep;
                     79:        }
                     80:        path_ptr = path;
                     81: }
                     82: 
                     83: /*
                     84:  * Path_build generates the next path of the tree and returns 0 if
                     85:  * there are no more paths.  Each path can be associated
                     86:  * with exactly one leaf.  Hence the ordering of paths generated by
                     87:  * this routine is the same as a left to right ordering of the leaves.
                     88:  */
                     89: path_build()
                     90: {
                     91:        Node *np, *ep;
                     92:        struct path *pp = &path[path_length-1];
                     93: 
                     94:        /*
                     95:         * Assert that the end of the last path was indeed
                     96:         * a leaf.
                     97:         */
                     98:        assert (pp->tag == P_NODE);
                     99:        assert ((pp->node)->children == NULL);
                    100: 
                    101:        /*
                    102:         * back up until we find a node that still has children
                    103:         */
                    104:        pp--;
                    105:        while (pp >= &path[1] && pp->node==NULL) pp -= 2;
                    106: 
                    107:        /*
                    108:         * If we hit the beginning of the path array, there are
                    109:         * no more leaves and hence no more paths.
                    110:         */
                    111:        if (pp < &path[1]) {
                    112:                /* reset path_length */
                    113:                path_length = 0;
                    114:                return(0);
                    115:        }
                    116: 
                    117:        /*
                    118:         * append the new leftmost branch onto the rest of
                    119:         * the path component list.
                    120:         */
                    121:        pp->branch++;
                    122:        np = pp->node;
                    123:        pp->node = np->siblings;
                    124:        path_length = pp-path+1;
                    125:        path_setup(np);
                    126:        return(1);
                    127: }
                    128: 
                    129: /*
                    130:  * Get the next component in the path component list.
                    131:  * When the end of a path is reached, NULL is returned and
                    132:  * the next call will retrieve the first component of the next path.
                    133:  * EOF is returned if there are no more paths.
                    134:  * A return value of 1 indicates that the value returned in mi is
                    135:  * valid.
                    136:  */
                    137: int
                    138: path_getsym(mi)
                    139:        register struct machine_input *mi;
                    140: {
                    141:        if(path_ptr > &path[path_length]) {
                    142:                /*
                    143:                 * When the end of that path is passed, generate the
                    144:                 * next path.
                    145:                 */
                    146:                if(!path_build())
                    147:                        return(EOF);
                    148:                path_ptr = path;
                    149:        }
                    150:        if (path_ptr == &path[path_length]) {
                    151:                /*
                    152:                 * Path_ptr just encountered the end of
                    153:                 * the path, return a marker value
                    154:                 * to notify caller.
                    155:                 */
                    156:                mi->value = 0;
                    157:                path_ptr++;
                    158:                return(NULL);
                    159:        } else if (path_ptr->tag != P_BRANCH) {
                    160:                /*
                    161:                 * Translate the right machine input value
                    162:                 */
                    163:                mi->sym = (path_ptr->node)->sym;
                    164:                switch((mi->sym)->attr) {
                    165: 
                    166:                case A_NODE:
                    167:                        mi->value = MV_NODE((mi->sym)->unique);
                    168:                        break;
                    169: 
                    170:                case A_LABEL:
                    171:                        mi->value = MV_LABEL((mi->sym)->unique);
                    172:                        break;
                    173: 
                    174:                default:
                    175:                        assert(0);
                    176:                }
                    177:        } else {
                    178:                mi->value = MV_BRANCH(path_ptr->branch);
                    179:        }
                    180:        path_ptr++;
                    181:        return(1);
                    182: }
                    183: 
                    184: /*
                    185:  * Prints out path for debugging
                    186:  */
                    187: void
                    188: prpath()
                    189: {
                    190:        register int i;
                    191:        for(i=0; i < path_length; i++) {
                    192:                struct path *pp = &path[i];
                    193:                if (pp->tag==P_NODE) {
                    194:                        struct node *np = pp->node;
                    195:                        printf("[%s]", (np->sym)->name);
                    196:                } else {
                    197:                        assert (pp->tag == P_BRANCH);
                    198:                        printf("%d", pp->branch);
                    199:                }
                    200:        }
                    201:        putchar('\n');
                    202: 
                    203: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.