diff --git a/c/externs.h b/c/externs.h index dae9a620f..e5a5be697 100644 --- a/c/externs.h +++ b/c/externs.h @@ -117,13 +117,12 @@ extern void S_phantom_bytevector_adjust(ptr ph, uptr new_sz); extern void S_fasl_init(void); extern ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path, ptr externals); extern ptr S_bv_fasl_read(ptr bv, int ty, uptr offset, uptr len, ptr path, ptr externals); -extern ptr S_boot_read(INT fd, const char *path); +extern ptr S_boot_read(faslFile f, const char *path); extern char *S_format_scheme_version(uptr n); extern char *S_lookup_machine_type(uptr n); extern void S_set_code_obj(char *who, IFASLCODE typ, ptr p, iptr n, ptr x, iptr o); extern ptr S_get_code_obj(IFASLCODE typ, ptr p, iptr n, iptr o); -extern int S_fasl_stream_read(void *stream, octet *dest, iptr n); extern int S_fasl_intern_rtd(ptr *x); #ifdef X86_64 extern void x86_64_set_popcount_present(ptr code); @@ -131,9 +130,16 @@ extern void x86_64_set_popcount_present(ptr code); #ifdef PORTABLE_BYTECODE_SWAPENDIAN extern void S_swap_dounderflow_header_endian(ptr code); #endif +extern void S_fasl_init_fd(fileFaslFile ffo, ptr path, INT fd, + int buffer_mode, uptr size); +extern void S_fasl_init_bytes(faslFile ffo, ptr path, void *data, iptr len); +extern void S_fasl_init_bv(faslFile ffo, ptr path, ptr bv); +extern int S_fasl_bytein(faslFile f); +extern uptr S_fasl_uptrin(faslFile f, INT *bytes_consumed); +extern void S_fasl_bytesin(octet *s, iptr n, faslFile f); /* vfasl.c */ -extern ptr S_vfasl(ptr bv, void *stream, iptr offset, iptr len); +extern ptr S_vfasl(ptr bv, faslFile stream, iptr offset, iptr len); extern ptr S_vfasl_to(ptr v); /* flushcache.c */ diff --git a/c/fasl.c b/c/fasl.c index 739fca875..ac9f56ba7 100644 --- a/c/fasl.c +++ b/c/fasl.c @@ -210,31 +210,16 @@ #define PREPARE_BYTEVECTOR(bv,n) {if (bv == Sfalse || Sbytevector_length(bv) < (n)) bv = S_bytevector(n);} -typedef struct unbufFaslFileObj { - ptr path; - INT type; - INT fd; -} *unbufFaslFile; - -typedef struct faslFileObj { - unbufFaslFile uf; - iptr size; - octet *next; - octet *end; - octet *buf; -} *faslFile; - /* locally defined functions */ -static INT uf_read(unbufFaslFile uf, octet *s, iptr n); -static octet uf_bytein(unbufFaslFile uf); -static uptr uf_uptrin(unbufFaslFile uf, INT *bytes_consumed); -static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externals); -static ptr bv_fasl_entry(ptr tc, ptr bv, IFASLCODE ty, uptr offset, uptr len, unbufFaslFile uf, ptr externals); +static iptr uf_read(unbufFaslFile uf, octet *s, iptr n); +static void uf_skipbytes(unbufFaslFile uf, iptr n); +static ptr fasl_entry(ptr tc, IFASLCODE situation, faslFile f, ptr externals); +static ptr bv_fasl_entry(ptr tc, ptr bv, IFASLCODE ty, uptr offset, uptr len, faslFile f, ptr externals); static void fillFaslFile(faslFile f); -static void bytesin(octet *s, iptr n, faslFile f); static void toolarge(ptr path); static iptr iptrin(faslFile f); -static uptr uptrin(faslFile f); +static int must_bytein(faslFile f); +static void skipbytes(iptr n, faslFile f); static float singlein(faslFile f); static double doublein(faslFile f); static iptr stringin(ptr *pstrbuf, iptr start, faslFile f); @@ -327,109 +312,59 @@ void S_fasl_init(void) { #endif } -ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path, ptr externals) { - ptr tc = get_thread_context(); - ptr x; struct unbufFaslFileObj uffo; +void S_fasl_init_fd(fileFaslFile ffo, ptr path, INT fd, + int buffer_mode, uptr size) { + ffo->f.uf.path = path; + ffo->f.uf.type = UFFO_TYPE_FD; + ffo->f.uf.fd = fd; - uffo.path = path; - uffo.type = UFFO_TYPE_FD; - uffo.fd = fd; - x = fasl_entry(tc, situation, &uffo, externals); - return x; + ffo->f.buffer_mode = buffer_mode; + ffo->f.remaining = size; + ffo->f.next = ffo->f.end = ffo->f.buf = ffo->buf_space; } -ptr S_bv_fasl_read(ptr bv, int ty, uptr offset, uptr len, ptr path, ptr externals) { - ptr tc = get_thread_context(); - ptr x; struct unbufFaslFileObj uffo; +void S_fasl_init_bytes(faslFile ffo, ptr path, void *data, iptr len) { + ffo->uf.path = path; + ffo->uf.type = UFFO_TYPE_BV; + ffo->uf.fd = 0; - uffo.path = path; - uffo.type = UFFO_TYPE_BV; - x = bv_fasl_entry(tc, bv, ty, offset, len, &uffo, externals); - return x; + ffo->buffer_mode = FASL_BUFFER_READ_ALL; + ffo->remaining = 0; + ffo->next = ffo->buf = data; + ffo->end = ffo->buf + len; } -ptr S_boot_read(INT fd, const char *path) { - ptr tc = get_thread_context(); - struct unbufFaslFileObj uffo; - - uffo.path = Sstring_utf8(path, -1); - uffo.type = UFFO_TYPE_FD; - uffo.fd = fd; - return fasl_entry(tc, fasl_type_visit_revisit, &uffo, S_G.null_vector); +void S_fasl_init_bv(faslFile ffo, ptr path, ptr bv) { + S_fasl_init_bytes(ffo, path, &BVIT(bv,0), Sbytevector_length(bv)); } -#ifdef WIN32 -#define IO_SIZE_T unsigned int -#else /* WIN32 */ -#define IO_SIZE_T size_t -#endif /* WIN32 */ - -static INT uf_read(unbufFaslFile uf, octet *s, iptr n) { - iptr k; - while (n > 0) { - uptr nx = n; - -#if (iptr_bits > 32) - if (WIN32 && (unsigned int)nx != nx) nx = 0xffffffff; -#endif +ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path, ptr externals) { + ptr tc = get_thread_context(); + struct fileFaslFileObj ffo; - switch (uf->type) { - case UFFO_TYPE_FD: - k = READ(uf->fd, s, (IO_SIZE_T)nx); - if (k > 0) - n -= k; - else if (k == 0) - return -1; - else if (errno != EINTR) - S_error1("", "error reading from ~a", uf->path); - break; - default: - return -1; - } + S_fasl_init_fd(&ffo, path, fd, + /* For `fasl-read`, don't consume any more bytes than + necessary from the file descriptor: */ + FASL_BUFFER_READ_MINIMAL, 0); - s += k; - } - return 0; + return fasl_entry(tc, situation, &ffo.f, externals); } +ptr S_bv_fasl_read(ptr bv, int ty, uptr offset, uptr len, ptr path, ptr externals) { + ptr tc = get_thread_context(); + struct faslFileObj ffo; -int S_fasl_stream_read(void *stream, octet *dest, iptr n) -{ - return uf_read((unbufFaslFile)stream, dest, n); -} - -static void uf_skipbytes(unbufFaslFile uf, iptr n) { - switch (uf->type) { - case UFFO_TYPE_FD: - if (LSEEK(uf->fd, n, SEEK_CUR) == -1) { - S_error1("", "error seeking ~a", uf->path); - } - break; - } -} + S_fasl_init_bv(&ffo, path, bv); -static octet uf_bytein(unbufFaslFile uf) { - octet buf[1]; - if (uf_read(uf, buf, 1) < 0) - S_error1("", "unexpected eof in fasl file ~a", uf->path); - return buf[0]; + return bv_fasl_entry(tc, bv, ty, offset, len, &ffo, externals); } -static uptr uf_uptrin(unbufFaslFile uf, INT *bytes_consumed) { - uptr n, m; octet k; +ptr S_boot_read(faslFile f, const char *path) { + ptr tc = get_thread_context(); - if (bytes_consumed) *bytes_consumed = 1; - k = uf_bytein(uf); - n = k & 0x7F; - while (k & 0x80) { - if (bytes_consumed) *bytes_consumed += 1; - k = uf_bytein(uf); - m = n << 7; - if (m >> 7 != n) toolarge(uf->path); - n = m | (k & 0x7F); - } + f->uf.path = Sstring_utf8(path, -1); - return n; + return fasl_entry(tc, fasl_type_visit_revisit, f, S_G.null_vector); } char *S_format_scheme_version(uptr n) { @@ -455,42 +390,40 @@ char *S_lookup_machine_type(uptr n) { return "unknown"; } -static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externals) { +static ptr fasl_entry(ptr tc, IFASLCODE situation, faslFile f, ptr externals) { ptr x; ptr strbuf = S_G.null_string; - octet tybuf[1]; IFASLCODE ty; iptr size; - /* gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28) co-locates buf and x if we put the declaration of buf down where we use it */ - octet buf[SBUFSIZ]; + IFASLCODE ty; iptr size; for (;;) { - if (uf_read(uf, tybuf, 1) < 0) return Seof_object; - ty = tybuf[0]; + ty = S_fasl_bytein(f); + if (ty == -1) return Seof_object; while (ty == fasl_type_header) { uptr n; ICHAR c; /* check for remainder of magic number */ - if (uf_bytein(uf) != 0 || - uf_bytein(uf) != 0 || - uf_bytein(uf) != 0 || - uf_bytein(uf) != 'c' || - uf_bytein(uf) != 'h' || - uf_bytein(uf) != 'e' || - uf_bytein(uf) != 'z') - S_error1("", "malformed fasl-object header (missing magic word) found in ~a", uf->path); + if (S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 'c' || + S_fasl_bytein(f) != 'h' || + S_fasl_bytein(f) != 'e' || + S_fasl_bytein(f) != 'z') + S_error1("", "malformed fasl-object header (missing magic word) found in ~a", f->uf.path); - if ((n = uf_uptrin(uf, (INT *)0)) != scheme_version) - S_error2("", "incompatible fasl-object version ~a found in ~a", S_string(S_format_scheme_version(n), -1), uf->path); + if ((n = S_fasl_uptrin(f, NULL)) != scheme_version) + S_error2("", "incompatible fasl-object version ~a found in ~a", S_string(S_format_scheme_version(n), -1), f->uf.path); - if ((n = uf_uptrin(uf, (INT *)0)) != machine_type_any && n != machine_type) - S_error2("", "incompatible fasl-object machine-type ~a found in ~a", S_string(S_lookup_machine_type(n), -1), uf->path); + if ((n = S_fasl_uptrin(f, NULL)) != machine_type_any && n != machine_type) + S_error2("", "incompatible fasl-object machine-type ~a found in ~a", S_string(S_lookup_machine_type(n), -1), f->uf.path); - if (uf_bytein(uf) != '(') - S_error1("", "malformed fasl-object header (missing open paren) found in ~a", uf->path); + if (S_fasl_bytein(f) != '(') + S_error1("", "malformed fasl-object header (missing open paren) found in ~a", f->uf.path); - while ((c = uf_bytein(uf)) != ')') - if (c < 0) S_error1("", "malformed fasl-object header (missing close paren) found in ~a", uf->path); + while ((c = S_fasl_bytein(f)) != ')') + if (c < 0) S_error1("", "malformed fasl-object header (missing close paren) found in ~a", f->uf.path); - ty = uf_bytein(uf); + ty = S_fasl_bytein(f); } switch (ty) { @@ -501,18 +434,20 @@ static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externa case fasl_type_terminator: return Seof_object; default: - S_error2("", "malformed fasl-object header (missing situation, got ~s) found in ~a", FIX(ty), uf->path); + S_error2("", "malformed fasl-object header (missing situation, got ~s) found in ~a", FIX(ty), f->uf.path); return (ptr)0; } - size = uf_uptrin(uf, (INT *)0); + size = S_fasl_uptrin(f, NULL); if (ty == situation || situation == fasl_type_visit_revisit || ty == fasl_type_visit_revisit) { - struct faslFileObj ffo; - ptr bv; IFASLCODE kind; + struct faslFileObj bv_ffo; + faslFile in_f; + ptr bv = (ptr)0; IFASLCODE kind; + int old_mode = FASL_BUFFER_READ_ALL; - ty = uf_bytein(uf); - kind = uf_bytein(uf); /* fasl or vfasl */ + ty = S_fasl_bytein(f); + kind = S_fasl_bytein(f); /* fasl or vfasl */ if ((kind == fasl_type_vfasl) && S_vfasl_boot_mode) { /* compact every time, because running previously loaded @@ -526,72 +461,70 @@ static ptr fasl_entry(ptr tc, IFASLCODE situation, unbufFaslFile uf, ptr externa case fasl_type_gzip: case fasl_type_lz4: { ptr result; INT bytes_consumed; - iptr dest_size = uf_uptrin(uf, &bytes_consumed); + iptr dest_size = S_fasl_uptrin(f, &bytes_consumed); iptr src_size = size - (2 + bytes_consumed); /* adjust for u8 compression type, u8 fasl type, and uptr dest_size */ PREPARE_BYTEVECTOR(SRCBV(tc), src_size); PREPARE_BYTEVECTOR(DSTBV(tc), dest_size); - if (uf_read(uf, &BVIT(SRCBV(tc),0), src_size) < 0) - S_error1("", "unexpected eof in fasl file ~a", uf->path); + S_fasl_bytesin(&BVIT(SRCBV(tc),0), src_size, f); result = S_bytevector_uncompress(DSTBV(tc), 0, dest_size, SRCBV(tc), 0, src_size, (ty == fasl_type_gzip ? COMPRESS_GZIP : COMPRESS_LZ4)); if (result != FIX(dest_size)) { if (Sstringp(result)) S_error2("fasl-read", "~@?", result, SRCBV(tc)); S_error3("fasl-read", "uncompressed size ~s for ~s is smaller than expected size ~s", result, SRCBV(tc), FIX(dest_size)); } - ffo.size = dest_size; - ffo.next = ffo.buf = &BVIT(DSTBV(tc),0); - ffo.end = &BVIT(DSTBV(tc),dest_size); - ffo.uf = uf; bv = DSTBV(tc); + S_fasl_init_bv(&bv_ffo, f->uf.path, bv); + size = dest_size; + in_f = &bv_ffo; break; } case fasl_type_uncompressed: { - ffo.size = size - 2; /* adjust for u8 compression type and u8 fasl type */ - ffo.next = ffo.end = ffo.buf = buf; - bv = (ptr)0; - ffo.uf = uf; + in_f = f; + old_mode = f->buffer_mode; + size -= 2; /* adjust for u8 compression type and u8 fasl type */ + if (old_mode == FASL_BUFFER_READ_MINIMAL) { + f->buffer_mode = FASL_BUFFER_READ_REMAINING; + f->remaining = size; + } break; } default: - S_error2("", "malformed fasl-object header (missing possibly-compressed, got ~s) found in ~a", FIX(ty), uf->path); + S_error2("", "malformed fasl-object header (missing possibly-compressed, got ~s) found in ~a", FIX(ty), f->uf.path); return (ptr)0; } switch (kind) { case fasl_type_fasl: - faslin(tc, &x, externals, &strbuf, &ffo); + faslin(tc, &x, externals, &strbuf, in_f); break; case fasl_type_vfasl: - x = S_vfasl(bv, uf, 0, ffo.size); + x = S_vfasl(bv, in_f, 0, size); break; default: - S_error2("", "malformed fasl-object header (got ~s) found in ~a", FIX(ty), uf->path); + S_error2("", "malformed fasl-object header (got ~s) found in ~a", FIX(ty), f->uf.path); return (ptr)0; } + if (old_mode == FASL_BUFFER_READ_MINIMAL) + in_f->buffer_mode = old_mode; S_flush_instruction_cache(tc); S_thread_end_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0); return x; } else { - uf_skipbytes(uf, size); + skipbytes(size, f); } } } -static ptr bv_fasl_entry(ptr tc, ptr bv, int ty, uptr offset, uptr len, unbufFaslFile uf, ptr externals) { +static ptr bv_fasl_entry(ptr tc, ptr bv, int ty, uptr offset, uptr len, faslFile f, ptr externals) { ptr x; ptr strbuf = S_G.null_string; - struct faslFileObj ffo; S_thread_start_code_write(tc, S_vfasl_boot_mode ? static_generation : 0, 1, NULL, 0); if (ty == fasl_type_vfasl) { - x = S_vfasl(bv, NULL, offset, len); + x = S_vfasl(bv, f, offset, len); } else if (ty == fasl_type_fasl) { - ffo.size = len; - ffo.next = ffo.buf = &BVIT(bv, offset); - ffo.end = &BVIT(bv, offset + len); - ffo.uf = uf; - - faslin(tc, &x, externals, &strbuf, &ffo); + f->next += offset; + faslin(tc, &x, externals, &strbuf, f); } else { S_error1("", "bad entry type (got ~s)", FIX(ty)); } @@ -602,18 +535,89 @@ static ptr bv_fasl_entry(ptr tc, ptr bv, int ty, uptr offset, uptr len, unbufFas return x; } +#ifdef WIN32 +#define IO_SIZE_T unsigned int +#else /* WIN32 */ +#define IO_SIZE_T size_t +#endif /* WIN32 */ + +static iptr uf_read(unbufFaslFile uf, octet *s, iptr n) { + iptr k, got = 0; + + while (n > 0) { + uptr nx = n; + +#if (iptr_bits > 32) + if (WIN32 && (unsigned int)nx != nx) nx = 0xffffffff; +#endif + + switch (uf->type) { + case UFFO_TYPE_FD: + k = READ(uf->fd, s, (IO_SIZE_T)nx); + if (k > 0) { + n -= k; + got += k; + s += k; + } else if (k == 0) + return got; + else if (errno != EINTR) { + if (uf->path != (ptr)0) + S_error1("", "error reading from ~a", uf->path); + else + return 0; + } + break; + default: + return 0; + } + } + return got; +} + +static void uf_skipbytes(unbufFaslFile uf, iptr n) { + switch (uf->type) { + case UFFO_TYPE_FD: + if (LSEEK(uf->fd, n, SEEK_CUR) == -1) { + S_error1("", "error seeking ~a", uf->path); + } + break; + } +} + static void fillFaslFile(faslFile f) { - iptr n = f->size < SBUFSIZ ? f->size : SBUFSIZ; - if (uf_read(f->uf, f->buf, n) < 0) - S_error1("", "unexpected eof in fasl file ~a", f->uf->path); - f->end = (f->next = f->buf) + n; - f->size -= n; + iptr n, got; + + if (f->buffer_mode == FASL_BUFFER_READ_REMAINING) { + n = (f->remaining < SBUFSIZ ? f->remaining : SBUFSIZ); + } else if (f->buffer_mode == FASL_BUFFER_READ_MINIMAL) + n = 1; + else + n = SBUFSIZ; + + got = uf_read(&f->uf, f->buf, n); + f->end = (f->next = f->buf) + got; + f->remaining -= got; } -#define bytein(f) ((((f)->next == (f)->end) ? fillFaslFile(f) : (void)0), *((f)->next++)) +/* returns -1 for EOF */ +int S_fasl_bytein(faslFile f) { + if (f->next == f->end) { + fillFaslFile(f); + if (f->next == f->end) + return -1; + } + return *(f->next++); +} -static void bytesin(octet *s, iptr n, faslFile f) { - iptr avail = f->end - f->next; +static int must_bytein(faslFile f) { + int b = S_fasl_bytein(f); + if ((b == -1) && (f->uf.path != (ptr)0)) + S_error1("", "unexpected eof in fasl file ~a", f->uf.path); + return b; +} + +void S_fasl_bytesin(octet *s, iptr n, faslFile f) { + iptr avail = f->end - f->next, got; if (avail < n) { if (avail != 0) { memcpy(s, f->next, avail); @@ -621,31 +625,46 @@ static void bytesin(octet *s, iptr n, faslFile f) { n -= avail; s += avail; } - if (uf_read(f->uf, s, n) < 0) - S_error1("", "unexpected eof in fasl file ~a", f->uf->path); - f->size -= n; + got = uf_read(&f->uf, s, n); + if (got != n) + S_error1("", "unexpected eof in fasl file ~a", f->uf.path); + f->remaining -= got; } else { memcpy(s, f->next, n); f->next += n; } } +static void skipbytes(iptr n, faslFile f) { + iptr avail = f->end - f->next; + if (avail < n) { + if (avail != 0) { + f->next = f->end; + n -= avail; + } + uf_skipbytes(&f->uf, n); + f->remaining -= n; + } else { + f->next += n; + } +} + static void code_bytesin(octet *s, iptr n, faslFile f) { #ifdef CANNOT_READ_DIRECTLY_INTO_CODE while (1) { iptr avail = f->end - f->next; if (avail < n) { - bytesin(s, avail, f); + S_fasl_bytesin(s, avail, f); n -= avail; s += avail; fillFaslFile(f); } else { - bytesin(s, n, f); + S_fasl_bytesin(s, n, f); break; } } #else - bytesin(s, n, f); + S_fasl_bytesin(s, n, f); #endif } @@ -653,6 +672,8 @@ static void toolarge(ptr path) { S_error1("", "fasl value too large for this machine type in ~a", path); } +#define bytein(f) (((f)->next == (f)->end) ? must_bytein(f) : *((f)->next++)) + static iptr iptrin(faslFile f) { uptr n, m; octet k, k0; @@ -661,7 +682,7 @@ static iptr iptrin(faslFile f) { while (k & 1) { k = bytein(f); m = n << 7; - if (m >> 7 != n) toolarge(f->uf->path); + if (m >> 7 != n) toolarge(f->uf.path); n = m | (k >> 1); } @@ -669,7 +690,7 @@ static iptr iptrin(faslFile f) { if (n < ((uptr)1 << (ptr_bits - 1))) { return -(iptr)n; } else if (n > ((uptr)1 << (ptr_bits - 1))) { - toolarge(f->uf->path); + toolarge(f->uf.path); } #if (fixnum_bits > 32) return (iptr)0x8000000000000000; @@ -677,26 +698,41 @@ static iptr iptrin(faslFile f) { return (iptr)0x80000000; #endif } else { - if (n >= ((uptr)1 << (ptr_bits - 1))) toolarge(f->uf->path); + if (n >= ((uptr)1 << (ptr_bits - 1))) toolarge(f->uf.path); return (iptr)n; } } -static uptr uptrin(faslFile f) { - uptr n, m; octet k; +/* `*bytes_consumed` is set to -1 on error when there's no + `f->uf.path` to report an error */ +uptr S_fasl_uptrin(faslFile f, INT *bytes_consumed) { + uptr n, m; int k; + if (bytes_consumed) *bytes_consumed = 1; k = bytein(f); + if (k < 0) return -1; /* in case `f->uf.path` is 0 */ n = (k & 0x7F); while (k & 0x80) { k = bytein(f); + if (k < 0) return -1; /* in case `f->uf.path` is 0 */ m = n << 7; - if (m >> 7 != n) toolarge(f->uf->path); + if (m >> 7 != n) { + if (f->uf.path != (ptr)0) + toolarge(f->uf.path); + else { + if (bytes_consumed) *bytes_consumed = -1; + return 0; + } + } n = m | (k & 0x7F); + if (bytes_consumed) *bytes_consumed += 1; } return n; } +#define uptrin(f) S_fasl_uptrin(f, NULL) + static float singlein(faslFile f) { union { float f; U32 u; } val; @@ -809,7 +845,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { p = &FXVECTIT(*x, 0); while (n--) { iptr t = iptrin(f); - if (!FIXRANGE(t)) toolarge(f->uf->path); + if (!FIXRANGE(t)) toolarge(f->uf.path); *p++ = FIX(t); } return; @@ -823,7 +859,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { ptr fl; faslin(tc, &fl, t, pstrbuf, f); if (!Sflonump(fl)) - S_error1("", "not a flonum in flvector ~a", f->uf->path); + S_error1("", "not a flonum in flvector ~a", f->uf.path); *p++ = Sflonum_value(fl); } return; @@ -833,7 +869,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { iptr n; n = uptrin(f); *x = S_bytevector(n); - bytesin(&BVIT(*x,0), n, f); + S_fasl_bytesin(&BVIT(*x,0), n, f); if (ty == fasl_type_immutable_bytevector) { if (Sbytevector_length(*x) == 0) *x = S_G.null_immutable_bytevector; @@ -880,7 +916,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { if (size != 0) { fasl_record(tc, &tmp, t, pstrbuf, f, size); if (!rtd_equiv(tmp, rtd)) - S_error2("", "incompatible record type ~s in ~a", RECORDDESCNAME(tmp), f->uf->path); + S_error2("", "incompatible record type ~s in ~a", RECORDDESCNAME(tmp), f->uf.path); } tc_mutex_release(); return; @@ -889,7 +925,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { size = uptrin(f); if (size == 0) - S_error2("", "unregistered record type ~s in ~a", rtd_uid, f->uf->path); + S_error2("", "unregistered record type ~s in ~a", rtd_uid, f->uf.path); fasl_record(tc, x, t, pstrbuf, f, size); rtd = *x; @@ -922,7 +958,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { INITPTRFIELD(ht,eq_hashtable_subtype_disp) = FIX(subtype); break; default: - S_error2("", "invalid eq-hashtable subtype code", FIX(subtype), f->uf->path); + S_error2("", "invalid eq-hashtable subtype code", FIX(subtype), f->uf.path); } INITPTRFIELD(ht,eq_hashtable_minlen_disp) = FIX(uptrin(f)); veclen = uptrin(f); @@ -990,7 +1026,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { } break; default: - S_error2("", "invalid symbol-hashtable equiv code", FIX(equiv_code), f->uf->path); + S_error2("", "invalid symbol-hashtable equiv code", FIX(equiv_code), f->uf.path); /* make compiler happy */ equiv = Sfalse; } @@ -1159,7 +1195,7 @@ static void faslin(ptr tc, ptr *x, ptr t, ptr *pstrbuf, faslFile f) { return; } default: - S_error2("", "invalid object type ~d in fasl file ~a", FIX(ty), f->uf->path); + S_error2("", "invalid object type ~d in fasl file ~a", FIX(ty), f->uf.path); } } diff --git a/c/scheme.c b/c/scheme.c index e85f9a337..939c83b0c 100644 --- a/c/scheme.c +++ b/c/scheme.c @@ -30,7 +30,6 @@ #define O_BINARY 0 #endif /* O_BINARY */ -static INT boot_count; static IBOOL verbose; typedef enum { UNINITIALIZED, BOOTING, RUNNING, DEINITIALIZED } heap_state; @@ -615,92 +614,106 @@ static IBOOL next_path(const char *execpath, char *path, /***************************************************************************/ /* BOOT FILES */ -typedef struct { - INT fd; +typedef struct boot_desc { + struct fileFaslFileObj ffo; iptr len; /* 0 => unknown */ iptr offset; - IBOOL need_check, close_after; + IBOOL is_fd, need_check, close_after; char path[BOOT_PATH_MAX]; + struct boot_desc *next; } boot_desc; -#define MAX_BOOT_FILES 10 -static boot_desc bd[MAX_BOOT_FILES]; +static boot_desc *boots = NULL, *last_boot = NULL; /* locally defined functions */ -static octet get_u8(INT fd); -static uptr get_uptr(INT fd, uptr *pn); -static INT get_string(INT fd, char *s, iptr max, INT *c); -static void load(ptr tc, iptr n, IBOOL base); +static INT get_string(faslFile fd, char *s, iptr max, INT *c); +static void load(ptr tc, struct boot_desc *boot, IBOOL base); static void check_boot_file_state(const char *who); -static IBOOL check_boot(int fd, IBOOL verbose, const char *path) { +static void add_boot(boot_desc *boot, const char *path) { + boot->next = NULL; + if (boots == NULL) + boots = boot; + else + last_boot->next = boot; + last_boot = boot; + + if (strlen(path) >= BOOT_PATH_MAX) { + fprintf(stderr, "boot-file path is too long %s\n", path); + S_abnormal_exit(); + } + strcpy(boot->path, path); +} + +static IBOOL check_boot(faslFile f, IBOOL verbose, const char *path) { uptr n = 0; + int got; /* check for magic number */ - if (get_u8(fd) != fasl_type_header || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 0 || - get_u8(fd) != 'c' || - get_u8(fd) != 'h' || - get_u8(fd) != 'e' || - get_u8(fd) != 'z') { + if (S_fasl_bytein(f) != fasl_type_header || + S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 0 || + S_fasl_bytein(f) != 'c' || + S_fasl_bytein(f) != 'h' || + S_fasl_bytein(f) != 'e' || + S_fasl_bytein(f) != 'z') { if (verbose) fprintf(stderr, "malformed fasl-object header in %s\n", path); - CLOSE(fd); + CLOSE(f->uf.fd); return 0; } /* check version */ - if (get_uptr(fd, &n) != 0) { + n = S_fasl_uptrin(f, &got); + if (got < 0) { if (verbose) fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); + CLOSE(f->uf.fd); return 0; } - if (n != scheme_version) { if (verbose) { fprintf(stderr, "%s is for Version %s; ", path, S_format_scheme_version(n)); /* use separate fprintf since S_format_scheme_version returns static string */ fprintf(stderr, "need Version %s\n", S_format_scheme_version(scheme_version)); } - CLOSE(fd); + CLOSE(f->uf.fd); return 0; } /* check machine type */ - if (get_uptr(fd, &n) != 0) { + n = S_fasl_uptrin(f, &got); + if (got < 0) { if (verbose) fprintf(stderr, "unexpected end of file on %s\n", path); - CLOSE(fd); + CLOSE(f->uf.fd); return 0; } - if (n != machine_type) { if (verbose) fprintf(stderr, "%s is for machine-type %s; need machine-type %s\n", path, S_lookup_machine_type(n), S_lookup_machine_type(machine_type)); - CLOSE(fd); + CLOSE(f->uf.fd); return 0; } return 1; } -static void check_dependencies_header(int fd, const char *path) { - if (get_u8(fd) != '(') { /* ) */ +static void check_dependencies_header(faslFile f, const char *path) { + if (S_fasl_bytein(f) != '(') { /* ) */ fprintf(stderr, "malformed boot file %s\n", path); - CLOSE(fd); + CLOSE(f->uf.fd); S_abnormal_exit(); } } -static void finish_dependencies_header(int fd, const char *path, int c) { +static void finish_dependencies_header(faslFile f, int c, const char *path) { while (c != ')') { if (c < 0) { fprintf(stderr, "malformed boot file %s\n", path); - CLOSE(fd); + CLOSE(f->uf.fd); S_abnormal_exit(); } - c = get_u8(fd); + c = S_fasl_bytein(f); } } @@ -708,10 +721,13 @@ static IBOOL find_boot(const char *execpath, const char *name, const char *ext, int fd, IBOOL errorp) { char pathbuf[BOOT_PATH_MAX], buf[BOOT_PATH_MAX]; - uptr n = 0; INT c; const char *path; char *expandedpath; + faslFile f; + struct boot_desc *boot; + + boot = malloc(sizeof(boot_desc)); if ((fd != -1) || direct_pathp || S_fixedpathp(name)) { if (strlen(name) >= BOOT_PATH_MAX) { @@ -738,7 +754,9 @@ static IBOOL find_boot(const char *execpath, const char *name, const char *ext, } if (verbose) fprintf(stderr, "trying %s...opened\n", path); - if (!check_boot(fd, 1, path)) + S_fasl_init_fd(&boot->ffo, (ptr)0, fd, FASL_BUFFER_READ_ALL, 0); + + if (!check_boot(&boot->ffo.f, 1, path)) S_abnormal_exit(); } else { const char *sp = Sschemeheapdirs; @@ -768,27 +786,31 @@ static IBOOL find_boot(const char *execpath, const char *name, const char *ext, if (verbose) fprintf(stderr, "trying %s...opened\n", path); - if (check_boot(fd, verbose, path)) + S_fasl_init_fd(&boot->ffo, (ptr)0, fd, FASL_BUFFER_READ_ALL, 0); + + if (check_boot(&boot->ffo.f, verbose, path)) break; } } if (verbose) fprintf(stderr, "version and machine type check\n"); - check_dependencies_header(fd, path); + f = &boot->ffo.f; + + check_dependencies_header(f, path); /* ( */ - if ((c = get_u8(fd)) == ')') { - if (boot_count != 0) { + if ((c = S_fasl_bytein(f)) == ')') { + if (boots != NULL) { fprintf(stderr, "base boot file %s must come before other boot files\n", path); CLOSE(fd); S_abnormal_exit(); } } else { - if (boot_count == 0) { + if (boots == NULL) { for (;;) { /* try to load heap or boot file this boot file requires */ - if (get_string(fd, buf, BOOT_PATH_MAX, &c) != 0) { + if (get_string(f, buf, BOOT_PATH_MAX, &c) != 0) { fprintf(stderr, "unexpected end of file on %s\n", path); CLOSE(fd); S_abnormal_exit(); @@ -802,13 +824,14 @@ static IBOOL find_boot(const char *execpath, const char *name, const char *ext, CLOSE(fd); S_abnormal_exit(); } - (void) get_uptr(fd, &n); /* version */ - (void) get_uptr(fd, &n); /* machine type */ - (void) get_u8(fd); /* open paren */ - c = get_u8(fd); + S_fasl_init_fd(&boot->ffo, (ptr)0, fd, FASL_BUFFER_READ_ALL, 0); + (void) S_fasl_uptrin(f, NULL); /* version */ + (void) S_fasl_uptrin(f, NULL); /* machine type */ + (void) S_fasl_bytein(f); /* open paren */ + c = S_fasl_bytein(f); for (sep = " "; ; sep = "or ") { if (c == ')') break; - (void) get_string(fd, buf, BOOT_PATH_MAX, &c); + (void) get_string(f, buf, BOOT_PATH_MAX, &c); fprintf(stderr, "%s%s.boot ", sep, buf); } fprintf(stderr, "required by %s\n", path); @@ -819,58 +842,29 @@ static IBOOL find_boot(const char *execpath, const char *name, const char *ext, } /* skip to end of header */ - finish_dependencies_header(fd, path, c); - } - - if (boot_count >= MAX_BOOT_FILES) { - fprintf(stderr, "exceeded maximum number of boot files (%d)\n", MAX_BOOT_FILES); - S_abnormal_exit(); + finish_dependencies_header(f, c, path); } - bd[boot_count].fd = fd; - bd[boot_count].offset = 0; - bd[boot_count].len = 0; - bd[boot_count].need_check = 0; - bd[boot_count].close_after = 1; - strcpy(bd[boot_count].path, path); - boot_count += 1; + boot->offset = 0; + boot->len = 0; + boot->is_fd = 1; + boot->need_check = 0; + boot->close_after = 1; + add_boot(boot, path); return 1; } -static octet get_u8(INT fd) { - octet buf[1]; - if (READ(fd, &buf, 1) != 1) return -1; - return buf[0]; -} - -static uptr get_uptr(INT fd, uptr *pn) { - uptr n, m; int c; octet k; - - if ((c = get_u8(fd)) < 0) return -1; - k = (octet)c; - n = k & 0x7F; - while (k & 128) { - if ((c = get_u8(fd)) < 0) return -1; - k = (octet)c; - m = n << 7; - if (m >> 7 != n) return -1; - n = m | (k & 0x7F); - } - *pn = n; - return 0; -} - -static INT get_string(INT fd, char *s, iptr max, INT *c) { +static INT get_string(faslFile f, char *s, iptr max, INT *c) { while (max-- > 0) { if (*c < 0) return -1; if (*c == ' ' || *c == ')') { - if (*c == ' ') *c = get_u8(fd); + if (*c == ' ') *c = S_fasl_bytein(f); *s = 0; return 0; } *s++ = *c; - *c = get_u8(fd); + *c = S_fasl_bytein(f); } return -1; } @@ -878,21 +872,21 @@ static INT get_string(INT fd, char *s, iptr max, INT *c) { static IBOOL loadecho = 0; #define LOADSKIP 0 -static int set_load_binary(iptr n) { +static int set_load_binary(boot_desc *boot) { if (!Ssymbolp(SYMVAL(S_G.scheme_version_id))) return 0; // set by back.ss ptr make_load_binary = SYMVAL(S_G.make_load_binary_id); if (Sprocedurep(make_load_binary)) { - S_G.load_binary = Scall1(make_load_binary, Sstring_utf8(bd[n].path, -1)); + S_G.load_binary = Scall1(make_load_binary, Sstring_utf8(boot->path, -1)); return 1; } return 0; } -static void boot_element(ptr tc, ptr x, iptr n) { +static void boot_element(ptr tc, ptr x, struct boot_desc *boot) { if (Sprocedurep(x)) { S_initframe(tc, 0); x = boot_call(tc, x, 0); - } else if (Sprocedurep(S_G.load_binary) || set_load_binary(n)) { + } else if (Sprocedurep(S_G.load_binary) || set_load_binary(boot)) { S_initframe(tc, 1); S_put_arg(tc, 1, x); x = boot_call(tc, S_G.load_binary, 1); @@ -900,50 +894,55 @@ static void boot_element(ptr tc, ptr x, iptr n) { /* sequence combination by vfasl, where vectors are not nested */ iptr i; for (i = 0; i < Svector_length(x); i++) - boot_element(tc, Svector_ref(x, i), n); + boot_element(tc, Svector_ref(x, i), boot); } } -static void load(ptr tc, iptr n, IBOOL base) { +static void load(ptr tc, struct boot_desc *boot, IBOOL base) { ptr x; iptr i; - if (bd[n].need_check) { - if (LSEEK(bd[n].fd, bd[n].offset, SEEK_SET) != bd[n].offset) { - fprintf(stderr, "seek in boot file %s failed\n", bd[n].path); - S_abnormal_exit(); + if (boot->need_check) { + if (boot->is_fd) { + if (LSEEK(boot->ffo.f.uf.fd, boot->offset, SEEK_SET) != boot->offset) { + fprintf(stderr, "seek in boot file %s failed\n", boot->path); + S_abnormal_exit(); + } + S_fasl_init_fd(&boot->ffo, (ptr)0, boot->ffo.f.uf.fd, + (boot->len > 0) ? FASL_BUFFER_READ_REMAINING : FASL_BUFFER_READ_ALL, + boot->len); } - check_boot(bd[n].fd, 1, bd[n].path); - check_dependencies_header(bd[n].fd, bd[n].path); - finish_dependencies_header(bd[n].fd, bd[n].path, 0); + check_boot(&boot->ffo.f, 1, boot->path); + check_dependencies_header(&boot->ffo.f, boot->path); + finish_dependencies_header(&boot->ffo.f, 0, boot->path); } if (base) { - S_G.error_invoke_code_object = S_boot_read(bd[n].fd, bd[n].path); + S_G.error_invoke_code_object = S_boot_read(&boot->ffo.f, boot->path); if (!Scodep(S_G.error_invoke_code_object)) { (void) fprintf(stderr, "first object on boot file not code object\n"); S_abnormal_exit(); } - S_G.invoke_code_object = S_boot_read(bd[n].fd, bd[n].path); + S_G.invoke_code_object = S_boot_read(&boot->ffo.f, boot->path); if (!Scodep(S_G.invoke_code_object)) { (void) fprintf(stderr, "second object on boot file not code object\n"); S_abnormal_exit(); } - S_G.base_rtd = S_boot_read(bd[n].fd, bd[n].path); + S_G.base_rtd = S_boot_read(&boot->ffo.f, boot->path); if (!Srecordp(S_G.base_rtd)) { S_abnormal_exit(); } } i = 0; - while (i++ < LOADSKIP && S_boot_read(bd[n].fd, bd[n].path) != Seof_object); + while (i++ < LOADSKIP && S_boot_read(&boot->ffo.f, boot->path) != Seof_object); - while ((x = S_boot_read(bd[n].fd, bd[n].path)) != Seof_object) { + while ((x = S_boot_read(&boot->ffo.f, boot->path)) != Seof_object) { if (loadecho) { printf("%ld: ", (long)i); fflush(stdout); } - boot_element(tc, x, n); + boot_element(tc, x, boot); if (loadecho) { S_prin1(x); putchar('\n'); @@ -953,8 +952,8 @@ static void load(ptr tc, iptr n, IBOOL base) { } S_G.load_binary = Sfalse; - if (bd[n].close_after) - CLOSE(bd[n].fd); + if (boot->close_after) + CLOSE(boot->ffo.f.uf.fd); } /***************************************************************************/ @@ -1034,7 +1033,7 @@ extern void Sscheme_init(void (*abnormal_exit)(void)) { S_G.enable_object_counts = 0; S_G.enable_object_backreferences = 0; - boot_count = 0; + boots = last_boot = NULL; #ifdef WIN32 Sschemeheapdirs = Sgetenv("SCHEMEHEAPDIRS"); @@ -1107,20 +1106,37 @@ extern void Sregister_boot_file_fd_region(const char *name, iptr offset, iptr len, int close_after) { + struct boot_desc *boot; + check_boot_file_state("Sregister_boot_file_fd_region"); - if (strlen(name) >= BOOT_PATH_MAX) { - fprintf(stderr, "boot-file path is too long %s\n", name); - S_abnormal_exit(); - } + boot = malloc(sizeof(boot_desc)); - bd[boot_count].fd = fd; - bd[boot_count].offset = offset; - bd[boot_count].len = len; - bd[boot_count].need_check = 1; - bd[boot_count].close_after = close_after; - strcpy(bd[boot_count].path, name); - boot_count += 1; + S_fasl_init_fd(&boot->ffo, (ptr)0, fd, FASL_BUFFER_READ_REMAINING, len); + boot->offset = offset; + boot->len = len; + boot->is_fd = 1; + boot->need_check = 1; + boot->close_after = close_after; + add_boot(boot, name); +} + +extern void Sregister_boot_file_bytes(const char *name, + void *data, + iptr len) { + struct boot_desc *boot; + + check_boot_file_state("Sregister_boot_bytes"); + + boot = malloc(sizeof(boot_desc)); + + S_fasl_init_bytes(&boot->ffo.f, (ptr)0, data, len); + boot->offset = 0; + boot->len = len; + boot->is_fd = 0; + boot->need_check = 1; + boot->close_after = 0; + add_boot(boot, name); } extern void Sregister_heap_file(UNUSED const char *path) { @@ -1149,7 +1165,7 @@ extern void Sbuild_heap(const char *execpath, void (*custom_init)(void)) { S_boot_time = 1; - if (boot_count == 0) { + if (boots == NULL) { const char *name = path_last(execpath); #if defined(ALWAYS_USE_BOOT_FILE) name = ALWAYS_USE_BOOT_FILE; @@ -1185,10 +1201,10 @@ extern void Sbuild_heap(const char *execpath, void (*custom_init)(void)) { } } - S_vfasl_boot_mode = 1; /* to static generation after compacting */ + if (boots != NULL) { + struct boot_desc *boot, *next_boot; - if (boot_count != 0) { - INT i = 0; + S_vfasl_boot_mode = 1; /* to static generation after compacting */ main_init(); if (custom_init) custom_init(); @@ -1209,15 +1225,24 @@ extern void Sbuild_heap(const char *execpath, void (*custom_init)(void)) { COMPRESSFORMAT(tc) = FIX(COMPRESS_LZ4); COMPRESSLEVEL(tc) = FIX(COMPRESS_MEDIUM); - load(tc, i++, 1); + load(tc, boots, 1); S_boot_time = 0; - while (i < boot_count) load(tc, i++, 0); - } + next_boot = boots->next; + free(boots); + + for (boot = next_boot; boot != NULL; boot = next_boot) { + next_boot = boot->next; + load(tc, boot, 0); + free(boot); + } - S_vfasl_boot_mode = 0; + Scompact_heap(); - if (boot_count != 0) Scompact_heap(); + S_vfasl_boot_mode = 0; + + boots = last_boot = NULL; + } /* complete the initialization on the Scheme side */ p = S_symbol_value(S_intern((const unsigned char *)"$scheme-init")); diff --git a/c/types.h b/c/types.h index 382d4af3d..c4bbba5eb 100644 --- a/c/types.h +++ b/c/types.h @@ -576,3 +576,27 @@ typedef struct thread_gc { else \ TRAP(tc) = (ptr)1; \ } while (0) + +typedef struct unbufFaslFileObj { + ptr path; + INT type; + INT fd; +} *unbufFaslFile; + +typedef struct faslFileObj { + struct unbufFaslFileObj uf; + int buffer_mode; + iptr remaining; + octet *next; + octet *end; + octet *buf; +} *faslFile; + +typedef struct fileFaslFileObj { + struct faslFileObj f; + octet buf_space[SBUFSIZ]; +} *fileFaslFile; + +#define FASL_BUFFER_READ_ALL 0 +#define FASL_BUFFER_READ_MINIMAL 1 +#define FASL_BUFFER_READ_REMAINING 2 diff --git a/c/vfasl.c b/c/vfasl.c index 4c9ecebc9..066b993a6 100644 --- a/c/vfasl.c +++ b/c/vfasl.c @@ -89,7 +89,7 @@ static ptr lookup_singleton(iptr which); /************************************************************/ /* Loading */ -ptr S_vfasl(ptr bv, void *stream, iptr offset, iptr input_len) +ptr S_vfasl(ptr bv, faslFile stream, iptr offset, iptr input_len) { ptr vspaces[vspaces_count]; uptr vspace_offsets[vspaces_count+1]; @@ -112,10 +112,8 @@ ptr S_vfasl(ptr bv, void *stream, iptr offset, iptr input_len) if (bv) memcpy(&header_space, &BVIT(bv, offset), size_vfasl_header); - else { - if (S_fasl_stream_read(stream, header_space, size_vfasl_header) < 0) - S_error("fasl-read", "input truncated"); - } + else + S_fasl_bytesin(header_space, size_vfasl_header, stream); used_len += VFASLHEADER_DATA_SIZE(header) + VFASLHEADER_TABLE_SIZE(header); if (used_len > input_len) @@ -152,8 +150,7 @@ ptr S_vfasl(ptr bv, void *stream, iptr offset, iptr input_len) #else dest = vspaces[s]; #endif - if (S_fasl_stream_read(stream, TO_VOIDP(dest), sz) < 0) - S_error("fasl-read", "input truncated"); + S_fasl_bytesin(TO_VOIDP(dest), sz, stream); #ifdef CANNOT_READ_DIRECTLY_INTO_CODE if (dest != vspaces[s]) memcpy(TO_VOIDP(vspaces[s]), TO_VOIDP(dest), sz); @@ -171,8 +168,7 @@ ptr S_vfasl(ptr bv, void *stream, iptr offset, iptr input_len) table = TO_PTR(bv_addr); else { newspace_find_room(tc, type_untyped, ptr_align(VFASLHEADER_TABLE_SIZE(header)), table); - if (S_fasl_stream_read(stream, TO_VOIDP(table), VFASLHEADER_TABLE_SIZE(header)) < 0) - S_error("fasl-read", "input truncated"); + S_fasl_bytesin(TO_VOIDP(table), VFASLHEADER_TABLE_SIZE(header), stream); } symrefs = TO_VOIDP(table); diff --git a/csug/foreign.stex b/csug/foreign.stex index 816dc9a24..32bf43639 100644 --- a/csug/foreign.stex +++ b/csug/foreign.stex @@ -3097,6 +3097,7 @@ program. \cfunction{void}{Sregister_boot_relative_file}{const char *\var{name}} \cfunction{void}{Sregister_boot_file_fd}{const char *\var{name}, int \var{fd}} \cfunctTwo{void}{Sregister_boot_file_fd_region}{const char *\var{name}, int \var{fd},}{iptr \var{offset}, iptr \var{len}, int \var{close}_\var{after}} +\cfunction{void}{Sregister_boot_file_bytes}{const char *\var{name}, void *\var{content}, iptr \var{len}} \cfunction{void}{Sbuild_heap}{const char *\var{exec}, void (*\var{custom}_\var{init})(void)} \cfunction{void}{Senable_expeditor}{const char *\var{history}_\var{file}} \cfunction{void}{Sretain_static_relocation}{void} @@ -3162,6 +3163,12 @@ descriptor is used for multiple boot files, then one. The boot file content is read only when \scheme{Sbuild_heap} is called. +The \scheme{Sregister_boot_file_bytes} function is another alternative +to the \scheme{Sregister_boot_file} functions that registers boot-file +content that is already loaded into memory, instead of reading from a +file. The registered bytes must remain available until +\scheme{Sbuild_heap} reads them. + \scheme{Sbuild_heap} creates the Scheme heap from the registered boot files. \var{exec} is assumed to be the name of or path to the executable diff --git a/s/mkheader.ss b/s/mkheader.ss index 23b6ca904..705c7f732 100644 --- a/s/mkheader.ss +++ b/s/mkheader.ss @@ -454,8 +454,9 @@ (export "void" "Sregister_boot_file" "(const char *)") (export "void" "Sregister_boot_executable_relative_file" "(const char *, const char *)") (export "void" "Sregister_boot_relative_file" "(const char *)") - (export "void" "Sregister_boot_file_fd" "(const char *, int fd)") - (export "void" "Sregister_boot_file_fd_region" "(const char *, int fd, iptr offset, iptr len, int close_after)") + (export "void" "Sregister_boot_file_fd" "(const char *, int)") + (export "void" "Sregister_boot_file_fd_region" "(const char *, int, iptr, iptr, int)") + (export "void" "Sregister_boot_file_bytes" "(const char *, void *, iptr)") (export "void" "Sregister_heap_file" "(const char *)") (export "void" "Scompact_heap" "(void)") (export "void" "Ssave_heap" "(const char *, int)")