The idea is the same, but I think that I did it in a more general adding the virtual io to tinycc with any source can be easily used like databases, compressed files,
Main code of vio:
/* virtual io */
LIBTCCAPI void tcc_set_vio_module(TCCState *s, vio_module_t *vio_module){
s->vio_module = vio_module;
vio_module->tcc_state = s;
}
void vio_initialize(vio_fd *fd) {
fd->fd = -1;
fd->vio_udata = NULL;
fd->vio_module = NULL;
}
int vio_open(struct TCCState *s, vio_fd *fd, const char *fn, int oflag) {
int rc;
vio_initialize(fd);
fd->vio_module = s->vio_module;
if(s->vio_module && (s->vio_module->call_vio_open_flags & CALL_VIO_OPEN_FIRST)) {
rc = s->vio_module->vio_open(fd, fn, oflag);
if(rc >= 0) return rc;
}
fd->fd = open(fn, oflag);
if(fd->fd < 0 && s->vio_module && (s->vio_module->call_vio_open_flags & CALL_VIO_OPEN_LAST)) {
rc = s->vio_module->vio_open(fd, fn, oflag);
if(rc >= 0) return rc;
}
//printf("vio_open = %d %s\n", fd->fd, fn);
return fd->fd;
}
off_t vio_lseek(vio_fd fd, off_t offset, int whence) {
if(fd.vio_udata) {
return fd.vio_module->vio_lseek(fd, offset, whence);
}
return lseek(fd.fd, offset, whence);
}
size_t vio_read(vio_fd fd, void *buf, size_t bytes) {
if(fd.vio_udata) {
return fd.vio_module->vio_read(fd, buf, bytes);
}
return read(fd.fd, buf, bytes);
}
int vio_close(vio_fd *fd) {
int rc = 0;
if(fd->vio_udata){
fd->vio_module->vio_close(fd);
} else rc = close(fd->fd);
vio_initialize(fd);
return rc;
}