int p_testOperand(SemVal *e, Opcode opcode) { register int ret; if ( (ret = !test_type(e, gp_opType[opcode])) ) util_semantic(gp_illegalType, gp_opstring[opcode]); return ret; }
SemVal *p_execute(SemVal *arr) { register size_t count; SemVal tmp, *argp, /* pointer to args */ e; count = arr->type; /* get argument count */ if (count < 6) /* to few arguments */ { util_semantic(gp_illegalArgCount, "execute"); return (arr); /* dummy args return */ } argp = codestruc(arr, 0); /* point to first arg */ e = *(argp + 2); /* cmd head info at e */ p_callRss(&e, f_cmd_head); /* code for cmd_head at e */ p_callRss(argp + 3, f_arg_head); /* code for arg_head */ p_catCode(&e, argp + 3); /* code appended to e*/ p_callRss(&argp[count - 2], f_arg_tail); /* code for arg_tail */ p_catCode(&e, &argp[count - 2]); /* code appended to e*/ p_callRss(&argp[count - 1], f_cmd_tail); /* code for cmd_tail */ p_catCode(&e, &argp[count - 1]); /* code appended to e*/ /* keep variable # of args */ memmove(argp + 2, argp + 4, (count - 2) * sizeof(SemVal)); arr->type -= 4; /* remove 4 arguments */ p_catCode(&e, p_specials(f_exec, arr)); /* catenate call-code */ free(gp_stringbuf); /* make sure empty string */ gp_stringbuf = rss_strdup(""); /* is pushed */ tmp = *p_stackFrame(e_str | e_const); /* empty string argument */ p_expr2stack(&tmp); p_catCode(&e, &tmp); /* empty string on the stack */ p_generateCode(&e, op_call_rss, f_cmd_tail); /* used with cmd_tail..cmd_head */ p_generateCode(&e, op_call_rss, f_arg_tail); p_generateCode(&e, op_call_rss, f_arg_head); p_callRss(&e, f_cmd_head); *arr = e; return arr; }
/* opstr is '=', or "/=", etc. */ SemVal *p_assignment(SemVal *lval, SemVal *rval, char *opstr) { SemVal *tmp; unsigned type; unsigned value; if (!test_type(lval, e_var)) { util_semantic(gp_lvalueNeeded, opstr); p_discard(rval); return lval; } p_trySIconvert(lval, rval); p_expr2stack(rval); /* convert rval to code */ /* same types */ if (lval->type & rval->type & (e_int | e_str | e_list)) { type = lval->type; /* save type/idx for return */ value = lval->evalue; p_generateCode(lval, op_copy_var, lval->evalue); tmp = p_catCode(rval, lval); /* catenate p_assignment code */ tmp->evalue = value; /* set lvalue type and idx */ tmp->type = type; return tmp; } util_semantic(gp_typeConflict, opstr); p_discard(rval); return lval; }
SemVal *p_callFunction(int funIdx, SemVal *e) { msg("calling function 0x%x", funIdx); register unsigned nParams; /* fprintf(stderr, "type: %d\n" "truelen: %d\n" "falselen: %d\n" "codelen: %d\n" "evalue: %d\n" "truelist: %p\n" "falselist: %p\n" "code: %p\n", e->type, e->truelen, e->falselen, e->codelen, e->evalue, e->truelist, e->falselist, e->code); */ if (funIdx == -1) /* function name not found ? */ return e; /* nothing to do here */ nParams = symtab_fun_nParams(funIdx); /* then check correct # of args */ if ((unsigned)e->type == nParams) p_checkArgumentTypes(nParams, funIdx, (SemVal *)e->code); else util_semantic("Function '%s()' requires %u arguments", symtab_funName(funIdx), nParams); p_catArgs(e); /* convert args to code */ /* call function and clean stack */ p_generateCode(e, op_call, symtab_funAddress(funIdx)); p_generateCode(e, op_asp, nParams); set_type(e, symtab_funType(funIdx)); return e; /* return called function code */ }
void p_beginFunction() { /* test if function name already exists */ if (symtab_addFunction(gp_varType, ftell(gp_bin)) != 0) { util_semantic("%s p_multiply defined", util_string()); return; } symtab_push(); /* setup the local symbol table */ /* 1 global, 1 local symbol table */ gp_dead_sp = 0; /* allow code generation */ gp_dead[0] = 0; ++gp_nestLevel; /* no code-writes to gp_bin in functions */ msg("END"); }
SemVal *p_negate(SemVal *e) /* expression so far */ { if (p_testOperand(e, op_umin)) /* test types ok */ { util_semantic(gp_illegalType, gp_opstring[op_umin]); return (e); } if (e->type & e_const) /* immediate value */ e->evalue = -(int)e->evalue; else { p_expr2stack(e); /* convert to code */ p_generateCode(e, op_umin); /* generate instruction */ } return (e); }
SemVal *p_not(SemVal *e) /* expression so far */ { if (p_testOperand(e, op_bnot)) /* test types ok */ { util_semantic(gp_illegalType, gp_opstring[op_bnot]); return e; } if ((e->type & (unsigned)~e_typeMask) == e_const) /* immediate value */ e->evalue = ~e->evalue; else { p_expr2stack(e); /* convert to code */ p_generateCode(e, op_bnot); /* generate instruction */ } return e; }
SemVal *p_indexOp(SemVal *larg, SemVal *rarg) { register int ok; ExprType type = f_element; SemVal *tmp; p_expr2stack(larg); /* arg to stack */ p_expr2stack(rarg); /* arg to stack */ /* This follows the code of `p_twoArgs.c' to compute a list/string */ /* element */ /* first arg must be int */ if (!test_type(larg, e_int)) /* first expression is no int */ { tmp = larg; /* then swap */ larg = rarg; rarg = tmp; } if ( (ok = test_type(larg, e_int)) ) /* right arg must be int */ { /* second arg == list: ok */ if (!(ok = test_type(rarg, e_list))) { /* second arg == string: ok */ ok = test_type(rarg, e_str); type = f_str_el; /* string element requested */ } } if (ok) { p_catCode(rarg, larg); /* make one code vector */ p_callRss(rarg, type); } else { util_semantic(gp_typeConflict, gp_funstring[type]); p_discard(larg); } return (rarg); }
SemVal *p_ternary(SemVal *cond, SemVal *ifTrue, SemVal *ifFalse) { if ((ifTrue->type & ifFalse->type & e_typeMask) == 0) { util_semantic(gp_typeConflict, "?:"); p_clearOperands(ifTrue, ifFalse); return cond; } if (test_type(cond, e_const)) /* constant: true or false */ { p_discard(cond); if (cond->evalue) { p_discard(ifFalse); p_expr2stack(ifTrue); return ifTrue; } p_discard(ifTrue); p_expr2stack(ifFalse); return ifFalse; } p_expr2stack(ifTrue); /* convert the expressions to code */ p_expr2stack(ifFalse); p_generateCode(cond, op_jmp_false, j_falselist); /* jmp around the ifTrue code */ p_patchupTrue(cond, 1); /* destination for the ifTrue code */ p_catCode(cond, ifTrue); /* cond = cond + ifTrue */ p_generateCode(cond, op_jmp, j_truelist); /* jmp around the ifFalse code */ p_patchupFalse(cond, 1); /* destination of the false alternative */ p_catCode(cond, ifFalse); /* cond = cond + ifTrue + jmp + ifFalse */ p_patchupTrue(cond, 1); /* jump from ifTrue to the end of expr. */ return cond; /* ?: return */ }
SemVal *p_oneArg(ExprType type, SemVal *arg) { msg("calling function 0x%x", type); register int ok; p_expr2stack(arg); /* arg to stack */ switch ((FunNr)type) { case f_ascii_int: if ( (ok = test_type(arg, e_str | e_int)) ) { if (test_type(arg, e_int)) /* int received */ type = f_ascii_str; /* string returned */ } break; case f_listlen: if (strcmp(scanner_savedText(), "listlen") != 0) rss_warning(util_sourceName(), scanner_savedLineNr(), "`%s' is deprecated. Use `listlen'\n", scanner_savedText()); ok = test_type(arg, e_list); break; case f_echo: ok = test_type(arg, e_int); break; default: /* case f_backtick: case f_getenv: case f_putenv: case f_eval: case f_exists: case f_cmd_head: case f_cmd_tail: case f_arg_head: case f_arg_tail: case f_g_path: case f_g_base: case f_g_ext: case f_strlen: case f_strlwr: case f_strupr: case f_trim: case f_trimright: case f_trimleft: */ ok = test_type(arg, e_str); } if (ok) p_callRss(arg, type); else util_semantic(gp_typeConflict, gp_funstring[type]); return (arg); }
SemVal *p_twoArgs(ExprType type, SemVal *larg, SemVal *rarg) { register int ok; msg("start"); p_expr2stack(larg); /* arg to stack */ p_expr2stack(rarg); /* arg to stack */ switch ((FunNr)type) { case f_fgets: ok = test_type(larg, e_str) && test_type(rarg, e_list); break; case f_element: /* f_element */ /* first arg must be int */ if ( (ok = test_type(larg, e_int)) ) { /* second arg == list: ok */ if (!(ok = test_type(rarg, e_list))) { /* second arg == string: ok */ ok = test_type(rarg, e_str); type = f_str_el; /* string element requested */ } } break; case f_resize: ok = test_type(larg, e_str) && test_type(rarg, e_int); break; case f_listfind: ok = test_type(larg, e_list) && test_type(rarg, e_str); break; case f_listunion: ok = test_type(larg, e_list) && test_type(rarg, e_str | e_list); break; default: /* case f_strchr: case f_strtok: case f_c_ext: case f_c_base: case f_c_path: case f_strfind: */ ok = larg->type & rarg->type & e_str; } msg("types test %d, funstring: %x", ok, type); if (ok) { p_catCode(rarg, larg); /* make one code vector */ p_callRss(rarg, type); } else { util_semantic(gp_typeConflict, gp_funstring[type]); p_discard(larg); rarg = p_stackFrame(e_null); } msg("leaving"); return rarg; }