You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by gs...@locus.apache.org on 2000/08/05 11:54:15 UTC

cvs commit: apache-2.0/src/lib/apr/buckets README.txt greg_patch.txt ap_filter.h filters.c register_patch.txt util_filter.c util_filter.h

gstein      00/08/05 02:54:15

  Modified:    src/lib/apr/buckets README.txt greg_patch.txt
  Removed:     src/lib/apr/buckets ap_filter.h filters.c register_patch.txt
                        util_filter.c util_filter.h
  Log:
  - remove patch #3 since it has been applied
  - regenerate patch #2 given ap_ -> apr_ rename and presence of patch #3
  - update the README
  
  Revision  Changes    Path
  1.7       +0 -9      apache-2.0/src/lib/apr/buckets/README.txt
  
  Index: README.txt
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/buckets/README.txt,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- README.txt	2000/07/25 00:44:59	1.6
  +++ README.txt	2000/08/05 09:54:14	1.7
  @@ -41,13 +41,4 @@
   Bachelor #2
   -----------
   
  -   ap_filter.h
  -   filters.c
      greg_patch.txt
  -
  -Bachelor #3  --  The combination of #1 and #2 (hopefully)
  ------------
  -
  -   util_filter.h
  -   util_filter.c
  -   register_patch.txt
  
  
  
  1.2       +266 -144  apache-2.0/src/lib/apr/buckets/greg_patch.txt
  
  Index: greg_patch.txt
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/buckets/greg_patch.txt,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- greg_patch.txt	2000/07/12 11:04:08	1.1
  +++ greg_patch.txt	2000/08/05 09:54:14	1.2
  @@ -1,48 +1,244 @@
  -Index: include/httpd.h
  +Index: include/util_filter.h
   ===================================================================
  -RCS file: /home/cvs/apache-2.0/src/include/httpd.h,v
  -retrieving revision 1.64
  -diff -u -r1.64 httpd.h
  ---- include/httpd.h	2000/06/30 21:18:13	1.64
  -+++ include/httpd.h	2000/07/12 11:00:55
  -@@ -731,7 +731,9 @@
  - #ifdef APACHE_XLATE
  -     struct ap_rr_xlate *rrx;
  - #endif /*APACHE_XLATE*/
  --    
  -+
  -+    struct ap_filter_t *filters;
  -+
  - /* Things placed at the end of the record to avoid breaking binary
  -  * compatibility.  It would be nice to remember to reorder the entire
  -  * record to improve 64bit alignment the next time we need to break
  +RCS file: /home/cvs/apache-2.0/src/include/util_filter.h,v
  +retrieving revision 1.3
  +diff -u -r1.3 util_filter.h
  +--- include/util_filter.h	2000/08/05 04:38:57	1.3
  ++++ include/util_filter.h	2000/08/05 09:48:20
  +@@ -91,8 +91,40 @@
  +  * unterminated SSI directive).
  +  */
  + 
  +-/* forward declare the filter type */
  ++/*
  ++ * BUCKETS
  ++ *
  ++ * Filtering uses a "bucket" metaphor for holding content to be processed.
  ++ * These buckets may contain arbitrary types of data. The selection of the
  ++ * type is dependent upon how the "upstream" filter/generator places content
  ++ * into the filter chain stream.
  ++ *
  ++ * For example, if a content generator uses ap_rwrite(), then the data will
  ++ * be placed into an AP_BUCKET_PTRLEN bucket. This bucket type contains a
  ++ * single pointer/length pair which will refer to the data.
  ++ *
  ++ * Buckets types are defined around the need to avoid copying the data if
  ++ * at all possible. Whatever the "natural" input form is for a piece of
  ++ * content, this is modelled within the bucket types. For example, when a
  ++ * content generator uses ap_rprintf() or a filter uses ap_fc_printf(),
  ++ * the format string and arguments are fed into/down the filter chain as
  ++ * just theat: a format string and its arguments. The filter mechanism avoids
  ++ * reducing the format/args to a final string for as long as possible. At
  ++ * some point, a filter or the output of the chain will combine these to
  ++ * produce actual bytes, but it is most optimal to defer this until it is
  ++ * truly needed.
  ++ *
  ++ * See the ap_bucket_type enumeration for the different bucket types which
  ++ * are currently defined.
  ++ *
  ++ * Buckets may also be linked into a list so that they may be passed as
  ++ * entire groups of content. The filter may insert/remove/replace the buckets
  ++ * within this list before passing the list to the next filter.
  ++ */
  ++
  ++/* forward declare some types */
  + typedef struct ap_filter_t ap_filter_t;
  ++typedef struct ap_bucket_t ap_bucket_t;
  + 
  + /*
  +  * ap_filter_func:
  +@@ -114,7 +146,7 @@
  +  * next/prev to insert/remove/replace elements in the bucket list, but
  +  * the types and values of the individual buckets should not be altered.
  +  */
  +-typedef apr_status_t (*ap_filter_func)();
  ++typedef void (*ap_filter_func)(ap_filter_t *filter, ap_bucket_t *bucket);
  + 
  + /*
  +  * ap_filter_type:
  +@@ -161,12 +193,155 @@
  +  */
  + struct ap_filter_t {
  +     ap_filter_func filter_func;
  ++    request_rec *r;
  + 
  +     void *ctx;
  + 
  +     ap_filter_type ftype;
  +     ap_filter_t *next;
  + };
  ++
  ++/*
  ++ * ap_bucket_type:
  ++ *
  ++ * This enumeration is used to specify what type of bucket is present when
  ++ * an ap_bucket_t is provided.
  ++ *
  ++ * AP_BUCKET_PTRLEN:
  ++ *     This bucket type defines a simple pointer/length pair for the content.
  ++ *     The content is NOT necessarily null-terminated.
  ++ *
  ++ *     This type occurs when ap_rwrite(), ap_fc_write(), ap_rputs(),
  ++ *     ap_fc_puts(), ap_rputc(), or ap_fc_putc() is used by the upstream
  ++ *     filter/generator.
  ++ *
  ++ * AP_BUCKET_STRINGS:
  ++ *     This bucket type defines a set of null-terminated strings. The actual
  ++ *     representation is through varargs' va_list type. A filter can sequence
  ++ *     through the arguments using the va_arg() macro (and the "const char *"
  ++ *     type). The filter should NOT use va_start() or va_end(). When va_arg()
  ++ *     returns a NULL pointer, the list of strings is complete.
  ++ *
  ++ *     Note that you can only sequence through the strings once, due to the
  ++ *     definition of va_list. Thus, the first filter to do this sequencing
  ++ *     must pass the resulting content to the next filter in a new form (the
  ++ *     bucket cannot simply be passed because ->va is useless).
  ++ *
  ++ *     This type occurs when ap_rvputs(), ap_fc_putstrs, or ap_fc_vputstrs()
  ++ *     is used by the upstream filter/generator.
  ++ *
  ++ * AP_BUCKET_PRINTF:
  ++ *     This bucket type defines a printf-style format and arguments. Similar
  ++ *     to AP_BUCKET_STRINGS, this type also uses the ->va field to refer to
  ++ *     the arguments. The format for the printf is stored in ->fmt.
  ++ *
  ++ *     Also similar to AP_BUCKET_STRINGS, the va_start/va_end macros should
  ++ *     not be used, and ->va should be processed only once. The bucket may
  ++ *     not be passed after this processing.
  ++ *
  ++ *     This type occurs when ap_rprintf(), ap_vrprintf(), ap_fc_printf(), or
  ++ *     ap_fc_vprintf() is used by the upstream filter/generator.
  ++ *
  ++ * AP_BUCKET_FILE:
  ++ *     This bucket type refers to an open file, from the current position
  ++ *     and extending for ->flen bytes. Since there are some ap_file_t
  ++ *     implementations/types that are not seekable, it may be impossible to
  ++ *     "rewind" the file's current position after reading the contenxt.
  ++ *     Therefore, it is important to note that once the content has been
  ++ *     read, it must be passed to the next filter in a different form.
  ++ *
  ++ *     Note: if there is a way to determine whether a file is seekable, then
  ++ *     it would be legal to fetch the current position, read the contents,
  ++ *     rewind to the original position, and then pass this bucket/file down
  ++ *     to the next filter in the output chain.
  ++ *
  ++ *     This type occurs when ap_send_fd(), ap_send_fd_length(), or
  ++ *     ap_fc_sendfile() are used by the upstream filter/generator.
  ++ *
  ++ * AP_BUCKET_EOS:
  ++ *     This bucket signals the end of the content stream. The filter should
  ++ *     flush any internal state and issue errors if the state specifies that
  ++ *     and end of stream cannot occur now (e.g. a command directive is
  ++ *     incomplete).
  ++ *
  ++ *     This type occurs when Apache finalizes a (sub)request, or when an
  ++ *     upstream filter passes this bucket along.
  ++ */
  ++typedef enum {
  ++    AP_BUCKET_PTRLEN,
  ++    AP_BUCKET_STRINGS,
  ++    AP_BUCKET_PRINTF,
  ++    AP_BUCKET_FILE,
  ++    AP_BUCKET_EOS
  ++} ap_bucket_type;
  ++
  ++/*
  ++ * ap_bucket_t:
  ++ *
  ++ * The actual bucket definition. The type is determined by the ->type field.
  ++ * Which fields are valid/useful in the bucket is determined by the type,
  ++ * as noted below and in the comments above for each type.
  ++ *
  ++ * Buckets are arranged in a doubly-linked list so that a filter may insert,
  ++ * remove, or replace elements in a list of buckets. Generally, a filter
  ++ * should not change any bucket values other than these link pointers.
  ++ */
  ++struct ap_bucket_t {
  ++    ap_bucket_type type;
  ++
  ++    const char *buf;            /* AP_BUCKET_PTRLEN */
  ++    apr_size_t len;             /* AP_BUCKET_PTRLEN */
  ++
  ++    const char *fmt;            /* AP_BUCKET_PRINTF */
  ++    va_list va;                 /* AP_BUCKET_STRINGS, _PRINTF */
  ++
  ++    apr_file_t *file;           /* AP_BUCKET_FILE */
  ++    apr_ssize_t flen;           /* AP_BUCKET_FILE */
  ++
  ++    ap_bucket_t *next;          /* next bucket in list */
  ++    ap_bucket_t *prev;          /* previous bucket in list */
  ++};
  ++
  ++/*
  ++ * FILTER CHAIN OUTPUT FUNCTIONS
  ++ *
  ++ * These functions are used to deliver output/content down to the next
  ++ * filter in the chain.
  ++ *
  ++ * ap_fc_write(): write a block of bytes
  ++ * ap_fc_putc(): write a single character
  ++ * ap_fc_puts(): write a null-terminated string
  ++ * ap_fc_putstrs(): write a set of null-termianted strings; the end is
  ++ *                  signaled by a NULL parameter
  ++ * ap_fc_vputstrs(): same as ap_fc_putstrs(), but where the set of strings
  ++ *                   is defined by a va_list
  ++ * ap_fc_printf(): use printf-like semantics for writing a string
  ++ * ap_fc_vprintf(): use printf-like semantics, but with a va_list for the args
  ++ * ap_fc_sendfile(): send the file contents, from the current file position,
  ++ *                   and extending for "len" bytes; AP_FC_SENDFILE_ALL is
  ++ *                   used to send from current-position to the end-of-file.
  ++ * ap_fc_putbucket(): write a bucket into the filter chain
  ++ */
  ++API_EXPORT(void) ap_fc_write(ap_filter_t *filter, const char *buf,
  ++                             apr_size_t len);
  ++API_EXPORT(void) ap_fc_putc(ap_filter_t *filter, int c);
  ++API_EXPORT(void) ap_fc_puts(ap_filter_t *filter, const char *str);
  ++
  ++API_EXPORT_NONSTD(void) ap_fc_putstrs(ap_filter_t *filter, ...);
  ++API_EXPORT(void) ap_fc_vputstrs(ap_filter_t *filter, va_list va);
  ++
  ++API_EXPORT_NONSTD(void) ap_fc_printf(ap_filter_t *filter,
  ++                                     const char *fmt, ...);
  ++API_EXPORT(void) ap_fc_vprintf(ap_filter_t *filter,
  ++                               const char *fmt, va_list va);
  ++
  ++API_EXPORT(void) ap_fc_sendfile(ap_filter_t *filter, apr_file_t *file,
  ++                                apr_ssize_t flen);
  ++#define AP_FC_SENDFILE_ALL ((apr_ssize_t) -1)
  ++
  ++/* note: bucket->next and ->prev may be changed upon return from this */
  ++API_EXPORT(void) ap_fc_putbucket(ap_filter_t *filter, ap_bucket_t *bucket);
  ++
  + 
  + /*
  +  * ap_register_filter():
   Index: main/http_protocol.c
   ===================================================================
   RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  -retrieving revision 1.95
  -diff -u -r1.95 http_protocol.c
  ---- main/http_protocol.c	2000/07/11 03:48:18	1.95
  -+++ main/http_protocol.c	2000/07/12 11:01:10
  -@@ -77,6 +77,8 @@
  +retrieving revision 1.100
  +diff -u -r1.100 http_protocol.c
  +--- main/http_protocol.c	2000/08/02 05:26:48	1.100
  ++++ main/http_protocol.c	2000/08/05 09:48:23
  +@@ -77,6 +77,7 @@
  +                                  * support code... */
    #include "util_date.h"          /* For parseHTTPdate and BAD_DATE */
    #include "util_charset.h"
  ++#include "util_filter.h"
    #include "mpm_status.h"
  -+#include "ap_filter.h"
  -+
  - #ifdef HAVE_STDARG_H
  + #ifdef APR_HAVE_STDARG_H
    #include <stdarg.h>
  - #endif
  -@@ -99,6 +101,9 @@
  +@@ -100,7 +101,10 @@
              ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
      } while (0)
    
   +#define DECL_FILTER_HEAD(r, f) \
   +    ap_filter_t f = { NULL, (r), NULL, 0, (r)->filters }
  -+
    
  ++
    /* if this is the first error, then log an INFO message and shut down the
     * connection.
  -@@ -406,6 +411,9 @@
  +  */
  +@@ -407,6 +411,9 @@
    
    API_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
    {
  @@ -50,39 +246,24 @@
   +        return 0;
   +
        r->clength = clength;
  -     ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
  +     apr_table_setn(r->headers_out, "Content-Length", apr_psprintf(r->pool, "%ld", clength));
        return 0;
  -@@ -1277,8 +1285,17 @@
  -     rnew->main = (request_rec *) r;
  - }
  +@@ -1280,10 +1287,10 @@
    
  -+static void flush_filters(request_rec *r)
  -+{
  + static void end_output_stream(request_rec *r)
  + {
  +-    /*
  +-    ** ### place holder to tell filters that no more content will be
  +-    ** ### arriving. typically, they will flush any pending content
  +-    */
   +    DECL_FILTER_HEAD(r, filter);
   +    ap_bucket_t bucket = { AP_BUCKET_EOS };
   +
   +    ap_fc_putbucket(&filter, &bucket);
  -+}
  -+
  - void ap_finalize_sub_req_protocol(request_rec *sub)
  - {
  -+    flush_filters(sub);
  -     SET_BYTES_SENT(sub->main);
  - }
  - 
  -@@ -1832,11 +1849,6 @@
  - #endif /*APACHE_XLATE*/
    }
    
  --static void flush_filters(request_rec *r)
  --{
  --    /* ### place holder to flush pending content through the filters */
  --}
  --
  - /* finalize_request_protocol is called at completion of sending the
  -  * response.  It's sole purpose is to send the terminating protocol
  -  * information for any wrappers around the response message body
  -@@ -2475,107 +2487,88 @@
  + void ap_finalize_sub_req_protocol(request_rec *sub)
  +@@ -2501,107 +2508,88 @@
    
    API_EXPORT(int) ap_rputc(int c, request_rec *r)
    {
  @@ -124,8 +305,8 @@
    
    API_EXPORT(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
    {
  --    ap_ssize_t n;
  --    ap_status_t rv;
  +-    apr_ssize_t n;
  +-    apr_status_t rv;
   +    DECL_FILTER_HEAD(r, filter);
    
        if (r->connection->aborted)
  @@ -168,9 +349,9 @@
    {
        va_list va;
   -    int n;
  -+
  -+    DECL_FILTER_HEAD(r, filter);
    
  ++    DECL_FILTER_HEAD(r, filter);
  ++
        if (r->connection->aborted)
            return EOF;
    
  @@ -214,7 +395,7 @@
    }
    
    API_EXPORT(int) ap_rflush(request_rec *r)
  -@@ -2589,6 +2582,210 @@
  +@@ -2615,6 +2603,210 @@
        return 0;
    }
    
  @@ -231,8 +412,8 @@
   +                n = ap_bputc(*bscan->buf, filter->r->connection->client);
   +            }
   +            else {
  -+                ap_status_t rv;
  -+                ap_ssize_t written;
  ++                apr_status_t rv;
  ++                apr_ssize_t written;
   +
   +                /* ### should loop to ensure everything is written */
   +                rv = ap_bwrite(filter->r->connection->client, bscan->buf,
  @@ -275,7 +456,7 @@
   +}
   +
   +API_EXPORT(void) ap_fc_write(ap_filter_t *filter, const char *buf,
  -+                             ap_size_t len)
  ++                             apr_size_t len)
   +{
   +    ap_filter_t *next;
   +    ap_bucket_t bucket = { AP_BUCKET_PTRLEN, buf, len };
  @@ -288,7 +469,7 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  @@ -306,7 +487,7 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  @@ -323,7 +504,7 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  @@ -352,7 +533,7 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  @@ -382,12 +563,12 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  -+API_EXPORT(void) ap_fc_sendfile(ap_filter_t *filter, ap_file_t *file,
  -+                                ap_ssize_t flen)
  ++API_EXPORT(void) ap_fc_sendfile(ap_filter_t *filter, apr_file_t *file,
  ++                                apr_ssize_t flen)
   +{
   +    ap_filter_t *next;
   +    ap_bucket_t bucket = {
  @@ -402,7 +583,7 @@
   +        BUFF_filter_callback(filter, &bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, &bucket);
  ++        (*next->filter_func)(next, &bucket);
   +    }
   +}
   +
  @@ -418,14 +599,14 @@
   +        BUFF_filter_callback(filter, bucket);
   +    }
   +    else {
  -+        (*next->bucket_cb)(next, bucket);
  ++        (*next->filter_func)(next, bucket);
   +    }
   +}
   +
    /* We should have named this send_canned_response, since it is used for any
     * response that can be generated by the server from the request record.
     * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
  -@@ -2977,6 +3174,7 @@
  +@@ -3003,6 +3195,7 @@
        ap_finalize_request_protocol(r);
        ap_rflush(r);
    }
  @@ -433,77 +614,18 @@
    
    AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
                              (request_rec *r),(r),OK,DECLINED)
  -Index: main/http_request.c
  -===================================================================
  -RCS file: /home/cvs/apache-2.0/src/main/http_request.c,v
  -retrieving revision 1.35
  -diff -u -r1.35 http_request.c
  ---- main/http_request.c	2000/06/24 17:33:57	1.35
  -+++ main/http_request.c	2000/07/12 11:01:23
  -@@ -769,6 +769,9 @@
  -     rnew->htaccess       = r->htaccess;
  -     rnew->per_dir_config = r->server->lookup_defaults;
  - 
  -+    /* start with the same set of output filters */
  -+    rnew->filters = r->filters;
  -+
  -     ap_set_sub_req_protocol(rnew, r);
  - 
  -     /* would be nicer to pass "method" to ap_set_sub_req_protocol */
  -@@ -857,6 +860,9 @@
  -     rnew->htaccess       = r->htaccess;
  -     rnew->chunked        = r->chunked;
  - 
  -+    /* start with the same set of output filters */
  -+    rnew->filters = r->filters;
  -+
  -     ap_set_sub_req_protocol(rnew, r);
  -     fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
  - 
  -@@ -960,16 +966,22 @@
  - 
  - API_EXPORT(int) ap_run_sub_req(request_rec *r)
  - {
  --#ifndef APACHE_XLATE
  --    int retval = ap_invoke_handler(r);
  --#else /*APACHE_XLATE*/
  --    /* Save the output conversion setting of the caller across subrequests */
  -     int retval;
  --    ap_xlate_t *saved_xlate;
  - 
  --    ap_bgetopt(r->connection->client, BO_WXLATE, &saved_xlate);
  --    retval  = ap_invoke_handler(r);
  --    ap_bsetopt(r->connection->client, BO_WXLATE, &saved_xlate);
  -+    /* see comments in process_request_internal() */
  -+    ap_run_insert_filter(r);
  -+
  -+#ifndef APACHE_XLATE
  -+    retval = ap_invoke_handler(r);
  -+#else /*APACHE_XLATE*/
  -+    {
  -+        /* Save the output conversion setting across subrequests */
  -+        ap_xlate_t *saved_xlate;
  -+
  -+        ap_bgetopt(r->connection->client, BO_WXLATE, &saved_xlate);
  -+        retval  = ap_invoke_handler(r);
  -+        ap_bsetopt(r->connection->client, BO_WXLATE, &saved_xlate);
  -+    }
  - #endif /*APACHE_XLATE*/
  -     ap_finalize_sub_req_protocol(r);
  -     return retval;
  -Index: main/Makefile.in
  +Index: main/util_filter.c
   ===================================================================
  -RCS file: /home/cvs/apache-2.0/src/main/Makefile.in,v
  -retrieving revision 1.16
  -diff -u -r1.16 Makefile.in
  ---- main/Makefile.in	2000/07/01 14:14:15	1.16
  -+++ main/Makefile.in	2000/07/12 11:01:35
  -@@ -8,7 +8,7 @@
  - 	http_protocol.c http_request.c http_vhost.c util.c util_date.c \
  - 	util_script.c util_uri.c util_md5.c util_cfgtree.c util_ebcdic.c \
  - 	rfc1413.c http_connection.c iol_file.c iol_socket.c listen.c \
  --        mpm_common.c util_charset.c util_debug.c util_xml.c
  -+        mpm_common.c util_charset.c util_debug.c util_xml.c filters.c
  - 
  - include $(top_srcdir)/build/ltlib.mk
  +RCS file: /home/cvs/apache-2.0/src/main/util_filter.c,v
  +retrieving revision 1.3
  +diff -u -r1.3 util_filter.c
  +--- main/util_filter.c	2000/08/05 04:38:58	1.3
  ++++ main/util_filter.c	2000/08/05 09:48:23
  +@@ -126,6 +126,7 @@
  +             f->filter_func = frec->filter_func;
  +             f->ctx = ctx;
  +             f->ftype = frec->ftype;
  ++            f->r = r;
    
  +             if (INSERT_BEFORE(f, r->filters)) {
  +                 f->next = r->filters;