MEDIUM: server: move parsing of keyword "id" to server.c

This is the first keyword to be moved to server.c.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4e06f7e..84988a6 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4028,38 +4028,7 @@
 		}
 
 		while (*args[cur_arg]) {
-			if (!defsrv && !strcmp(args[cur_arg], "id")) {
-				struct eb32_node *node;
-
-				if (!*args[cur_arg + 1]) {
-					Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
-						file, linenum, args[cur_arg]);
-					err_code |= ERR_ALERT | ERR_FATAL;
-					goto out;
-				}
-
-				newsrv->puid = atol(args[cur_arg + 1]);
-				newsrv->conf.id.key = newsrv->puid;
-
-				if (newsrv->puid <= 0) {
-					Alert("parsing [%s:%d]: custom id has to be > 0.\n",
-						file, linenum);
-					err_code |= ERR_ALERT | ERR_FATAL;
-					goto out;
-				}
-
-				node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
-				if (node) {
-					struct server *target = container_of(node, struct server, conf.id);
-					Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
-					      file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
-					err_code |= ERR_ALERT | ERR_FATAL;
-					goto out;
-				}
-				eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
-				cur_arg += 2;
-			}
-			else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
+			if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
 				newsrv->cookie = strdup(args[cur_arg + 1]);
 				newsrv->cklen = strlen(args[cur_arg + 1]);
 				cur_arg += 2;
diff --git a/src/server.c b/src/server.c
index ae46af5..568d042 100644
--- a/src/server.c
+++ b/src/server.c
@@ -12,6 +12,7 @@
  */
 
 #include <common/config.h>
+#include <common/errors.h>
 #include <common/time.h>
 
 #include <proto/server.h>
@@ -106,6 +107,55 @@
 	}
 }
 
+/* parse the "id" server keyword */
+static int srv_parse_id(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err)
+{
+	struct eb32_node *node;
+
+	if (!*args[*cur_arg + 1]) {
+		memprintf(err, "'%s' : expects an integer argument", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	newsrv->puid = atol(args[*cur_arg + 1]);
+	newsrv->conf.id.key = newsrv->puid;
+
+	if (newsrv->puid <= 0) {
+		memprintf(err, "'%s' : custom id has to be > 0", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
+	if (node) {
+		struct server *target = container_of(node, struct server, conf.id);
+		memprintf(err, "'%s' : custom id %d already used at %s:%d ('server %s')",
+		          args[*cur_arg], newsrv->puid, target->conf.file, target->conf.line,
+		          target->id);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
+	return 0;
+}
+
+/* Note: must not be declared <const> as its list will be overwritten.
+ * Please take care of keeping this list alphabetically sorted, doing so helps
+ * all code contributors.
+ * Optional keywords are also declared with a NULL ->parse() function so that
+ * the config parser can report an appropriate error when a known keyword was
+ * not enabled.
+ */
+static struct srv_kw_list srv_kws = { "ALL", { }, {
+	{ "id",           srv_parse_id,           1,  0 }, /* set id# of server */
+	{ NULL, NULL, 0 },
+}};
+
+__attribute__((constructor))
+static void __listener_init(void)
+{
+	srv_register_keywords(&srv_kws);
+}
+
 /*
  * Local variables:
  *  c-indent-level: 8