/** * Check input type, translate if matching */ int cmd_case() { aspectype_t *exprtype; revmexpr_t *matchme; revmexpr_t *candid; int ret; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (!world.curjob->recur[world.curjob->curscope].rwrt.matchexpr) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Case is not in a match", -1); exprtype = aspect_type_get_by_id(ASPECT_TYPE_EXPR); if (!exprtype) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Expression type not found : lacking reflection ?", -1); /* If a previous case has already matched, simply end the transformation now : We must do that here because some "post" commands can be put after a matching "case", so we only stop rewriting at the first case -following- a matching case */ if (world.curjob->recur[world.curjob->curscope].rwrt.matched) { revm_move_pc(world.curjob->curcmd->endlabel); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /* Check if we match */ matchme = (revmexpr_t *) world.curjob->recur[world.curjob->curscope].rwrt.matchexpr; if (!matchme->type) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid type for matchme expression", -1); candid = revm_expr_create(matchme->type, "$candid", strdup(world.curjob->curcmd->param[0])); ret = (!candid ? 1 : revm_expr_match(candid, matchme)); /* No match or bad match : nothing happens */ if (ret) { world.curjob->recur[world.curjob->curscope].rwrt.matched = 0; PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); } /* Matched : transform and execute post side effects if any */ world.curjob->recur[world.curjob->curscope].rwrt.matched = 1; /* Sometimes the case command comes directly with appended post side-effects */ if (!world.curjob->curcmd->param[1]) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); /* The rewrite output was directly specified in the case command */ revm_case_transform(matchme, strdup(world.curjob->curcmd->param[1])); /* Additional side-effects were specified in the case command */ if (world.curjob->curcmd->param[2] && revm_case_execmd(world.curjob->curcmd->param[2]) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Post-side-effects commands failed", -1); /* Jump to end of the match construct */ PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Perform the transformation (can be called from case or into commands) * @param matchme * @param destvalue * @return */ static int revm_case_transform(revmexpr_t *matchme, char *destvalue) { u_int dstnbr; char *curptr; char *foundptr; u_int curidx; list_t *exprlist; aspectype_t *type; char namebuf[BUFSIZ]; char *rname; revmexpr_t *candid; list_t *looplist; int ret; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* We matched : first find how many elements there is in the target (list) type */ exprlist = world.curjob->recur[world.curjob->curscope].rwrt.transformed; dstnbr = 1; for (curidx = world.curjob->iter[world.curjob->curloop].elmidx - 1, curptr = destvalue; curptr && *curptr; curptr = foundptr + 2, curidx++, dstnbr++) { foundptr = strstr(curptr, "::"); if (!foundptr && dstnbr == 1) break; if (foundptr) *foundptr = 0x00; type = revm_exprtype_get(curptr); snprintf(namebuf, BUFSIZ, "%s-%u", world.curjob->iter[world.curjob->curloop].curkey, curidx); rname = strdup(namebuf); candid = revm_expr_create(type, rname, curptr); if (!candid || !candid->annot) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid target type(s) for transformation", -1); candid->annot->inhash = 1; elist_append(exprlist, rname, candid); if (!foundptr) break; } /* XXX: Case where the rewritten element is not part of an iterated list -- unsupported */ looplist = (list_t *) world.curjob->iter[world.curjob->curloop].container; if (!looplist) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Rewriting of non-list element unimplemented", -1); else if (looplist->type != ASPECT_TYPE_EXPR) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Rewrite of non-expression variables unimplemented", -1); /* Simply replace the current list element now */ /* The type of the list (list_t->type) does not change : it still is a list of revmexpr_t */ /* Just one element to swap */ else if (dstnbr == 1) { /* No transformation, keep the original expression */ if (!strcmp(destvalue, ".")) candid = matchme; else { /* Case where we did not have a simple value here but a real expression */ rname = revm_tmpvar_create(); type = revm_exprtype_get(destvalue); candid = revm_expr_create(type, rname, destvalue); if (!candid || !candid->annot) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Malformed destination type", -1); candid->annot->inhash = 1; /** ** ** XXX: Disabled -- do not remove -- to enable when SSA transform is ready ** if (revm_links_propagate(candid, matchme) < 0) ** PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, ** "Error while propagating dataflow links", -1); ** ** XXX: Also address the propagate for the case where dstnbr != 1 */ ret = elist_set(looplist, world.curjob->iter[world.curjob->curloop].curkey, candid); if (ret < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Failed to store transformed expr in input list", -1); /* ** We reuse the same key for transform list, so that any change in transform list ** can be recorded back to the element of the original list. We also refresh the ** induction variable of current loop context. ** ** XXX: we should probably update context hashes too */ elist_append(exprlist, strdup(world.curjob->iter[world.curjob->curloop].curkey), candid); char *name = world.curjob->iter[world.curjob->curloop].curind->label; world.curjob->iter[world.curjob->curloop].curind = candid; world.curjob->iter[world.curjob->curloop].curind->label = name; } } /* Insert a list at a certain offset of the list and remove matched element */ else { elist_replace(looplist, world.curjob->iter[world.curjob->curloop].curkey, elist_copy(exprlist, ELIST_DATA_NOCOPY)); world.curjob->iter[world.curjob->curloop].elmidx += exprlist->elmnbr - 1; } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/* Declare a new typed variable */ int cmd_declare() { aspectype_t *type; char *varname; char buf[BUFSIZ]; u_int curlen; u_int curidx; u_int curpidx; u_int openbrace; u_int closebrace; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Preliminary checks */ if (world.curjob->curcmd->argc < 3 || strcmp(world.curjob->curcmd->param[1], "=")) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid syntax for command", -1); /* Preliminary checks */ type = aspect_type_get_by_name(world.curjob->curcmd->name); if (!type) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown type for new variable", -1); /* Create the new data structure */ bzero(buf, BUFSIZ); /* Create a unique string for the value of the object */ for (openbrace = closebrace = curlen = 0, curidx = 2; world.curjob->curcmd->param[curidx]; curidx++, curlen += curpidx) for (curpidx = 0; world.curjob->curcmd->param[curidx][curpidx]; curpidx++) switch (world.curjob->curcmd->param[curidx][curpidx]) { case '(': *(buf + curlen + curpidx) = '('; openbrace++; break; case ')': *(buf + curlen + curpidx) = ')'; closebrace++; if (closebrace > openbrace) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid closing structure for variable", -1); break; case ' ': *(buf + curlen + curpidx) = ','; break; default: *(buf + curlen + curpidx) = world.curjob->curcmd->param[curidx][curpidx]; break; } /* Some first checks on the value */ if (closebrace != openbrace) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid nesting structure for variable", -1); #if __DEBUG_EXPRS__ fprintf(stderr, "Expression to write in variable: %s \n", buf); #endif curlen = strlen(world.curjob->curcmd->param[0]); varname = alloca(curlen + 2); snprintf(varname, curlen + 2, "$%s", world.curjob->curcmd->param[0]); /* Perform the real operation now */ if (type->childs) { if (!revm_expr_create(type, varname, buf)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid value for variable", -1); } else { if (!revm_simple_expr_create(type, varname, buf)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid value for variable", -1); } /* Print success */ if (!world.state.revm_quiet) { snprintf(buf, sizeof(buf), " [*] Variable %s succesfully initialized \n\n", world.curjob->curcmd->param[0]); revm_output(buf); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }