void sdf_select_instance(const char*celltype, const char*cellinst) { char buffer[128]; /* First follow the hierarchical parts of the cellinst name to get to the cell that I'm looking for. */ vpiHandle scope = sdf_scope; const char*src = cellinst; const char*dp; while ( (dp=strchr(src, '.')) ) { int len = dp - src; assert(len < sizeof buffer); strncpy(buffer, src, len); buffer[len] = 0; vpiHandle tmp_scope = find_scope(scope, buffer); if (tmp_scope == 0) { vpi_printf("SDF WARNING: Cannot find %s in %s?\n", buffer, vpi_get_str(vpiName,scope)); break; } assert(tmp_scope); scope = tmp_scope; src = dp + 1; } /* Now find the cell. */ if (src[0] == 0) sdf_cur_cell = sdf_scope; else sdf_cur_cell = find_scope(scope, src); if (sdf_cur_cell == 0) { vpi_printf("SDF WARNING: Unable to find %s in current scope\n", cellinst); return; } /* The scope that matches should be a module. */ if (vpi_get(vpiType,sdf_cur_cell) != vpiModule) { vpi_printf("SDF ERROR: Scope %s in %s is not a module.\n", cellinst, vpi_get_str(vpiName,sdf_scope)); } /* The matching scope (a module) should have the expected type. */ if (strcmp(celltype,vpi_get_str(vpiDefName,sdf_cur_cell)) != 0) { vpi_printf("SDF ERROR: Module %s in %s is not a %s; " "it is an %s\n", cellinst, vpi_get_str(vpiName,sdf_scope), celltype, vpi_get_str(vpiDefName,sdf_cur_cell)); } }
void check_main(sym_table *table) { scope *m = find_scope("main", table); if (m == NULL) { print_missing_main_error(); isValid = FALSE; } }
void analyse_function(Function *f, sym_table *prog, char *scope_id, int line_no) { //Find the scope of the function scope *called = find_scope(f->id, prog); //Find the scope if (!called) { //Ooops this is an error. Report it. print_undefined_proc_call_error(f, line_no); isValid = FALSE; return; } Params *fcallee = (Params *) called->params; Exprs *fcaller = f->args; //Check number of variables int call_no = count_list((void *)fcaller); int expect_no = count_list((void *)fcallee); if (call_no != expect_no) { print_func_pmismatch_error(f, fcallee, line_no, expect_no, call_no); isValid = FALSE; } else { //Go through each variable and try match. We know these are the same //lenght now. int par_num = 1; while (fcallee != NULL) { Expr *e = fcaller->first; Param *p = fcallee->first; Type caller = get_expr_type(e, NULL, prog, scope_id, line_no); if (caller != p->type && p->ind == VAL_IND) { if ((caller == INT_TYPE) && (p->type == FLOAT_TYPE)) { // This is valid, we can cast an int val into a float val } else { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } } else if (caller != p->type && p->ind == REF_IND) { if ((caller == FLOAT_TYPE) && (p->type == INT_TYPE)) { // This is valid, we can cast an int into a float to store // in the ref. } else { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } } else if (caller != p->type && caller != INVALID_TYPE) { //Then the parameter calls are incorrect print_func_ptype_error(par_num, caller, p->type, f, line_no); isValid = FALSE; } fcallee = fcallee->rest; fcaller = fcaller->rest; par_num ++; } } }
Walker::ApplyStatus smp_c_for_statement_walker::operator () (SuifObject *x) { SuifEnv *the_env = get_env(); CForStatement *c_for_stmt = to<CForStatement>(x); BrickAnnote *loop_label_annote = to<BrickAnnote>(c_for_stmt->lookup_annote_by_name("c_for_label")); StringBrick *loop_label_brick = to<StringBrick>(loop_label_annote->get_brick(0)); String current_loop_label = loop_label_brick->get_value(); if (current_loop_label != loop_label_argument) return Walker::Continue; Statement *body = c_for_stmt->get_body(); if (body) { VariableSymbol* loop_counter = get_c_for_basic_induction_variable(c_for_stmt); VariableSymbol* strip_loop_counter = new_anonymous_variable(the_env, find_scope(c_for_stmt), loop_counter->get_type()); name_variable(strip_loop_counter); // step size of the strip is the step size of the original loop int strip_step_size = get_c_for_step(c_for_stmt); c_for_stmt->set_body(0); CForStatement* strip = make_strip(the_env, strip_loop_counter, strip_size, strip_step_size, body); c_for_stmt->set_body(strip); set_c_for_step(c_for_stmt, strip_size); smp_load_variable_expression_walker walker(the_env, loop_counter, strip_loop_counter); body->walk(walker); } return Walker::Truncate; }
Walker::ApplyStatus multi_way_branch_statement_compactor::operator () (SuifObject *x) { MultiWayBranchStatement *the_case = to<MultiWayBranchStatement>(x); // is the table already compact? if (is_compact(the_case)) return Walker::Continue; SymbolTable *scope = find_scope(x); if (!scope) return Walker::Continue; CodeLabelSymbol *default_lab = the_case->get_default_target(); // very special case - the case list is empty, so just jump to the default label if (the_case->get_case_count() == 0) { Statement *replacement = create_jump_statement(get_env(),default_lab); the_case->get_parent()->replace(the_case,replacement); set_address(replacement); return Walker::Replaced; } StatementList *replacement = create_statement_list(get_env()); Expression *operand = the_case->get_decision_operand (); remove_suif_object(operand); DataType *type = operand->get_result_type(); VariableSymbol *decision = create_variable_symbol(get_env(),get_type_builder(get_env())->get_qualified_type(type)); scope->add_symbol(decision); replacement->append_statement(create_store_variable_statement(get_env(),decision,operand)); the_case->set_default_target(0); MultiWayGroupList jump_list(get_env(),default_lab,decision);; Iter<MultiWayBranchStatement::case_pair > iter = the_case->get_case_iterator(); while (iter.is_valid()) { MultiWayBranchStatement::case_pair pair = iter.current(); jump_list.add_element(pair.first,pair.second); iter.next(); } // we have built the new structure, now need to generate code for it jump_list.generate_code(replacement); the_case->get_parent()->replace(the_case,replacement); set_address(replacement); return Walker::Replaced; }
static const slang_variable_scope * find_scope(const slang_variable_scope *s, slang_atom name) { GLuint i; for (i = 0; i < s->num_variables; i++) { if (s->variables[i]->a_name == name) return s; } if (s->outer_scope) return find_scope(s->outer_scope, name); else return NULL; }
void check_unused_symbols(sym_table *table, Program *prog) { //For each proc get it's symbol table, then for each symbol //Map against all symbols and check if used Procs *procs = prog->procedures; while (procs != NULL) { Proc *p = procs->first; //Get the scope scope *s = find_scope(p->header->id, table); //Now we want to map over the scope and print any duplicate errors. map_over_symbols(s->table, report_unused_symbols); procs = procs->rest; } }
NodeBuilder::NodeBuilder(ScopedObject* sobj) : _symtab(find_scope(sobj)), _suif_env(sobj->get_suif_env()), _type_builder(get_type_builder(_suif_env)) {}
// analyzes the wasm opcode. static int wasm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { ut64 addr2 = UT64_MAX; int i; WasmOp wop = {0}; memset (op, '\0', sizeof (RAnalOp)); int ret = wasm_dis (&wop, data, len); op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->size = ret; op->addr = addr; op->sign = true; op->type = R_ANAL_OP_TYPE_UNK; op->id = wop.op; if (!wop.txt || !strncmp (wop.txt, "invalid", 7)) { op->type = R_ANAL_OP_TYPE_ILL; wasm_stack_ptr = 0; free (wop.txt); return -1; } if (wasm_stack_ptr >= WASM_STACK_SIZE) { wasm_stack_ptr = 0; op->type = R_ANAL_OP_TYPE_NULL; free (wop.txt); return -1; } switch (wop.op) { /* Calls here are using index instead of address */ case WASM_OP_LOOP: addr2 = find_scope (addr + op->size, data + op->size, len - op->size, true); op->type = R_ANAL_OP_TYPE_NOP; if (addr2 != UT64_MAX && addr_old != addr) { //eprintf("0x%016x > stack %u (loop)\n", addr, wasm_stack_ptr); wasm_stack[wasm_stack_ptr].loop = addr; wasm_stack[wasm_stack_ptr].end = addr2; wasm_stack[wasm_stack_ptr].size = wop.len; wasm_stack_ptr++; } //op->fail = addr + op->size; break; case WASM_OP_BLOCK: op->type = R_ANAL_OP_TYPE_NOP; addr2 = find_scope (addr + op->size, data + op->size, len - op->size, true); if (addr2 != UT64_MAX && addr_old != addr) { //eprintf("0x%016x > stack %u (block)\n", addr, wasm_stack_ptr); wasm_stack[wasm_stack_ptr].loop = UT64_MAX; wasm_stack[wasm_stack_ptr].end = addr2; wasm_stack[wasm_stack_ptr].size = wop.len; wasm_stack_ptr++; } break; case WASM_OP_IF: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = find_scope (addr + op->size, data + op->size, len - op->size, false); op->fail = addr + op->size; if (op->jump != UT64_MAX && addr_old != addr) { //eprintf("0x%016x > stack %u (if)\n", addr, wasm_stack_ptr); wasm_stack[wasm_stack_ptr].loop = UT64_MAX; wasm_stack[wasm_stack_ptr].end = op->fail; wasm_stack[wasm_stack_ptr].size = wop.len; wasm_stack_ptr++; } break; case WASM_OP_ELSE: op->type = R_ANAL_OP_TYPE_JMP; op->jump = find_scope (addr + op->size, data + op->size, len - op->size, false); break; case WASM_OP_I32REMS: case WASM_OP_I32REMU: op->type = R_ANAL_OP_TYPE_MOD; break; case WASM_OP_END: //eprintf("0x%016x < stack %u (end)\n", addr, wasm_stack_ptr); if (wasm_stack_ptr > 0) { op->type = R_ANAL_OP_TYPE_NOP; if (addr != UT64_MAX) { for (i = wasm_stack_ptr - 1; i > 0; i--) { if (wasm_stack[i].end == addr && wasm_stack[i].loop != UT64_MAX) { op->type = R_ANAL_OP_TYPE_CJMP; op->jump = wasm_stack[i].loop; op->fail = addr + op->size; break; } } } wasm_stack_ptr--; } else { // all wasm routines ends with an end. op->eob = true; op->type = R_ANAL_OP_TYPE_RET; } break; case WASM_OP_GETLOCAL: case WASM_OP_I32LOAD: case WASM_OP_I64LOAD: case WASM_OP_F32LOAD: case WASM_OP_F64LOAD: case WASM_OP_I32LOAD8S: case WASM_OP_I32LOAD8U: case WASM_OP_I32LOAD16S: case WASM_OP_I32LOAD16U: case WASM_OP_I64LOAD8S: case WASM_OP_I64LOAD8U: case WASM_OP_I64LOAD16S: case WASM_OP_I64LOAD16U: case WASM_OP_I64LOAD32S: case WASM_OP_I64LOAD32U: op->type = R_ANAL_OP_TYPE_LOAD; break; case WASM_OP_SETLOCAL: case WASM_OP_TEELOCAL: op->type = R_ANAL_OP_TYPE_STORE; break; case WASM_OP_I32EQZ: case WASM_OP_I32EQ: case WASM_OP_I32NE: case WASM_OP_I32LTS: case WASM_OP_I32LTU: case WASM_OP_I32GTS: case WASM_OP_I32GTU: case WASM_OP_I32LES: case WASM_OP_I32LEU: case WASM_OP_I32GES: case WASM_OP_I32GEU: case WASM_OP_I64EQZ: case WASM_OP_I64EQ: case WASM_OP_I64NE: case WASM_OP_I64LTS: case WASM_OP_I64LTU: case WASM_OP_I64GTS: case WASM_OP_I64GTU: case WASM_OP_I64LES: case WASM_OP_I64LEU: case WASM_OP_I64GES: case WASM_OP_I64GEU: case WASM_OP_F32EQ: case WASM_OP_F32NE: case WASM_OP_F32LT: case WASM_OP_F32GT: case WASM_OP_F32LE: case WASM_OP_F32GE: case WASM_OP_F64EQ: case WASM_OP_F64NE: case WASM_OP_F64LT: case WASM_OP_F64GT: case WASM_OP_F64LE: case WASM_OP_F64GE: op->type = R_ANAL_OP_TYPE_CMP; break; case WASM_OP_I64OR: case WASM_OP_I32OR: op->type = R_ANAL_OP_TYPE_OR; break; case WASM_OP_I64XOR: case WASM_OP_I32XOR: op->type = R_ANAL_OP_TYPE_XOR; break; case WASM_OP_I32CONST: case WASM_OP_I64CONST: case WASM_OP_F32CONST: case WASM_OP_F64CONST: op->type = R_ANAL_OP_TYPE_MOV; { ut8 arg = data[1]; r_strbuf_setf (&op->esil, "4,sp,-=,%d,sp,=[4]", arg); } break; case WASM_OP_I64ADD: case WASM_OP_I32ADD: case WASM_OP_F32ADD: case WASM_OP_F64ADD: op->type = R_ANAL_OP_TYPE_ADD; break; case WASM_OP_I64SUB: case WASM_OP_I32SUB: case WASM_OP_F32SUB: case WASM_OP_F64SUB: op->type = R_ANAL_OP_TYPE_SUB; break; case WASM_OP_NOP: op->type = R_ANAL_OP_TYPE_NOP; r_strbuf_setf (&op->esil, ""); break; case WASM_OP_CALL: case WASM_OP_CALLINDIRECT: op->type = R_ANAL_OP_TYPE_CALL; op->jump = get_cf_offset (anal, data); op->fail = addr + op->size; if (op->jump != UT64_MAX) { op->ptr = op->jump; } r_strbuf_setf (&op->esil, "4,sp,-=,0x%"PFMT64x",sp,=[4],0x%"PFMT64x",pc,=", op->fail, op->jump); break; case WASM_OP_BR: op->type = R_ANAL_OP_TYPE_JMP; set_br_jump(op, data, len - op->size); break; case WASM_OP_BRIF: op->fail = addr + op->size; op->type = R_ANAL_OP_TYPE_CJMP; set_br_jump(op, data, len - op->size); break; case WASM_OP_RETURN: // should be ret, but if there the analisys is stopped. op->type = R_ANAL_OP_TYPE_CRET; default: break; } op_old = wop.op; addr_old = addr; free (wop.txt); return op->size; }
void slang_print_tree(const slang_operation *op, int indent) { GLuint i; switch (op->type) { case SLANG_OPER_NONE: spaces(indent); printf("SLANG_OPER_NONE\n"); break; case SLANG_OPER_BLOCK_NO_NEW_SCOPE: spaces(indent); printf("{ locals=%p outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope); print_generic(op, NULL, indent+3); spaces(indent); printf("}\n"); break; case SLANG_OPER_BLOCK_NEW_SCOPE: spaces(indent); printf("{{ // new scope locals=%p outer=%p: ", (void *) op->locals, (void *) op->locals->outer_scope); for (i = 0; i < op->locals->num_variables; i++) { printf("%s ", (char *) op->locals->variables[i]->a_name); } printf("\n"); print_generic(op, NULL, indent+3); spaces(indent); printf("}}\n"); break; case SLANG_OPER_VARIABLE_DECL: assert(op->num_children == 0 || op->num_children == 1); { slang_variable *v; v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE); if (v) { const slang_variable_scope *scope; spaces(indent); printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope); print_type(&v->type); printf(" %s (%p)", (char *) op->a_id, (void *) find_var(op->locals, op->a_id)); scope = find_scope(op->locals, op->a_id); printf(" (in scope %p) ", (void *) scope); assert(scope); if (op->num_children == 1) { printf(" :=\n"); slang_print_tree(&op->children[0], indent + 3); } else if (v->initializer) { printf(" := INITIALIZER\n"); slang_print_tree(v->initializer, indent + 3); } else { printf(";\n"); } /* spaces(indent); printf("TYPE: "); print_type(&v->type); spaces(indent); printf("ADDR: %d size: %d\n", v->address, v->size); */ } else { spaces(indent); printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id); } } break; case SLANG_OPER_ASM: spaces(indent); printf("ASM: %s at %p locals=%p outer=%p\n", (char *) op->a_id, (void *) op, (void *) op->locals, (void *) op->locals->outer_scope); print_generic(op, "ASM", indent+3); break; case SLANG_OPER_BREAK: spaces(indent); printf("BREAK\n"); break; case SLANG_OPER_CONTINUE: spaces(indent); printf("CONTINUE\n"); break; case SLANG_OPER_DISCARD: spaces(indent); printf("DISCARD\n"); break; case SLANG_OPER_RETURN: spaces(indent); printf("RETURN\n"); if (op->num_children > 0) slang_print_tree(&op->children[0], indent + 3); break; case SLANG_OPER_LABEL: spaces(indent); printf("LABEL %s\n", (char *) op->a_id); break; case SLANG_OPER_EXPRESSION: spaces(indent); printf("EXPR: locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/ slang_print_tree(&op->children[0], indent + 3); break; case SLANG_OPER_IF: spaces(indent); printf("IF\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("THEN\n"); slang_print_tree(&op->children[1], indent + 3); spaces(indent); printf("ELSE\n"); slang_print_tree(&op->children[2], indent + 3); spaces(indent); printf("ENDIF\n"); break; case SLANG_OPER_WHILE: assert(op->num_children == 2); spaces(indent); printf("WHILE LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("WHILE cond:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("WHILE body:\n"); slang_print_tree(&op->children[1], indent + 3); indent -= 3; spaces(indent); printf("END WHILE LOOP\n"); break; case SLANG_OPER_DO: spaces(indent); printf("DO LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("DO body:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("DO cond:\n"); slang_print_tree(&op->children[1], indent + 3); indent -= 3; spaces(indent); printf("END DO LOOP\n"); break; case SLANG_OPER_FOR: spaces(indent); printf("FOR LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("FOR init:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("FOR condition:\n"); slang_print_tree(&op->children[1], indent + 3); spaces(indent); printf("FOR step:\n"); slang_print_tree(&op->children[2], indent + 3); spaces(indent); printf("FOR body:\n"); slang_print_tree(&op->children[3], indent + 3); indent -= 3; spaces(indent); printf("ENDFOR\n"); /* print_generic(op, "FOR", indent + 3); */ break; case SLANG_OPER_VOID: spaces(indent); printf("(oper-void)\n"); break; case SLANG_OPER_LITERAL_BOOL: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%s ", op->literal[0] ? "TRUE" : "FALSE"); printf(")\n"); break; case SLANG_OPER_LITERAL_INT: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%d ", (int) op->literal[i]); printf(")\n"); break; case SLANG_OPER_LITERAL_FLOAT: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%f ", op->literal[i]); printf(")\n"); break; case SLANG_OPER_IDENTIFIER: { const slang_variable_scope *scope; spaces(indent); if (op->var && op->var->a_name) { scope = find_scope(op->locals, op->var->a_name); printf("VAR %s (in scope %p)\n", (char *) op->var->a_name, (void *) scope); assert(scope); } else { scope = find_scope(op->locals, op->a_id); printf("VAR' %s (in scope %p) locals=%p outer=%p\n", (char *) op->a_id, (void *) scope, (void *) op->locals, (void *) op->locals->outer_scope); assert(scope); } } break; case SLANG_OPER_SEQUENCE: print_generic(op, "COMMA-SEQ", indent+3); break; case SLANG_OPER_ASSIGN: spaces(indent); printf("ASSIGNMENT locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); print_binary(op, ":=", indent); break; case SLANG_OPER_ADDASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "+=", indent); break; case SLANG_OPER_SUBASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "-=", indent); break; case SLANG_OPER_MULASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "*=", indent); break; case SLANG_OPER_DIVASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "/=", indent); break; /*SLANG_OPER_MODASSIGN,*/ /*SLANG_OPER_LSHASSIGN,*/ /*SLANG_OPER_RSHASSIGN,*/ /*SLANG_OPER_ORASSIGN,*/ /*SLANG_OPER_XORASSIGN,*/ /*SLANG_OPER_ANDASSIGN,*/ case SLANG_OPER_SELECT: spaces(indent); printf("SLANG_OPER_SELECT n=%d\n", op->num_children); assert(op->num_children == 3); slang_print_tree(&op->children[0], indent+3); spaces(indent); printf("?\n"); slang_print_tree(&op->children[1], indent+3); spaces(indent); printf(":\n"); slang_print_tree(&op->children[2], indent+3); break; case SLANG_OPER_LOGICALOR: print_binary(op, "||", indent); break; case SLANG_OPER_LOGICALXOR: print_binary(op, "^^", indent); break; case SLANG_OPER_LOGICALAND: print_binary(op, "&&", indent); break; /*SLANG_OPER_BITOR*/ /*SLANG_OPER_BITXOR*/ /*SLANG_OPER_BITAND*/ case SLANG_OPER_EQUAL: print_binary(op, "==", indent); break; case SLANG_OPER_NOTEQUAL: print_binary(op, "!=", indent); break; case SLANG_OPER_LESS: print_binary(op, "<", indent); break; case SLANG_OPER_GREATER: print_binary(op, ">", indent); break; case SLANG_OPER_LESSEQUAL: print_binary(op, "<=", indent); break; case SLANG_OPER_GREATEREQUAL: print_binary(op, ">=", indent); break; /*SLANG_OPER_LSHIFT*/ /*SLANG_OPER_RSHIFT*/ case SLANG_OPER_ADD: print_binary(op, "+", indent); break; case SLANG_OPER_SUBTRACT: print_binary(op, "-", indent); break; case SLANG_OPER_MULTIPLY: print_binary(op, "*", indent); break; case SLANG_OPER_DIVIDE: print_binary(op, "/", indent); break; /*SLANG_OPER_MODULUS*/ case SLANG_OPER_PREINCREMENT: spaces(indent); printf("PRE++\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_PREDECREMENT: spaces(indent); printf("PRE--\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_PLUS: spaces(indent); printf("SLANG_OPER_PLUS\n"); break; case SLANG_OPER_MINUS: spaces(indent); printf("SLANG_OPER_MINUS\n"); break; /*SLANG_OPER_COMPLEMENT*/ case SLANG_OPER_NOT: spaces(indent); printf("NOT\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_SUBSCRIPT: spaces(indent); printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); print_generic(op, NULL, indent+3); break; case SLANG_OPER_CALL: #if 0 slang_function *fun = _slang_function_locate(A->space.funcs, oper->a_id, oper->children, oper->num_children, &A->space, A->atoms); #endif spaces(indent); printf("CALL %s(\n", (char *) op->a_id); for (i = 0; i < op->num_children; i++) { slang_print_tree(&op->children[i], indent+3); if (i + 1 < op->num_children) { spaces(indent + 3); printf(",\n"); } } spaces(indent); printf(")\n"); break; case SLANG_OPER_METHOD: spaces(indent); printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id); break; case SLANG_OPER_FIELD: spaces(indent); printf("FIELD %s of\n", (char*) op->a_id); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_POSTINCREMENT: spaces(indent); printf("POST++\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_POSTDECREMENT: spaces(indent); printf("POST--\n"); slang_print_tree(&op->children[0], indent+3); break; default: printf("unknown op->type %d\n", (int) op->type); } }