/* ** Name: walk3 - Print out all nodes at a given level ** ** Description: ** This function prints out all nodes at a given level of the tree. ** ** Inputs: ** tnode Pointer to root of tree ** pnode Pointer to root of parallel tree ** ch Current level ** ph Level to print ** control Pointer to control structure ** ** Outputs: ** None ** Returns: ** None ** Exceptions: ** none ** ** Side Effects: ** Prints nodes ** ** History: ** 07-may-86 (jeff) ** Adapted from walk3() in jutil!fmttree.c in 4.0 ** 17-Aug-2010 (horda03) b124274 ** If the node is marked as a segment root, then ** display the connection box. If this is the ** display of the segment root then the root ** node is displayed and the tree walk continues. */ static VOID walk3( PTR tnode, PARATREE *pnode, i4 ch, i4 ph, ULD_CONTROL *control ) { register PTR t = tnode; register PARATREE *p = pnode; if (p == (PARATREE *) NULL) return; if (ch == ph) { control->ilvl = p->x; if (p->new_root) { /* Either a terminator for the end of the ** the truncated display, or the start of ** the next segment. */ pr_connect( p->new_root, ch, control ); if (ch) return; } (*control->pnod)(t, (PTR) control); return; } control->type = LEFT; walk3((*control->lson)(t), p->lf, ch + 1, ph, control); control->type = RIGHT; walk3((*control->rson)(t), p->rt, ch + 1, ph, control); }
/* PR_SETCACHE -- Set the size of the process cache. This is automatically * called whenever the value of the parameter cl.szprcache is set. Changing * the cache size on an active cache causes the cache to be flushed and all * locked processes to be reconnected. */ void pr_setcache (int new_szprcache) { struct process *pr; char pname[MAXSUBPROC][SZ_PATHNAME+1]; int nprocs=0, pid, i; FILE *fdummy; if (pr_head == NULL) pr_initcache(); else { /* Get the names of any processes currently locked into the cache, * then dump the cache. */ for (pr=pr_head; pr != NULL; pr=pr->pr_dn) if (pr->pr_pid != NULL && (pr->pr_flags & P_LOCKED)) strcpy (pname[nprocs++], pr->pr_name); pr_dumpcache (0, 1); } /* Set the new value of sz_prcache. */ sz_prcache = new_szprcache; if (sz_prcache < 2) sz_prcache = 2; else if (sz_prcache > MAXSUBPROC) sz_prcache = MAXSUBPROC; /* Relink the empty cache for sz_prcache cache slots. */ pr_initcache(); /* Attempt to recache the formerly locked processes. There must be * at least one empty slot left for new subprocesses. */ if (nprocs+1 > sz_prcache) nprocs = sz_prcache-1; for (i=0; i < nprocs; i++) { pid = pr_connect (findexe(NULL,pname[i]), "\n", &fdummy, &fdummy, stdin, stdout, stderr, 0,0,0, 0); pr_disconnect (pid); pr_lock (pid); } }
/* PR_CACHETASK -- Cache the process containing the named logical task. * If the process is already connected merely returns its pid, else connect * the process and return its pid. */ int pr_cachetask ( char *ltname /* logical task name */ ) { register int pid; struct ltask *ltp; FILE *fdummy; ltp = ltasksrch ("", ltname); if (ltp->lt_flags & (LT_SCRIPT|LT_BUILTIN)) return (ERR); if ((pid = pr_pnametopid(findexe(ltp->lt_pkp,ltp->lt_pname))) == NULL) { pid = pr_connect (findexe(ltp->lt_pkp,ltp->lt_pname), "\n", &fdummy, &fdummy, stdin, stdout, stderr, 0,0,0, 0); pr_disconnect (pid); } return (pid); }
/* EXECNEWTASK -- Called from the EXEC instruction after all param and stdio * processing for the new task is complete. Here we actually run the new task, * either directly in the case of a builtin function, or as a new case for * main()'s loop. Do not set newtask to NULL so that run() can tell what it * exec'd. */ void execnewtask (void) { /* VMS C V2.1 cannot handle this (see below). * register struct pfile *pfp; */ static struct pfile *pfp; struct param *pp; FILE *fopen(); if (newtask == NULL) /* if this ever happens, i don't want to know about it. */ return; currentask->t_pc = pc; /* instruction after EXEC */ if (cldebug) eprintf ("execnewtask: pc = %d\n", pc); if (newtask->t_flags & T_BUILTIN) { /* set yyin in case a builtin reads someday; none do now. * unlink newtask's fake param file and reset top of dictionary * to what it was before the fake param file was added; it is * still there, however, for the builtin to use. this is done * since some builtins (eg task) want to add things that are * to stay on the dictionary and the tools all start at topd. * the return is back to run(); it will continue since it will * see that newtask was just a builtin. * note that we do not reset pf_n, as with other fake pfiles, * as this is the way builtins get their number of arguments * (it's faster than building them a $nargs). */ yyin = newtask->t_in = currentask->t_in; /* inherit pipe */ newtask->t_out = currentask->t_out; newtask->t_modep = currentask->t_modep; /* inherit mode */ /* VMS C 2.1 Optimizer cannot handle this. * parhead = dereference (reference (pfile, parhead)->pf_npf); */ pfp = reference (pfile, parhead); parhead = dereference (pfp->pf_npf); topd = currentask->t_topd; currentask = newtask; newtask->t_flags |= T_RUNNING; if (cldebug) eprintf ("execnewtask: calling new task@%x\n", newtask); if (cltrace) eprintf ("\t----- exec %s %s -----\n", (newtask->t_flags & T_FOREIGN) ? "foreign" : "builtin", newtask->t_ltp->lt_lname); (*newtask->t_ltp->lt_f)(); oneof(); /* proceed as though this task saw eof */ return; } pfp = newtask->t_pfp; /* If the new task is a cl, we are not running in background and * its t_in is stdin, it is interactive. Note that when a package * is loaded by a script task rather than interactively by the user, * the t_in of the cl() in the package script task will be reading * from the calling script task rather than from the original stdin * (the user terminal), hence is not interactive. If this task is * flagged interactive, taskunwind() may elect to restart it on an * error so save present state for restor(). */ if (newtask->t_flags & T_CL) { if (cldebug) eprintf ("execnewtask: new task is the CL\n"); if (cltrace) eprintf ("\t----- exec cl -----\n"); /* Call set_clio to set the command input and output streams * t_in and t_out for a cl() or package_name() command. */ set_clio (newtask); /* This code is a temporary patch to allow packages to be * loaded from within scripts regardless of whether there * are enclosing brackets. If a CL statement is executed * within a script which is itself called within another * script, then we will do an implicit keep before the CL. */ if (topcs + 2*TASKSIZ <= STACKSIZ) if ((strcmp (newtask->t_ltp->lt_lname, "cl") == 0) || (strcmp (newtask->t_ltp->lt_lname, "clbye") == 0)) if ((currentask->t_flags & T_SCRIPT) && (prevtask->t_flags & T_SCRIPT)) keep(prevtask); /* If newtask is cleof(), close the input stream of the current * task (the task whose input contained the cleof), and reopen * as the null file. */ if (newtask->t_flags & T_CLEOF) { if (currentask->t_in != stdin) fclose (currentask->t_in); if (currentask != firstask) currentask->t_in = fopen ("dev$null", "r"); } if (!(firstask->t_flags & T_BATCH) && (newtask->t_in == stdin) && (newtask->t_out == stdout)) { newtask->t_flags |= T_INTERACTIVE; newtask->t_topd = topd; newtask->t_topos = topos; newtask->t_topcs = topcs; newtask->t_curpack = curpack; } } /* Standardize the pfile. * Set (or create if necessary) `$nargs', number of command line args, * based on pf_n which is set for each command line argument by * posargset, et al. * If this ltask had no paramfile and we built one up from the * command line, then we need to add a `mode' param. If it did have * a paramfile, then pfileload has already added it for us. * Point t_modep to the mode param for newtask. */ pp = paramfind (pfp, "$nargs", 0, YES); if (pp == NULL || (XINT)pp == ERR) { char nabuf[FAKEPARAMLEN]; sprintf (nabuf, "$nargs,i,h,%d\n", pfp->pf_n); pp = addparam (pfp, nabuf, NULL); pp->p_mode |= M_FAKE; /* never flush out $nargs */ } else pp->p_val.v_i = pfp->pf_n; if (pfp->pf_flags & PF_FAKE) { newtask->t_modep = addparam (pfp, "mode,s,h,q\n", NULL); /* pf_n will be used by paramsrch() to count positional arg * matches; see it and param.h. */ pfp->pf_n = 0; } else { newtask->t_modep = paramfind (pfp, "mode", 0, YES); } if (newtask->t_modep == NULL) cl_error (E_IERR, "no mode param for task `%s'", newtask->t_ltp->lt_lname); /* If task is being run in menu mode, call up eparam so that the user * can edit/inspect the parameters. If eparam is exited with ctrl/c * do not run the task or update the pfile. The parameter editor * will make a copy of the task's pfile(s), edit it, and if necessary * update the incore version created earlier by callnewtask(). */ if ((taskmode(newtask) & M_MENU) || (newtask->t_flags & T_PSET)) { if (epset (newtask->t_ltp->lt_lname) == ERR) { if (newtask->t_flags & T_PSET) cl_error (E_UERR, "parameter file not updated"); else cl_error (E_UERR, "menu mode task execution aborted"); } } /* Set up bascode so new task has a good place to start building * code. See how the pc is set up before each call to the parser in * main() loop. */ newtask->t_bascode = topos + 1; /* Set up io paths. If the new task is cl(), it's command input * and output streams are connected to those of the task which * called currentask. If the currentask is the firstask, there * was no caller (no prevtask), so we must watch out for that. * In the case of a script, commands are read from the script. * In the case of a process, commands are read from the process. */ if (newtask->t_flags & T_PSET) { newtask->t_in = fopen ("dev$null", "r"); newtask->t_out = newtask->t_stdout; } else if (newtask->t_flags & T_SCRIPT) { if (cltrace) eprintf ("\t----- exec script %s (%s) -----\n", newtask->t_ltp->lt_lname, newtask->t_ltp->lt_pname); newtask->t_in = fopen (newtask->t_ltp->lt_pname, "r"); if (newtask->t_in == NULL) cl_error (E_UERR|E_P, "can not open script file `%s'", newtask->t_ltp->lt_pname); newtask->t_out = newtask->t_stdout; } else if (newtask->t_flags & T_CL) { /* The command streams t_in and t_out have already been * set up above by set_clio() in the test for T_INTERACTIVE. */ /* Do nothing */ } else { char startup_msg[SZ_STARTUPMSG+1]; int timeit; /* Connect to an executable process. */ mk_startupmsg (newtask, startup_msg, SZ_STARTUPMSG); timeit = (newtask->t_flags & T_TIMEIT) != 0; if (cltrace) eprintf ("\t----- exec external task %s -----\n", newtask->t_ltp->lt_lname); newtask->t_pid = pr_connect ( findexe (newtask->t_ltp->lt_pkp, newtask->t_ltp->lt_pname), startup_msg, &newtask->t_in, &newtask->t_out, newtask->t_stdin, newtask->t_stdout, newtask->t_stderr, newtask->t_stdgraph, newtask->t_stdimage, newtask->t_stdplot, timeit); } yyin = newtask->t_in; /* set the input for the parser */ /* Tell parser what to expect. */ parse_state = PARSE_FREE; if (newtask->t_flags & T_SCRIPT) { proc_script = (newtask->t_flags & T_PSET) ? NO : procscript(yyin); if (proc_script) { parse_state = PARSE_BODY; /* Skip to the BEGIN statement */ newtask->t_scriptln = skip_to (yyin, "begin"); if (newtask->t_scriptln == ERR) cl_error (E_UERR, "No BEGIN statement in procedure script"); /* Reset pointer here. */ proc_script = NO; } } /* Log a start message for script and executable tasks. */ if (keeplog() && log_trace()) if (newtask->t_flags & T_SCRIPT || newtask->t_pid != -1) { char logmsg[SZ_LINE]; sprintf (logmsg, "Start (%s)", newtask->t_ltp->lt_pname); putlog (newtask, logmsg); } newtask->t_flags |= T_RUNNING; currentask = newtask; /* continue as new the new task; at last. */ if (cldebug) eprintf ("Returning from execnewtask.yyin, ct_in, nt_in:%d %d %d\n", yyin, currentask->t_in, newtask->t_in); }