void walkReplaceBuiltin(ACCExpr *expr) { while(1) { if (expr->value == "__bitconcat") { ACCExpr *list = expr->operands.front(); if (list->value == PARAMETER_MARKER) list->value = "{"; expr->value = list->value; expr->operands = list->operands; } else if (expr->value == "__bitsubstr") { ACCExpr *list = expr->operands.front(); ACCExpr *bitem = list->operands.front(); if (!isIdChar(bitem->value[0])) { // can only do bit select on net or reg (not expressions) printf("[%s:%d] can only do __bitsubstr on elementary items\n", __FUNCTION__, __LINE__); dumpExpr("BITSUB", expr); exit(-1); } bitem->operands.push_back(allocExpr("[", allocExpr(":", getRHS(list), getRHS(list, 2)))); expr->value = bitem->value; expr->operands = bitem->operands; } else if (expr->value == "__phi") { ACCExpr *list = expr->operands.front(); // get "(" list of [":", cond, value] items int size = list->operands.size(); ACCExpr *firstInList = getRHS(list, 0), *secondInList = getRHS(list); ACCExpr *newe = nullptr; if (size == 2 && matchExpr(getRHS(firstInList, 0), invertExpr(getRHS(secondInList, 0)))) newe = allocExpr("?", getRHS(firstInList, 0), getRHS(firstInList), getRHS(secondInList)); else if (size == 2 && getRHS(firstInList, 0)->value == "__default" && exprWidth(getRHS(secondInList)) == 1) newe = allocExpr("&", getRHS(secondInList, 0), getRHS(secondInList)); else if (size == 1) newe = getRHS(firstInList); else { //dumpExpr("PHI", list); newe = allocExpr("|"); for (auto item: list->operands) { dumpExpr("PHIELEMENTBEF", item); if (checkInteger(getRHS(item), "0")) continue; // default value is already '0' item->value = "?"; // Change from ':' -> '?' item->operands.push_back(allocExpr("0")); updateWidth(item, exprWidth(getRHS(item))); newe->operands.push_back(item); if (trace_expr) dumpExpr("PHIELEMENT", item); } } expr->value = newe->value; expr->operands = newe->operands; } else break; } for (auto item: expr->operands) walkReplaceBuiltin(item); }
/* * dereference macro ... return one of the DEREF_* values * for DEREF_ERROR, error is reported here */ static int varDeref(char *name) { Symbol s; Expr *x; LexIn *t; /* lookup macro name */ if ((s = symLookup(&vars, name)) == NULL) { fprintf(stderr, "undefined macro name $%s\n", name); return DEREF_ERROR; } x = symValue(s); /* string macro */ if (x->sem == SEM_CHAR) { t = (LexIn *) zalloc(sizeof(LexIn)); t->prev = lin; lin = t; lin->name = (char *) alloc(strlen(name) + 1); strcpy(lin->name, name); lin->macro = (char *) x->ring; lin->lno = 1; lin->cno = 0; return DEREF_STRING; } /* boolean valued macro */ if (x->sem == SEM_BOOLEAN) { yylval.x = x; return DEREF_BOOL; } /* constant numeric valued macro */ if (x->sem == SEM_NUMCONST) { /* * need to copy the Expr as the one returned here may be freed * later after constant folding, and we need the real macro's * value to be available for use in later rules */ yylval.x = newExpr(NOP, NULL, NULL, -1, -1, -1, 1, SEM_NUMCONST); yylval.x->smpls[0].ptr = x->smpls[0].ptr; yylval.x->valid = 1; return DEREF_NUMBER; } /* variable numeric valued macro */ if (x->sem == SEM_NUMVAR) { yylval.x = x; return DEREF_NUMBER; } fprintf(stderr, "varDeref(%s): internal botch sem=%d?\n", name, x->sem); dumpExpr(x); exit(1); }
void dumpExpr(std::string tag, ACCExpr *next) { printf("DE: %s %p %s\n", tag.c_str(), (void *)next, next ? next->value.c_str() : ""); int i = 0; if (next) for (auto item: next->operands) { dumpExpr(tag + "_" + autostr(i), item); i++; } }
/* fill in appropriate evaluator function for given Expr */ void findEval(Expr *x) { int arity = 0; Metric *m; /* * arity values constructed from bit masks * 1 arg1 has tspan 1, and must always have one metric value * 2 arg2 has tspan 1, and must always have one metric value */ if (x->arg1 && x->arg1->tspan == 1) { for (m = x->arg1->metrics; m; m = m->next) { if (m->desc.indom == PM_INDOM_NULL) continue; if (m->specinst == 0) break; } if (m == NULL) arity |= 1; } if (x->arg2 && x->arg2->tspan == 1) { for (m = x->arg2->metrics; m; m = m->next) { if (m->desc.indom == PM_INDOM_NULL) continue; if (m->specinst == 0) break; } if (m == NULL) arity |= 2; } /* * never come here with x->op == NULL or OP_VAR */ switch (x->op) { case RULE: x->eval = rule; break; case CND_RULESET: x->eval = ruleset; break; case CND_FETCH: if (x->metrics->desc.indom == PM_INDOM_NULL || x->metrics->conv == 0) x->eval = cndFetch_1; else if (x->metrics->specinst == 0) x->eval = cndFetch_all; else x->eval = cndFetch_n; break; case CND_SUM_HOST: x->eval = cndSum_host; break; case CND_SUM_INST: x->eval = cndSum_inst; break; case CND_SUM_TIME: x->eval = cndSum_time; break; case CND_AVG_HOST: x->eval = cndAvg_host; break; case CND_AVG_INST: x->eval = cndAvg_inst; break; case CND_AVG_TIME: x->eval = cndAvg_time; break; case CND_MAX_HOST: x->eval = cndMax_host; break; case CND_MAX_INST: x->eval = cndMax_inst; break; case CND_MAX_TIME: x->eval = cndMax_time; break; case CND_MIN_HOST: x->eval = cndMin_host; break; case CND_MIN_INST: x->eval = cndMin_inst; break; case CND_MIN_TIME: x->eval = cndMin_time; break; case CND_ALL_HOST: x->eval = cndAll_host; break; case CND_ALL_INST: x->eval = cndAll_inst; break; case CND_ALL_TIME: x->eval = cndAll_time; break; case CND_SOME_HOST: x->eval = cndSome_host; break; case CND_SOME_INST: x->eval = cndSome_inst; break; case CND_SOME_TIME: x->eval = cndSome_time; break; case CND_PCNT_HOST: x->eval = cndPcnt_host; break; case CND_PCNT_INST: x->eval = cndPcnt_inst; break; case CND_PCNT_TIME: x->eval = cndPcnt_time; break; case CND_COUNT_HOST: x->eval = cndCount_host; break; case CND_COUNT_INST: x->eval = cndCount_inst; break; case CND_COUNT_TIME: x->eval = cndCount_time; break; case ACT_SEQ: x->eval = actAnd; break; case ACT_ALT: x->eval = actOr; break; case ACT_SHELL: x->eval = actShell; break; case ACT_ALARM: x->eval = actAlarm; break; case ACT_STOMP: x->eval = actStomp; break; case ACT_SYSLOG: x->eval = actSyslog; break; case ACT_PRINT: x->eval = actPrint; break; case ACT_ARG: x->eval = actArg; break; case CND_DELAY: if (arity & 1) x->eval = cndDelay_1; else x->eval = cndDelay_n; break; case CND_RATE: if (arity & 1) x->eval = cndRate_1; else x->eval = cndRate_n; break; case CND_INSTANT: if (arity & 1) x->eval = cndInstant_1; else x->eval = cndInstant_n; break; case CND_NEG: if (arity & 1) x->eval = cndNeg_1; else x->eval = cndNeg_n; break; case CND_NOT: if (arity & 1) x->eval = cndNot_1; else x->eval = cndNot_n; break; case CND_RISE: if (arity & 1) x->eval = cndRise_1; else x->eval = cndRise_n; break; case CND_FALL: if (arity & 1) x->eval = cndFall_1; else x->eval = cndFall_n; break; case CND_ADD: if (arity & 1) { if (arity & 2) x->eval = cndAdd_1_1; else x->eval = cndAdd_1_n; } else { if (arity & 2) x->eval = cndAdd_n_1; else x->eval = cndAdd_n_n; } break; case CND_SUB: if (arity & 1) { if (arity & 2) x->eval = cndSub_1_1; else x->eval = cndSub_1_n; } else { if (arity & 2) x->eval = cndSub_n_1; else x->eval = cndSub_n_n; } break; case CND_MUL: if (arity & 1) { if (arity & 2) x->eval = cndMul_1_1; else x->eval = cndMul_1_n; } else { if (arity & 2) x->eval = cndMul_n_1; else x->eval = cndMul_n_n; } break; case CND_DIV: if (arity & 1) { if (arity & 2) x->eval = cndDiv_1_1; else x->eval = cndDiv_1_n; } else { if (arity & 2) x->eval = cndDiv_n_1; else x->eval = cndDiv_n_n; } break; case CND_EQ: if (arity & 1) { if (arity & 2) x->eval = cndEq_1_1; else x->eval = cndEq_1_n; } else { if (arity & 2) x->eval = cndEq_n_1; else x->eval = cndEq_n_n; } break; case CND_NEQ: if (arity & 1) { if (arity & 2) x->eval = cndNeq_1_1; else x->eval = cndNeq_1_n; } else { if (arity & 2) x->eval = cndNeq_n_1; else x->eval = cndNeq_n_n; } break; case CND_LT: if (arity & 1) { if (arity & 2) x->eval = cndLt_1_1; else x->eval = cndLt_1_n; } else { if (arity & 2) x->eval = cndLt_n_1; else x->eval = cndLt_n_n; } break; case CND_LTE: if (arity & 1) { if (arity & 2) x->eval = cndLte_1_1; else x->eval = cndLte_1_n; } else { if (arity & 2) x->eval = cndLte_n_1; else x->eval = cndLte_n_n; } break; case CND_GT: if (arity & 1) { if (arity & 2) x->eval = cndGt_1_1; else x->eval = cndGt_1_n; } else { if (arity & 2) x->eval = cndGt_n_1; else x->eval = cndGt_n_n; } break; case CND_GTE: if (arity & 1) { if (arity & 2) x->eval = cndGte_1_1; else x->eval = cndGte_1_n; } else { if (arity & 2) x->eval = cndGte_n_1; else x->eval = cndGte_n_n; } break; case CND_AND: if (arity & 1) { if (arity & 2) x->eval = cndAnd_1_1; else x->eval = cndAnd_1_n; } else { if (arity & 2) x->eval = cndAnd_n_1; else x->eval = cndAnd_n_n; } break; case CND_OR: if (arity & 1) { if (arity & 2) x->eval = cndOr_1_1; else x->eval = cndOr_1_n; } else { if (arity & 2) x->eval = cndOr_n_1; else x->eval = cndOr_n_n; } break; case CND_MATCH: case CND_NOMATCH: x->eval = cndMatch_inst; break; case CND_OTHER: /* OTHER is not really evaluated in this sense, see ruleset() */ x->eval = NULL; break; default: __pmNotifyErr(LOG_ERR, "findEval: internal error: bad op (%d) %s\n", x->op, opStrings(x->op)); dumpExpr(x); exit(1); } /* patch in fake actions for archive mode */ if (archives && (x->op == ACT_SHELL || x->op == ACT_ALARM || x->op == ACT_SYSLOG || x->op == ACT_PRINT || x->op == ACT_STOMP)) { x->eval = actFake; } }
/* reinitialize Metric - only for live host */ int /* 1: ok, 0: try again later, -1: fail */ reinitMetric(Metric *m) { char *hname = symName(m->hname); char *mname = symName(m->mname); char **inames; int *iids; int handle; int ret = 1; int sts; int i, j; /* set up temporary context */ if ((handle = newContext(hname)) < 0) return 0; host_state_changed(hname, STATE_RECONN); if ((sts = pmLookupName(1, &mname, &m->desc.pmid)) < 0) { ret = 0; goto end; } /* fill in performance metric descriptor */ if ((sts = pmLookupDesc(m->desc.pmid, &m->desc)) < 0) { ret = 0; goto end; } if (m->desc.type == PM_TYPE_STRING || m->desc.type == PM_TYPE_AGGREGATE || m->desc.type == PM_TYPE_AGGREGATE_STATIC || m->desc.type == PM_TYPE_EVENT || m->desc.type == PM_TYPE_HIGHRES_EVENT || m->desc.type == PM_TYPE_UNKNOWN) { fprintf(stderr, "%s: metric %s has non-numeric type\n", pmProgname, mname); ret = -1; } else if (m->desc.indom == PM_INDOM_NULL) { if (m->specinst != 0) { fprintf(stderr, "%s: metric %s has no instances\n", pmProgname, mname); ret = -1; } else m->m_idom = 1; } else { if ((sts = pmGetInDom(m->desc.indom, &iids, &inames)) < 0) { /* full profile */ ret = 0; } else { if (m->specinst == 0) { /* all instances */ m->iids = iids; m->m_idom = sts; m->inames = alloc(m->m_idom*sizeof(char *)); for (i = 0; i < m->m_idom; i++) { m->inames[i] = sdup(inames[i]); } } else { /* explicit instance profile */ m->m_idom = 0; for (i = 0; i < m->specinst; i++) { /* look for first matching instance name */ for (j = 0; j < sts; j++) { if (eqinst(m->inames[i], inames[j])) { m->iids[i] = iids[j]; m->m_idom++; break; } } if (j == sts) { m->iids[i] = PM_IN_NULL; ret = 0; } } if (sts > 0) { /* * pmGetInDom or pmGetInDomArchive returned some * instances above */ free(iids); } /* * if specinst != m_idom, then some not found ... move these * to the end of the list */ for (j = m->specinst-1; j >= 0; j--) { if (m->iids[j] != PM_IN_NULL) break; } for (i = 0; i < j; i++) { if (m->iids[i] == PM_IN_NULL) { /* need to swap */ char *tp; tp = m->inames[i]; m->inames[i] = m->inames[j]; m->iids[i] = m->iids[j]; m->inames[j] = tp; m->iids[j] = PM_IN_NULL; j--; } } } #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { int numinst; fprintf(stderr, "reinitMetric: %s from %s: instance domain specinst=%d\n", mname, hname, m->specinst); if (m->m_idom < 1) fprintf(stderr, " %d instances!\n", m->m_idom); if (m->specinst == 0) numinst = m->m_idom; else numinst = m->specinst; for (i = 0; i < numinst; i++) { fprintf(stderr, " indom[%d]", i); if (m->iids[i] == PM_IN_NULL) fprintf(stderr, " ?missing"); else fprintf(stderr, " %d", m->iids[i]); fprintf(stderr, " \"%s\"\n", m->inames[i]); } } #endif if (sts > 0) { /* * pmGetInDom or pmGetInDomArchive returned some instances * above */ free(inames); } } } if (ret == 1) { /* compute conversion factor into canonical units - non-zero conversion factor flags initialized metric */ m->conv = scale(m->desc.units); /* automatic rate computation */ if (m->desc.sem == PM_SEM_COUNTER) { m->vals = (double *) ralloc(m->vals, m->m_idom * sizeof(double)); for (j = 0; j < m->m_idom; j++) m->vals[j] = 0; } } if (ret >= 0) { /* * re-shape, starting here are working up the expression until * we reach the top of the tree or the designated metrics * associated with the node are not the same */ Expr *x = m->expr; while (x) { /* * only re-shape expressions that may have set values */ if (x->op == CND_FETCH || x->op == CND_NEG || x->op == CND_ADD || x->op == CND_SUB || x->op == CND_MUL || x->op == CND_DIV || x->op == CND_SUM_HOST || x->op == CND_SUM_INST || x->op == CND_SUM_TIME || x->op == CND_AVG_HOST || x->op == CND_AVG_INST || x->op == CND_AVG_TIME || x->op == CND_MAX_HOST || x->op == CND_MAX_INST || x->op == CND_MAX_TIME || x->op == CND_MIN_HOST || x->op == CND_MIN_INST || x->op == CND_MIN_TIME || x->op == CND_EQ || x->op == CND_NEQ || x->op == CND_LT || x->op == CND_LTE || x->op == CND_GT || x->op == CND_GTE || x->op == CND_NOT || x->op == CND_AND || x->op == CND_OR || x->op == CND_RISE || x->op == CND_FALL || x->op == CND_INSTANT || x->op == CND_MATCH || x->op == CND_NOMATCH) { instFetchExpr(x); findEval(x); #if PCP_DEBUG if (pmDebug & DBG_TRACE_APPL1) { fprintf(stderr, "reinitMetric: re-shaped ...\n"); dumpExpr(x); } #endif } if (x->parent) { x = x->parent; if (x->metrics == m) continue; } break; } } end: /* destroy temporary context */ pmDestroyContext(handle); return ret; }
static ACCExpr *get1Token(void) { std::string lexToken; auto getNext = [&] (void) -> void { lexToken += lexChar; lexChar = lexString[lexIndex++]; }; ACCExpr *ret = repeatGet1Token; repeatGet1Token = nullptr; if (ret) return ret; while (lexChar == ' ' || lexChar == '\t') lexChar = lexString[lexIndex++]; if(lexIndex > lexString.length() || lexChar == 0) return nullptr; if (isIdChar(lexChar)) { do { getNext(); } while (isIdChar(lexChar) || isdigit(lexChar)); if (lexAllowRange && lexChar == '[') { do { getNext(); } while (lexChar != ']'); getNext(); } if (lexToken == "__defaultClock") lexToken = "CLK"; else if (lexToken == "__defaultnReset") lexToken = "nRST"; } else if (isdigit(lexChar)) do { getNext(); } while (isdigit(lexChar) || lexChar == '.' || lexChar == '\'' || lexChar == 'b' || lexChar == 'h' || lexChar == 'd' || lexChar == 'o'); else if (lexChar == '+' || lexChar == '-' || lexChar == '*' || lexChar == '&' || lexChar == '|') do { getNext(); } while (lexChar == lexToken[0]); else if (lexChar == '=' || lexChar == '<' || lexChar == '>' || lexChar == '!') do { getNext(); } while (lexChar == '=' || lexChar == '<' || lexChar == '>'); else if (isParen(lexChar) || lexChar == '/' || lexChar == '%' || lexChar == '.' || lexChar == ']' || lexChar == '}' || lexChar == ')' || lexChar == '^' || lexChar == ',' || lexChar == '?' || lexChar == ':' || lexChar == ';') getNext(); else if (lexChar == '@') { // special 'escape' character for internal SUBSCRIPT_MARKER/PARAMETER_MARKER sequences getNext(); getNext(); } else if (lexChar == '"') { do { if (lexChar == '\\') getNext(); getNext(); } while (lexChar != '"'); getNext(); } else { printf("[%s:%d] lexString '%s' unknown lexChar %c %x\n", __FUNCTION__, __LINE__, lexString.c_str(), lexChar, lexChar); exit(-1); } ret = allocExpr(lexToken); if (isParen(ret->value)) { std::string val = ret->value; if (trace_expr) printf("[%s:%d] before subparse of '%s'\n", __FUNCTION__, __LINE__, ret->value.c_str()); ret = getExprList(ret, treePost(ret).substr(1), false, true); if (ret->value != val) ret = allocExpr(val, ret); // over optimization of '(<singleItem>)' if (trace_expr) { printf("[%s:%d] after subparse of '%s'\n", __FUNCTION__, __LINE__, ret->value.c_str()); dumpExpr("SUBPAREN", ret); } } return ret; }