gawk: Output Wrappers

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