gawk: Output Wrappers

 
 16.4.5.5 Customized Output Wrappers
 ...................................
 
 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 (SeeRedirection).
 
    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.
 
    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.
 
    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'.