MEDIUM: counters: support passing the counter number as a fetch argument

One very annoying issue when trying to extend the sticky counters beyond
the current 3 counters is that it requires a massive copy-paste of fetch
functions (we don't have to copy-paste code anymore), just so that the
fetch names exist.

So let's have an alternate form like "sc_*(num)" to allow passing the
counter number as an argument without having to redefine new fetch names.
The MAX_SESS_STKCTR macro defines the number of usable sticky counters,
which defaults to 3.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 3579107..b7b2949 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8939,7 +8939,10 @@
 methods described here are usable as low as the "tcp-request connection" rule
 sets unless they require some future information. Those generally include
 TCP/IP addresses and ports, as well as elements from stick-tables related to
-the incoming connection.
+the incoming connection. For retrieving a value from a sticky counters, the
+counter number can be explicitly set as 0, 1, or 2 using the pre-defined
+"sc0_", "sc1_", or "sc2_" prefix, or it can be specified as the first integer
+argument when using the "sc_" prefix.
 
 be_id : integer
   Returns an integer containing the current backend's id. It can be used in
@@ -8975,6 +8978,7 @@
   backends to check from which backend it was called, or to stick all users
   coming via a same frontend to the same server.
 
+sc_bytes_in_rate(<ctr>) : integer
 sc0_bytes_in_rate : integer
 sc1_bytes_in_rate : integer
 sc2_bytes_in_rate : integer
@@ -8982,6 +8986,7 @@
   counters, measured in amount of bytes over the period configured in the
   table. See also src_bytes_in_rate.
 
+sc_bytes_out_rate(<ctr>) : integer
 sc0_bytes_out_rate : integer
 sc1_bytes_out_rate : integer
 sc2_bytes_out_rate : integer
@@ -8989,6 +8994,7 @@
   counters, measured in amount of bytes over the period configured in the
   table. See also src_bytes_out_rate.
 
+sc_clr_gpc0(<ctr>) : integer
 sc0_clr_gpc0 : integer
 sc1_clr_gpc0 : integer
 sc2_clr_gpc0 : integer
@@ -9006,12 +9012,14 @@
         tcp-request connection accept if !abuse save
         tcp-request connection reject if abuse kill
 
+sc_conn_cnt(<ctr>) : integer
 sc0_conn_cnt : integer
 sc1_conn_cnt : integer
 sc2_conn_cnt : integer
   Returns the cumulated number of incoming connections from currently tracked
   counters. See also src_conn_cnt.
 
+sc_conn_cur(<ctr>) : integer
 sc0_conn_cur : integer
 sc1_conn_cur : integer
 sc2_conn_cur : integer
@@ -9019,6 +9027,7 @@
   tracked counters. This number is automatically incremented when tracking
   begins and decremented when tracking stops. See also src_conn_cur.
 
+sc_conn_rate(<ctr>) : integer
 sc0_conn_rate : integer
 sc1_conn_rate : integer
 sc2_conn_rate : integer
@@ -9026,22 +9035,25 @@
   measured in amount of connections over the period configured in the table.
   See also src_conn_rate.
 
+sc_get_gpc0(<ctr>) : integer
 sc0_get_gpc0 : integer
 sc1_get_gpc0 : integer
 sc2_get_gpc0 : integer
   Returns the value of the first General Purpose Counter associated to the
-  currently tracked counters. See also src_get_gpc0 and sc0/sc1/sc2_get_gpc0.
+  currently tracked counters. See also src_get_gpc0 and sc/sc0/sc1/sc2_inc_gpc0.
 
+sc_gpc0_rate(<ctr>) : integer
 sc0_gpc0_rate : integer
 sc1_gpc0_rate : integer
 sc2_gpc0_rate : integer
   Returns the average increment rate of the first General Purpose Counter
   associated to the currently tracked counters. It reports the frequency
   which the gpc0 counter was incremented over the configured period. See also
-  src_gpc0_rate, sc0/sc1/sc2_get_gpc0, and sc0/sc1/sc2_inc_gpc0. Note that the
-  "gpc0_rate" counter must be stored in the stick-table for a value to be
-  returned, as "gpc0" only holds the event count.
+  src_gpc0_rate, sc/sc0/sc1/sc2_get_gpc0, and sc/sc0/sc1/sc2_inc_gpc0. Note
+  that the "gpc0_rate" counter must be stored in the stick-table for a value to
+  be returned, as "gpc0" only holds the event count.
 
+sc_http_err_cnt(<ctr>) : integer
 sc0_http_err_cnt : integer
 sc1_http_err_cnt : integer
 sc2_http_err_cnt : integer
@@ -9049,6 +9061,7 @@
   counters. This includes the both request errors and 4xx error responses.
   See also src_http_err_cnt.
 
+sc_http_err_rate(<ctr>) : integer
 sc0_http_err_rate : integer
 sc1_http_err_rate : integer
 sc2_http_err_rate : integer
@@ -9057,6 +9070,7 @@
   includes the both request errors and 4xx error responses. See also
   src_http_err_rate.
 
+sc_http_req_cnt(<ctr>) : integer
 sc0_http_req_cnt : integer
 sc1_http_req_cnt : integer
 sc2_http_req_cnt : integer
@@ -9064,6 +9078,7 @@
   counters. This includes every started request, valid or not. See also
   src_http_req_cnt.
 
+sc_http_req_rate(<ctr>) : integer
 sc0_http_req_rate : integer
 sc1_http_req_rate : integer
 sc2_http_req_rate : integer
@@ -9072,6 +9087,7 @@
   the table. This includes every started request, valid or not. See also
   src_http_req_rate.
 
+sc_inc_gpc0(<ctr>) : integer
 sc0_inc_gpc0 : integer
 sc1_inc_gpc0 : integer
 sc2_inc_gpc0 : integer
@@ -9085,6 +9101,7 @@
         acl kill  sc0_inc_gpc0 gt 0
         tcp-request connection reject if abuse kill
 
+sc_kbytes_in(<ctr>) : integer
 sc0_kbytes_in : integer
 sc1_kbytes_in : integer
 sc2_kbytes_in : integer
@@ -9093,6 +9110,7 @@
   test is currently performed on 32-bit integers, which limits values to 4
   terabytes. See also src_kbytes_in.
 
+sc_kbytes_out(<ctr>) : integer
 sc0_kbytes_out : integer
 sc1_kbytes_out : integer
 sc2_kbytes_out : integer
@@ -9101,6 +9119,7 @@
   test is currently performed on 32-bit integers, which limits values to 4
   terabytes. See also src_kbytes_out.
 
+sc_sess_cnt(<ctr>) : integer
 sc0_sess_cnt : integer
 sc1_sess_cnt : integer
 sc2_sess_cnt : integer
@@ -9111,6 +9130,7 @@
   backend sessions if some HTTP keep-alive is performed over the connection
   with the client. See also src_sess_cnt.
 
+sc_sess_rate(<ctr>) : integer
 sc0_sess_rate : integer
 sc1_sess_rate : integer
 sc2_sess_rate : integer
@@ -9121,6 +9141,7 @@
   connection could result in many backend sessions if some HTTP keep-alive is
   performed over the connection with the client. See also src_sess_rate.
 
+sc_tracked(<ctr>) : boolean
 sc0_tracked : boolean
 sc1_tracked : boolean
 sc2_tracked : boolean
@@ -9128,6 +9149,7 @@
   the current session. This can be useful when deciding whether or not we want
   to set some values in a header passed to the server.
 
+sc_trackers(<ctr>) : integer
 sc0_trackers : integer
 sc1_trackers : integer
 sc2_trackers : integer
@@ -9158,13 +9180,13 @@
   Returns the average bytes rate from the incoming connection's source address
   in the current proxy's stick-table or in the designated stick-table, measured
   in amount of bytes over the period configured in the table. If the address is
-  not found, zero is returned. See also sc0/sc1/sc2_bytes_in_rate.
+  not found, zero is returned. See also sc/sc0/sc1/sc2_bytes_in_rate.
 
 src_bytes_out_rate([<table>]) : integer
   Returns the average bytes rate to the incoming connection's source address in
   the current proxy's stick-table or in the designated stick-table, measured in
   amount of bytes over the period configured in the table. If the address is
-  not found, zero is returned. See also sc0/sc1/sc2_bytes_out_rate.
+  not found, zero is returned. See also sc/sc0/sc1/sc2_bytes_out_rate.
 
 src_clr_gpc0([<table>]) : integer
   Clears the first General Purpose Counter associated to the incoming
@@ -9186,40 +9208,40 @@
   Returns the cumulated number of connections initiated from the current
   incoming connection's source address in the current proxy's stick-table or in
   the designated stick-table. If the address is not found, zero is returned.
-  See also sc0/sc1/sc2_conn_cnt.
+  See also sc/sc0/sc1/sc2_conn_cnt.
 
 src_conn_cur([<table>]) : integer
   Returns the current amount of concurrent connections initiated from the
   current incoming connection's source address in the current proxy's
   stick-table or in the designated stick-table. If the address is not found,
-  zero is returned. See also sc0/sc1/sc2_conn_cur.
+  zero is returned. See also sc/sc0/sc1/sc2_conn_cur.
 
 src_conn_rate([<table>]) : integer
   Returns the average connection rate from the incoming connection's source
   address in the current proxy's stick-table or in the designated stick-table,
   measured in amount of connections over the period configured in the table. If
-  the address is not found, zero is returned. See also sc0/sc1/sc2_conn_rate.
+  the address is not found, zero is returned. See also sc/sc0/sc1/sc2_conn_rate.
 
 src_get_gpc0([<table>]) : integer
   Returns the value of the first General Purpose Counter associated to the
   incoming connection's source address in the current proxy's stick-table or in
   the designated stick-table. If the address is not found, zero is returned.
-  See also sc0/sc1/sc2_get_gpc0 and src_inc_gpc0.
+  See also sc/sc0/sc1/sc2_get_gpc0 and src_inc_gpc0.
 
 src_gpc0_rate([<table>]) : integer
   Returns the average increment rate of the first General Purpose Counter
   associated to the incoming connection's source address in the current proxy's
   stick-table or in the designated stick-table. It reports the frequency
   which the gpc0 counter was incremented over the configured period. See also
-  sc0/sc1/sc2_gpc0_rate, src_get_gpc0, and sc0/sc1/sc2_inc_gpc0. Note that the
-  "gpc0_rate" counter must be stored in the stick-table for a value to be
-  returned, as "gpc0" only holds the event count.
+  sc/sc0/sc1/sc2_gpc0_rate, src_get_gpc0, and sc/sc0/sc1/sc2_inc_gpc0. Note
+  that the "gpc0_rate" counter must be stored in the stick-table for a value to
+  be returned, as "gpc0" only holds the event count.
 
 src_http_err_cnt([<table>]) : integer
   Returns the cumulated number of HTTP errors from the incoming connection's
   source address in the current proxy's stick-table or in the designated
   stick-table. This includes the both request errors and 4xx error responses.
-  See also sc0/sc1/sc2_http_err_cnt. If the address is not found, zero is
+  See also sc/sc0/sc1/sc2_http_err_cnt. If the address is not found, zero is
   returned.
 
 src_http_err_rate([<table>]) : integer
@@ -9227,20 +9249,20 @@
   address in the current proxy's stick-table or in the designated stick-table,
   measured in amount of errors over the period configured in the table. This
   includes the both request errors and 4xx error responses. If the address is
-  not found, zero is returned. See also sc0/sc1/sc2_http_err_rate.
+  not found, zero is returned. See also sc/sc0/sc1/sc2_http_err_rate.
 
 src_http_req_cnt([<table>]) : integer
   Returns the cumulated number of HTTP requests from the incoming connection's
   source address in the current proxy's stick-table or in the designated stick-
   table. This includes every started request, valid or not. If the address is
-  not found, zero is returned. See also sc0/sc1/sc2_http_req_cnt.
+  not found, zero is returned. See also sc/sc0/sc1/sc2_http_req_cnt.
 
 src_http_req_rate([<table>]) : integer
   Returns the average rate of HTTP requests from the incoming connection's
   source address in the current proxy's stick-table or in the designated stick-
   table, measured in amount of requests over the period configured in the
   table. This includes every started request, valid or not. If the address is
-  not found, zero is returned. See also sc0/sc1/sc2_http_req_rate.
+  not found, zero is returned. See also sc/sc0/sc1/sc2_http_req_rate.
 
 src_inc_gpc0([<table>]) : integer
   Increments the first General Purpose Counter associated to the incoming
@@ -9259,14 +9281,15 @@
   address in the current proxy's stick-table or in the designated stick-table,
   measured in kilobytes over the period configured in the table. If the address
   is not found, zero is returned. The test is currently performed on 32-bit
-  integers, which limits values to 4 terabytes. See also sc0/sc1/sc2_kbytes_in.
+  integers, which limits values to 4 terabytes. See also
+  sc/sc0/sc1/sc2_kbytes_in.
 
 src_kbytes_out([<table>]) : integer
   Returns the amount of data sent to the incoming connection's source address
   in the current proxy's stick-table or in the designated stick-table, measured
   in kilobytes over the period configured in the table. If the address is not
   found, zero is returned. The test is currently performed on 32-bit integers,
-  which limits values to 4 terabytes. See also sc0/sc1/sc2_kbytes_out.
+  which limits values to 4 terabytes. See also sc/sc0/sc1/sc2_kbytes_out.
 
 src_port : integer
   Returns an integer value corresponding to the TCP source port of the
@@ -9279,14 +9302,14 @@
   connection's source IPv4 address in the current proxy's stick-table or in the
   designated stick-table, that were transformed into sessions, which means that
   they were accepted by "tcp-request" rules. If the address is not found, zero
-  is returned. See also sc0/sc1/sc2_sess_cnt.
+  is returned. See also sc/sc0/sc1/sc2_sess_cnt.
 
 src_sess_rate([<table>]) : integer
   Returns the average session rate from the incoming connection's source
   address in the current proxy's stick-table or in the designated stick-table,
   measured in amount of sessions over the period configured in the table. A
   session is a connection that went past the early "tcp-request" rules. If the
-  address is not found, zero is returned. See also sc0/sc1/sc2_sess_rate.
+  address is not found, zero is returned. See also sc/sc0/sc1/sc2_sess_rate.
 
 src_updt_conn_cnt([<table>]) : integer
   Creates or updates the entry associated to the incoming connection's source
diff --git a/src/session.c b/src/session.c
index ec78be1..ef96f0e 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2578,10 +2578,11 @@
 /*           All supported ACL keywords must be declared here.          */
 /************************************************************************/
 
-/* Returns a pointer to an stkctr depending on the fetch keyword name.
- * It is designed to be called as sc[0-9]_* or src_* exclusively.
+/* Returns a pointer to a stkctr depending on the fetch keyword name.
+ * It is designed to be called as sc[0-9]_* sc_* or src_* exclusively.
  * sc[0-9]_* will return a pointer to the respective field in the
- * session <l4>. src_* will fill a locally allocated structure with
+ * session <l4>. sc_* requires an UINT argument specifying the stick
+ * counter number. src_* will fill a locally allocated structure with
  * the table and entry corresponding to what is specified with src_*.
  * NULL may be returned if the designated stkctr is not tracked.
  */
@@ -2589,10 +2590,17 @@
 smp_fetch_sc_stkctr(struct session *l4, const struct arg *args, const char *kw)
 {
 	static struct stkctr stkctr;
-	unsigned char num = kw[2];
+	unsigned int num = kw[2] - '0';
 
-	if (num - '0' <= 9) { /* sc[0-9]_* variant */
-		return l4->stkctr[num - '0'].entry ? &l4->stkctr[num - '0'] : NULL;
+	if (num <= 9) { /* sc[0-9]_* variant */
+		return l4->stkctr[num].entry ? &l4->stkctr[num] : NULL;
+	}
+	else if (num == '_' - '0') {
+		/* sc_* variant, arg[0] = ctr# (mandatory) */
+		num = args[0].data.uint;
+		if (num >= MAX_SESS_STKCTR)
+			return NULL;
+		return l4->stkctr[num].entry ? &l4->stkctr[num] : NULL;
 	}
 	else { /* src_* variant, arg[0] = table */
 		struct stktable_key *key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
@@ -3154,6 +3162,25 @@
  * Please take care of keeping this list alphabetically sorted.
  */
 static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
+	{ "sc_bytes_in_rate",   smp_fetch_sc_bytes_in_rate,  ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_bytes_out_rate",  smp_fetch_sc_bytes_out_rate, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_clr_gpc0",        smp_fetch_sc_clr_gpc0,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_conn_cnt",        smp_fetch_sc_conn_cnt,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_conn_cur",        smp_fetch_sc_conn_cur,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_conn_rate",       smp_fetch_sc_conn_rate,      ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_get_gpc0",        smp_fetch_sc_get_gpc0,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_gpc0_rate",       smp_fetch_sc_gpc0_rate,      ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_http_err_cnt",    smp_fetch_sc_http_err_cnt,   ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_http_err_rate",   smp_fetch_sc_http_err_rate,  ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_http_req_cnt",    smp_fetch_sc_http_req_cnt,   ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_http_req_rate",   smp_fetch_sc_http_req_rate,  ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_inc_gpc0",        smp_fetch_sc_inc_gpc0,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_kbytes_in",       smp_fetch_sc_kbytes_in,      ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_L4CLI, },
+	{ "sc_kbytes_out",      smp_fetch_sc_kbytes_out,     ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_L4CLI, },
+	{ "sc_sess_cnt",        smp_fetch_sc_sess_cnt,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_sess_rate",       smp_fetch_sc_sess_rate,      ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc_tracked",         smp_fetch_sc_tracked,        ARG1(1,UINT), NULL, SMP_T_BOOL, SMP_USE_INTRN, },
+	{ "sc_trackers",        smp_fetch_sc_trackers,       ARG1(1,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "sc0_bytes_in_rate",  smp_fetch_sc_bytes_in_rate,   0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "sc0_bytes_out_rate", smp_fetch_sc_bytes_out_rate,  0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "sc0_clr_gpc0",       smp_fetch_sc_clr_gpc0,        0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },