Ejemplo n.º 1
0
Archivo: lib.c Proyecto: omasanori/benz
struct pic_lib *
pic_open_library(pic_state *pic, pic_value name)
{
  struct pic_lib *lib;
  struct pic_senv *senv;
  struct pic_dict *exports;

  if ((lib = pic_find_library(pic, name)) != NULL) {

#if DEBUG
    printf("* reopen library: ");
    pic_debug(pic, name);
    puts("");
#endif

    return lib;
  }

  senv = pic_null_syntactic_environment(pic);
  exports = pic_make_dict(pic);

  lib = (struct pic_lib *)pic_obj_alloc(pic, sizeof(struct pic_lib), PIC_TT_LIB);
  lib->name = name;
  lib->env = senv;
  lib->exports = exports;

  /* register! */
  pic->libs = pic_acons(pic, name, pic_obj_value(lib), pic->libs);

  return lib;
}
Ejemplo n.º 2
0
/*
 * Open device and perform command
 */
int
main(int argc, char **argv)
{
	char *execdup, *execname;
	int rc = EX_OK;

	/* Get exec name */
	execdup = (char *)strdup(argv[0]);
	if (execdup == NULL) {
		printf("%s: fatal error: strdup failed\n", __func__);
		io_exit(EX_OSERR); /* Panic */
	}
	execname = basename(execdup);
	if (execname == NULL) {
		printf("%s: fatal error: basename failed\n", __func__);
		io_exit(EX_OSERR); /* Panic */
	}

	/* Get configuration */
	getconf();
	
	/* Open device */
	if (io_open() < 0) {
		usage(execname, io_error());
	}

	/* Raise priority */
	setpriority(PRIO_PROCESS, 0, -20);

	/* Reset uid */
	if (getuid() != geteuid()) {
		if (setuid(getuid()) < 0) {
			printf("%s: fatal error: setuid failed\n", __func__);
			io_exit(EX_OSERR); /* Panic */
		}
	}

	/* Determine arch: 12 | 14 | 16 | 24 | 32 */
	if (pic_arch(execname) == 0)
		usage_pickle();

	/* Perform operation */
	if (argc < 2)
		usage(execname, "Missing arg(s)");

	/* Device selection */
	int argv1 = tolower((int)argv[1][0]);
	if (argv1 == 's') { /* Select device */
		if (argc < 3) {
			pic_selector();
			io_exit(EX_OK);
		}
		if (mystrcasestr(argv[2], "dspic") == argv[2]) {
			strncpy(p.devicename, argv[2], STRLEN);
		} else if (mystrcasestr(argv[2], "pic") == argv[2]) {
			strncpy(p.devicename, argv[2], STRLEN);
		} else {
			int32_t temp = strtol(argv[2], NULL, 0);
			if (temp < 10 || temp > 33) {
				usage(execname, "Invalid arg [select]");
			}
			if (temp == 30 || temp == 33) {
				strcpy(p.devicename, "dspic");
				strncpy(&p.devicename[5], argv[2], STRLEN - 5);
			} else {
				strcpy(p.devicename, "pic");
				strncpy(&p.devicename[3], argv[2], STRLEN - 3);
			}
		}
		argc -= 2;
		argv += 2;
		if (argc < 2)
			usage(execname, "Missing arg(s)");
	} else if (p.pic->arch == ARCH12BIT) {
		usage(execname, "Missing select");
	}

	/* Key entry */
	argv1 = tolower((int)argv[1][0]);
	if (argv1 == 'l') {			/* LVP 32-bit key entry */
		if (p.pic->arch == ARCH12BIT) {
			usage(execname, "Invalid arg [lvp]");
		}
		/* ARCH14BIT || ARCH16BIT || ARCH24BIT || ARCH32BIT */
		p.key = LVPKEY;
		argc -= 1;
		argv += 1;
		if (argc < 2)
			usage(execname, "Missing arg(s)");
	}
	else if (argv1 == 'h') {		/* HVP 32-bit key entry */
		if (p.pic->arch == ARCH12BIT || p.pic->arch == ARCH14BIT || p.pic->arch == ARCH32BIT) {
			usage(execname, "Invalid arg [hvp]");
		}
		/* ARCH16BIT || ARCH24BIT */
		p.key = HVPKEY;
		argc -= 1;
		argv += 1;
		if (argc < 2)
			usage(execname, "Missing arg(s)");
	}
	else if (p.pic->arch == ARCH32BIT) {	/* LVP 32-bit key entry */
		/* ARCH32BIT */
		p.key = LVPKEY;
	}
	else {					/* No key entry */
		/* ARCH12BIT || ARCH14BIT || ARCH16BIT || ARCH24BIT */
		p.key = NOKEY;
	}

	/* Command */
	argv1 = tolower((int)argv[1][0]);
	int argv11 = tolower((int)argv[1][1]);
	switch (argv1) {
	case 'b':	if (argv11 == 'o') {		/* BOOT */
				uint32_t addr = UINT32_MAX, words = UINT32_MAX;
				if (argc > 4)
					usage(execname, "Too many args [boot]");
				if (argc >= 3) {
					words = strtoul(argv[2], NULL, 0);
					if (words == 0)
						usage(execname, "Invalid arg [boot]");
				}
				if (argc == 4) {
					addr = strtoul(argv[3], NULL, 0);
				}
				pic_dumpboot(addr, words);
			} else {			/* BLANK */
				int config = 1;
				if (argc > 3)
					usage(execname, "Too many args [blank]");
				if (argc == 3) switch (argv[2][0]) {
					case 'n':
					case 'N':
					case '0': config = 0;
						break;
					case 'y':
					case 'Y':
					case '1': config = 1;
						break;
					default:usage(execname, "invalid arg [blank]");
						break;
				}
				if (areyousure("Blank device")) {
					pic_blank(config);
				}
			}
			break;

	case 'c':	if (argc > 3)
				usage(execname, "Too many args [config]");
			if (argc == 2)
				pic_dumpconfig();
			else
				pic_writebandgap(strtoul(argv[2], NULL, 0));
			break;
	
	case 'd':	if (argv11 == 'a') {		/* DATA */
				if (argc > 2)
					usage(execname, "Too many args [data]");
				pic_dumpdata();
			} else if (argv11 == 'e') { 	/* DEBUG */
				pic_debug();
			} else {			/* DUMP */
				if (argc > 2)
					usage(execname, "Too many args [dump]");
				pic_dumpdevice();
			}
			break;

	case 'e':	if (argv11 == 'r') {		/* ERASE FLASH | ID | ROW[NROWS] */
				uint32_t row = 0, nrows = 1;
				char prompt[STRLEN] = {0}, *endptr = NULL;

				if (argc < 3)
					usage(execname, "Missing arg [erase]");
				if (argc > 4)
					usage(execname, "Too many args [erase]");
				
				int argv2 = tolower((int)argv[2][0]);
				switch (argv2) {
				case 'i': /* IDLOCATION    */
				case 'u': /* USERID/CONFIG */
					row = PIC_ERASE_ID;
					strncpy(prompt, "Erase id", STRLEN);
					break;
				case 'c': /* CONFIG */
					row = PIC_ERASE_CONFIG;
					strncpy(prompt, "Erase config", STRLEN);
					break;
				case 'e': /* EEPROM */
					row = PIC_ERASE_EEPROM;
					strncpy(prompt, "Erase EEPROM", STRLEN);
					break;
				case 'f': /* FLASH */
					nrows = UINT32_MAX;
					strncpy(prompt, "Erase program flash", STRLEN);
					break;
				default:  /* FLASH ROW */
					row = strtoul(argv[2], &endptr, 0);
					if (endptr == argv[2])
						usage(execname, "Invalid arg [erase]");
					if (argc == 4) {
						nrows = strtoul(argv[3], NULL, 0);
						if (nrows == 0)
							usage(execname, "Invalid arg [erase]");
					}
					snprintf(prompt, STRLEN, "Erase %u row(s) at row %u",
						nrows, row);
					break;
				}
				if (areyousure(prompt))
					pic_erase(row, nrows);
			} else if (argv11 == 'x') {	/* EXECUTIVE */
				uint32_t addr = UINT32_MAX, words = UINT32_MAX;
				if (argc > 4)
					usage(execname, "Too many args [executive]");
				if (argc >= 3) {
					words = strtoul(argv[2], NULL, 0);
					if (words == 0)
						usage(execname, "Invalid arg [executive]");
				}
				if (argc == 4) {
					addr = strtoul(argv[3], NULL, 0);
				}
				pic_dumpexec(addr, words);
			} else {			/* EEPROM */
				if (argc > 2)
					usage(execname, "Too many args [eeprom]");
				pic_dumpdata();
			}
			break;

	case 'f':	{
			uint32_t words = UINT32_MAX, addr = UINT32_MAX;
			if (argc > 4)
				usage(execname, "Too many args [program flash]");
			if (argc >= 3) {
				words = strtoul(argv[2], NULL, 0);
				if (words == 0)
					usage(execname, "Invalid arg [program flash]");
			}
			if (argc == 4) {
				addr = strtoul(argv[3], NULL, 0);
			}
			pic_dumpprogram(addr, words);
			}
			break;

	case 'i':	if (argc > 2)
				usage(execname, "Too many args [id]");
			pic_dumpdeviceid();
			break;

	case 'o':	if (argc > 3)
				usage(execname, "Too many args [osccal]");
			if (argc == 2)
				pic_dumposccal();
			else
				pic_writeosccal(strtoul(argv[2], NULL, 0));
			break;

	case 'p':	{
			int blank = 1;
			if (argc > 4)
				usage(execname, "Too many args [program]");
			if (argc == 4) switch (argv[3][0]) {
				case 'n':
				case 'N':
				case '0': blank = 0;
					break;
				case 'y':
				case 'Y':
				case '1': blank = 1;
					break;
				default:usage(execname, "invalid arg [program]");
					break;
			}
			if (argc < 3)
				pic_program("-", 1);
			else
				pic_program(argv[2], blank);
			}
			break;

	case 'v':	if (argv11 == 'i') {		/* VIEW */
				int raw = 0;
				if (argc > 4)
					usage(execname, "Too many args [view]");
				if (argc == 4) switch (argv[3][0]) {
					case 'r':
					case 'R': raw = 1;
						break;
					default:usage(execname, "invalid arg [view]");
						break;
				}
				if (argc < 3)
					pic_view("-", 0);
				else
					pic_view(argv[2], raw);
			} else {			/* VERIFY */
				if (argc > 3)
					usage(execname, "Too many args [verify]");
				if (argc < 3)
					rc = 0 - pic_verify("-");
				else
					rc = 0 - pic_verify(argv[2]);
			}
			break;
#ifdef TTY
	case '/':	if (strstr(argv[1], "/dev/tty") != argv[1]) {
				usage(execname, "Invalid device [TTY]");
			}
			if (strstr(argv[1], p.device) != NULL) {
				usage(execname, "Device in use [TTY]");
			}
			stk500v2_listen(argv[1], 0);
			break;

	case '8':	stk500v2_listen("0.0.0.0", 8048);
			break;
#endif
	default:	usage(execname, "Unknown operation");
			break;
	}

	free(execdup);
	io_exit(rc);
}
Ejemplo n.º 3
0
Archivo: vm.c Proyecto: hiromu/picrin
pic_value
pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv)
{
  struct pic_code *pc, c;
  int ai = pic_gc_arena_preserve(pic);
  jmp_buf jmp;
  size_t argc, i;
  struct pic_code boot[2];

#if PIC_DIRECT_THREADED_VM
  static void *oplabels[] = {
    &&L_OP_POP, &&L_OP_PUSHNIL, &&L_OP_PUSHTRUE, &&L_OP_PUSHFALSE, &&L_OP_PUSHFLOAT,
    &&L_OP_PUSHINT, &&L_OP_PUSHCHAR, &&L_OP_PUSHCONST,
    &&L_OP_GREF, &&L_OP_GSET, &&L_OP_LREF, &&L_OP_LSET, &&L_OP_CREF, &&L_OP_CSET,
    &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_CALL, &&L_OP_TAILCALL, &&L_OP_RET, &&L_OP_LAMBDA,
    &&L_OP_CONS, &&L_OP_CAR, &&L_OP_CDR, &&L_OP_NILP,
    &&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, &&L_OP_DIV,
    &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_STOP
  };
#endif

  if (setjmp(jmp) == 0) {
    pic->jmp = &jmp;
  }
  else {
    goto L_RAISE;
  }

  argc = pic_length(pic, argv) + 1;

#if VM_DEBUG
  puts("== booting VM...");
  printf("  proc = ");
  pic_debug(pic, pic_obj_value(proc));
  puts("");
  printf("  argv = ");
  pic_debug(pic, argv);
  puts("");
  printf("  irep = ");
  print_irep(pic, proc->u.irep);
  puts("\nLet's go!");
#endif

  PUSH(pic_obj_value(proc));
  for (i = 1; i < argc; ++i) {
    PUSH(pic_car(pic, argv));
    argv = pic_cdr(pic, argv);
  }

  /* boot! */
  boot[0].insn = OP_CALL;
  boot[0].u.i = argc;
  boot[1].insn = OP_STOP;
  pc = boot;
  c = *pc;
  goto L_CALL;

  VM_LOOP {
    CASE(OP_POP) {
      POPN(1);
      NEXT;
    }
    CASE(OP_PUSHNIL) {
      PUSH(pic_nil_value());
      NEXT;
    }
    CASE(OP_PUSHTRUE) {
      PUSH(pic_true_value());
      NEXT;
    }
    CASE(OP_PUSHFALSE) {
      PUSH(pic_false_value());
      NEXT;
    }
    CASE(OP_PUSHFLOAT) {
      PUSH(pic_float_value(c.u.f));
      NEXT;
    }
    CASE(OP_PUSHINT) {
      PUSH(pic_int_value(c.u.i));
      NEXT;
    }
    CASE(OP_PUSHCHAR) {
      PUSH(pic_char_value(c.u.c));
      NEXT;
    }
    CASE(OP_PUSHCONST) {
      PUSH(pic->pool[c.u.i]);
      NEXT;
    }
    CASE(OP_GREF) {
      PUSH(pic->globals[c.u.i]);
      NEXT;
    }
    CASE(OP_GSET) {
      pic->globals[c.u.i] = POP();
      NEXT;
    }
    CASE(OP_LREF) {
      PUSH(pic->ci->fp[c.u.i]);
      NEXT;
    }
    CASE(OP_LSET) {
      pic->ci->fp[c.u.i] = POP();
      NEXT;
    }
    CASE(OP_CREF) {
      int depth = c.u.r.depth;
      struct pic_env *env;

      env = pic->ci->env;
      while (depth--) {
	env = env->up;
      }
      PUSH(env->values[c.u.r.idx]);
      NEXT;
    }
    CASE(OP_CSET) {
      int depth = c.u.r.depth;
      struct pic_env *env;

      env = pic->ci->env;
      while (depth--) {
	env = env->up;
      }
      env->values[c.u.r.idx] = POP();
      NEXT;
    }
    CASE(OP_JMP) {
      pc += c.u.i;
      JUMP;
    }
    CASE(OP_JMPIF) {
      pic_value v;

      v = POP();
      if (! pic_false_p(v)) {
	pc += c.u.i;
	JUMP;
      }
      NEXT;
    }
    CASE(OP_CALL) {
      pic_value x, v;
      pic_callinfo *ci;
      struct pic_proc *proc;

    L_CALL:
      x = pic->sp[-c.u.i];
      if (! pic_proc_p(x)) {
	pic->errmsg = "invalid application";
	goto L_RAISE;
      }
      proc = pic_proc_ptr(x);

      ci = PUSHCI();
      ci->argc = c.u.i;
      ci->pc = pc;
      ci->fp = pic->sp - c.u.i;
      ci->env = NULL;
      if (pic_proc_cfunc_p(x)) {
	v = proc->u.cfunc(pic);
	pic->sp = ci->fp;
	POPCI();
	PUSH(v);
	pic_gc_arena_restore(pic, ai);
	NEXT;
      }
      else {
	int i;
	pic_value rest;

	if (ci->argc != proc->u.irep->argc) {
	  if (! (proc->u.irep->varg && ci->argc >= proc->u.irep->argc)) {
	    pic->errmsg = "wrong number of arguments";
	    goto L_RAISE;
	  }
	}
	/* prepare rest args */
	if (proc->u.irep->varg) {
	  rest = pic_nil_value();
	  for (i = 0; i < ci->argc - proc->u.irep->argc; ++i) {
	    pic_gc_protect(pic, v = POP());
	    rest = pic_cons(pic, v, rest);
	  }
	  PUSH(rest);
	}

	/* prepare env */
	if (proc->u.irep->cv_num == 0) {
	  ci->env = proc->env;
	}
	else {
	  ci->env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV);
	  ci->env->up = proc->env;
	  ci->env->valuec = proc->u.irep->cv_num;
	  ci->env->values = (pic_value *)pic_calloc(pic, ci->env->valuec, sizeof(pic_value));
	  for (i = 0; i < ci->env->valuec; ++i) {
	    ci->env->values[i] = ci->fp[proc->u.irep->cv_tbl[i]];
	  }
	}

	pc = proc->u.irep->code;
	pic_gc_arena_restore(pic, ai);
	JUMP;
      }
    }
    CASE(OP_TAILCALL) {
      int argc;
      pic_value *argv;

      argc = c.u.i;
      argv = pic->sp - argc;
      for (i = 0; i < argc; ++i) {
	pic->ci->fp[i] = argv[i];
      }
      pic->sp = pic->ci->fp + argc;
      pc = POPCI()->pc;

      /* c is not changed */
      goto L_CALL;
    }
    CASE(OP_RET) {
      pic_value v;
      pic_callinfo *ci;

      if (pic->errmsg) {

      L_RAISE:
	goto L_STOP;
      }
      else {
	v = POP();
	ci = POPCI();
	pc = ci->pc;
	pic->sp = ci->fp;
	PUSH(v);
      }
      NEXT;
    }
    CASE(OP_LAMBDA) {
      struct pic_proc *proc;

      proc = pic_proc_new(pic, pic->irep[c.u.i], pic->ci->env);
      PUSH(pic_obj_value(proc));
      pic_gc_arena_restore(pic, ai);
      NEXT;
    }
    CASE(OP_CONS) {
      pic_value a, b;
      pic_gc_protect(pic, b = POP());
      pic_gc_protect(pic, a = POP());
      PUSH(pic_cons(pic, a, b));
      pic_gc_arena_restore(pic, ai);
      NEXT;
    }
    CASE(OP_CAR) {
      pic_value p;
      p = POP();
      PUSH(pic_car(pic, p));
      NEXT;
    }
    CASE(OP_CDR) {
      pic_value p;
      p = POP();
      PUSH(pic_cdr(pic, p));
      NEXT;
    }
    CASE(OP_NILP) {
      pic_value p;
      p = POP();
      PUSH(pic_bool_value(pic_nil_p(p)));
      NEXT;
    }

#define DEFINE_ARITH_OP(opcode, op)				\
    CASE(opcode) {						\
      pic_value a, b;						\
      b = POP();						\
      a = POP();						\
      if (pic_int_p(a) && pic_int_p(b)) {			\
	double f = (double)pic_int(a) op (double)pic_int(b);	\
	if (INT_MIN <= f && f <= INT_MAX) {			\
	  PUSH(pic_int_value((int)f));				\
	}							\
	else {							\
	  PUSH(pic_float_value(f));				\
	}							\
      }								\
      else if (pic_float_p(a) && pic_float_p(b)) {		\
	PUSH(pic_float_value(pic_float(a) op pic_float(b)));	\
      }								\
      else if (pic_int_p(a) && pic_float_p(b)) {		\
	PUSH(pic_float_value(pic_int(a) op pic_float(b)));	\
      }								\
      else if (pic_float_p(a) && pic_int_p(b)) {		\
	PUSH(pic_float_value(pic_float(a) op pic_int(b)));	\
      }								\
      else {							\
	pic->errmsg = #op " got non-number operands";		\
	goto L_RAISE;						\
      }								\
      NEXT;							\
    }

    DEFINE_ARITH_OP(OP_ADD, +);
    DEFINE_ARITH_OP(OP_SUB, -);
    DEFINE_ARITH_OP(OP_MUL, *);

    /* special care for (int / int) division */
    CASE(OP_DIV) {
      pic_value a, b;
      b = POP();
      a = POP();
      if (pic_int_p(a) && pic_int_p(b)) {
	PUSH(pic_float_value((double)pic_int(a) / pic_int(b)));
      }
      else if (pic_float_p(a) && pic_float_p(b)) {
	PUSH(pic_float_value(pic_float(a) / pic_float(b)));
      }
      else if (pic_int_p(a) && pic_float_p(b)) {
	PUSH(pic_float_value(pic_int(a) / pic_float(b)));
      }
      else if (pic_float_p(a) && pic_int_p(b)) {
	PUSH(pic_float_value(pic_float(a) / pic_int(b)));
      }
      else {
	pic->errmsg = "/ got non-number operands";
	goto L_RAISE;
      }
      NEXT;
    }

#define DEFINE_COMP_OP(opcode, op)				\
    CASE(opcode) {						\
      pic_value a, b;						\
      b = POP();						\
      a = POP();						\
      if (pic_int_p(a) && pic_int_p(b)) {			\
	PUSH(pic_bool_value(pic_int(a) op pic_int(b)));		\
      }								\
      else if (pic_float_p(a) && pic_float_p(b)) {		\
	PUSH(pic_bool_value(pic_float(a) op pic_float(b)));	\
      }								\
      else if (pic_int_p(a) && pic_int_p(b)) {			\
	PUSH(pic_bool_value(pic_int(a) op pic_float(b)));	\
      }								\
      else if (pic_float_p(a) && pic_int_p(b)) {		\
	PUSH(pic_bool_value(pic_float(a) op pic_int(b)));	\
      }								\
      else {							\
	pic->errmsg = #op " got non-number operands";		\
	goto L_RAISE;						\
      }								\
      NEXT;							\
    }

    DEFINE_COMP_OP(OP_EQ, ==);
    DEFINE_COMP_OP(OP_LT, <);
    DEFINE_COMP_OP(OP_LE, <=);

    CASE(OP_STOP) {
      pic_value val;

    L_STOP:
      val = POP();

      pic->jmp = NULL;
      if (pic->errmsg) {
	return pic_undef_value();
      }

#if VM_DEBUG
      puts("**VM END STATE**");
      printf("stbase\t= %p\nsp\t= %p\n", pic->stbase, pic->sp);
      printf("cibase\t= %p\nci\t= %p\n", pic->cibase, pic->ci);
      if (pic->stbase < pic->sp) {
	pic_value *sp;
	printf("* stack trace:");
	for (sp = pic->stbase; pic->sp != sp; ++sp) {
	  pic_debug(pic, *sp);
	  puts("");
	}
      }
      if (pic->stbase > pic->sp) {
	puts("*** stack underflow!");
      }
#endif

      pic_gc_protect(pic, val);

      return val;
    }
  } VM_LOOP_END;
}