static void setenv( char *env, char *value ) { push_str( value ); push_str( env ); fword("$setenv"); }
static void ob_esp_initialize(ATTRIBUTE_UNUSED esp_private_t **esp) { phandle_t ph = get_cur_dev(); set_int_property(ph, "#address-cells", 2); set_int_property(ph, "#size-cells", 0); /* set device type */ push_str("scsi"); fword("device-type"); /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By setting this attribute, we prevent the Solaris ESP kernel driver from trying to use this feature when booting a disk image (and failing) */ PUSH(0x58); fword("encode-int"); push_str("scsi-options"); fword("property"); PUSH(0x24); fword("encode-int"); PUSH(0); fword("encode-int"); fword("encode+"); push_str("intr"); fword("property"); }
void ob_init_iommu(uint64_t base) { struct iommu_regs *regs; regs = iommu_init(&ciommu, base); push_str("/iommu"); fword("find-device"); PUSH((unsigned long)regs); fword("encode-int"); push_str("address"); fword("property"); PUSH(base >> 32); fword("encode-int"); PUSH(base & 0xffffffff); fword("encode-int"); fword("encode+"); PUSH(IOMMU_REGS); fword("encode-int"); fword("encode+"); push_str("reg"); fword("property"); bind_func("map-in", ob_iommu_map_in); bind_func("map-out", ob_iommu_map_out); }
void boot(void) { char *path, *param; /* Copy the incoming path */ fword("2dup"); path = pop_fstr_copy(); /* Boot preloaded kernel */ if (kernel_size) { void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5); printk("[sparc64] Kernel already loaded\n"); entry = (void *) (unsigned long)kernel_image; entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface); } /* Invoke Linux directly -- probably not supported */ if(!path) { /* No path specified, so grab defaults from /chosen */ push_str("bootpath"); push_str("/chosen"); fword("(find-dev)"); POP(); fword("get-package-property"); POP(); /* Update our local copy of path as well as the one on the stack */ fword("2dup"); path = pop_fstr_copy(); } if (path) { param = strchr(path, ' '); if(param) { *param = '\0'; param++; } else if (cmdline_size) { param = (char *)qemu_cmdline; } else { push_str("boot-args"); push_str("/options"); fword("(find-dev)"); POP(); fword("get-package-property"); POP(); param = pop_fstr_copy(); } /* Invoke platform-specific Linux loader */ linux_load(&sys_info, path, param); free(path); } }
static void add_alias(const char *device, const char *alias) { DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias); push_str("/aliases"); fword("find-device"); push_str(device); fword("encode-string"); push_str(alias); fword("property"); }
void bind_func( const char *name, void (*func)(void) ) { PUSH( pointer2cell(func) ); push_str( name ); fword("is-cfunc"); }
static void push_verror(CParseInfo *pCPI, enum CTErrorSeverity severity, const char *fmt, va_list *pap) { void *str = F.newstr(); F.vscatf(str, fmt, pap); push_str(pCPI, severity, str); F.destroy(str); }
void ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base, uint64_t offset, int intr) { phandle_t aliases; char nodebuff[128]; snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name); REGISTER_NAMED_NODE(pc_serial, nodebuff); push_str(nodebuff); fword("find-device"); PUSH(offset); PUSH(find_package_method("init", get_cur_dev())); fword("execute"); push_str("serial"); fword("device-type"); PUSH((base + offset) >> 32); fword("encode-int"); PUSH((base + offset) & 0xffffffff); fword("encode-int"); fword("encode+"); PUSH(SER_SIZE); fword("encode-int"); fword("encode+"); push_str("reg"); fword("property"); #if !defined(CONFIG_SPARC64) PUSH(offset); fword("encode-int"); push_str("address"); fword("property"); #endif #if defined(CONFIG_SPARC64) set_int_property(get_cur_dev(), "interrupts", 1); #endif aliases = find_dev("/aliases"); set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1); }
void bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) ) { PUSH_xt( xt ); PUSH( arg ); PUSH( pointer2cell(func) ); push_str( name ); fword("is-xt-cfunc"); }
void LuaGossip::OnSelectOption(Object* pObject, Player* Plr, uint32 Id, const char* EnteredCode) { GET_LOCK; if(pObject->GetTypeId() == TYPEID_UNIT) { if(m_unit_gossip_binding == NULL) { RELEASE_LOCK; return; } lua_engine::BeginLuaFunctionCall(m_unit_gossip_binding->refs[GOSSIP_EVENT_ON_SELECT_OPTION]); push_creature(TO_CREATURE(pObject)); push_int(GOSSIP_EVENT_ON_SELECT_OPTION); push_player(Plr); push_int(Id); push_str(EnteredCode); lua_engine::ExecuteLuaFunction(5); } else if(pObject->GetTypeId() == TYPEID_ITEM) { if(m_item_gossip_binding == NULL) { RELEASE_LOCK; return; } lua_engine::BeginLuaFunctionCall(m_item_gossip_binding->refs[GOSSIP_EVENT_ON_SELECT_OPTION]); push_item(TO_ITEM(pObject)); push_int(GOSSIP_EVENT_ON_SELECT_OPTION); push_player(Plr); push_int(Id); push_str(EnteredCode); lua_engine::ExecuteLuaFunction(5); } else if(pObject->GetTypeId() == TYPEID_GAMEOBJECT) { if(m_go_gossip_binding == NULL) { RELEASE_LOCK; return; } lua_engine::BeginLuaFunctionCall(m_go_gossip_binding->refs[GOSSIP_EVENT_ON_SELECT_OPTION]); push_go(TO_GAMEOBJECT(pObject)); push_int(GOSSIP_EVENT_ON_SELECT_OPTION); push_player(Plr); push_int(Id); push_str(EnteredCode); lua_engine::ExecuteLuaFunction(5); } RELEASE_LOCK }
static int genll(Error_printer *err, Frag *frag, Node * n) { switch (n->what) { case nEMPTY: { return 0; } case nSEMI: { int result = genll(err, frag, n->r); return result + genll(err, frag, n->l); } case nNAM: { push_str(frag); emits(frag, n->s, n->n); return 1; } case nSET: { if (n->l->what == nNAM) { push_str(frag); emits(frag, n->l->s, n->l->n); return 1; } } } error_2(err, "\"%s\" %d: incorrect local list", n->loc->name, n->loc->line); return 0; }
static void ob_cuda_initialize (int *idx) { phandle_t ph=get_cur_dev(); int props[2]; push_str("via-cuda"); fword("device-type"); set_int_property(ph, "#address-cells", 1); set_int_property(ph, "#size-cells", 0); set_property(ph, "compatible", "cuda", 5); props[0] = __cpu_to_be32(IO_CUDA_OFFSET); props[1] = __cpu_to_be32(IO_CUDA_SIZE); set_property(ph, "reg", (char *)&props, sizeof(props)); /* on newworld machines the cuda is on interrupt 0x19 */ props[0] = 0x19; props[1] = 0; NEWWORLD(set_property(ph, "interrupts", (char *)props, sizeof(props))); NEWWORLD(set_int_property(ph, "#interrupt-cells", 2)); /* we emulate an oldworld hardware, so we must use * non-standard oldworld property (needed by linux 2.6.18) */ OLDWORLD(set_int_property(ph, "AAPL,interrupts", 0x12)); bind_func("ppc32-reset-all", ppc32_reset_all); push_str("' ppc32-reset-all to reset-all"); fword("eval"); }
static void ofmem_set_property( phandle_t ph, const char *name, const char *buf, int len ) { /* This is very similar to set_property() in libopenbios/bindings.c but allows us to set the property pointer directly, rather than having to copy it into the Forth dictonary every time we update the memory properties */ if( !ph ) { printk("ofmem_set_property: NULL phandle\n"); return; } PUSH(pointer2cell(buf)); PUSH(len); push_str(name); PUSH_ph(ph); fword("encode-property"); }
void my_ucpp_warning(pUCPP_ long line, char *fmt, ...) { va_list ap; void *str; INIT_CHECK; va_start(ap, fmt); str = F.newstr(); if (line > 0) F.scatf(str, "%s, line %ld: (warning) ", r_current_filename, line); else if (line == 0) F.scatf(str, "%s: (warning) ", r_current_filename); else F.scatf(str, "(warning) "); F.vscatf(str, fmt, &ap); if (line >= 0) { struct stack_context *sc = report_context(aUCPP); size_t i; for (i = 0; sc[i].line >= 0; i++) F.scatf(str, "\n\tincluded from %s:%ld", sc[i].long_name ? sc[i].long_name : sc[i].name, sc[i].line); freemem(sc); } va_end(ap); push_str(r_callback_arg, CTES_WARNING, str); F.destroy(str); }
bool run(struct context *context, struct byte_array *program, struct map *env, bool in_context) { null_check(context); null_check(program); program = byte_array_copy(program); program->current = program->data; struct program_state *state = NULL; enum Opcode inst = VM_NIL; if (context->runtime) { if (in_context) { if (!state) state = (struct program_state*)stack_peek(context->program_stack, 0); env = state->named_variables; // use the caller's variable set in the new state } else state = program_state_new(context, env); } while (program->current < program->data + program->length) { inst = (enum Opcode)*program->current; bool really = inst & VM_RLY; inst &= ~VM_RLY; #ifdef DEBUG display_program_counter(context, program); #endif program->current++; // increment past the instruction int32_t pc_offset = 0; switch (inst) { case VM_COM: case VM_ITR: if (iterate(context, inst, state, program)) goto done; break; case VM_RET: if (ret(context, program)) goto done; break; case VM_TRO: if (tro(context)) goto done; break; case VM_TRY: if (vm_trycatch(context, program)) goto done; break; case VM_EQU: case VM_MUL: case VM_DIV: case VM_ADD: case VM_SUB: case VM_NEQ: case VM_GTN: case VM_LTN: case VM_GRQ: case VM_LEQ: case VM_BND: case VM_BOR: case VM_MOD: case VM_XOR: case VM_INV: case VM_RSF: case VM_LSF: binary_op(context, inst); break; case VM_ORR: case VM_AND: pc_offset = boolean_op(context, program, inst); break; case VM_NEG: case VM_NOT: unary_op(context, inst); break; case VM_SRC: src(context, inst, program); break; case VM_DST: dst(context, really); break; case VM_STX: case VM_SET: set(context, inst, state, program); break; case VM_JMP: pc_offset = jump(context, program); break; case VM_IFF: pc_offset = iff(context, program); break; case VM_CAL: func_call(context, inst, program, NULL); break; case VM_LST: push_list(context, program); break; case VM_MAP: push_map(context, program); break; case VM_NIL: push_nil(context); break; case VM_INT: push_int(context, program); break; case VM_FLT: push_float(context, program); break; case VM_BUL: push_bool(context, program); break; case VM_STR: push_str(context, program); break; case VM_VAR: push_var(context, program); break; case VM_FNC: push_fnc(context, program); break; case VM_GET: list_get(context, really); break; case VM_PTX: case VM_PUT: list_put(context, inst, really); break; case VM_MET: method(context, program, really); break; default: vm_exit_message(context, ERROR_OPCODE); return false; } program->current += pc_offset; } if (!context->runtime) return false; done: if (!in_context) stack_pop(context->program_stack); return inst == VM_RET; }
void setup_romvec(void) { /* SPARC32 is slightly unusual in that before invoking any loaders, a romvec array needs to be set up to pass certain parameters using a C struct. Hence this function extracts the relevant boot information and places it in obp_arg. */ int intprop, proplen, target, device, i; unsigned int *intprop_ptr; phandle_t chosen; char *prop, *id, *name; static char bootpathbuf[128], bootargsbuf[128], buf[128]; struct linux_mlist_v0 **pp; /* Get the stdin and stdout paths */ chosen = find_dev("/chosen"); intprop = get_int_property(chosen, "stdin", &proplen); PUSH(intprop); fword("get-instance-path"); ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy(); intprop = get_int_property(chosen, "stdout", &proplen); PUSH(intprop); fword("get-instance-path"); ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy(); /* Get the name of the selected boot device, along with the device and unit number */ prop = get_property(chosen, "bootpath", &proplen); strncpy(bootpathbuf, prop, proplen); prop = get_property(chosen, "bootargs", &proplen); strncpy(bootargsbuf, prop, proplen); /* Set bootpath pointer used in romvec table to the bootpath */ push_str(bootpathbuf); fword("pathres-resolve-aliases"); bootpath = pop_fstr_copy(); printk("bootpath: %s\n", bootpath); /* Now do some work to get hold of the target, partition etc. */ push_str(bootpathbuf); feval("open-dev"); feval("ihandle>boot-device-handle drop to my-self"); push_str("name"); fword("get-my-property"); POP(); name = pop_fstr_copy(); if (!strncmp(name, "sd", 2)) { /* Old-style SunOS disk paths are given in the form: sd(c,t,d):s where: c = controller (Nth controller in system, usually 0) t = target (my-unit phys.hi) d = device/LUN (my-unit phys.lo) s = slice/partition (my-args) */ /* Controller currently always 0 */ obp_arg.boot_dev_ctrl = 0; /* Get the target, device and slice */ fword("my-unit"); target = POP(); device = POP(); fword("my-args"); id = pop_fstr_copy(); if (id != NULL) { snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", target, device, id[0]); obp_arg.dev_partition = id[0] - 'a'; } else { snprintf(buf, sizeof(buf), "sd(0,%d,%d)", target, device); obp_arg.dev_partition = 0; } obp_arg.boot_dev_unit = target; obp_arg.boot_dev[0] = buf[0]; obp_arg.boot_dev[1] = buf[1]; obp_arg.argv[0] = buf; obp_arg.argv[1] = bootargsbuf; } else if (!strncmp(name, "SUNW,fdtwo", 10)) { obp_arg.boot_dev_ctrl = 0; obp_arg.boot_dev_unit = 0; obp_arg.dev_partition = 0; strcpy(buf, "fd()"); obp_arg.boot_dev[0] = buf[0]; obp_arg.boot_dev[1] = buf[1]; obp_arg.argv[0] = buf; obp_arg.argv[1] = bootargsbuf; } else if (!strncmp(name, "le", 2)) { obp_arg.boot_dev_ctrl = 0; obp_arg.boot_dev_unit = 0; obp_arg.dev_partition = 0; strcpy(buf, "le()"); obp_arg.boot_dev[0] = buf[0]; obp_arg.boot_dev[1] = buf[1]; obp_arg.argv[0] = buf; obp_arg.argv[1] = bootargsbuf; } /* Generate the totphys (total memory available) list */ prop = get_property(s_phandle_memory, "reg", &proplen); intprop_ptr = (unsigned int *)prop; for (pp = &totphyslist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); (**pp).theres_more = NULL; (**pp).start_adr = (char *)intprop_ptr[1]; (**pp).num_bytes = intprop_ptr[2]; intprop_ptr += 3; } /* Generate the avail (physical memory available) list */ prop = get_property(s_phandle_memory, "available", &proplen); intprop_ptr = (unsigned int *)prop; for (pp = &availlist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); (**pp).theres_more = NULL; (**pp).start_adr = (char *)intprop_ptr[1]; (**pp).num_bytes = intprop_ptr[2]; intprop_ptr += 3; } /* Generate the prommap (taken virtual memory) list from inverse of available */ prop = get_property(s_phandle_mmu, "available", &proplen); intprop_ptr = (unsigned int *)prop; for (pp = &prommaplist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); (**pp).theres_more = NULL; (**pp).start_adr = (char *)(intprop_ptr[1] + intprop_ptr[2]); if (i + 3 < (proplen / sizeof(int))) { /* Size from next entry */ (**pp).num_bytes = (intprop_ptr[4] + intprop_ptr[5]) - (intprop_ptr[1] + intprop_ptr[2]); } else { /* Tail (size from top of virtual memory) */ (**pp).num_bytes = ofmem_arch_get_virt_top() - 1 - (intprop_ptr[1] + intprop_ptr[2]) + 1; } intprop_ptr += 3; } /* Finally set the memory properties */ ((struct linux_romvec *)romvec)->pv_v0mem.v0_totphys = &totphyslist; ((struct linux_romvec *)romvec)->pv_v0mem.v0_available = &availlist; ((struct linux_romvec *)romvec)->pv_v0mem.v0_prommap = &prommaplist; }
void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size, unsigned long rom, uint32_t rom_size) { phandle_t ph, chosen, aliases, options; char buf[6]; int width = VGA_DEFAULT_WIDTH; int height = VGA_DEFAULT_HEIGHT; int depth = VGA_DEFAULT_DEPTH; int linebytes = VGA_DEFAULT_LINEBYTES; #if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC64)) int w, h, d; w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH); h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT); d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH); if (w && h && d) { width = w; height = h; depth = d; linebytes = (width * ((depth + 7) / 8)); } #ifdef CONFIG_SPARC64 #define VGA_VADDR 0xfe000000 ofmem_claim_phys(fb, fb_size, 0); ofmem_claim_virt(VGA_VADDR, fb_size, 0); ofmem_map(fb, VGA_VADDR, fb_size, 0x76); fb = VGA_VADDR; #endif #endif vga_vbe_set_mode(width, height, depth); #if 0 ph = find_dev(path); #else ph = get_cur_dev(); #endif set_int_property(ph, "width", width); set_int_property(ph, "height", height); set_int_property(ph, "depth", depth); set_int_property(ph, "linebytes", linebytes); set_int_property(ph, "address", (u32)(fb & ~0x0000000F)); chosen = find_dev("/chosen"); push_str(path); fword("open-dev"); set_int_property(chosen, "display", POP()); aliases = find_dev("/aliases"); set_property(aliases, "screen", path, strlen(path) + 1); options = find_dev("/options"); snprintf(buf, sizeof(buf), "%d", width / FONT_WIDTH); set_property(options, "screen-#columns", buf, strlen(buf) + 1); snprintf(buf, sizeof(buf), "%d", height / FONT_HEIGHT); set_property(options, "screen-#rows", buf, strlen(buf) + 1); if (rom_size >= 8) { const char *p; int size; p = (const char *)rom; if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') { size = *(uint32_t*)(p + 4); set_property(ph, "driver,AAPL,MacOS,PowerPC", p + 8, size); } } init_video(fb, width, height, depth, linebytes); }
void load(ihandle_t dev) { /* Invoke the loaders on the specified device */ char *param; ucell valid; #ifdef CONFIG_LOADER_ELF /* Grab the boot arguments */ push_str("bootargs"); push_str("/chosen"); fword("(find-dev)"); POP(); fword("get-package-property"); POP(); param = pop_fstr_copy(); elf_load(&sys_info, dev, param, &elf_boot_notes); feval("state-valid @"); valid = POP(); if (valid) { return; } #endif #ifdef CONFIG_LOADER_AOUT aout_load(&sys_info, dev); feval("state-valid @"); valid = POP(); if (valid) { return; } #endif #ifdef CONFIG_LOADER_FCODE fcode_load(dev); feval("state-valid @"); valid = POP(); if (valid) { return; } #endif #ifdef CONFIG_LOADER_FORTH forth_load(dev); feval("state-valid @"); valid = POP(); if (valid) { return; } #endif #ifdef CONFIG_LOADER_BOOTCODE /* Check for a "raw" %BOOT bootcode payload */ feval("want-bootcode @"); valid = POP(); if (valid) { bootcode_load(dev); } #endif }
static void gen(Error_printer *err, Frag *frag, Node * n) { switch(n->what) { case nCOMMA: { genn(err, frag, n->l), gen(err, frag, n->r); break; } case nPAREN: { gen(err, frag, n->r); break; } case nLIST: { int amnt = genl(err, frag, n->r); push_lst(frag); emitn(frag, amnt); emitc(frag, iFIX); fixlooplvl(frag, amnt); break; } case nVOID: { push_void(frag); break; } case nTHIS: { push_this(frag); break; } case nNUM: { push_num(frag); emitl(frag, n->n); break; } case nFP: { push_fp(frag); emitd(frag, n->fp); break; } case nSTR: { push_str(frag); emits(frag, n->s, n->n); break; } case nNAM: { push_nam(frag); emitp(frag, n->s); emitc(frag, iGET_ATOM); break; } case nSET: { gen(err, frag, n->r); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); break; } case nIF: { gencond(err, frag, n->r, 1); break; } case nPOST: { gen(err, frag, n->l); gen(err, frag, n->r); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); emitc(frag, iPOP); rmlooplvl(frag, lvlVALUE, 0, 0); break; } case nADDR: { /* Generate a code snippet */ genfunc(err, frag, consempty(n->loc), n->r); break; } case nDEFUN: { if (n->r->what==nSEMI) { if (n->r->l->what==nCALL && n->r->l->l->what==nNAM) { /* fn sq(x) x*x */ genfunc(err, frag, n->r->l->r, n->r->r); push_nam(frag); emitp(frag, n->r->l->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nNAM && n->r->r->what==nSEMI && n->r->r->l->what==nPAREN) { /* fn sq (x) x*x */ genfunc(err, frag, n->r->r->l, n->r->r->r); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nNAM && n->r->r->what==nPAREN) { /* fn sq (x) */ genfunc(err, frag, n->r->r, consempty(n->loc)); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if (n->r->l->what==nPAREN) { /* fn (x) x*x */ genfunc(err, frag, n->r->l, n->r->r); } else { error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line); push_void(frag); } } else if(n->r->what==nCALL && n->r->l->what==nNAM) { /* fn sq(x) */ genfunc(err, frag, n->r->r, consempty(n->loc)); push_nam(frag); emitp(frag, n->r->l->s); emitc(frag, iGETF_ATOM); emitc(frag, iSET); rmlooplvl(frag, lvlVALUE, 0, 0); } else if(n->r->what==nPAREN) { /* fn () */ genfunc(err,frag, n->r, consempty(n->loc)); } else { error_2(err, "\"%s\" %d: ill-formed fn", n->r->loc->name, n->r->loc->line); push_void(frag); } break; } case nLAMBDA: { genfunc(err, frag, n->r->l, n->r->r); break; } case nSEMI: { if (n->r->what == nELSE) { int done = genelif(err, frag, n->l, 1); if (!done) error_2(err, "\"%s\" %d: else w/o if error", n->r->loc->name, n->r->loc->line); if (n->r->r->what == nIF) { addlist(frag, done, genbra(err, frag, n->r->r->l, 1)); n = n->r; } mklooplvl(frag, lvlSCOPE, 0, 0); gen(err, frag, n->r->r); rmlooplvl(frag, lvlSCOPE, 0, 0); setlist(frag, done, frag->code); } else { genn(err, frag, n->l); gen(err, frag, n->r); } break; } case nEQ: case nNE: case nGT: case nLT: case nGE: case nLE: case nLAND: case nLOR: case nNOT: { int b = genbra(err, frag, n, 1); int link; push_num(frag); emitl(frag, 1); emitc(frag, iBRA); link=emitn(frag, 0); setlist(frag, b, frag->code); push_num(frag); emitl(frag, 0); *(int *)(frag->begcode+link)=frag->code-link; break; } case nCALL: { // int nargs = genl(err, frag, n->r); /* By value */ int nargs = gencl(err, frag, n->r); /* Functionalize */ push_lst(frag); emitn(frag, nargs); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iCALL); fixlooplvl(frag, nargs + 1); break; } case nCALL1: { /* Ends up being the same as above */ // if (n->r->what != nNAM) // error_2(err, "\"%s\" %d: Invalid member name", n->r->loc->name, n->r->loc->line); if (n->r->what == nNAM) { /* Turn it into a string .x -> ."x" */ n->r->what = nSTR; } int nargs = gencl(err, frag, n->r); // push_str(frag); // emits(frag, n->r->s, n->r->n); push_lst(frag); emitn(frag, nargs); // gena(err, frag, n->l); (lvalue change) gen(err, frag, n->l); emitc(frag, iCALL); fixlooplvl(frag, nargs + 1); break; } case nCOM: case nNEG: case nSHL: case nSHR: case nMUL: case nDIV: case nMOD: case nAND: case nADD: case nSUB: case nOR: case nXOR: case nAT: { if (n->l) gen(err, frag, n->l); if (n->r) gen(err, frag, n->r); emitc(frag, what_tab[n->what].i); if (n->r && n->l) rmlooplvl(frag, lvlVALUE, 0, 0); break; } default: { genn(err, frag, n); push_void(frag); } } }
/* WARNING: sloooow - AVOID */ cell feval( const char *str ) { push_str( str ); return eword("evaluate", 2); }
/* ( open -- flag ) */ static void pcparts_open( pcparts_info_t *di ) { char *str = my_args_copy(); char *argstr = strdup(""); char *parstr = strdup(""); int bs, parnum=-1; int found = 0; phandle_t ph; ducell offs, size; /* Layout of PC partition table */ struct pc_partition { unsigned char boot; unsigned char head; unsigned char sector; unsigned char cyl; unsigned char type; unsigned char e_head; unsigned char e_sector; unsigned char e_cyl; u32 start_sect; /* unaligned little endian */ u32 nr_sects; /* ditto */ } *p, *partition; unsigned char buf[512]; DPRINTF("pcparts_open '%s'\n", str ); /* Arguments that we accept: id: [0-7] [(id)][,][filespec] */ if ( strlen(str) ) { /* Detect the arguments */ if ((*str >= '0' && *str <= '7') || (*str == ',')) { push_str(str); PUSH(','); fword("left-parse-string"); parstr = pop_fstr_copy(); argstr = pop_fstr_copy(); } else { argstr = str; } /* Convert the id to a partition number */ if (parstr && strlen(parstr)) parnum = atol(parstr); } /* Make sure argstr is not null */ if (argstr == NULL) argstr = strdup(""); DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); free(parstr); if( parnum < 0 ) parnum = 0; di->filesystem_ph = 0; di->read_xt = find_parent_method("read"); di->seek_xt = find_parent_method("seek"); SEEK( 0 ); if( READ(buf, 512) != 512 ) RET(0); /* Check Magic */ if (!has_pc_part_magic(buf)) { DPRINTF("pc partition magic not found.\n"); RET(0); } /* Actual partition data */ partition = (struct pc_partition *) (buf + 0x1be); /* Make sure we use a copy accessible from an aligned pointer (some archs e.g. SPARC will crash otherwise) */ p = malloc(sizeof(struct pc_partition)); bs = 512; if (parnum < 4) { /* primary partition */ partition += parnum; memcpy(p, partition, sizeof(struct pc_partition)); if (p->type == 0 || is_pc_extended_part(p->type)) { DPRINTF("partition %d does not exist\n", parnum+1 ); RET( 0 ); } offs = (long long)(__le32_to_cpu(p->start_sect)) * bs; di->offs_hi = offs >> BITS; di->offs_lo = offs & (ucell) -1; size = (long long)(__le32_to_cpu(p->nr_sects)) * bs; di->size_hi = size >> BITS; di->size_lo = size & (ucell) -1; DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect)); /* If PReP boot partition, exit immediately with no filesystem probe */ if (p->type == 0x41) { RET(-1); } found = 1; } else {
static int espdma_init(unsigned int slot, uint64_t base, unsigned long offset, struct esp_dma *espdma) { espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10); if (espdma->regs == NULL) { DPRINTF("espdma_init: cannot map registers\n"); return -1; } DPRINTF("dma1: "); switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) { case DMA_VERS0: espdma->revision = dvmarev0; DPRINTF("Revision 0 "); break; case DMA_ESCV1: espdma->revision = dvmaesc1; DPRINTF("ESC Revision 1 "); break; case DMA_VERS1: espdma->revision = dvmarev1; DPRINTF("Revision 1 "); break; case DMA_VERS2: espdma->revision = dvmarev2; DPRINTF("Revision 2 "); break; case DMA_VERHME: espdma->revision = dvmahme; DPRINTF("HME DVMA gate array "); break; case DMA_VERSPLUS: espdma->revision = dvmarevplus; DPRINTF("Revision 1 PLUS "); break; default: DPRINTF("unknown dma version %x", (espdma->regs->cond_reg) & DMA_DEVICE_ID); /* espdma->allocated = 1; */ break; } DPRINTF("\n"); push_str("/iommu/sbus/espdma"); fword("find-device"); /* set reg */ PUSH(slot); fword("encode-int"); PUSH(offset); fword("encode-int"); fword("encode+"); PUSH(0x00000010); fword("encode-int"); fword("encode+"); push_str("reg"); fword("property"); return 0; }
int ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset, unsigned long dmaoffset) { int id, diskcount = 0, cdcount = 0, *counter_ptr; char nodebuff[256], aliasbuff[256]; esp_private_t *esp; unsigned int i; DPRINTF("Initializing SCSI..."); esp = malloc(sizeof(esp_private_t)); if (!esp) { DPRINTF("Can't allocate ESP private structure\n"); return -1; } global_esp = esp; if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) { return -1; } /* Get the IO region */ esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset, sizeof(struct esp_regs)); if (esp->ll == NULL) { DPRINTF("Can't map ESP registers\n"); return -1; } esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma); if (!esp->buffer || !esp->buffer_dvma) { DPRINTF("Can't get a DVMA buffer\n"); return -1; } // Chip reset esp->ll->regs[ESP_CMD] = ESP_CMD_RC; DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp, (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma); DPRINTF("done\n"); DPRINTF("Initializing SCSI devices..."); for (id = 0; id < 8; id++) { esp->sd[id].id = id; if (!inquiry(esp, &esp->sd[id])) { DPRINTF("Unit %d not present\n", id); continue; } /* Clear Unit Attention condition from reset */ for (i = 0; i < 5; i++) { if (test_unit_ready(esp, &esp->sd[id])) { break; } } if (i == 5) { DPRINTF("Unit %d present but won't become ready\n", id); continue; } DPRINTF("Unit %d present\n", id); read_capacity(esp, &esp->sd[id]); #ifdef CONFIG_DEBUG_ESP dump_drive(&esp->sd[id]); #endif } REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp"); device_end(); /* set reg */ push_str("/iommu/sbus/espdma/esp"); fword("find-device"); PUSH(slot); fword("encode-int"); PUSH(espoffset); fword("encode-int"); fword("encode+"); PUSH(0x00000010); fword("encode-int"); fword("encode+"); push_str("reg"); fword("property"); PUSH(0x02625a00); fword("encode-int"); push_str("clock-frequency"); fword("property"); for (id = 0; id < 8; id++) { if (!esp->sd[id].present) continue; push_str("/iommu/sbus/espdma/esp"); fword("find-device"); fword("new-device"); push_str("sd"); fword("device-name"); push_str("block"); fword("device-type"); fword("is-deblocker"); PUSH(id); fword("encode-int"); PUSH(0); fword("encode-int"); fword("encode+"); push_str("reg"); fword("property"); fword("finish-device"); snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0", id); REGISTER_NODE_METHODS(ob_sd, nodebuff); if (esp->sd[id].media == TYPE_ROM) { counter_ptr = &cdcount; } else { counter_ptr = &diskcount; } if (*counter_ptr == 0) { add_alias(nodebuff, esp->sd[id].media_str[0]); add_alias(nodebuff, esp->sd[id].media_str[1]); } snprintf(aliasbuff, sizeof(aliasbuff), "%s%d", esp->sd[id].media_str[0], *counter_ptr); add_alias(nodebuff, aliasbuff); snprintf(aliasbuff, sizeof(aliasbuff), "%s%d", esp->sd[id].media_str[1], *counter_ptr); add_alias(nodebuff, aliasbuff); snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id); add_alias(nodebuff, aliasbuff); snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id); add_alias(nodebuff, aliasbuff); (*counter_ptr)++; } DPRINTF("done\n"); return 0; }
/* ( -- success? ) */ static void dlabel_open( dlabel_info_t *di ) { char *path; char block0[512]; phandle_t ph; int success=0; cell status; path = my_args_copy(); DPRINTF("dlabel-open '%s'\n", path ); di->part_ih = 0; /* Find parent methods */ di->filesystem_ph = 0; di->parent_seek_xt = find_parent_method("seek"); di->parent_tell_xt = find_parent_method("tell"); di->parent_read_xt = find_parent_method("read"); /* If arguments have been passed, determine the partition/filesystem type */ if (path && strlen(path)) { /* Read first block from parent device */ DPUSH(0); call_package(di->parent_seek_xt, my_parent()); POP(); PUSH(pointer2cell(block0)); PUSH(sizeof(block0)); call_package(di->parent_read_xt, my_parent()); status = POP(); if (status != sizeof(block0)) goto out; /* Find partition handler */ PUSH( pointer2cell(block0) ); selfword("find-part-handler"); ph = POP_ph(); if( ph ) { /* We found a suitable partition handler, so interpose it */ DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph); push_str(path); PUSH_ph(ph); fword("interpose"); success = 1; } else { /* unknown (or missing) partition map, * try the whole disk */ DPRINTF("Unknown or missing partition map; trying whole disk\n"); /* Probe for filesystem from start of device */ DPUSH ( 0 ); PUSH_ih( my_self() ); selfword("find-filesystem"); ph = POP_ph(); if( ph ) { /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */ di->filesystem_ph = ph; DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph); DPRINTF("path: %s length: %d\n", path, strlen(path)); if (path && strlen(path)) { DPRINTF("INTERPOSE!\n"); push_str( path ); PUSH_ph( ph ); fword("interpose"); } } else if (path && strcmp(path, "%BOOT") != 0) { goto out; } success = 1; } } else { /* No arguments were passed, so we just use the parent raw device directly */ success = 1; } out: if( path ) free( path ); if( !success ) { dlabel_close( di ); RET(0); } PUSH(-1); }
/* ( open -- flag ) */ static void macparts_open( macparts_info_t *di ) { char *str = my_args_copy(); char *parstr = NULL, *argstr = NULL; char *tmpstr; int bs, parnum=-1, apple_parnum=-1; int parlist[2], parlist_size = 0; desc_map_t dmap; part_entry_t par; int ret = 0, i = 0, j = 0; int want_bootcode = 0; phandle_t ph; ducell offs = 0, size = -1; DPRINTF("macparts_open '%s'\n", str ); /* Arguments that we accept: id: [0-7] [(id)][,][filespec] */ if ( str && strlen(str) ) { /* Detect the arguments */ if ((*str >= '0' && *str <= '9') || (*str == ',')) { push_str(str); PUSH(','); fword("left-parse-string"); parstr = pop_fstr_copy(); argstr = pop_fstr_copy(); } else { argstr = str; } /* Make sure argstr is not null */ if (argstr == NULL) argstr = strdup(""); /* Convert the id to a partition number */ if (parstr && strlen(parstr)) parnum = atol(parstr); /* Detect if we are looking for the bootcode */ if (strcmp(argstr, "%BOOT") == 0) { want_bootcode = 1; } } DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); DPRINTF("want_bootcode %d\n", want_bootcode); DPRINTF("macparts_open %d\n", parnum); di->filesystem_ph = 0; di->read_xt = find_parent_method("read"); di->seek_xt = find_parent_method("seek"); SEEK( 0 ); if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) ) goto out; /* partition maps might support multiple block sizes; in this case, * pmPyPartStart is typically given in terms of 512 byte blocks. */ bs = __be16_to_cpu(dmap.sbBlockSize); if( bs != 512 ) { SEEK( 512 ); READ( &par, sizeof(par) ); if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE ) bs = 512; } SEEK( bs ); if( READ(&par, sizeof(par)) != sizeof(par) ) goto out; if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE) goto out; /* * Implement partition selection as per the PowerPC Microprocessor CHRP bindings */ if (argstr == NULL || parnum == 0) { /* According to the spec, partition 0 as well as no arguments means the whole disk */ offs = (long long)0; size = (long long)__be32_to_cpu(dmap.sbBlkCount) * bs; di->blocksize = (unsigned int)bs; di->offs_hi = offs >> BITS; di->offs_lo = offs & (ucell) -1; di->size_hi = size >> BITS; di->size_lo = size & (ucell) -1; ret = -1; goto out; } else if (parnum == -1) {
static struct token fetch_token(struct parser *parser, struct lexer *lex) { /* {{{ fetch_token body */ /* a nifty shorthand for the current position */ #define p (lex->curr_pos) char tmp_arr[MAX_NAME_LENGTH + 1] = { '\0' }; char *tmp_str = NULL; int i = 0; bool keyword_found = false, typename_found = false; int slen = 0; struct token ret; /* {{{ skip over whitespace and comments */ do { if (isspace(*p)){ for (; isspace(*p); p++){ if (*p == '\n'){ lex->line++; lex->col = 0; } else { lex->col++; } } } else if (*p == '/' && *(p + 1) == '*'){ int nest_level = 1; p += 2; lex->col += 2; for (; *p != '\0' && nest_level > 0; p++){ if (*p == '\n'){ lex->line++; lex->col = 0; } else if (*p == '/' && *(p + 1) == '*'){ nest_level++; p++; lex->col += 2; } else if (*p == '*' && *(p + 1) == '/'){ nest_level--; p++; lex->col += 2; } else lex->col++; } } } while (isspace(*p) || (*p == '/' && *(p + 1) == '*')); /* }}} */ if (p == NULL || *p == '\0' || (lex->fptr != NULL && feof(lex->fptr))){ ret.type = TOK_EOS; return ret; } if (name_beg(*p)){ /* {{{ NAME / KEYWORD / TYPE NAME */ const char **kptr = NULL; strncpy(tmp_arr, p, MAX_NAME_LENGTH - 1); tmp_arr[MAX_NAME_LENGTH] = '\0'; while (name_mid(*p)){ p++; i++; } tmp_arr[i] = '\0'; /* see if it's a keyword */ for (kptr = keywords; *kptr != NULL; kptr++){ if (!strcmp(*kptr, tmp_arr)){ keyword_found = true; break; } } /* see if it's a type name (only if it's not a keyword already) */ if (!keyword_found){ struct types_list *q; for (q = NM_types; q != NULL; q = q->next){ /* don't check anonymous types */ if (q->type->name != NULL){ if (!strcmp(q->type->name, tmp_arr)){ typename_found = true; break; } } } } if (keyword_found){ ret.type = TOK_KEYWORD; strcpy(ret.value.s, *kptr); lex->col += strlen(*kptr); } else if (typename_found){ ret.type = TOK_TYPE; strcpy(ret.value.s, tmp_arr); lex->col += strlen(tmp_arr); } else { ret.type = TOK_NAME; strcpy(ret.value.s, tmp_arr); lex->col += strlen(tmp_arr); } /* }}} */ } else if (isdigit(*p)){ /* {{{ NUMBER */ int i2 = 0; while (isdigit(*p) || (*p == '_' && isdigit(*(p + 1)))){ if (isdigit(*p)){ tmp_arr[i2++] = *p; } p++; i++; } if (*p == '.'){ /* {{{ FLOAT */ tmp_arr[i2++] = '.'; p++; i++; /* skip over the '.' */ if (isdigit(*p)){ while (isdigit(*p) || (*p == '_' && isdigit(*(p + 1)))){ if (isdigit(*p)){ tmp_arr[i2++] = *p; } p++; i++; } tmp_arr[i2] = '\0'; ret.type = TOK_REAL; ret.value.f = strtod(tmp_arr, NULL); } else { /* it's something like 2. */ tmp_arr[i] = '\0'; ret.type = TOK_REAL; ret.value.f = strtod(tmp_arr, NULL); } /* }}} */ } else { /* {{{ DECIMAL */ ret.type = TOK_INTEGER; ret.value.i = strtol(tmp_arr, NULL, 10); /* }}} */ } lex->col += i; /* }}} */ } else if (*p == '`'){ /* {{{ CHAR */ nchar_t value; /* skip over the opening "'" */ p++; /* fetch the (possibly multibyte) character */ value = u8_fetch_char(&p); if (*p != '`') err(parser, lex, "unterminated character"); /* skip over the closing "'" */ p++; ret.type = TOK_CHAR; ret.value.c = value; /* }}} */ } else if (*p == '"'){ /* {{{ STRING */ char *savep; int i2 = 0; p++; i++; lex->col++; savep = p; /* skip over the opening '"' */ while (*p != '"' && *p != '\n'){ p++; i++; lex->col++; slen++; } if (*p == '\n'){ err(parser, lex, "unterminated string"); } tmp_str = nmalloc(/* sizeof(char) times */slen + 1); while (*savep != '"') *(tmp_str + i2++) = *savep++; i--; p++; /* jump to the next character so the next `fetch_token' doesn't start lexing at the closing '"' */ push_str(lex, tmp_str); ret.type = TOK_STRING; ret.value.sp = tmp_str; /* }}} */ } else if (*p == '\''){ /* {{{ TYPE VARIABLE */ /* skip over the ' */ p++; ret.type = TOK_TYPE_VARIABLE; ret.value.c = u8_fetch_char(&p); /* }}} */ } else if (*p == '%'){ if (isdigit(*(p + 1))){ /* {{{ ACCUMULATOR */ unsigned i = 0; tmp_arr[i++] = '%'; p++; while (isdigit(*p) && i < MAX_NAME_LENGTH) tmp_arr[i++] = *p++; lex->col += i; strcpy(ret.value.s, tmp_arr); ret.type = TOK_ACCUMULATOR; /* }}} */ } else { /* {{{ PERCENT SIGN */ if (*(p + 1) == '='){ /* %= */ lex->col += 2; p += 2; ret.type = TOK_PERCENT_EQ; } else { /* % */ lex->col++; p++; ret.type = TOK_PERCENT; } /* }}} */ } } else switch (*p){ /* {{{ OPERATOR */ #define single(TYPE) { \ lex->col++; \ p++; \ ret.type = TOK_##TYPE; \ } \ break /* no semicolon */ #define possibly_double(TYPE) \ if (*(p + 1) == *p){ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_2; \ } else \ single(TYPE); /* `single` already handles the `break` */ #define possibly_eq(TYPE) \ if (*(p + 1) == '='){ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_EQ; \ } else \ single(TYPE); /* `single` already handles the `break` */ #define possibly_double_or_eq(TYPE) \ if (*(p + 1) == *p){ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_2; \ } else if (*(p + 1) == '='){ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_EQ; \ } else \ single(TYPE); /* `single` already handles the `break` */ #define possibly_double_or_eq_or_both(TYPE) \ if (*(p + 1) == *p){ \ if (*(p + 2) == '='){ \ /* double and eq */ \ lex->col += 3; \ p += 3; \ ret.type = TOK_##TYPE##_2_EQ; \ } else { \ /* double */ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_2; \ } \ } else if (*(p + 1) == '='){ \ /* single and eq */ \ lex->col += 2; \ p += 2; \ ret.type = TOK_##TYPE##_EQ; \ } else \ single(TYPE); /* `single` already handles the `break` */ case '=': possibly_double(EQ); case ':': single(COLON); case ';': single(SEMICOLON); case ',': single(COMMA); case '-': possibly_double_or_eq(MINUS); case '+': possibly_double_or_eq(PLUS); case '*': possibly_eq(TIMES); case '/': possibly_eq(SLASH); case '(': single(LPAREN); case ')': single(RPAREN); case '{': single(LMUSTASHE); case '}': single(RMUSTASHE); case '[': single(LBRACKET); case ']': single(RBRACKET); case '!': possibly_eq(BANG); case '?': single(QUESTION); case '&': possibly_double_or_eq(AMPERSAND); case '^': possibly_eq(CARET); case '|': possibly_double_or_eq(PIPE); case '<': possibly_double_or_eq_or_both(LCHEVRON); case '>': possibly_double_or_eq_or_both(RCHEVRON); /* no case for the percent sign - it was already covered by the * 'accumulator' thingy */ default: fprintf(stderr, "nemo: unknown character '%c' (0x%x) in %s" " at line %u column %u\n", *p, *p, lex->name, lex->line, lex->col); /* FIXME don't exit here */ exit(1); /* }}} */ } #undef p #undef single #undef possibly_double #undef possibly_eq #undef possibly_double_or_eq #undef possibly_double_or_eq_or_both return ret; /* }}} */ }
static char * exec_instr( pInstr s ) { pCell tc, tc2; char buffer[16]; switch (s->opcode) { case SET: /* operand must be a string */ tc = temp_pop(); switch (tc->type) { case mu: fprintf(stderr, "exec_inst/SET: warning - unhandled case mu\n" ); break; case string_t: var_put(s->operand.contents.s, tc->contents.s); break; case int_t: var_put_int(s->operand.contents.s, tc->contents.i); break; } break; case EMIT: tc = temp_pop(); switch (tc->type) { case mu: fprintf(stderr, "exec_inst/EMIT: warning - unhandled case mu\n" ); break; case string_t: return tc->contents.s; case int_t: sprintf(buffer, "%i", tc->contents.i); return strdup(buffer); } case PUSHV: { struct var *v = var_lookup(vars, s->operand.contents.s); if (v == 0) { fprintf(stderr, "attempted to use unknown variable \"%s\" in expression.\n", s->operand.contents.s); push_str("(NULL)"); } else { switch (v->type) { case mu: fprintf(stderr, "exec_inst/PUSHV: warning - unhandled case mu\n" ); break; case string_t: push_str(strdup(v->value.s)); break; case int_t: push_int(v->value.i); break; } } } break; case INVOKE: { pRule r = rule_find(rule_base, s->operand.contents.s); if (r) { push_str(resolve_rule(rule_base, r)); } else { fprintf(stderr, "attempted to invoke non-existent rule \"%s\" in expression.\n", s->operand.contents.s); push_str(NULL); } } break; case PUSH: switch (s->operand.type) { case mu: fprintf(stderr, "exec_inst/PUSH: warning - unhandled case mu\n" ); break; case string_t: push_str(strdup(s->operand.contents.s)); break; case int_t: push_int(s->operand.contents.i); break; } break; case ADD: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc->contents.i + tc2->contents.i); } else { char *s0, *s1; /* string concatenation */ s0 = ((tc->type == int_t) ? itoa(tc->contents.i) : (tc->contents.s)); s1 = ((tc2->type == int_t) ? itoa(tc2->contents.i) : (tc2->contents.s)); push_str(concat(s1, s0)); free(s0); free(s1); } break; case SUB: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i + tc->contents.i); } break; case MUL: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc->contents.i * tc2->contents.i); } break; case DIV: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i / tc->contents.i); } break; case MOD: tc = temp_pop(); tc2 = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(tc2->contents.i % tc->contents.i); } break; case RANDOM: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int((ranq1() % (tc2->contents.i - tc->contents.i + 1)) + tc->contents.i); } break; case LESSER: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(min(tc->contents.i, tc2->contents.i)); } break; case GREATER: tc2 = temp_pop(); tc = temp_pop(); if ((tc->type == int_t) && (tc2->type == int_t)) { push_int(max(tc->contents.i, tc2->contents.i)); } break; } return NULL; }