Beispiel #1
0
static void
setenv( char *env, char *value )
{
	push_str( value );
	push_str( env );
	fword("$setenv");
}
Beispiel #2
0
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");
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
        }
}
Beispiel #5
0
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");
}
Beispiel #6
0
void
bind_func( const char *name, void (*func)(void) )
{
	PUSH( pointer2cell(func) );
	push_str( name );
	fword("is-cfunc");
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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");
}
Beispiel #10
0
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
}
Beispiel #11
0
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;
}
Beispiel #12
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");
}
Beispiel #13
0
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");
}
Beispiel #14
0
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);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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);
}
Beispiel #18
0
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

}
Beispiel #19
0
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);
		}
	}
}
Beispiel #20
0
/* WARNING: sloooow - AVOID */
cell
feval( const char *str )
{
	push_str( str );
	return eword("evaluate", 2);
}
Beispiel #21
0
/* ( 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 {
Beispiel #22
0
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;
}
Beispiel #23
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;
}
Beispiel #24
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);
}
Beispiel #25
0
/* ( 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) {
Beispiel #26
0
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;
  /* }}} */
}
Beispiel #27
0
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;
}