Let's see if I can explain it better.
The modifications I did was replace:
"fd" -> "fd or fd->fd depending on the context"
"fd = -1;" -> void vio_initialize(vio_fd *fd);
"fd = open(file_name, mode)" -> int vio_open(struct TCCState *s, vio_fd *fd, const char *fn, int oflag);
"pos = lseek(fd, offset, whence);" -> off_t vio_lseek(vio_fd fd, off_t offset, int whence);
"size = read(fd, buf, count);" -> size_t vio_read(vio_fd fd, void *buf, size_t bytes);
"close(fd);" -> int vio_close(vio_fd *fd);
And add a new API function "LIBTCCAPI void tcc_set_vio_module(TCCState *s, vio_module_t *vio_module)" that allow install a module that will handle the read io operations required by tcc.
bin2c: is a utility used on one implementation of "vio_module".
-------
/* virtual io */
struct vio_module_t;
typedef struct vio_fd {
int fd;
void *vio_udata;
struct vio_module_t *vio_module;
} vio_fd;
#define CALL_VIO_OPEN_FIRST 0x01
#define CALL_VIO_OPEN_LAST 0x02
typedef struct vio_module_t {
void *user_data;
struct TCCState *tcc_state;
int call_vio_open_flags; /*CALL_VIO_OPEN_FIRST, CALL_VIO_OPEN_LAST, one or both */
int (*vio_open)(vio_fd *fd, const char *fn, int oflag) ;
off_t (*vio_lseek)(vio_fd fd, off_t offset, int whence);
size_t (*vio_read)(vio_fd fd, void *buf, size_t bytes);
int (*vio_close)(vio_fd *fd);
} vio_module_t;
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;
}