/** * take one step in the execution state machine given a run-tree context * * a run_tree is expected to have a code tree as the first child, parameters as the second, * and optionally an error handling routine as the third child. * * @param[in] processes context of defined processes * @param[in] pointer to context pointer * @returns the next state that will be called for the context */ Error _p_step(Defs *defs, R **contextP) { R *context = *contextP; switch(context->state) { case noReductionErr: case Block: case Send: raise_error0("whoa, virtual states can't be executed!"); // shouldn't be calling step if Done or noErr or Block or Send break; case Pop: // if this was the successful reduction by an error handler // move the value to the 1st child if (context->err) { T *t = _t_detach_by_idx(context->run_tree,3); if (t) { _t_replace(context->run_tree,1,t); context->err = noReductionErr; } } // if this is top caller on the stack then we are completely done if (!context->caller) { context->state = Done; break; } else { // otherwise pop the context R *ctx = context; context = context->caller; // set the new context if (!ctx->err) { // get results of the run_tree T *np = _t_detach_by_idx(ctx->run_tree,1); _t_replace(context->parent,context->idx,np); // replace the process call node with the result rt_cur_child(np) = RUN_TREE_EVALUATED; context->node_pointer = np; context->state = Eval; // or possible ascend?? } else context->state = ctx->err; // cleanup _t_free(ctx->run_tree); free(ctx); context->callee = 0; *contextP = context; } break; case Eval: { T *np = context->node_pointer; if (!np) { raise_error0("Whoa! Null node pointer"); } Process s = _t_symbol(np); if (semeq(s,PARAM_REF)) { T *param = _t_get(context->run_tree,(int *)_t_surface(np)); if (!param) { raise_error0("request for non-existent param"); } context->node_pointer = np = _t_rclone(param); _t_replace(context->parent, context->idx,np); s = _t_symbol(np); } // @todo what if the replaced parameter is itself a PARAM_REF tree ?? // if this node is not a process, i.e. it's data, then we are done descending // and it will be the result so ascend if (!is_process(s)) { context->state = Ascend; } else { int c = _t_children(np); if (c == rt_cur_child(np) || semeq(s,QUOTE)) { // if the current child == the child count this means // all the children have been processed, so we can evaluate this process // if the process is QUOTE that's a special case and we evaluate it // immediately without descending. if (!is_sys_process(s)) { // if it's user defined process then we check the signature and then make // a new run-tree run that process Error e = __p_check_signature(defs,s,np); if (e) context->state = e; else { T *run_tree = __p_make_run_tree(defs->processes,s,np); context->state = Pushed; *contextP = __p_make_context(run_tree,context); } } else { // if it's a sys process we can just reduce it in and then ascend // or move to the error handling state Error e = __p_reduce_sys_proc(context,s,np); context->state = e ? e : Ascend; } } else if(c) { //descend and increment the current child we're working on! context->state = Descend; } else { raise_error0("whoa! brain fart!"); } } } break; case Ascend: rt_cur_child(context->node_pointer) = RUN_TREE_EVALUATED; context->node_pointer = context->parent; context->parent = _t_parent(context->node_pointer); if (!context->parent || context->parent == context->run_tree) { context->idx = 1; } else context->idx = rt_cur_child(context->parent); if (context->node_pointer == context->run_tree) context->state = Pop; else context->state = Eval; break; case Descend: context->parent = context->node_pointer; context->idx = ++rt_cur_child(context->node_pointer); context->node_pointer = _t_child(context->node_pointer,context->idx); context->state = Eval; break; default: context->err = context->state; if (_t_children(context->run_tree) <= 2) { // no error handler so just return the error context->state = Pop; } else { // the first parameter to the error code is always a reduction error // which gets added on as the 4th child of the run tree when the // error happens. T *ps = _t_newr(context->run_tree,PARAMS); //@todo: fix this so we don't actually use an error value that // then has to be translated into a symbol, but rather so that we // can programatically calculate the symbol. Symbol se; switch(context->state) { case tooFewParamsReductionErr: se=TOO_FEW_PARAMS_ERR;break; case tooManyParamsReductionErr: se=TOO_MANY_PARAMS_ERR;break; case signatureMismatchReductionErr: se=SIGNATURE_MISMATCH_ERR;break; case notProcessReductionError: se=NOT_A_PROCESS_ERR;break; case notInSignalContextReductionError: se=NOT_IN_SIGNAL_CONTEXT_ERR; case divideByZeroReductionErr: se=ZERO_DIVIDE_ERR;break; case incompatibleTypeReductionErr: se=INCOMPATIBLE_TYPE_ERR;break; case raiseReductionErr: se = *(Symbol *)_t_surface(_t_child(context->node_pointer,1)); break; default: raise_error("unknown reduction error: %d",context->state); } T *err = __t_new(ps,se,0,0,sizeof(rT)); int *path = _t_get_path(context->node_pointer); _t_new(err,ERROR_LOCATION,path,sizeof(int)*(_t_path_depth(path)+1)); free(path); // switch the node_pointer to the top of the error handling routine context->node_pointer = _t_child(context->run_tree,3); context->idx = 3; context->parent = context->run_tree; context->state = Eval; } } return context->state; }
void getProcStats (struct procStats *procPtr, int iter) { struct procStatNode *nodePtr; DIR *d; struct dirent *ent; FILE *f; int ppid, pgrp, session, tty_nr, tpgid; unsigned flags; unsigned long minflt, majflt, cmajflt, utime, stime, cutime, cstime; long int priority, nice, num_thr, itrealv; unsigned long startTime; char fname[100]; procPtr->procTotal = 0; procPtr->procRun = 0; procPtr->procSleep = 0; procPtr->procDSleep = 0; procPtr->procZombie = 0; procPtr->procTrace = 0; procPtr->procPaging = 0; procPtr->head = NULL; if (d = opendir ("/proc")) { while (ent = readdir(d)) { if (is_process(ent->d_name)) { if (procPtr->head == NULL) { procPtr->head = (struct procStatNode *) malloc (sizeof(struct procStatNode));; nodePtr = procPtr->head; } else { nodePtr->nxtProc = (struct procStatNode *) malloc (sizeof(struct procStatNode)); nodePtr = nodePtr->nxtProc; } nodePtr->nxtProc = NULL; sprintf (fname, "/proc/%s/stat", ent->d_name); if (f = fopen(fname, "r")) { int nodePtrPid = 0; fscanf (f, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld", &nodePtrPid, (char*)&(nodePtr->cmd), &(nodePtr->state), &ppid, &pgrp, &session, &tty_nr, &tpgid, &flags, &minflt, &majflt, &cmajflt, &utime, &stime, &cutime, &cstime, &priority, &nice, &num_thr, &itrealv, &startTime); nodePtr->pid = (uint64_t)nodePtrPid; fclose(f); // Calculate CPU utilization here // nodePtr->cpuUtil = (utime + stime)/100.0; nodePtr->cpuTime = (utime + stime); // Assumption startTime/100 = wall time in secs // getWallTime(&(nodePtr->wt), startTime); nodePtr->wallTime = startTime/100; } else printf ("Error! %s file not found\n", fname); sprintf (fname, "/proc/%s/statm", ent->d_name); if (f = fopen(fname, "r")) { int nodePtrSizeTotal = 0; int nodePtrSizeRes = 0; int nodePtrPages = 0; fscanf (f, "%d %d %d", &nodePtrSizeTotal, &nodePtrSizeRes, &nodePtrPages); nodePtr->sizeTotal = (uint64_t)nodePtrSizeTotal; nodePtr->sizeRes = (uint64_t)nodePtrSizeRes; nodePtr->pages = (uint64_t)nodePtrPages; fclose(f); // To avoid divide by 0 if (nodePtr->sizeTotal > 0) nodePtr->memUtil = (nodePtr->sizeRes/(1.0*nodePtr->sizeTotal))*100; else nodePtr->memUtil = 0.0; } else printf ("Error! %s file not found\n", fname); // Process counters procPtr->procTotal ++; if (nodePtr->state == 'R') procPtr->procRun ++; else if (nodePtr->state == 'S') procPtr->procSleep ++; else if (nodePtr->state == 'D') procPtr->procDSleep ++; else if (nodePtr->state == 'Z') procPtr->procZombie ++; else if (nodePtr->state == 'T') procPtr->procTrace ++; else if (nodePtr->state == 'W') procPtr->procPaging ++; } } } else { printf ("Error! Can not open /proc\n"); } }
/* * update_input: does varying amount of updating on the input line depending * upon the position of the cursor and the update flag. If the cursor has * move toward one of the edge boundaries on the screen, update_cursor() * flips the input line to the next (previous) line of text. The update flag * may be: * * NO_UPDATE - only do the above bounds checking. * * UPDATE_JUST_CURSOR - do bounds checking and position cursor where is should * be. * * UPDATE_FROM_CURSOR - does all of the above, and makes sure everything from * the cursor to the right edge of the screen is current (by redrawing it). * * UPDATE_ALL - redraws the entire line */ void update_input(int update) { int old_start; static int co = 0, li = 0; char *ptr; int len, free_it = 1, cnt, ansi_count, max; char *prompt; cursor_to_input(); if (current_screen->promptlist) prompt = current_screen->promptlist->prompt; else prompt = input_prompt; if (prompt) { if (update != NO_UPDATE) { char *inp_ptr = NULL; int args_used; if (is_process(get_target_by_refnum(0))) { ptr = (char *) get_prompt_by_refnum(0); free_it = 0; } else if (!get_int_var(DISPLAY_ANSI_VAR)) ptr = expand_alias(stripansicodes(prompt), empty_str, &args_used, NULL); else ptr = expand_alias(prompt, empty_str, &args_used, NULL); if (*ptr && ((my_strnicmp(ptr, "Password:"******"Operator Password:"******"Server Password:", 16) == 0))) term_echo(0); else term_echo(1); len = strlen(ptr); if (strncmp(ptr, current_screen->input_buffer, len) || !len) { malloc_strcpy(&inp_ptr, INPUT_BUFFER + MIN_POS); strmcpy(INPUT_BUFFER, ptr, INPUT_BUFFER_SIZE); THIS_POS += (len - MIN_POS); MIN_POS = strlen(ptr); ADD_TO_INPUT(inp_ptr); new_free(&inp_ptr); update = UPDATE_ALL; } if (free_it) new_free(&ptr); } } else term_echo(1); if ((li != term_rows) || (co != term_cols)) { /* resized? Keep it simple and reset everything */ input_line = term_rows - 1; zone = term_cols - (WIDTH * 2) + 4; lower_mark = WIDTH; upper_mark = term_cols - WIDTH; cursor = current_screen->buffer_min_pos; current_screen->buffer_pos = current_screen->buffer_min_pos; str_start = 0; li = term_rows; co = term_cols; } old_start = str_start; ansi_count = count_ansi(current_screen->input_buffer, zone); if (old_ansi != ansi_count || current_screen->buffer_pos - ansi_count > zone) { lower_mark = WIDTH; upper_mark = term_cols - WIDTH; str_start = 0; } ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); while ((current_screen->buffer_pos - ansi_count < lower_mark) && lower_mark > WIDTH) { upper_mark = lower_mark - ansi_count; lower_mark -= (zone + ansi_count); str_start -= (zone + ansi_count); if (str_start < zone) { str_start = 0; ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); lower_mark -= ansi_count; upper_mark -= ansi_count; } } while (current_screen->buffer_pos - ansi_count >= upper_mark) { lower_mark = upper_mark + ansi_count; upper_mark += zone + ansi_count; str_start += zone + ansi_count; if (ansi_count) ansi_count = 0; } /* we need to count ansi characters again, this time in the part of the string we are gonna display in a few moments */ ansi_count = count_ansi(&(current_screen->input_buffer[str_start]), zone); old_ansi = count_ansi(current_screen->input_buffer, zone); /* we need to substract number of ansi characters from cursor position since those are not visible, otherwise we'd display cursor * in wrong place */ cursor = current_screen->buffer_pos - str_start - ansi_count; if ((old_start != str_start) || (update == UPDATE_ALL)) { term_move_cursor(0, input_line); if ((str_start == 0) && (MIN_POS > 0)) { int echo; echo = term_echo(1); if (MIN_POS > (term_cols - WIDTH)) len = term_cols - WIDTH - 1 /* + ansi_count */ ; else len = MIN_POS; cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), len); term_echo(echo); cnt += /* term_puts */ safe_puts(&(current_screen->input_buffer[ str_start + len]), term_cols - len + ansi_count); } else cnt = /* term_puts */ safe_puts(&(INPUT_BUFFER[str_start]), term_cols); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_FROM_CURSOR) { term_move_cursor(cursor, input_line); cnt = cursor; max = term_cols - (current_screen->buffer_pos - str_start) + ansi_count; if ((len = strlen(&(THIS_CHAR))) > max) len = max; cnt += /* term_puts */ safe_puts(&(THIS_CHAR), len); term_clear_to_eol(); term_move_cursor(cursor, input_line); } else if (update == UPDATE_JUST_CURSOR) term_move_cursor(cursor, input_line); term_flush(); }