#ifndef MAWK_VIO_H
#define MAWK_VIO_H
/* virtual I/O */
typedef enum mawk_vio_open_mode_e {
MAWK_VIO_O_TRUNC,
MAWK_VIO_O_APPEND,
MAWK_VIO_I
} mawk_vio_open_mode_t;
/**** init-type entry points: used to create a new vio or do a one-time-thing
without an existing vio; MAWK->vio_init.* point to the defaults
but the application is free to create a vf using a different
implementation directly ****/
/* open a normal file */
typedef mawk_vio_t *mawk_vio_open_t(mawk_state_t *MAWK, const char *name, mawk_vio_open_mode_t mode);
/* open and close pipe (background process) */
typedef mawk_vio_t *mawk_vio_open_pipe_t(mawk_state_t *MAWK, const char *name, int type);
/* execute a shell command (system()-like wrapper around execl()) */
typedef void mawk_vio_exec_shell_t(mawk_state_t *MAWK, const char *cmd);
/**** regular vio calls on existing vios - vf->imp points to these ****/
/* write data to a vio * */
typedef int mawk_vio_putc_t(mawk_state_t *MAWK, mawk_vio_t *vf, char c);
typedef int mawk_vio_write_str_t(mawk_state_t *MAWK, mawk_vio_t *vf, const char *str);
typedef int mawk_vio_write_t(mawk_state_t *MAWK, mawk_vio_t *vf, const char *data, int len);
typedef int mawk_vio_printf_t(mawk_state_t *MAWK, mawk_vio_t *vf, const char *fmt, ...);
/* return -2 if there's no more input at the moment */
typedef int mawk_vio_read_t(mawk_state_t *MAWK, mawk_vio_t *f, char *dst, long int size);
typedef int mawk_vio_close_t(mawk_state_t *MAWK, mawk_vio_t *vf);
typedef int mawk_vio_flush_t(mawk_state_t *MAWK, mawk_vio_t *vf);
/* check the error state of a file node (ferror()-style) */
typedef int mawk_vio_error_t(mawk_state_t *MAWK, mawk_vio_t *vf);
/* mark the file no-close; this is useful for working on files that are
not really open by the vio implementation, for example stdout/stderr
in vio_orig. */
typedef void mawk_vio_mark_no_close_t(mawk_state_t *MAWK, mawk_vio_t *vf);
/* stdio hacks */
/* per file hooks */
typedef struct mawk_vio_imp_s {
mawk_vio_putc_t *vputc;
mawk_vio_write_str_t *vwrite_str;
mawk_vio_write_t *vwrite;
mawk_vio_printf_t *vprintf;
mawk_vio_read_t *vread;
mawk_vio_close_t *vclose;
mawk_vio_flush_t *vflush;
mawk_vio_error_t *error;
mawk_vio_mark_no_close_t *mark_no_close;
} mawk_vio_imp_t;
/* per file struct */
struct mawk_vio_s {
/* common header */
const mawk_vio_imp_t *imp;
int refco; /* how many times this vf is open (and referenced from the FILE_NODEs) */
/* implementations may have further fields here, never depend on sizeof(mawk_vio_t)! */
};
/* per script instance hooks */
typedef struct mawk_vio_init_s {
mawk_vio_open_t *vopen;
mawk_vio_open_pipe_t *vopen_pipe;
mawk_vio_exec_shell_t *exec_shell;
int inited;
} mawk_vio_init_t;
#define mawk_vio_putc(MAWK, vf, c) (vf)->imp->vputc(MAWK, (vf), (c))
#define mawk_vio_write_str(MAWK, vf, str) (vf)->imp->vwrite_str(MAWK, (vf), (str))
#define mawk_vio_write(MAWK, vf, data, len) (vf)->imp->vwrite(MAWK, (vf), (data), (len))
/* can not be implemented without C99 vararg macros:
#define mawk_vio_printf_t(MAWK, vf, const char *fmt, ...); */
#define mawk_vio_read(MAWK, vf, dst, size) (vf)->imp->vread(MAWK, (vf), (dst), (size))
#define mawk_vio_close(MAWK, vf) ((((vf) == NULL) || ((vf)->imp->vclose == NULL)) ? (-1) : ((vf)->imp->vclose(MAWK, (vf))))
#define mawk_vio_flush(MAWK, vf) (vf)->imp->vflush(MAWK, (vf))
#define mawk_vio_error(MAWK, vf) (vf)->imp->error(MAWK, (vf))
/* default init (entry) hooks */
#define mawk_vio_open(MAWK, name, mode) MAWK->vio_init.vopen(MAWK, (name), (mode))
#define mawk_vio_open_pipe(MAWK, name, type) MAWK->vio_init.vopen_pipe(MAWK, (name), (type))
#define mawk_vio_exec_shell(MAWK, cmd) MAWK->vio_init.exec_shell(MAWK, (cmd))
#define mawk_vio_setup_stdouts(MAWK) MAWK->vio_init.mawk_vio_setup_stdouts(MAWK)
#endif