118 10 Delegates — Callback Functions ___________________________________________________________________________ typedef int (* lineM) (void *, const void *, const char *, char *); typedef int (* wrapM) (void *, const void *, const char *); typedef int (* quitM) (void *, const void *); % Class Filter: Object { Object @ delegate; flagM flag; nameM name; fileM file; lineM line; wrapM wrap; quitM quit;
// // // // // //
process a flag process a filename argument process an opened file process a line buffer done with a file done with all files
const char * progname; char ** argv;
// argv[0] // current argument and byte
char * buf; unsigned blen;
// dynamic line buffer // current maximum length
% int mainLoop (_self, char ** argv); const char * argval (_self); const char * progname (const _self); int doit (_self, const char * arg); %}
Unfortunately, ANSI-C does not permit a typedef to be used to define a function header, but a client class like Wc can still use the function type to make sure its callback function matches the expectations of Filter: #include "Filter.h" % Wc wc { // (self, filter, fnm, buf) %casts assert((lineM) wc == wc); ...
The assertion is trivially true but a good ANSI-C compiler will complain about a type mismatch if lineM does not match the type of wc(): In function `Wc_wc’: warning: comparison of distinct pointer types lacks a cast
We still have not seen why our filter knows to call wc() to process an input line. Filter_ctor() receives the delegate object as an argument and it can set the interesting components for filter: % Filter ctor { struct Filter * self = super_ctor(Filter(), _self, app); self —> delegate = va_arg(* app, void *); self —> flag = (flagM) respondsTo(self —> delegate, "flag"); ... self —> quit = (quitM) respondsTo(self —> delegate, "quit"); return self; }