An output wrapper is the mirror image of an input parser.
It allows an extension to take over the output to a file opened
with the ‘>’ or ‘>>’ I/O redirection operators (see Redirecting Output of print
and printf
).
The output wrapper is very similar to the input parser structure:
typedef struct awk_output_wrapper { const char *name; /* name of the wrapper */ awk_bool_t (*can_take_file)(const awk_output_buf_t *outbuf); awk_bool_t (*take_control_of)(awk_output_buf_t *outbuf); awk_const struct awk_output_wrapper *awk_const next; /* for gawk */ } awk_output_wrapper_t;
The members are as follows:
const char *name;
This is the name of the output wrapper.
awk_bool_t (*can_take_file)(const awk_output_buf_t *outbuf);
This points to a function that examines the information in
the awk_output_buf_t
structure pointed to by outbuf
.
It should return true if the output wrapper wants to take over the
file, and false otherwise. It should not change any state (variable
values, etc.) within gawk
.
awk_bool_t (*take_control_of)(awk_output_buf_t *outbuf);
The function pointed to by this field is called when gawk
decides to let the output wrapper take control of the file. It should
fill in appropriate members of the awk_output_buf_t
structure,
as described next, and return true if successful, false otherwise.
awk_const struct output_wrapper *awk_const next;
This is for use by gawk
;
therefore it is marked awk_const
so that the extension cannot
modify it.
The awk_output_buf_t
structure looks like this:
typedef struct awk_output_buf { const char *name; /* name of output file */ const char *mode; /* mode argument to fopen */ FILE *fp; /* stdio file pointer */ awk_bool_t redirected; /* true if a wrapper is active */ void *opaque; /* for use by output wrapper */ size_t (*gawk_fwrite)(const void *buf, size_t size, size_t count, FILE *fp, void *opaque); int (*gawk_fflush)(FILE *fp, void *opaque); int (*gawk_ferror)(FILE *fp, void *opaque); int (*gawk_fclose)(FILE *fp, void *opaque); } awk_output_buf_t;
Here too, your extension will define XXX_can_take_file()
and XXX_take_control_of()
functions that examine and update
data members in the awk_output_buf_t
.
The data members are as follows:
const char *name;
The name of the output file.
const char *mode;
The mode string (as would be used in the second argument to fopen()
)
with which the file was opened.
FILE *fp;
The FILE
pointer from <stdio.h>
. gawk
opens the file
before attempting to find an output wrapper.
awk_bool_t redirected;
This field must be set to true by the XXX_take_control_of()
function.
void *opaque;
This pointer is opaque to gawk
. The extension should use it to store
a pointer to any private data associated with the file.
size_t (*gawk_fwrite)(const void *buf, size_t size, size_t count,
FILE *fp, void *opaque);
int (*gawk_fflush)(FILE *fp, void *opaque);
int (*gawk_ferror)(FILE *fp, void *opaque);
int (*gawk_fclose)(FILE *fp, void *opaque);
These pointers should be set to point to functions that perform
the equivalent function as the <stdio.h>
functions do, if appropriate.
gawk
uses these function pointers for all output.
gawk
initializes the pointers to point to internal “pass-through”
functions that just call the regular <stdio.h>
functions, so an
extension only needs to redefine those functions that are appropriate for
what it does.
The XXX_can_take_file()
function should make a decision based
upon the name
and mode
fields, and any additional state
(such as awk
variable values) that is appropriate.
gawk
attempts to open the named file for writing. The fp
member will be NULL
only if it fails.
When gawk
calls XXX_take_control_of()
, that function should fill
in the other fields as appropriate, except for fp
, which it should just
use normally if it’s not NULL
.
You register your output wrapper with the following function:
void register_output_wrapper(awk_output_wrapper_t *output_wrapper);
Register the output wrapper pointed to by output_wrapper
with
gawk
.