Exemplo n.º 1
0
Arquivo: file.c Projeto: perl11/potion
/**\memberof PNFile
 \c "write" a binary representation of obj to the file handle.
 \param obj PNString, PNBytes, PNInteger (long or double), PNBoolean (char 0 or 1)
 \return PNInteger written bytes or PN_NIL */
PN potion_file_write(Potion *P, PN cl, pn_file self, PN obj) {
  long len = 0;
  char *ptr = NULL;
  union { double d; long l; char c; } tmp;
  //TODO: maybe extract ptr+len to seperate function
  if (!PN_IS_PTR(obj)) {
    if (!obj) return PN_NIL; //silent
    else if (PN_IS_INT(obj)) {
      tmp.l = PN_NUM(obj); len = sizeof(tmp); ptr = (char *)&tmp.l;
    }
    else if (PN_IS_BOOL(obj)) {
      tmp.c = (obj == PN_TRUE) ? 1 : 0; len = 1; ptr = (char *)&tmp.c;
    }
    else {
      assert(0 && "Invalid primitive type");
    }
  } else {
    switch (PN_TYPE(obj)) {
      case PN_TSTRING: len = PN_STR_LEN(obj); ptr = PN_STR_PTR(obj); break;
      case PN_TBYTES:  len = potion_send(obj, PN_STR("length")); ptr = PN_STR_PTR(obj); break;
      case PN_TNUMBER: {
        tmp.d = PN_DBL(obj); len = sizeof(tmp); ptr = (char *)&tmp.d;
        break;
      }
      default: return potion_type_error(P, obj);
    }
  }
  int r = write(self->fd, ptr, len);
  if (r == -1)
    return potion_io_error(P, "write");
  return PN_NUM(r);
}
Exemplo n.º 2
0
PN potion_file_write(Potion *P, PN cl, pn_file self, PN str) {
  int r = write(self->fd, PN_STR_PTR(str), PN_STR_LEN(str));
  if (r == -1) {
    perror("write");
    // TODO: error
    return PN_NIL;
  }
  return PN_NUM(r);
}
Exemplo n.º 3
0
char *potion_find_file(char *str, PN_SIZE str_len)
{
	char *r = NULL;
	struct stat st;
	PN_TUPLE_EACH(pn_loader_path, i, prefix,
			{ PN_SIZE prefix_len = PN_STR_LEN(prefix); char dirname[prefix_len + 1 + str_len + 1]; char *str_pos = dirname + prefix_len + 1; char *dot; const char *ext; memcpy(str_pos, str, str_len); dot = memchr(str, '.', str_len); if (dot == NULL) dirname[sizeof(dirname) - 1] = '\0'; else *dot = '\0'; memcpy(dirname, PN_STR_PTR(prefix), prefix_len); dirname[prefix_len] = '/'; if (stat(dirname, &st) == 0 && S_ISREG(st.st_mode)) { if (asprintf(&r, "%s", dirname) == -1) potion_allocation_error(); break; } else if ((ext = find_extension(dirname)) != NULL) { if (asprintf(&r, "%s%s", dirname, ext) == -1) potion_allocation_error(); break; } else { char *file; if ((file = strrchr(str, '/')) == NULL) file = str; else file++; if (asprintf(&r, "%s/%s", dirname, file) == -1) potion_allocation_error(); if (stat(r, &st) != 0 || !S_ISREG(st.st_mode)) { int r_len = prefix_len + 1 + str_len * 2 + 1; if ((ext = find_extension(r)) == NULL) { free(r); r = NULL; continue; } r = realloc(r, r_len + strlen(ext)); if (r == NULL) potion_allocation_error(); strcpy(r + r_len, ext); } break; } });
Exemplo n.º 4
0
PN_SIZE potion_type_size(Potion *P, const struct PNObject *ptr) {
  int sz = 0;

  switch (((struct PNFwd *)ptr)->fwd) {
    case POTION_COPIED:
    case POTION_FWD:
      sz = ((struct PNFwd *)ptr)->siz;
      goto done;
  }

  if (ptr->vt > PN_TUSER) {
    sz = sizeof(struct PNObject) +
      (((struct PNVtable *)PN_VTABLE(ptr->vt))->ivlen * sizeof(PN));
    goto done;
  }

  switch (ptr->vt) {
    case PN_TNUMBER:
      sz = sizeof(struct PNDecimal);
    break;
    case PN_TSTRING:
      sz = sizeof(struct PNString) + PN_STR_LEN(ptr) + 1;
    break;
    case PN_TCLOSURE:
      sz = sizeof(struct PNClosure) + (PN_CLOSURE(ptr)->extra * sizeof(PN));
    break;
    case PN_TTUPLE:
      sz = sizeof(struct PNTuple) + (sizeof(PN) * ((struct PNTuple *)ptr)->len);
    break;
    case PN_TSTATE:
      sz = sizeof(Potion);
    break;
    case PN_TFILE:
      sz = sizeof(struct PNFile);
    break;
    case PN_TVTABLE:
      sz = sizeof(struct PNVtable);
    break;
    case PN_TSOURCE:
    // TODO: look up ast size (see core/ast.c)
      sz = sizeof(struct PNSource) + (3 * sizeof(PN));
    break;
    case PN_TBYTES:
      sz = sizeof(struct PNBytes) + ((struct PNBytes *)ptr)->siz;
    break;
    case PN_TPROTO:
      sz = sizeof(struct PNProto);
    break;
    case PN_TTABLE:
      sz = sizeof(struct PNTable) + kh_mem(PN, ptr);
    break;
    case PN_TSTRINGS:
      sz = sizeof(struct PNTable) + kh_mem(str, ptr);
    break;
    case PN_TFLEX:
      sz = sizeof(PNFlex) + ((PNFlex *)ptr)->siz;
    break;
    case PN_TCONT:
      sz = sizeof(struct PNCont) + (((struct PNCont *)ptr)->len * sizeof(PN));
    break;
    case PN_TUSER:
      sz = sizeof(struct PNData) + ((struct PNData *)ptr)->siz;
    break;
  }

done:
  if (sz < sizeof(struct PNFwd))
    sz = sizeof(struct PNFwd);
  return PN_ALIGN(sz, 8); // force 64-bit alignment
}
Exemplo n.º 5
0
static void potion_cmd_compile
(
		char *filename,
		int exec,
		int verbose,
		void *sp
)
{
	PN buf, code;
	int fd = -1;
	struct stat stats;
	Potion *P = potion_create(sp);
	if (stat(filename, &stats) == -1)
	{
		potion_warn("** %s does not exist.\n", filename);
		goto done;
	}

	fd = open(filename, O_RDONLY | O_BINARY);
	if (fd == -1)
	{
		potion_warn("** could not open %s. check permissions.\n", filename);
		goto done;
	}

	buf = potion_bytes(P, stats.st_size);
	if (read(fd, PN_STR_PTR(buf), stats.st_size) == stats.st_size)
	{
		PN_STR_PTR(buf)[stats.st_size] = '\0';
		code = potion_source_load(P, PN_NIL, buf);
		if (PN_IS_PROTO(code))
		{
			if (verbose > 1)
				printf("\n\n-- loaded --\n");
		}
		else
		{
			code = potion_parse(P, buf);
			if (PN_TYPE(code) == PN_TERROR)
			{
				potion_send(potion_send(code, PN_string), PN_print);
				goto done;
			}
			if (verbose > 1)
			{
				printf("\n-- parsed --\n");
				potion_send(potion_send(code, PN_string), PN_print);
				printf("\n");
			}
			code =
					potion_send(code, PN_compile, potion_str(P, filename), PN_NIL);
			if (verbose > 1)
				printf("\n-- compiled --\n");
		}
		if (verbose > 1)
		{
			potion_send(potion_send(code, PN_string), PN_print);
			printf("\n");
		}
		if (exec == 1)
		{
			code = potion_vm(P, code, P->lobby, PN_NIL, 0, NULL );
			if (verbose > 1)
				printf(
						"\n-- vm returned %p (fixed=%ld, actual=%ld, reserved=%ld) --\n",
						(void *) code, PN_INT(potion_gc_fixed(P, 0, 0)),
						PN_INT(potion_gc_actual(P, 0, 0)),
						PN_INT(potion_gc_reserved(P, 0, 0)));
			if (verbose)
			{
				potion_send(potion_send(code, PN_string), PN_print);
				printf("\n");
			}
		}
		else if (exec == 2)
		{
#if POTION_JIT == 1
			PN val;
			PN cl = potion_closure_new(P, (PN_F)potion_jit_proto(P, code, POTION_JIT_TARGET), PN_NIL, 1);
			PN_CLOSURE(cl)->data[0] = code;
			val = PN_PROTO(code)->jit(P, cl, P->lobby);
			if (verbose > 1)
			printf("\n-- jit returned %p (fixed=%ld, actual=%ld, reserved=%ld) --\n", PN_PROTO(code)->jit,
					PN_INT(potion_gc_fixed(P, 0, 0)), PN_INT(potion_gc_actual(P, 0, 0)),
					PN_INT(potion_gc_reserved(P, 0, 0)));
			if (verbose)
			{
				potion_send(potion_send(val, PN_string), PN_print);
				printf("\n");
			}
#else
			potion_warn("** potion built without JIT support\n");
#endif
		}
		else
		{
			char pnbpath[255];
			FILE *pnb;
			sprintf(pnbpath, "%sb", filename);
			pnb = fopen(pnbpath, "wb");
			if (!pnb)
			{
				potion_warn("** could not open %s for writing. check permissions.\n",pnbpath);
				goto done;
			}

			code = potion_source_dump(P, PN_NIL, code);
			if (fwrite(PN_STR_PTR(code), 1, PN_STR_LEN(code),
					pnb) == PN_STR_LEN(code))
			{
				potion_notice("** compiled code saved to %s\n", pnbpath);
				potion_notice("** run it with: potion %s\n", pnbpath);
				fclose(pnb);
			}
			else
			{
				potion_warn("** could not write all bytecode.\n");
			}
		}

#if 0
		void *scanptr = (void *)((char *)P->mem->old_lo + (sizeof(PN) * 2));
		while ((PN)scanptr < (PN)P->mem->old_cur)
		{
			printf("%p.vt = %lx (%u)\n",
					scanptr, ((struct PNObject *)scanptr)->vt,
					potion_type_size(P, scanptr));
			if (((struct PNFwd *)scanptr)->fwd != POTION_FWD && ((struct PNFwd *)scanptr)->fwd != POTION_COPIED)
			{
				if (((struct PNObject *)scanptr)->vt < 0 || ((struct PNObject *)scanptr)->vt > PN_TUSER)
				{
					printf("wrong type for allocated object: %p.vt = %lx\n",
							scanptr, ((struct PNObject *)scanptr)->vt);
					break;
				}
			}
			scanptr = (void *)((char *)scanptr + potion_type_size(P, scanptr));
			if ((PN)scanptr > (PN)P->mem->old_cur)
			{
				printf("allocated object goes beyond GC pointer\n");
				break;
			}
		}
#endif

	}
	else
	{
		potion_warn("** could not read entire file.");
	}

	done: if (fd != -1)
		close(fd);
	if (P != NULL )
		potion_destroy(P);
}
Exemplo n.º 6
0
PN_SIZE potion_type_size(Potion *P, const struct PNObject *ptr) {
  int sz = 0;

  switch (((struct PNFwd *)ptr)->fwd) {
    case POTION_COPIED:
    case POTION_FWD:
      sz = ((struct PNFwd *)ptr)->siz;
      goto done;
  }

  if (ptr->vt < PN_TNIL) goto err;
  if (ptr->vt > PN_TUSER) {
    if (P->vts && ptr->vt < P->vts->len
        && PN_VTABLE(ptr->vt) && PN_TYPECHECK(ptr->vt)) {
      sz = sizeof(struct PNObject) +
        (((struct PNVtable *)PN_VTABLE(ptr->vt))->ivlen * sizeof(PN));
      //sz = potion_send((PN)ptr, PN_size); //cannot use bind with POTION_COPIED objs during GC!
    } else {
    err:
      if (P->flags & (DEBUG_VERBOSE
#ifdef DEBUG
			 |DEBUG_GC
#endif
			 ))
      fprintf(stderr, "** Invalid User Object 0x%lx vt: 0x%lx\n",
	      (unsigned long)ptr, (unsigned long)ptr->vt);
      return 0;
    }
    goto done;
  }

  switch (ptr->vt) {
    case PN_TNUMBER:
      sz = sizeof(struct PNDecimal);
    break;
    case PN_TSTRING:
      sz = sizeof(struct PNString) + PN_STR_LEN(ptr) + 1;
    break;
    case PN_TCLOSURE:
      sz = sizeof(struct PNClosure) + (PN_CLOSURE(ptr)->extra * sizeof(PN));
    break;
    case PN_TTUPLE:
      sz = sizeof(struct PNTuple) + (sizeof(PN) * ((struct PNTuple *)ptr)->alloc);
    break;
    case PN_TSTATE:
      sz = sizeof(Potion);
    break;
    case PN_TFILE:
      sz = sizeof(struct PNFile);
    break;
    case PN_TVTABLE:
      sz = sizeof(struct PNVtable);
    break;
    case PN_TSOURCE:
      sz = sizeof(struct PNSource);
    break;
    case PN_TBYTES:
      sz = sizeof(struct PNBytes) + ((struct PNBytes *)ptr)->siz;
    break;
    case PN_TPROTO:
      sz = sizeof(struct PNProto);
    break;
    case PN_TTABLE:
      sz = sizeof(struct PNTable) + kh_mem(PN, ptr);
    break;
    case PN_TLICK:
      sz = sizeof(struct PNLick);
    break;
    case PN_TSTRINGS:
      sz = sizeof(struct PNTable) + kh_mem(str, ptr);
    break;
    case PN_TFLEX:
      sz = sizeof(PNFlex) + ((PNFlex *)ptr)->siz;
    break;
    case PN_TCONT:
      sz = sizeof(struct PNCont) + (((struct PNCont *)ptr)->len * sizeof(PN));
    break;
    case PN_TUSER:
      sz = sizeof(struct PNData) + ((struct PNData *)ptr)->siz;
    break;
  }

done:
  if (sz < sizeof(struct PNFwd))
    sz = sizeof(struct PNFwd);
  return PN_ALIGN(sz, 8); // force 64-bit alignment
}