frontlib: Improved and unified parameter checking, moved the cmdlineClient out
authorMedo <smaxein@googlemail.com>
Thu, 05 Jul 2012 00:33:24 +0200
changeset 7316 f7b49b2c5d84
parent 7314 6171f0bad318
child 7318 a446eafcddeb
frontlib: Improved and unified parameter checking, moved the cmdlineClient out of the frontlib code.
project_files/frontlib/base64/base64.c
project_files/frontlib/base64/base64.h
project_files/frontlib/cmdlineClient.c
project_files/frontlib/frontlib.c
project_files/frontlib/frontlib.h
project_files/frontlib/ipc/gameconn.c
project_files/frontlib/ipc/gameconn.h
project_files/frontlib/ipc/ipcbase.c
project_files/frontlib/ipc/ipcprotocol.c
project_files/frontlib/ipc/mapconn.c
project_files/frontlib/model/cfg.c
project_files/frontlib/model/gamesetup.c
project_files/frontlib/model/gamesetup.h
project_files/frontlib/model/map.c
project_files/frontlib/model/map.h
project_files/frontlib/model/mapcfg.c
project_files/frontlib/model/roomlist.c
project_files/frontlib/model/schemelist.c
project_files/frontlib/model/team.c
project_files/frontlib/model/teamlist.c
project_files/frontlib/model/teamlist.h
project_files/frontlib/model/weapon.c
project_files/frontlib/net/netbase.c
project_files/frontlib/net/netconn.c
project_files/frontlib/net/netconn.h
project_files/frontlib/net/netconn_callbacks.c
project_files/frontlib/net/netconn_send.c
project_files/frontlib/test.c.nocompile
project_files/frontlib/util/buffer.c
project_files/frontlib/util/inihelper.c
project_files/frontlib/util/list.h
project_files/frontlib/util/logging.c
project_files/frontlib/util/logging.h
project_files/frontlib/util/refcounter.c
project_files/frontlib/util/util.c
project_files/frontlib/util/util.h
--- a/project_files/frontlib/base64/base64.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/base64/base64.c	Thu Jul 05 00:33:24 2012 +0200
@@ -1,423 +1,572 @@
-/* base64.c -- Encode binary data using printable characters.
-   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software
-   Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-/* Written by Simon Josefsson.  Partially adapted from GNU MailUtils
- * (mailbox/filter_trans.c, as of 2004-11-28).  Improved by review
- * from Paul Eggert, Bruno Haible, and Stepan Kasal.
- *
- * See also RFC 3548 <http://www.ietf.org/rfc/rfc3548.txt>.
- *
- * Be careful with error checking.  Here is how you would typically
- * use these functions:
- *
- * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
- * if (!ok)
- *   FAIL: input was not valid base64
- * if (out == NULL)
- *   FAIL: memory allocation error
- * OK: data in OUT/OUTLEN
- *
- * size_t outlen = base64_encode_alloc (in, inlen, &out);
- * if (out == NULL && outlen == 0 && inlen != 0)
- *   FAIL: input too long
- * if (out == NULL)
- *   FAIL: memory allocation error
- * OK: data in OUT/OUTLEN.
- *
- */
-
-/* Get prototype. */
-#include "base64.h"
-
-/* Get malloc. */
-#include <stdlib.h>
-
-/* Get UCHAR_MAX. */
-#include <limits.h>
-
-/* C89 compliant way to cast 'char' to 'unsigned char'. */
-static inline unsigned char
-to_uchar (char ch)
-{
-  return ch;
-}
-
-/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
-   If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
-   possible.  If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
-   terminate the output buffer. */
-void
-base64_encode (const char *restrict in, size_t inlen,
-	       char *restrict out, size_t outlen)
-{
-  static const char b64str[64] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-  while (inlen && outlen)
-    {
-      *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
-      if (!--outlen)
-	break;
-      *out++ = b64str[((to_uchar (in[0]) << 4)
-		       + (--inlen ? to_uchar (in[1]) >> 4 : 0))
-		      & 0x3f];
-      if (!--outlen)
-	break;
-      *out++ =
-	(inlen
-	 ? b64str[((to_uchar (in[1]) << 2)
-		   + (--inlen ? to_uchar (in[2]) >> 6 : 0))
-		  & 0x3f]
-	 : '=');
-      if (!--outlen)
-	break;
-      *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
-      if (!--outlen)
-	break;
-      if (inlen)
-	inlen--;
-      if (inlen)
-	in += 3;
-    }
-
-  if (outlen)
-    *out = '\0';
-}
-
-/* Allocate a buffer and store zero terminated base64 encoded data
-   from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
-   the length of the encoded data, excluding the terminating zero.  On
-   return, the OUT variable will hold a pointer to newly allocated
-   memory that must be deallocated by the caller.  If output string
-   length would overflow, 0 is returned and OUT is set to NULL.  If
-   memory allocation failed, OUT is set to NULL, and the return value
-   indicates length of the requested memory block, i.e.,
-   BASE64_LENGTH(inlen) + 1. */
-size_t
-base64_encode_alloc (const char *in, size_t inlen, char **out)
-{
-  size_t outlen = 1 + BASE64_LENGTH (inlen);
-
-  /* Check for overflow in outlen computation.
-   *
-   * If there is no overflow, outlen >= inlen.
-   *
-   * If the operation (inlen + 2) overflows then it yields at most +1, so
-   * outlen is 0.
-   *
-   * If the multiplication overflows, we lose at least half of the
-   * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
-   * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
-   * (inlen > 4).
-   */
-  if (inlen > outlen)
-    {
-      *out = NULL;
-      return 0;
-    }
-
-  *out = malloc (outlen);
-  if (!*out)
-    return outlen;
-
-  base64_encode (in, inlen, *out, outlen);
-
-  return outlen - 1;
-}
-
-/* With this approach this file works independent of the charset used
-   (think EBCDIC).  However, it does assume that the characters in the
-   Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255.  POSIX
-   1003.1-2001 require that char and unsigned char are 8-bit
-   quantities, though, taking care of that problem.  But this may be a
-   potential problem on non-POSIX C99 platforms.
-
-   IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
-   as the formal parameter rather than "x".  */
-#define B64(_)					\
-  ((_) == 'A' ? 0				\
-   : (_) == 'B' ? 1				\
-   : (_) == 'C' ? 2				\
-   : (_) == 'D' ? 3				\
-   : (_) == 'E' ? 4				\
-   : (_) == 'F' ? 5				\
-   : (_) == 'G' ? 6				\
-   : (_) == 'H' ? 7				\
-   : (_) == 'I' ? 8				\
-   : (_) == 'J' ? 9				\
-   : (_) == 'K' ? 10				\
-   : (_) == 'L' ? 11				\
-   : (_) == 'M' ? 12				\
-   : (_) == 'N' ? 13				\
-   : (_) == 'O' ? 14				\
-   : (_) == 'P' ? 15				\
-   : (_) == 'Q' ? 16				\
-   : (_) == 'R' ? 17				\
-   : (_) == 'S' ? 18				\
-   : (_) == 'T' ? 19				\
-   : (_) == 'U' ? 20				\
-   : (_) == 'V' ? 21				\
-   : (_) == 'W' ? 22				\
-   : (_) == 'X' ? 23				\
-   : (_) == 'Y' ? 24				\
-   : (_) == 'Z' ? 25				\
-   : (_) == 'a' ? 26				\
-   : (_) == 'b' ? 27				\
-   : (_) == 'c' ? 28				\
-   : (_) == 'd' ? 29				\
-   : (_) == 'e' ? 30				\
-   : (_) == 'f' ? 31				\
-   : (_) == 'g' ? 32				\
-   : (_) == 'h' ? 33				\
-   : (_) == 'i' ? 34				\
-   : (_) == 'j' ? 35				\
-   : (_) == 'k' ? 36				\
-   : (_) == 'l' ? 37				\
-   : (_) == 'm' ? 38				\
-   : (_) == 'n' ? 39				\
-   : (_) == 'o' ? 40				\
-   : (_) == 'p' ? 41				\
-   : (_) == 'q' ? 42				\
-   : (_) == 'r' ? 43				\
-   : (_) == 's' ? 44				\
-   : (_) == 't' ? 45				\
-   : (_) == 'u' ? 46				\
-   : (_) == 'v' ? 47				\
-   : (_) == 'w' ? 48				\
-   : (_) == 'x' ? 49				\
-   : (_) == 'y' ? 50				\
-   : (_) == 'z' ? 51				\
-   : (_) == '0' ? 52				\
-   : (_) == '1' ? 53				\
-   : (_) == '2' ? 54				\
-   : (_) == '3' ? 55				\
-   : (_) == '4' ? 56				\
-   : (_) == '5' ? 57				\
-   : (_) == '6' ? 58				\
-   : (_) == '7' ? 59				\
-   : (_) == '8' ? 60				\
-   : (_) == '9' ? 61				\
-   : (_) == '+' ? 62				\
-   : (_) == '/' ? 63				\
-   : -1)
-
-static const signed char b64[0x100] = {
-  B64 (0), B64 (1), B64 (2), B64 (3),
-  B64 (4), B64 (5), B64 (6), B64 (7),
-  B64 (8), B64 (9), B64 (10), B64 (11),
-  B64 (12), B64 (13), B64 (14), B64 (15),
-  B64 (16), B64 (17), B64 (18), B64 (19),
-  B64 (20), B64 (21), B64 (22), B64 (23),
-  B64 (24), B64 (25), B64 (26), B64 (27),
-  B64 (28), B64 (29), B64 (30), B64 (31),
-  B64 (32), B64 (33), B64 (34), B64 (35),
-  B64 (36), B64 (37), B64 (38), B64 (39),
-  B64 (40), B64 (41), B64 (42), B64 (43),
-  B64 (44), B64 (45), B64 (46), B64 (47),
-  B64 (48), B64 (49), B64 (50), B64 (51),
-  B64 (52), B64 (53), B64 (54), B64 (55),
-  B64 (56), B64 (57), B64 (58), B64 (59),
-  B64 (60), B64 (61), B64 (62), B64 (63),
-  B64 (64), B64 (65), B64 (66), B64 (67),
-  B64 (68), B64 (69), B64 (70), B64 (71),
-  B64 (72), B64 (73), B64 (74), B64 (75),
-  B64 (76), B64 (77), B64 (78), B64 (79),
-  B64 (80), B64 (81), B64 (82), B64 (83),
-  B64 (84), B64 (85), B64 (86), B64 (87),
-  B64 (88), B64 (89), B64 (90), B64 (91),
-  B64 (92), B64 (93), B64 (94), B64 (95),
-  B64 (96), B64 (97), B64 (98), B64 (99),
-  B64 (100), B64 (101), B64 (102), B64 (103),
-  B64 (104), B64 (105), B64 (106), B64 (107),
-  B64 (108), B64 (109), B64 (110), B64 (111),
-  B64 (112), B64 (113), B64 (114), B64 (115),
-  B64 (116), B64 (117), B64 (118), B64 (119),
-  B64 (120), B64 (121), B64 (122), B64 (123),
-  B64 (124), B64 (125), B64 (126), B64 (127),
-  B64 (128), B64 (129), B64 (130), B64 (131),
-  B64 (132), B64 (133), B64 (134), B64 (135),
-  B64 (136), B64 (137), B64 (138), B64 (139),
-  B64 (140), B64 (141), B64 (142), B64 (143),
-  B64 (144), B64 (145), B64 (146), B64 (147),
-  B64 (148), B64 (149), B64 (150), B64 (151),
-  B64 (152), B64 (153), B64 (154), B64 (155),
-  B64 (156), B64 (157), B64 (158), B64 (159),
-  B64 (160), B64 (161), B64 (162), B64 (163),
-  B64 (164), B64 (165), B64 (166), B64 (167),
-  B64 (168), B64 (169), B64 (170), B64 (171),
-  B64 (172), B64 (173), B64 (174), B64 (175),
-  B64 (176), B64 (177), B64 (178), B64 (179),
-  B64 (180), B64 (181), B64 (182), B64 (183),
-  B64 (184), B64 (185), B64 (186), B64 (187),
-  B64 (188), B64 (189), B64 (190), B64 (191),
-  B64 (192), B64 (193), B64 (194), B64 (195),
-  B64 (196), B64 (197), B64 (198), B64 (199),
-  B64 (200), B64 (201), B64 (202), B64 (203),
-  B64 (204), B64 (205), B64 (206), B64 (207),
-  B64 (208), B64 (209), B64 (210), B64 (211),
-  B64 (212), B64 (213), B64 (214), B64 (215),
-  B64 (216), B64 (217), B64 (218), B64 (219),
-  B64 (220), B64 (221), B64 (222), B64 (223),
-  B64 (224), B64 (225), B64 (226), B64 (227),
-  B64 (228), B64 (229), B64 (230), B64 (231),
-  B64 (232), B64 (233), B64 (234), B64 (235),
-  B64 (236), B64 (237), B64 (238), B64 (239),
-  B64 (240), B64 (241), B64 (242), B64 (243),
-  B64 (244), B64 (245), B64 (246), B64 (247),
-  B64 (248), B64 (249), B64 (250), B64 (251),
-  B64 (252), B64 (253), B64 (254), B64 (255)
-};
-
-#if UCHAR_MAX == 255
-# define uchar_in_range(c) true
-#else
-# define uchar_in_range(c) ((c) <= 255)
-#endif
-
-/* Return true if CH is a character from the Base64 alphabet, and
-   false otherwise.  Note that '=' is padding and not considered to be
-   part of the alphabet.  */
-bool
-isbase64 (char ch)
-{
-  return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
-}
-
-/* Decode base64 encoded input array IN of length INLEN to output
-   array OUT that can hold *OUTLEN bytes.  Return true if decoding was
-   successful, i.e. if the input was valid base64 data, false
-   otherwise.  If *OUTLEN is too small, as many bytes as possible will
-   be written to OUT.  On return, *OUTLEN holds the length of decoded
-   bytes in OUT.  Note that as soon as any non-alphabet characters are
-   encountered, decoding is stopped and false is returned.  This means
-   that, when applicable, you must remove any line terminators that is
-   part of the data stream before calling this function.  */
-bool
-base64_decode (const char *restrict in, size_t inlen,
-	       char *restrict out, size_t *outlen)
-{
-  size_t outleft = *outlen;
-
-  while (inlen >= 2)
-    {
-      if (!isbase64 (in[0]) || !isbase64 (in[1]))
-	break;
-
-      if (outleft)
-	{
-	  *out++ = ((b64[to_uchar (in[0])] << 2)
-		    | (b64[to_uchar (in[1])] >> 4));
-	  outleft--;
-	}
-
-      if (inlen == 2)
-	break;
-
-      if (in[2] == '=')
-	{
-	  if (inlen != 4)
-	    break;
-
-	  if (in[3] != '=')
-	    break;
-
-	}
-      else
-	{
-	  if (!isbase64 (in[2]))
-	    break;
-
-	  if (outleft)
-	    {
-	      *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
-			| (b64[to_uchar (in[2])] >> 2));
-	      outleft--;
-	    }
-
-	  if (inlen == 3)
-	    break;
-
-	  if (in[3] == '=')
-	    {
-	      if (inlen != 4)
-		break;
-	    }
-	  else
-	    {
-	      if (!isbase64 (in[3]))
-		break;
-
-	      if (outleft)
-		{
-		  *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
-			    | b64[to_uchar (in[3])]);
-		  outleft--;
-		}
-	    }
-	}
-
-      in += 4;
-      inlen -= 4;
-    }
-
-  *outlen -= outleft;
-
-  if (inlen != 0)
-    return false;
-
-  return true;
-}
-
-/* Allocate an output buffer in *OUT, and decode the base64 encoded
-   data stored in IN of size INLEN to the *OUT buffer.  On return, the
-   size of the decoded data is stored in *OUTLEN.  OUTLEN may be NULL,
-   if the caller is not interested in the decoded length.  *OUT may be
-   NULL to indicate an out of memory error, in which case *OUTLEN
-   contains the size of the memory block needed.  The function returns
-   true on successful decoding and memory allocation errors.  (Use the
-   *OUT and *OUTLEN parameters to differentiate between successful
-   decoding and memory error.)  The function returns false if the
-   input was invalid, in which case *OUT is NULL and *OUTLEN is
-   undefined. */
-bool
-base64_decode_alloc (const char *in, size_t inlen, char **out,
-		     size_t *outlen)
-{
-  /* This may allocate a few bytes too much, depending on input,
-     but it's not worth the extra CPU time to compute the exact amount.
-     The exact amount is 3 * inlen / 4, minus 1 if the input ends
-     with "=" and minus another 1 if the input ends with "==".
-     Dividing before multiplying avoids the possibility of overflow.  */
-  size_t needlen = 3 * (inlen / 4) + 2;
-
-  *out = malloc (needlen);
-  if (!*out)
-    return true;
-
-  if (!base64_decode (in, inlen, *out, &needlen))
-    {
-      free (*out);
-      *out = NULL;
-      return false;
-    }
-
-  if (outlen)
-    *outlen = needlen;
-
-  return true;
-}
+/* base64.c -- Encode binary data using printable characters.
+   Copyright (C) 1999-2001, 2004-2006, 2009-2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Simon Josefsson.  Partially adapted from GNU MailUtils
+ * (mailbox/filter_trans.c, as of 2004-11-28).  Improved by review
+ * from Paul Eggert, Bruno Haible, and Stepan Kasal.
+ *
+ * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
+ *
+ * Be careful with error checking.  Here is how you would typically
+ * use these functions:
+ *
+ * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
+ * if (!ok)
+ *   FAIL: input was not valid base64
+ * if (out == NULL)
+ *   FAIL: memory allocation error
+ * OK: data in OUT/OUTLEN
+ *
+ * size_t outlen = base64_encode_alloc (in, inlen, &out);
+ * if (out == NULL && outlen == 0 && inlen != 0)
+ *   FAIL: input too long
+ * if (out == NULL)
+ *   FAIL: memory allocation error
+ * OK: data in OUT/OUTLEN.
+ *
+ */
+
+/* Get prototype. */
+#include "base64.h"
+
+/* Get malloc. */
+#include <stdlib.h>
+
+/* Get UCHAR_MAX. */
+#include <limits.h>
+
+#include <string.h>
+
+/* C89 compliant way to cast 'char' to 'unsigned char'. */
+static inline unsigned char
+to_uchar (char ch)
+{
+  return ch;
+}
+
+/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
+   If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
+   possible.  If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
+   terminate the output buffer. */
+void
+base64_encode (const char *restrict in, size_t inlen,
+               char *restrict out, size_t outlen)
+{
+  static const char b64str[64] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  while (inlen && outlen)
+    {
+      *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
+      if (!--outlen)
+        break;
+      *out++ = b64str[((to_uchar (in[0]) << 4)
+                       + (--inlen ? to_uchar (in[1]) >> 4 : 0))
+                      & 0x3f];
+      if (!--outlen)
+        break;
+      *out++ =
+        (inlen
+         ? b64str[((to_uchar (in[1]) << 2)
+                   + (--inlen ? to_uchar (in[2]) >> 6 : 0))
+                  & 0x3f]
+         : '=');
+      if (!--outlen)
+        break;
+      *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
+      if (!--outlen)
+        break;
+      if (inlen)
+        inlen--;
+      if (inlen)
+        in += 3;
+    }
+
+  if (outlen)
+    *out = '\0';
+}
+
+/* Allocate a buffer and store zero terminated base64 encoded data
+   from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
+   the length of the encoded data, excluding the terminating zero.  On
+   return, the OUT variable will hold a pointer to newly allocated
+   memory that must be deallocated by the caller.  If output string
+   length would overflow, 0 is returned and OUT is set to NULL.  If
+   memory allocation failed, OUT is set to NULL, and the return value
+   indicates length of the requested memory block, i.e.,
+   BASE64_LENGTH(inlen) + 1. */
+size_t
+base64_encode_alloc (const char *in, size_t inlen, char **out)
+{
+  size_t outlen = 1 + BASE64_LENGTH (inlen);
+
+  /* Check for overflow in outlen computation.
+   *
+   * If there is no overflow, outlen >= inlen.
+   *
+   * If the operation (inlen + 2) overflows then it yields at most +1, so
+   * outlen is 0.
+   *
+   * If the multiplication overflows, we lose at least half of the
+   * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
+   * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
+   * (inlen > 4).
+   */
+  if (inlen > outlen)
+    {
+      *out = NULL;
+      return 0;
+    }
+
+  *out = malloc (outlen);
+  if (!*out)
+    return outlen;
+
+  base64_encode (in, inlen, *out, outlen);
+
+  return outlen - 1;
+}
+
+/* With this approach this file works independent of the charset used
+   (think EBCDIC).  However, it does assume that the characters in the
+   Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255.  POSIX
+   1003.1-2001 require that char and unsigned char are 8-bit
+   quantities, though, taking care of that problem.  But this may be a
+   potential problem on non-POSIX C99 platforms.
+
+   IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
+   as the formal parameter rather than "x".  */
+#define B64(_)                                  \
+  ((_) == 'A' ? 0                               \
+   : (_) == 'B' ? 1                             \
+   : (_) == 'C' ? 2                             \
+   : (_) == 'D' ? 3                             \
+   : (_) == 'E' ? 4                             \
+   : (_) == 'F' ? 5                             \
+   : (_) == 'G' ? 6                             \
+   : (_) == 'H' ? 7                             \
+   : (_) == 'I' ? 8                             \
+   : (_) == 'J' ? 9                             \
+   : (_) == 'K' ? 10                            \
+   : (_) == 'L' ? 11                            \
+   : (_) == 'M' ? 12                            \
+   : (_) == 'N' ? 13                            \
+   : (_) == 'O' ? 14                            \
+   : (_) == 'P' ? 15                            \
+   : (_) == 'Q' ? 16                            \
+   : (_) == 'R' ? 17                            \
+   : (_) == 'S' ? 18                            \
+   : (_) == 'T' ? 19                            \
+   : (_) == 'U' ? 20                            \
+   : (_) == 'V' ? 21                            \
+   : (_) == 'W' ? 22                            \
+   : (_) == 'X' ? 23                            \
+   : (_) == 'Y' ? 24                            \
+   : (_) == 'Z' ? 25                            \
+   : (_) == 'a' ? 26                            \
+   : (_) == 'b' ? 27                            \
+   : (_) == 'c' ? 28                            \
+   : (_) == 'd' ? 29                            \
+   : (_) == 'e' ? 30                            \
+   : (_) == 'f' ? 31                            \
+   : (_) == 'g' ? 32                            \
+   : (_) == 'h' ? 33                            \
+   : (_) == 'i' ? 34                            \
+   : (_) == 'j' ? 35                            \
+   : (_) == 'k' ? 36                            \
+   : (_) == 'l' ? 37                            \
+   : (_) == 'm' ? 38                            \
+   : (_) == 'n' ? 39                            \
+   : (_) == 'o' ? 40                            \
+   : (_) == 'p' ? 41                            \
+   : (_) == 'q' ? 42                            \
+   : (_) == 'r' ? 43                            \
+   : (_) == 's' ? 44                            \
+   : (_) == 't' ? 45                            \
+   : (_) == 'u' ? 46                            \
+   : (_) == 'v' ? 47                            \
+   : (_) == 'w' ? 48                            \
+   : (_) == 'x' ? 49                            \
+   : (_) == 'y' ? 50                            \
+   : (_) == 'z' ? 51                            \
+   : (_) == '0' ? 52                            \
+   : (_) == '1' ? 53                            \
+   : (_) == '2' ? 54                            \
+   : (_) == '3' ? 55                            \
+   : (_) == '4' ? 56                            \
+   : (_) == '5' ? 57                            \
+   : (_) == '6' ? 58                            \
+   : (_) == '7' ? 59                            \
+   : (_) == '8' ? 60                            \
+   : (_) == '9' ? 61                            \
+   : (_) == '+' ? 62                            \
+   : (_) == '/' ? 63                            \
+   : -1)
+
+static const signed char b64[0x100] = {
+  B64 (0), B64 (1), B64 (2), B64 (3),
+  B64 (4), B64 (5), B64 (6), B64 (7),
+  B64 (8), B64 (9), B64 (10), B64 (11),
+  B64 (12), B64 (13), B64 (14), B64 (15),
+  B64 (16), B64 (17), B64 (18), B64 (19),
+  B64 (20), B64 (21), B64 (22), B64 (23),
+  B64 (24), B64 (25), B64 (26), B64 (27),
+  B64 (28), B64 (29), B64 (30), B64 (31),
+  B64 (32), B64 (33), B64 (34), B64 (35),
+  B64 (36), B64 (37), B64 (38), B64 (39),
+  B64 (40), B64 (41), B64 (42), B64 (43),
+  B64 (44), B64 (45), B64 (46), B64 (47),
+  B64 (48), B64 (49), B64 (50), B64 (51),
+  B64 (52), B64 (53), B64 (54), B64 (55),
+  B64 (56), B64 (57), B64 (58), B64 (59),
+  B64 (60), B64 (61), B64 (62), B64 (63),
+  B64 (64), B64 (65), B64 (66), B64 (67),
+  B64 (68), B64 (69), B64 (70), B64 (71),
+  B64 (72), B64 (73), B64 (74), B64 (75),
+  B64 (76), B64 (77), B64 (78), B64 (79),
+  B64 (80), B64 (81), B64 (82), B64 (83),
+  B64 (84), B64 (85), B64 (86), B64 (87),
+  B64 (88), B64 (89), B64 (90), B64 (91),
+  B64 (92), B64 (93), B64 (94), B64 (95),
+  B64 (96), B64 (97), B64 (98), B64 (99),
+  B64 (100), B64 (101), B64 (102), B64 (103),
+  B64 (104), B64 (105), B64 (106), B64 (107),
+  B64 (108), B64 (109), B64 (110), B64 (111),
+  B64 (112), B64 (113), B64 (114), B64 (115),
+  B64 (116), B64 (117), B64 (118), B64 (119),
+  B64 (120), B64 (121), B64 (122), B64 (123),
+  B64 (124), B64 (125), B64 (126), B64 (127),
+  B64 (128), B64 (129), B64 (130), B64 (131),
+  B64 (132), B64 (133), B64 (134), B64 (135),
+  B64 (136), B64 (137), B64 (138), B64 (139),
+  B64 (140), B64 (141), B64 (142), B64 (143),
+  B64 (144), B64 (145), B64 (146), B64 (147),
+  B64 (148), B64 (149), B64 (150), B64 (151),
+  B64 (152), B64 (153), B64 (154), B64 (155),
+  B64 (156), B64 (157), B64 (158), B64 (159),
+  B64 (160), B64 (161), B64 (162), B64 (163),
+  B64 (164), B64 (165), B64 (166), B64 (167),
+  B64 (168), B64 (169), B64 (170), B64 (171),
+  B64 (172), B64 (173), B64 (174), B64 (175),
+  B64 (176), B64 (177), B64 (178), B64 (179),
+  B64 (180), B64 (181), B64 (182), B64 (183),
+  B64 (184), B64 (185), B64 (186), B64 (187),
+  B64 (188), B64 (189), B64 (190), B64 (191),
+  B64 (192), B64 (193), B64 (194), B64 (195),
+  B64 (196), B64 (197), B64 (198), B64 (199),
+  B64 (200), B64 (201), B64 (202), B64 (203),
+  B64 (204), B64 (205), B64 (206), B64 (207),
+  B64 (208), B64 (209), B64 (210), B64 (211),
+  B64 (212), B64 (213), B64 (214), B64 (215),
+  B64 (216), B64 (217), B64 (218), B64 (219),
+  B64 (220), B64 (221), B64 (222), B64 (223),
+  B64 (224), B64 (225), B64 (226), B64 (227),
+  B64 (228), B64 (229), B64 (230), B64 (231),
+  B64 (232), B64 (233), B64 (234), B64 (235),
+  B64 (236), B64 (237), B64 (238), B64 (239),
+  B64 (240), B64 (241), B64 (242), B64 (243),
+  B64 (244), B64 (245), B64 (246), B64 (247),
+  B64 (248), B64 (249), B64 (250), B64 (251),
+  B64 (252), B64 (253), B64 (254), B64 (255)
+};
+
+#if UCHAR_MAX == 255
+# define uchar_in_range(c) true
+#else
+# define uchar_in_range(c) ((c) <= 255)
+#endif
+
+/* Return true if CH is a character from the Base64 alphabet, and
+   false otherwise.  Note that '=' is padding and not considered to be
+   part of the alphabet.  */
+bool
+isbase64 (char ch)
+{
+  return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
+}
+
+/* Initialize decode-context buffer, CTX.  */
+void
+base64_decode_ctx_init (struct base64_decode_context *ctx)
+{
+  ctx->i = 0;
+}
+
+/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
+   none of those four is a newline, then return *IN.  Otherwise, copy up to
+   4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
+   index CTX->i and setting CTX->i to reflect the number of bytes copied,
+   and return CTX->buf.  In either case, advance *IN to point to the byte
+   after the last one processed, and set *N_NON_NEWLINE to the number of
+   verified non-newline bytes accessible through the returned pointer.  */
+static inline char *
+get_4 (struct base64_decode_context *ctx,
+       char const *restrict *in, char const *restrict in_end,
+       size_t *n_non_newline)
+{
+  if (ctx->i == 4)
+    ctx->i = 0;
+
+  if (ctx->i == 0)
+    {
+      char const *t = *in;
+      if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
+        {
+          /* This is the common case: no newline.  */
+          *in += 4;
+          *n_non_newline = 4;
+          return (char *) t;
+        }
+    }
+
+  {
+    /* Copy non-newline bytes into BUF.  */
+    char const *p = *in;
+    while (p < in_end)
+      {
+        char c = *p++;
+        if (c != '\n')
+          {
+            ctx->buf[ctx->i++] = c;
+            if (ctx->i == 4)
+              break;
+          }
+      }
+
+    *in = p;
+    *n_non_newline = ctx->i;
+    return ctx->buf;
+  }
+}
+
+#define return_false                            \
+  do                                            \
+    {                                           \
+      *outp = out;                              \
+      return false;                             \
+    }                                           \
+  while (false)
+
+/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
+   into the output buffer, *OUT, of size *OUTLEN bytes.  Return true if
+   decoding is successful, false otherwise.  If *OUTLEN is too small,
+   as many bytes as possible are written to *OUT.  On return, advance
+   *OUT to point to the byte after the last one written, and decrement
+   *OUTLEN to reflect the number of bytes remaining in *OUT.  */
+static inline bool
+decode_4 (char const *restrict in, size_t inlen,
+          char *restrict *outp, size_t *outleft)
+{
+  char *out = *outp;
+  if (inlen < 2)
+    return false;
+
+  if (!isbase64 (in[0]) || !isbase64 (in[1]))
+    return false;
+
+  if (*outleft)
+    {
+      *out++ = ((b64[to_uchar (in[0])] << 2)
+                | (b64[to_uchar (in[1])] >> 4));
+      --*outleft;
+    }
+
+  if (inlen == 2)
+    return_false;
+
+  if (in[2] == '=')
+    {
+      if (inlen != 4)
+        return_false;
+
+      if (in[3] != '=')
+        return_false;
+    }
+  else
+    {
+      if (!isbase64 (in[2]))
+        return_false;
+
+      if (*outleft)
+        {
+          *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
+                    | (b64[to_uchar (in[2])] >> 2));
+          --*outleft;
+        }
+
+      if (inlen == 3)
+        return_false;
+
+      if (in[3] == '=')
+        {
+          if (inlen != 4)
+            return_false;
+        }
+      else
+        {
+          if (!isbase64 (in[3]))
+            return_false;
+
+          if (*outleft)
+            {
+              *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
+                        | b64[to_uchar (in[3])]);
+              --*outleft;
+            }
+        }
+    }
+
+  *outp = out;
+  return true;
+}
+
+/* Decode base64-encoded input array IN of length INLEN to output array
+   OUT that can hold *OUTLEN bytes.  The input data may be interspersed
+   with newlines.  Return true if decoding was successful, i.e. if the
+   input was valid base64 data, false otherwise.  If *OUTLEN is too
+   small, as many bytes as possible will be written to OUT.  On return,
+   *OUTLEN holds the length of decoded bytes in OUT.  Note that as soon
+   as any non-alphabet, non-newline character is encountered, decoding
+   is stopped and false is returned.  If INLEN is zero, then process
+   only whatever data is stored in CTX.
+
+   Initially, CTX must have been initialized via base64_decode_ctx_init.
+   Subsequent calls to this function must reuse whatever state is recorded
+   in that buffer.  It is necessary for when a quadruple of base64 input
+   bytes spans two input buffers.
+
+   If CTX is NULL then newlines are treated as garbage and the input
+   buffer is processed as a unit.  */
+
+bool
+base64_decode_ctx (struct base64_decode_context *ctx,
+                   const char *restrict in, size_t inlen,
+                   char *restrict out, size_t *outlen)
+{
+  size_t outleft = *outlen;
+  bool ignore_newlines = ctx != NULL;
+  bool flush_ctx = false;
+  unsigned int ctx_i = 0;
+
+  if (ignore_newlines)
+    {
+      ctx_i = ctx->i;
+      flush_ctx = inlen == 0;
+    }
+
+
+  while (true)
+    {
+      size_t outleft_save = outleft;
+      if (ctx_i == 0 && !flush_ctx)
+        {
+          while (true)
+            {
+              /* Save a copy of outleft, in case we need to re-parse this
+                 block of four bytes.  */
+              outleft_save = outleft;
+              if (!decode_4 (in, inlen, &out, &outleft))
+                break;
+
+              in += 4;
+              inlen -= 4;
+            }
+        }
+
+      if (inlen == 0 && !flush_ctx)
+        break;
+
+      /* Handle the common case of 72-byte wrapped lines.
+         This also handles any other multiple-of-4-byte wrapping.  */
+      if (inlen && *in == '\n' && ignore_newlines)
+        {
+          ++in;
+          --inlen;
+          continue;
+        }
+
+      /* Restore OUT and OUTLEFT.  */
+      out -= outleft_save - outleft;
+      outleft = outleft_save;
+
+      {
+        char const *in_end = in + inlen;
+        char const *non_nl;
+
+        if (ignore_newlines)
+          non_nl = get_4 (ctx, &in, in_end, &inlen);
+        else
+          non_nl = in;  /* Might have nl in this case. */
+
+        /* If the input is empty or consists solely of newlines (0 non-newlines),
+           then we're done.  Likewise if there are fewer than 4 bytes when not
+           flushing context and not treating newlines as garbage.  */
+        if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
+          {
+            inlen = 0;
+            break;
+          }
+        if (!decode_4 (non_nl, inlen, &out, &outleft))
+          break;
+
+        inlen = in_end - in;
+      }
+    }
+
+  *outlen -= outleft;
+
+  return inlen == 0;
+}
+
+/* Allocate an output buffer in *OUT, and decode the base64 encoded
+   data stored in IN of size INLEN to the *OUT buffer.  On return, the
+   size of the decoded data is stored in *OUTLEN.  OUTLEN may be NULL,
+   if the caller is not interested in the decoded length.  *OUT may be
+   NULL to indicate an out of memory error, in which case *OUTLEN
+   contains the size of the memory block needed.  The function returns
+   true on successful decoding and memory allocation errors.  (Use the
+   *OUT and *OUTLEN parameters to differentiate between successful
+   decoding and memory error.)  The function returns false if the
+   input was invalid, in which case *OUT is NULL and *OUTLEN is
+   undefined. */
+bool
+base64_decode_alloc_ctx (struct base64_decode_context *ctx,
+                         const char *in, size_t inlen, char **out,
+                         size_t *outlen)
+{
+  /* This may allocate a few bytes too many, depending on input,
+     but it's not worth the extra CPU time to compute the exact size.
+     The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
+     input ends with "=" and minus another 1 if the input ends with "==".
+     Dividing before multiplying avoids the possibility of overflow.  */
+  size_t needlen = 3 * (inlen / 4) + 3;
+
+  *out = malloc (needlen);
+  if (!*out)
+    return true;
+
+  if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
+    {
+      free (*out);
+      *out = NULL;
+      return false;
+    }
+
+  if (outlen)
+    *outlen = needlen;
+
+  return true;
+}
--- a/project_files/frontlib/base64/base64.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/base64/base64.h	Thu Jul 05 00:33:24 2012 +0200
@@ -1,45 +1,60 @@
-/* base64.h -- Encode binary data using printable characters.
-   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
-   Written by Simon Josefsson.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-
-#ifndef BASE64_H
-# define BASE64_H
-
-/* Get size_t. */
-# include <stddef.h>
-
-/* Get bool. */
-# include <stdbool.h>
-
-/* This uses that the expression (n+(k-1))/k means the smallest
-   integer >= n/k, i.e., the ceiling of n/k.  */
-# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
-
-extern bool isbase64 (char ch);
-
-extern void base64_encode (const char *restrict in, size_t inlen,
-			   char *restrict out, size_t outlen);
-
-extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
-
-extern bool base64_decode (const char *restrict in, size_t inlen,
-			   char *restrict out, size_t *outlen);
-
-extern bool base64_decode_alloc (const char *in, size_t inlen,
-				 char **out, size_t *outlen);
-
-#endif /* BASE64_H */
+/* base64.h -- Encode binary data using printable characters.
+   Copyright (C) 2004-2006, 2009-2012 Free Software Foundation, Inc.
+   Written by Simon Josefsson.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef BASE64_H
+# define BASE64_H
+
+/* Get size_t. */
+# include <stddef.h>
+
+/* Get bool. */
+# include <stdbool.h>
+
+/* This uses that the expression (n+(k-1))/k means the smallest
+   integer >= n/k, i.e., the ceiling of n/k.  */
+# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
+
+struct base64_decode_context
+{
+  unsigned int i;
+  char buf[4];
+};
+
+extern bool isbase64 (char ch);
+
+extern void base64_encode (const char *restrict in, size_t inlen,
+                           char *restrict out, size_t outlen);
+
+extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
+
+extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
+
+extern bool base64_decode_ctx (struct base64_decode_context *ctx,
+                               const char *restrict in, size_t inlen,
+                               char *restrict out, size_t *outlen);
+
+extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
+                                     const char *in, size_t inlen,
+                                     char **out, size_t *outlen);
+
+#define base64_decode(in, inlen, out, outlen) \
+        base64_decode_ctx (NULL, in, inlen, out, outlen)
+
+#define base64_decode_alloc(in, inlen, out, outlen) \
+        base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
+
+#endif /* BASE64_H */
--- a/project_files/frontlib/cmdlineClient.c	Wed Jun 27 22:52:19 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,482 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#include "frontlib.h"
-#include "util/logging.h"
-#include "util/buffer.h"
-#include "util/util.h"
-#include "util/list.h"
-#include "model/map.h"
-#include "model/weapon.h"
-#include "model/schemelist.h"
-#include "ipc/mapconn.h"
-#include "ipc/gameconn.h"
-#include "net/netconn.h"
-#include "base64/base64.h"
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <string.h>
-#include <conio.h>
-#include <windows.h>
-
-#define ENGINE_DIR ".\\"
-#define CONFIG_DIR "..\\share\\hedgewars"
-#define DATA_DIR CONFIG_DIR"\\Data"
-
-static flib_netconn *netconn;
-static flib_gameconn *gameconn;
-static flib_mapconn *mapconn;
-static char nickname[128];
-static flib_cfg_meta *metacfg;
-static bool netConnected = false;
-
-// Callback function that will be called when the map is rendered
-static void handleMapGenerated(void *context, const uint8_t *bitmap, int numHedgehogs) {
-	printf("Drawing map for %i brave little hogs...", numHedgehogs);
-
-	// Draw the map as ASCII art
-	for(int y=0; y<MAPIMAGE_HEIGHT; y+=8) {
-		for(int x=0; x<MAPIMAGE_WIDTH; x+=6) {
-			int pixelnum = x + y*MAPIMAGE_WIDTH;
-			bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
-			printf(pixel ? "#" : " ");
-		}
-		printf("\n");
-	}
-
-	flib_mapconn_destroy(mapconn);
-	mapconn = NULL;
-}
-
-static void onGameDisconnect(void *context, int reason) {
-	flib_log_i("Connection closed. Reason: %i", reason);
-	flib_gameconn_destroy(gameconn);
-	gameconn = NULL;
-	if(netconn) {
-		flib_netconn_send_roundfinished(netconn, reason==GAME_END_FINISHED);
-	}
-}
-
-// Callback function that will be called on error
-static void handleMapFailure(void *context, const char *errormessage) {
-	flib_log_e("Map rendering failed: %s", errormessage);
-	flib_mapconn_destroy(mapconn);
-	mapconn = NULL;
-}
-
-static void startEngineMap(int port) {
-	char cmdbuffer[255];
-	char argbuffer[255];
-	snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
-	snprintf(argbuffer, 255, "%s %i landpreview", CONFIG_DIR, port);
-	ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
-}
-
-static void startEngineGame(int port) {
-	char cmdbuffer[255];
-	char argbuffer[255];
-	char base64PlayerName[255];
-	base64_encode(nickname, strlen(nickname), base64PlayerName, sizeof(base64PlayerName));
-	snprintf(cmdbuffer, 255, "%shwengine.exe", ENGINE_DIR);
-	snprintf(argbuffer, 255, "%s 1024 768 32 %i 0 0 0 10 10 %s 0 0 %s 0 0 en.txt", CONFIG_DIR, port, DATA_DIR, base64PlayerName);
-	ShellExecute(NULL, NULL, cmdbuffer, argbuffer, NULL, SW_HIDE);
-}
-
-void handleNetDisconnect(void *context, int reason, const char *message) {
-	printf("Disconnected: %s", message);
-	flib_netconn_destroy(netconn);
-	netconn = NULL;
-}
-
-void printRoomList() {
-	const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
-	if(roomlist) {
-		if(roomlist->roomCount>0) {
-			for(int i=0; i<roomlist->roomCount; i++) {
-				if(i>0) {
-					printf(", ");
-				}
-				flib_room *room = roomlist->rooms[i];
-				printf("%s", room->name);
-			}
-		} else {
-			puts("Unfortunately, there are no rooms at the moment.");
-		}
-	} else {
-		puts("Sorry, due to an error the room list is not available.");
-	}
-	puts("\n");
-}
-
-void printTeamList() {
-	flib_gamesetup *setup = flib_netconn_create_gamesetup(netconn);
-	if(setup) {
-		puts("The following teams are in this room:");
-		for(int i=0; i<setup->teamlist->teamCount; i++) {
-			if(i>0) {
-				printf(", ");
-			}
-			printf("%s", setup->teamlist->teams[i]->name);
-		}
-		puts("\n");
-	} else {
-		puts("Sorry, due to an error the team list is not available.");
-	}
-	flib_gamesetup_destroy(setup);
-}
-
-void handleNetConnected(void *context) {
-	printf("You enter the lobby of a strange house inhabited by hedgehogs. Looking around, you see hallways branching off to these rooms:\n");
-	printRoomList();
-	printf("\n\nNow, you can chat by just entering text, or join a room with /join <roomname>.");
-	printf(" You can also /quit or let me /describe <roomname>. Once in a room, you can /add <teamname> and set yourself /ready. You can also /list the available rooms (in the lobby) or the teams (in a room).\n");
-	netConnected = true;
-}
-
-void handleChat(void *context, const char *nick, const char *msg) {
-	if(gameconn) {
-		flib_gameconn_send_chatmsg(gameconn, nick, msg);
-	}
-	printf("%s: %s\n", nick, msg);
-}
-
-void handleEnterRoom(void *context, bool isChief) {
-	puts("You have entered the room.");
-}
-
-void handleRoomJoin(void *context, const char *nick) {
-	if(strcmp(nick, nickname)) {
-		printf("%s is here.\n", nick);
-	}
-}
-
-void handleRoomLeave(void *context, const char *nick, const char *partmsg) {
-	if(strcmp(nick, nickname)) {
-		printf("%s leaves.\n", nick);
-	}
-}
-
-void handleReady(void *context, const char *nick, bool ready) {
-	if(strcmp(nick, nickname)) {
-		if(ready) {
-			printf("%s is ready to go.\n", nick);
-		} else {
-			printf("%s is not ready.\n", nick);
-		}
-	} else {
-		if(ready) {
-			printf("You are ready to go.\n");
-		} else {
-			printf("You are not ready.\n");
-		}
-	}
-}
-
-void handleEmFromNet(void *context, const uint8_t *em, size_t size) {
-	if(gameconn) {
-		flib_gameconn_send_enginemsg(gameconn, (const uint8_t*)em, size);
-	}
-}
-
-void handleEmFromEngine(void *context, const uint8_t *em, size_t size) {
-	if(netconn) {
-		flib_netconn_send_engineMessage(netconn, em, size);
-	}
-}
-
-void handleChatFromGame(void *context, const char *message, bool teamchat) {
-	if(netconn) {
-		if(teamchat) {
-			flib_netconn_send_teamchat(netconn, message);
-		} else {
-			flib_netconn_send_chat(netconn, message);
-		}
-	}
-}
-
-void handleRunGame(void *context) {
-	flib_gamesetup *gamesetup = flib_netconn_create_gamesetup(netconn);
-	if(gameconn) {
-		flib_log_e("Request to start game, but a game is already running.");
-	} else if(gamesetup) {
-		gameconn = flib_gameconn_create(nickname, gamesetup, true);
-		flib_gameconn_onEngineMessage(gameconn, handleEmFromEngine, NULL);
-		flib_gameconn_onDisconnect(gameconn, onGameDisconnect, NULL);
-		flib_gameconn_onChat(gameconn, handleChatFromGame, NULL);
-		startEngineGame(flib_gameconn_getport(gameconn));
-	}
-	flib_gamesetup_destroy(gamesetup);
-}
-
-void handleNickTaken(void *context, const char *nick) {
-	printf("The nickname %s is already in use, please choose a different one:\n", nick);
-	flib_gets(nickname, sizeof(nickname));
-	flib_netconn_send_nick(netconn, nickname);
-}
-
-void handlePwRequest(void *context, const char *nick) {
-	printf("A password is required to log in as %s, please enter (warning: shown in cleartext):\n", nick);
-	char password[256];
-	flib_gets(password, sizeof(password));
-	flib_netconn_send_password(netconn, password);
-}
-
-void handleMessage(void *context, int type, const char *msg) {
-	if(gameconn) {
-		flib_gameconn_send_textmsg(gameconn, 1, msg);
-	}
-	printf("*** %s\n", msg);
-}
-
-void handleTeamAccepted(void *context, const char *teamname) {
-	printf("The team %s has been accepted.\n", teamname);
-}
-
-void handleMapChanged(void *context, const flib_map *map, int changetype) {
-	if(map->mapgen != MAPGEN_NAMED && changetype != NETCONN_MAPCHANGE_THEME) {
-		if(mapconn) {
-			flib_mapconn_destroy(mapconn);
-			mapconn = NULL;
-		}
-		mapconn = flib_mapconn_create(map);
-		if(mapconn) {
-			flib_mapconn_onSuccess(mapconn, handleMapGenerated, NULL);
-			flib_mapconn_onFailure(mapconn, handleMapFailure, NULL);
-			startEngineMap(flib_mapconn_getport(mapconn));
-		}
-	} else if(map->mapgen == MAPGEN_NAMED) {
-		printf("The map %s has been selected.\n", map->name);
-	}
-}
-
-void handleLeaveRoom(void *context, int reason, const char *msg) {
-	if(reason == NETCONN_ROOMLEAVE_ABANDONED) {
-		printf("The chief has abandoned the room.");
-	} else if(reason == NETCONN_ROOMLEAVE_KICKED) {
-		printf("You have been kicked from the room.");
-	}
-	if(msg) {
-		printf(" (%s)", msg);
-	}
-	puts(" You are back in the lobby.");
-}
-
-void handleSchemeChanged(void *context, flib_cfg *scheme) {
-	printf("Game scheme: %s.\n", scheme->name);
-}
-
-void handleWeaponsetChanged(void *context, flib_weaponset *weaponset) {
-	printf("Weaponset: %s.\n", weaponset->name);
-}
-
-void handleHogcountChanged(void *context, const char *team, int count) {
-	printf("Team %s will send %i hogs into the fight.\n", team, count);
-}
-
-void handleRoomAdd(void *context, const flib_room *room) {
-	printf("%s created a new room called %s.\n", room->owner, room->name);
-}
-
-void handleRoomDelete(void *context, const char *roomName) {
-	printf("The room %s has collapsed.\n", roomName);
-}
-
-void handleScriptChanged(void *context, const char *script) {
-	printf("Game Type: %s\n", script);
-}
-
-void handleTeamAdd(void *context, flib_team *team) {
-	printf("%s puts the team %s to the planning board.\n", team->ownerName, team->name);
-}
-
-void handleTeamDelete(void *context, const char *teamName) {
-	printf("The team %s decided not to fight this battle after all.\n", teamName);
-}
-
-void handleTeamColorChanged(void *context, const char *name, int colorIndex) {
-	static const char* colorNames[] = {"red", "blue", "teal", "purple", "pink", "green", "orange", "brown", "yellow"};
-	const char *colorName = "strange";
-	if(colorIndex>=0 && colorIndex < 9) {
-		colorName = colorNames[colorIndex];
-	}
-	printf("The team %s will wear %s uniforms today.\n", name, colorName);
-}
-
-void tick() {
-	if(gameconn) {
-		flib_gameconn_tick(gameconn);
-	}
-	if(netconn) {
-		flib_netconn_tick(netconn);
-	}
-	if(mapconn) {
-		flib_mapconn_tick(mapconn);
-	}
-}
-
-static HANDLE hStdin;
-
-static int init() {
-	hStdin = GetStdHandle(STD_INPUT_HANDLE);
-	if(hStdin == INVALID_HANDLE_VALUE) {
-		flib_log_e("Unable to get stdin handle");
-		return 1;
-	}
-	if(!flib_init(0)) {
-		flib_log_setLevel(FLIB_LOGLEVEL_WARNING);
-		freopen( "CON", "w", stdout );
-		freopen( "CON", "w", stderr );
-		metacfg = flib_cfg_meta_from_ini("metasettings.ini");
-		if(!metacfg) {
-			flib_quit();
-			return -1;
-		} else {
-			return 0;
-		}
-	}
-	return -1;
-}
-
-int main(int argc, char *argv[]) {
-	if(init()) {
-		return -1;
-	}
-
-	puts("Please enter a nickname:");
-	flib_gets(nickname, sizeof(nickname));
-
-	netconn = flib_netconn_create(nickname, metacfg, DATA_DIR"\\", "140.247.62.101", 46631);
-	if(!netconn) {
-		flib_quit();
-		return -1;
-	}
-
-	flib_netconn_onConnected(netconn, handleNetConnected, NULL);
-	flib_netconn_onDisconnected(netconn, handleNetDisconnect, NULL);
-	flib_netconn_onChat(netconn, handleChat, NULL);
-	flib_netconn_onEnterRoom(netconn, handleEnterRoom, NULL);
-	flib_netconn_onRunGame(netconn, handleRunGame, NULL);
-	flib_netconn_onEngineMessage(netconn, handleEmFromNet, NULL);
-	flib_netconn_onRoomJoin(netconn, handleRoomJoin, NULL);
-	flib_netconn_onRoomLeave(netconn, handleRoomLeave, NULL);
-	flib_netconn_onReadyState(netconn, handleReady, NULL);
-	flib_netconn_onNickTaken(netconn, handleNickTaken, NULL);
-	flib_netconn_onPasswordRequest(netconn, handlePwRequest, NULL);
-	flib_netconn_onMessage(netconn, handleMessage, NULL);
-	flib_netconn_onTeamAccepted(netconn, handleTeamAccepted, NULL);
-	flib_netconn_onMapChanged(netconn, handleMapChanged, NULL);
-	flib_netconn_onLeaveRoom(netconn, handleLeaveRoom, NULL);
-	flib_netconn_onCfgScheme(netconn, handleSchemeChanged, NULL);
-	flib_netconn_onWeaponsetChanged(netconn, handleWeaponsetChanged, NULL);
-	flib_netconn_onHogCountChanged(netconn, handleHogcountChanged, NULL);
-	flib_netconn_onRoomAdd(netconn, handleRoomAdd, NULL);
-	flib_netconn_onRoomDelete(netconn, handleRoomDelete, NULL);
-	flib_netconn_onScriptChanged(netconn, handleScriptChanged, NULL);
-	flib_netconn_onTeamAdd(netconn, handleTeamAdd, NULL);
-	flib_netconn_onTeamDelete(netconn, handleTeamDelete, NULL);
-	flib_netconn_onTeamColorChanged(netconn, handleTeamColorChanged, NULL);
-
-	INPUT_RECORD inputRecord;
-	DWORD eventCount = 0;
-
-	while(netconn || gameconn) {
-		tick();
-		if(netconn && netConnected) {
-			while(PeekConsoleInput(hStdin, &inputRecord, 1, &eventCount) && eventCount>0) {
-				if(inputRecord.EventType != KEY_EVENT) {
-					ReadConsoleInput(hStdin, &inputRecord, 1, &eventCount);
-				} else {
-					printf("%s: ", nickname);
-					char input[256];
-					if(!flib_gets(input, sizeof(input))) {
-						if(!memcmp("/quit", input, strlen("/quit"))) {
-							flib_netconn_send_quit(netconn, "Player quit.");
-						} else if(!memcmp("/describe ", input, strlen("/describe "))) {
-							const char *roomname = input+strlen("/describe ");
-							const flib_roomlist *roomlist = flib_netconn_get_roomlist(netconn);
-							flib_room *room = flib_roomlist_find(roomlist, roomname);
-							if(!room) {
-								puts("Unknown room.");
-							} else {
-								char *text = flib_asprintf(
-										"%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
-										room->name,
-										room->owner,
-										room->playerCount,
-										room->teamCount,
-										room->inProgress ? "fighting" : "preparing to fight",
-										room->map[0]=='+' ? "" : "the map ",
-										!strcmp("+rnd+", room->map) ? "a random map" :
-												!strcmp("+maze+", room->map) ? "a random maze" :
-												!strcmp("+drawn+", room->map) ? "a hand-drawn map" :
-												room->map,
-										room->scheme,
-										room->weapons);
-								if(text) {
-									puts(text);
-								}
-								free(text);
-							}
-						} else if(!memcmp("/join ", input, strlen("/join "))) {
-							const char *roomname = input+strlen("/join ");
-							flib_netconn_send_joinRoom(netconn, roomname);
-						} else if(!memcmp("/ready", input, strlen("/ready"))) {
-							flib_netconn_send_toggleReady(netconn);
-						} else if(!memcmp("/loglevel ", input, strlen("/loglevel "))) {
-							int loglevel = atoi(input+strlen("/loglevel "));
-							flib_log_setLevel(loglevel);
-						} else if(!memcmp("/list", input, strlen("/list"))) {
-							if(flib_netconn_is_in_room_context(netconn)) {
-								printTeamList();
-							} else {
-								puts("From this big and expansive lobby, hallways branch off to these rooms:");
-								printRoomList();
-							}
-						} else if(!memcmp("/addteam ", input, strlen("/addteam "))) {
-							const char *teamname = input+strlen("/addteam ");
-							if(!flib_contains_dir_separator(teamname)) {
-								char *teamfilename = flib_asprintf("%s.hwt", teamname);
-								if(teamfilename) {
-									flib_team *team = flib_team_from_ini(teamfilename);
-									if(team) {
-										flib_netconn_send_addTeam(netconn, team);
-									} else {
-										printf("Teamfile %s not found.\n", teamfilename);
-									}
-									flib_team_release(team);
-								}
-								free(teamfilename);
-							}
-						} else if(strlen(input)>0) {
-							flib_netconn_send_chat(netconn, input);
-						}
-					}
-				}
-			}
-		}
-		fflush(stdout);
-		Sleep(10);
-	}
-
-
-	flib_cfg_meta_release(metacfg);
-	return 0;
-}
--- a/project_files/frontlib/frontlib.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/frontlib.c	Thu Jul 05 00:33:24 2012 +0200
@@ -19,27 +19,12 @@
 
 #include "frontlib.h"
 #include "util/logging.h"
-#include <SDL.h>
 #include <SDL_net.h>
 
-static int flib_initflags;
-
 int flib_init(int flags) {
-	flib_initflags = flags;
-
 	flib_log_d("Initializing frontlib");
-	if(!(flib_initflags | FRONTLIB_SDL_ALREADY_INITIALIZED)) {
-		if(SDL_Init(0)==-1) {
-		    flib_log_e("Error in SDL_Init: %s", SDL_GetError());
-		    return -1;
-		}
-	}
-
 	if(SDLNet_Init()==-1) {
 		flib_log_e("Error in SDLNet_Init: %s", SDLNet_GetError());
-		if(!(flib_initflags | FRONTLIB_SDL_ALREADY_INITIALIZED)) {
-			SDL_Quit();
-		}
 		return -1;
 	}
 
@@ -49,7 +34,4 @@
 void flib_quit() {
 	flib_log_d("Shutting down frontlib");
 	SDLNet_Quit();
-	if(!(flib_initflags | FRONTLIB_SDL_ALREADY_INITIALIZED)) {
-		SDL_Quit();
-	}
 }
--- a/project_files/frontlib/frontlib.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/frontlib.h	Thu Jul 05 00:33:24 2012 +0200
@@ -26,6 +26,10 @@
 #ifndef FRONTLIB_H_
 #define FRONTLIB_H_
 
+#include "ipc/gameconn.h"
+#include "ipc/mapconn.h"
+#include "net/netconn.h"
+
 #define FRONTLIB_SDL_ALREADY_INITIALIZED 1
 
 /**
--- a/project_files/frontlib/ipc/gameconn.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.c	Thu Jul 05 00:33:24 2012 +0200
@@ -84,29 +84,30 @@
 
 static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) {
 	flib_gameconn *result = NULL;
-	if(!log_badparams_if(!playerName)) {
-		flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
-		if(tempConn) {
-			tempConn->ipcBase = flib_ipcbase_create();
-			tempConn->configBuffer = flib_vector_create();
-			tempConn->playerName = flib_strdupnull(playerName);
-			if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) {
-				if(record) {
-					tempConn->demoBuffer = flib_vector_create();
-				}
-				tempConn->state = AWAIT_CONNECTION;
-				tempConn->netgame = netGame;
-				clearCallbacks(tempConn);
-				result = tempConn;
-				tempConn = NULL;
+	flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
+	if(tempConn) {
+		tempConn->ipcBase = flib_ipcbase_create();
+		tempConn->configBuffer = flib_vector_create();
+		tempConn->playerName = flib_strdupnull(playerName);
+		if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) {
+			if(record) {
+				tempConn->demoBuffer = flib_vector_create();
 			}
+			tempConn->state = AWAIT_CONNECTION;
+			tempConn->netgame = netGame;
+			clearCallbacks(tempConn);
+			result = tempConn;
+			tempConn = NULL;
 		}
-		flib_gameconn_destroy(tempConn);
 	}
+	flib_gameconn_destroy(tempConn);
 	return result;
 }
 
 flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame) {
+	if(log_badargs_if2(playerName==NULL, setup==NULL)) {
+		return NULL;
+	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, netgame);
 	if(tempConn) {
@@ -121,7 +122,10 @@
 	return result;
 }
 
-flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, int size) {
+flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, size_t size) {
+	if(log_badargs_if(demo==NULL && size>0)) {
+		return NULL;
+	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(false, "Player", false);
 	if(tempConn) {
@@ -134,7 +138,10 @@
 	return result;
 }
 
-flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, int size) {
+flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, size_t size) {
+	if(log_badargs_if(save==NULL && size>0)) {
+		return NULL;
+	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false);
 	if(tempConn) {
@@ -148,6 +155,9 @@
 }
 
 flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script) {
+	if(log_badargs_if3(playerName==NULL, seed==NULL, script==NULL)) {
+		return NULL;
+	}
 	flib_gameconn *result = NULL;
 	flib_gameconn *tempConn = flib_gameconn_create_partial(true, playerName, false);
 	if(tempConn) {
@@ -184,10 +194,10 @@
 }
 
 int flib_gameconn_getport(flib_gameconn *conn) {
-	if(!log_badparams_if(!conn)) {
-		return flib_ipcbase_port(conn->ipcBase);
+	if(log_badargs_if(conn==NULL)) {
+		return 0;
 	}
-	return 0;
+	return flib_ipcbase_port(conn->ipcBase);
 }
 
 static void demo_append(flib_gameconn *conn, const void *data, size_t len) {
@@ -207,11 +217,11 @@
 	bool meMessage = msglen >= 4 && !memcmp(message, "/me ", 4);
 	const char *template = meMessage ? "s\x02* %s %s  " : "s\x01%s: %s  ";
 	int size = snprintf((char*)buffer+1, 256, template, playerName, meMessage ? message+4 : message);
-	if(size>0) {
+	if(log_e_if(size<=0, "printf error")) {
+		return -1;
+	} else {
 		buffer[0] = size>255 ? 255 : size;
 		return 0;
-	} else {
-		return -1;
 	}
 }
 
@@ -235,100 +245,78 @@
 }
 
 int flib_gameconn_send_enginemsg(flib_gameconn *conn, const uint8_t *data, size_t len) {
-	int result = -1;
-	if(!log_badparams_if(!conn || (!data && len>0))
-			&& !flib_ipcbase_send_raw(conn->ipcBase, data, len)) {
+	if(log_badargs_if2(conn==NULL, data==NULL && len>0)) {
+		return -1;
+	}
+	int result = flib_ipcbase_send_raw(conn->ipcBase, data, len);
+	if(!result) {
 		demo_append(conn, data, len);
-		result = 0;
 	}
 	return result;
 }
 
 int flib_gameconn_send_textmsg(flib_gameconn *conn, int msgtype, const char *msg) {
+	if(log_badargs_if2(conn==NULL, msg==NULL)) {
+		return -1;
+	}
 	int result = -1;
-	if(!conn || !msg) {
-		flib_log_e("null parameter in flib_gameconn_send_textmsg");
-	} else {
-		uint8_t converted[257];
-		int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg);
-		if(size>0) {
-			converted[0] = size>255 ? 255 : size;
-			if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
-				demo_append(conn, converted, converted[0]+1);
-				result = 0;
-			}
+	uint8_t converted[257];
+	int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg);
+	if(size>0) {
+		converted[0] = size>255 ? 255 : size;
+		if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
+			demo_append(conn, converted, converted[0]+1);
+			result = 0;
 		}
 	}
 	return result;
 }
 
 int flib_gameconn_send_chatmsg(flib_gameconn *conn, const char *playername, const char *msg) {
-	int result = -1;
-	uint8_t converted[257];
-	if(!conn || !playername || !msg) {
-		flib_log_e("null parameter in flib_gameconn_send_chatmsg");
-	} else if(format_chatmessage(converted, playername, msg)) {
-		flib_log_e("Error formatting message in flib_gameconn_send_chatmsg");
-	} else if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
-		demo_append(conn, converted, converted[0]+1);
-		result = 0;
+	if(log_badargs_if3(conn==NULL, playername==NULL, msg==NULL)) {
+		return -1;
 	}
-	return result;
-}
-
-void flib_gameconn_onConnect(flib_gameconn *conn, void (*callback)(void* context), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onConnect");
-	} else {
-		conn->onConnectCb = callback ? callback : &defaultCallback_onConnect;
-		conn->onConnectCtx = context;
+	uint8_t converted[257];
+	if(!format_chatmessage(converted, playername, msg)
+			&& !flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
+		demo_append(conn, converted, converted[0]+1);
+		return 0;
 	}
-}
-
-void flib_gameconn_onDisconnect(flib_gameconn *conn, void (*callback)(void* context, int reason), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onDisconnect");
-	} else {
-		conn->onDisconnectCb = callback ? callback : &defaultCallback_onDisconnect;
-		conn->onDisconnectCtx = context;
-	}
+	return -1;
 }
 
-void flib_gameconn_onErrorMessage(flib_gameconn *conn, void (*callback)(void* context, const char *msg), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onErrorMessage");
-	} else {
-		conn->onErrorMessageCb = callback ? callback : &defaultCallback_onErrorMessage;
-		conn->onErrorMessageCtx = context;
+/**
+ * This macro generates a callback setter function. It uses the name of the callback to
+ * automatically generate the function name and the fields to set, so a consistent naming
+ * convention needs to be enforced (not that that is a bad thing). If null is passed as
+ * callback to the generated function, the defaultCb will be set instead (with conn
+ * as the context).
+ */
+#define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \
+	void flib_gameconn_##cbName(flib_gameconn *conn, void (*callback)cbParameterTypes, void *context) { \
+		if(!log_badargs_if(conn==NULL)) { \
+			conn->cbName##Cb = callback ? callback : &defaultCb; \
+			conn->cbName##Ctx = callback ? context : conn; \
+		} \
 	}
-}
-
-void flib_gameconn_onChat(flib_gameconn *conn, void (*callback)(void* context, const char *msg, bool teamchat), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onChat");
-	} else {
-		conn->onChatCb = callback ? callback : &defaultCallback_onChat;
-		conn->onChatCtx = context;
-	}
-}
 
-void flib_gameconn_onGameRecorded(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *record, int size, bool isSavegame), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onGameRecorded");
-	} else {
-		conn->onGameRecordedCb = callback ? callback : &defaultCallback_onGameRecorded;
-		conn->onGameRecordedCtx = context;
-	}
-}
+/**
+ * Generate a callback setter function like GENERATE_CB_SETTER, and automatically generate a
+ * no-op callback function as well that is used as default.
+ */
+#define GENERATE_CB_SETTER_AND_DEFAULT(cbName, cbParameterTypes) \
+	static void _noop_callback_##cbName cbParameterTypes {} \
+	GENERATE_CB_SETTER(cbName, cbParameterTypes, _noop_callback_##cbName)
 
-void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, size_t size), void* context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_onEngineMessage");
-	} else {
-		conn->onEngineMessageCb = callback ? callback : &defaultCallback_onEngineMessage;
-		conn->onEngineMessageCtx = context;
-	}
-}
+GENERATE_CB_SETTER_AND_DEFAULT(onConnect, (void *context));
+GENERATE_CB_SETTER_AND_DEFAULT(onDisconnect, (void* context, int reason));
+GENERATE_CB_SETTER(onErrorMessage, (void* context, const char *msg), defaultCallback_onErrorMessage);
+GENERATE_CB_SETTER_AND_DEFAULT(onChat, (void* context, const char *msg, bool teamchat));
+GENERATE_CB_SETTER_AND_DEFAULT(onGameRecorded, (void *context, const uint8_t *record, int size, bool isSavegame));
+GENERATE_CB_SETTER_AND_DEFAULT(onEngineMessage, (void *context, const uint8_t *em, size_t size));
+
+#undef GENERATE_CB_SETTER_AND_DEFAULT
+#undef GENERATE_CB_SETTER
 
 static void flib_gameconn_wrappedtick(flib_gameconn *conn) {
 	if(conn->state == AWAIT_CONNECTION) {
@@ -432,13 +420,9 @@
 }
 
 void flib_gameconn_tick(flib_gameconn *conn) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_gameconn_tick");
-	} else if(conn->running) {
-		flib_log_w("Call to flib_gameconn_tick from a callback");
-	} else if(conn->state == FINISHED) {
-		flib_log_w("Call to flib_gameconn_tick, but we are already done.");
-	} else {
+	if(!log_badargs_if(conn == NULL)
+			&& !log_w_if(conn->running, "Call to flib_gameconn_tick from a callback")
+			&& !log_w_if(conn->state == FINISHED, "We are already done.")) {
 		conn->running = true;
 		flib_gameconn_wrappedtick(conn);
 		conn->running = false;
--- a/project_files/frontlib/ipc/gameconn.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/ipc/gameconn.h	Thu Jul 05 00:33:24 2012 +0200
@@ -31,12 +31,11 @@
 #define GAME_END_HALTED 2
 #define GAME_END_ERROR 3
 
-struct _flib_gameconn;
 typedef struct _flib_gameconn flib_gameconn;
 
 flib_gameconn *flib_gameconn_create(const char *playerName, const flib_gamesetup *setup, bool netgame);
-flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, int size);
-flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, int size);
+flib_gameconn *flib_gameconn_create_playdemo(const uint8_t *demo, size_t size);
+flib_gameconn *flib_gameconn_create_loadgame(const char *playerName, const uint8_t *save, size_t size);
 flib_gameconn *flib_gameconn_create_campaign(const char *playerName, const char *seed, const char *script);
 
 void flib_gameconn_destroy(flib_gameconn *conn);
--- a/project_files/frontlib/ipc/ipcbase.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/ipc/ipcbase.c	Thu Jul 05 00:33:24 2012 +0200
@@ -64,8 +64,7 @@
 }
 
 uint16_t flib_ipcbase_port(flib_ipcbase *ipc) {
-	if(!ipc) {
-		flib_log_e("null parameter in flib_ipcbase_port");
+	if(log_badargs_if(ipc==NULL)) {
 		return 0;
 	}
 	return ipc->port;
@@ -80,8 +79,7 @@
 }
 
 IpcState flib_ipcbase_state(flib_ipcbase *ipc) {
-	if(!ipc) {
-		flib_log_e("null parameter in flib_ipcbase_state");
+	if(log_badargs_if(ipc==NULL)) {
 		return IPC_NOT_CONNECTED;
 	} else if(ipc->sock) {
 		return IPC_CONNECTED;
@@ -109,8 +107,7 @@
 }
 
 int flib_ipcbase_recv_message(flib_ipcbase *ipc, void *data) {
-	if(!ipc || !data) {
-		flib_log_e("null parameter in flib_ipcbase_recv_message");
+	if(log_badargs_if2(ipc==NULL, data==NULL)) {
 		return -1;
 	}
 
@@ -134,8 +131,7 @@
 }
 
 int flib_ipcbase_recv_map(flib_ipcbase *ipc, void *data) {
-	if(!ipc || !data) {
-		flib_log_e("null parameter in flib_ipcbase_recv_map");
+	if(log_badargs_if2(ipc==NULL, data==NULL)) {
 		return -1;
 	}
 
@@ -167,15 +163,10 @@
 }
 
 int flib_ipcbase_send_raw(flib_ipcbase *ipc, const void *data, size_t len) {
-	if(!ipc || (!data && len>0)) {
-		flib_log_e("null parameter in flib_ipcbase_send_raw");
+	if(log_badargs_if2(ipc==NULL, data==NULL && len>0)
+			|| log_w_if(!ipc->sock, "flib_ipcbase_send_raw: Not connected.")) {
 		return -1;
 	}
-	if(!ipc->sock) {
-		flib_log_w("flib_ipcbase_send_raw: Not connected.");
-		return -1;
-	}
-
 	if(flib_socket_send(ipc->sock, data, len) == len) {
 		logSentMsg(data, len);
 		return 0;
@@ -188,11 +179,7 @@
 }
 
 int flib_ipcbase_send_message(flib_ipcbase *ipc, void *data, size_t len) {
-	if(!ipc || (!data && len>0)) {
-		flib_log_e("null parameter in flib_ipcbase_send_message");
-		return -1;
-	} else if(len>255) {
-		flib_log_e("Overlong message (%zu bytes) in flib_ipcbase_send_message", len);
+	if(log_badargs_if3(ipc==NULL, data==NULL && len>0, len>255)) {
 		return -1;
 	}
 
@@ -203,9 +190,7 @@
 }
 
 void flib_ipcbase_accept(flib_ipcbase *ipc) {
-	if(!ipc) {
-		flib_log_e("null parameter in flib_ipcbase_accept");
-	} else if(!ipc->sock && ipc->acceptor) {
+	if(!log_badargs_if(ipc==NULL) && !ipc->sock && ipc->acceptor) {
 		ipc->sock = flib_socket_accept(ipc->acceptor, true);
 		if(ipc->sock) {
 			flib_acceptor_close(ipc->acceptor);
--- a/project_files/frontlib/ipc/ipcprotocol.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/ipc/ipcprotocol.c	Thu Jul 05 00:33:24 2012 +0200
@@ -30,7 +30,7 @@
 
 int flib_ipc_append_message(flib_vector *vec, const char *fmt, ...) {
 	int result = -1;
-	if(!log_badparams_if(!vec || !fmt)) {
+	if(!log_badargs_if2(vec==NULL, fmt==NULL)) {
 		// 1 byte size prefix, 255 bytes max message length, 1 0-byte for vsnprintf
 		char msgbuffer[257];
 
@@ -55,7 +55,7 @@
 int flib_ipc_append_mapconf(flib_vector *vec, const flib_map *map, bool mappreview) {
 	int result = -1;
 	flib_vector *tempvector = flib_vector_create();
-	if(!log_badparams_if(!vec || !map)) {
+	if(!log_badargs_if2(vec==NULL, map==NULL)) {
 		bool error = false;
 
 		if(map->mapgen == MAPGEN_NAMED) {
@@ -103,16 +103,16 @@
 }
 
 int flib_ipc_append_seed(flib_vector *vec, const char *seed) {
-	if(!log_badparams_if(!vec || !seed)) {
-		return flib_ipc_append_message(vec, "eseed %s", seed);
+	if(log_badargs_if2(vec==NULL, seed==NULL)) {
+		return -1;
 	}
-	return -1;
+	return flib_ipc_append_message(vec, "eseed %s", seed);
 }
 
 int flib_ipc_append_script(flib_vector *vec, const char *script) {
 	int result = -1;
 	char *copy = flib_strdupnull(script);
-	if(!log_badparams_if(!vec) && copy) {
+	if(!log_badargs_if(vec==NULL) && copy) {
 		if(!strcmp("Normal", copy)) {
 			// "Normal" means no gametype script
 			result = 0;
@@ -131,7 +131,7 @@
 	return result;
 }
 
-uint32_t buildModFlags(const flib_cfg *scheme) {
+static uint32_t buildModFlags(const flib_cfg *scheme) {
 	uint32_t result = 0;
 	for(int i=0; i<scheme->meta->modCount; i++) {
 		if(scheme->mods[i]) {
@@ -145,7 +145,7 @@
 int flib_ipc_append_gamescheme(flib_vector *vec, const flib_cfg *scheme) {
 	int result = -1;
 	flib_vector *tempvector = flib_vector_create();
-	if(!log_badparams_if(!vec || !scheme) && tempvector) {
+	if(!log_badargs_if2(vec==NULL, scheme==NULL) && tempvector) {
 		const flib_cfg_meta *meta = scheme->meta;
 		bool error = false;
 		error |= flib_ipc_append_message(tempvector, "e$gmflags %"PRIu32, buildModFlags(scheme));
@@ -182,22 +182,20 @@
 }
 
 static void calculateMd5Hex(const char *in, char out[33]) {
-	if(!log_badparams_if(!in)) {
-		md5_state_t md5state;
-		uint8_t md5bytes[16];
-		md5_init(&md5state);
-		md5_append(&md5state, (unsigned char*)in, strlen(in));
-		md5_finish(&md5state, md5bytes);
-		for(int i=0;i<sizeof(md5bytes); i++) {
-			snprintf(out+i*2, 3, "%02x", (unsigned)md5bytes[i]);
-		}
+	md5_state_t md5state;
+	uint8_t md5bytes[16];
+	md5_init(&md5state);
+	md5_append(&md5state, (unsigned char*)in, strlen(in));
+	md5_finish(&md5state, md5bytes);
+	for(int i=0;i<sizeof(md5bytes); i++) {
+		snprintf(out+i*2, 3, "%02x", (unsigned)md5bytes[i]);
 	}
 }
 
 int flib_ipc_append_addteam(flib_vector *vec, const flib_team *team, bool perHogAmmo, bool noAmmoStore) {
 	int result = -1;
 	flib_vector *tempvector = flib_vector_create();
-	if(!log_badparams_if(!vec || !team) && tempvector) {
+	if(!log_badargs_if2(vec==NULL, team==NULL) && tempvector) {
 		bool error = false;
 
 		if(!perHogAmmo && !noAmmoStore) {
@@ -251,7 +249,7 @@
 int flib_ipc_append_fullconfig(flib_vector *vec, const flib_gamesetup *setup, bool netgame) {
 	int result = -1;
 	flib_vector *tempvector = flib_vector_create();
-	if(!log_badparams_if(!vec || !setup) && tempvector) {
+	if(!log_badargs_if2(vec==NULL, setup==NULL) && tempvector) {
 		bool error = false;
 		bool perHogAmmo = false;
 		bool sharedAmmo = false;
--- a/project_files/frontlib/ipc/mapconn.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/ipc/mapconn.c	Thu Jul 05 00:33:24 2012 +0200
@@ -75,6 +75,9 @@
 }
 
 flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) {
+	if(log_badargs_if(mapdesc==NULL)) {
+		return NULL;
+	}
 	flib_mapconn *result = NULL;
 	flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn));
 	if(tempConn) {
@@ -110,27 +113,21 @@
 }
 
 int flib_mapconn_getport(flib_mapconn *conn) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_mapconn_getport");
+	if(log_badargs_if(conn==NULL)) {
 		return 0;
-	} else {
-		return flib_ipcbase_port(conn->ipcBase);
 	}
+	return flib_ipcbase_port(conn->ipcBase);
 }
 
 void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_mapconn_onSuccess");
-	} else {
+	if(!log_badargs_if(conn==NULL)) {
 		conn->onSuccessCb = callback ? callback : &noop_handleSuccess;
 		conn->onSuccessCtx = context;
 	}
 }
 
 void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_mapconn_onError");
-	} else {
+	if(!log_badargs_if(conn==NULL)) {
 		conn->onFailureCb = callback ? callback : &noop_handleFailure;
 		conn->onFailureCtx = context;
 	}
@@ -175,13 +172,9 @@
 }
 
 void flib_mapconn_tick(flib_mapconn *conn) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_mapconn_tick");
-	} else if(conn->running) {
-		flib_log_w("Call to flib_mapconn_tick from a callback");
-	} else if(conn->progress == FINISHED) {
-		flib_log_w("Call to flib_mapconn_tick, but we are already done. Best destroy your flib_mapconn object in the callbacks.");
-	} else {
+	if(!log_badargs_if(conn==NULL)
+			&& !log_w_if(conn->running, "Call to flib_mapconn_tick from a callback")
+			&& !log_w_if(conn->progress == FINISHED, "We are already done.")) {
 		conn->running = true;
 		flib_mapconn_wrappedtick(conn);
 		conn->running = false;
--- a/project_files/frontlib/model/cfg.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/cfg.c	Thu Jul 05 00:33:24 2012 +0200
@@ -118,8 +118,7 @@
 }
 
 flib_cfg_meta *flib_cfg_meta_from_ini(const char *filename) {
-	if(!filename) {
-		flib_log_e("null parameter in flib_cfg_meta_from_ini");
+	if(log_badargs_if(filename==NULL)) {
 		return NULL;
 	}
 	flib_cfg_meta *result = flib_cfg_meta_retain(flib_calloc(1, sizeof(flib_cfg_meta)));
@@ -168,8 +167,7 @@
 
 flib_cfg *flib_cfg_create(flib_cfg_meta *meta, const char *schemeName) {
 	flib_cfg *result = flib_cfg_retain(flib_calloc(1, sizeof(flib_cfg)));
-	if(!meta || !result || !schemeName) {
-		flib_log_e("null parameter in flib_cfg_create");
+	if(log_badargs_if2(meta==NULL, schemeName==NULL) || result==NULL) {
 		return NULL;
 	}
 
@@ -215,21 +213,25 @@
 }
 
 bool flib_cfg_get_mod(flib_cfg *cfg, const char *name) {
-	for(int i=0; i<cfg->meta->modCount; i++) {
-		if(!strcmp(cfg->meta->mods[i].name, name)) {
-			return cfg->mods[i];
+	if(!log_badargs_if2(cfg==NULL, name==NULL)) {
+		for(int i=0; i<cfg->meta->modCount; i++) {
+			if(!strcmp(cfg->meta->mods[i].name, name)) {
+				return cfg->mods[i];
+			}
 		}
+		flib_log_e("Unable to find game mod %s", name);
 	}
-	flib_log_e("Unable to find game mod %s", name);
 	return false;
 }
 
 int flib_cfg_get_setting(flib_cfg *cfg, const char *name, int def) {
-	for(int i=0; i<cfg->meta->settingCount; i++) {
-		if(!strcmp(cfg->meta->settings[i].name, name)) {
-			return cfg->settings[i];
+	if(!log_badargs_if2(cfg==NULL, name==NULL)) {
+		for(int i=0; i<cfg->meta->settingCount; i++) {
+			if(!strcmp(cfg->meta->settings[i].name, name)) {
+				return cfg->settings[i];
+			}
 		}
+		flib_log_e("Unable to find game setting %s", name);
 	}
-	flib_log_e("Unable to find game setting %s", name);
 	return def;
 }
--- a/project_files/frontlib/model/gamesetup.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.c	Thu Jul 05 00:33:24 2012 +0200
@@ -18,6 +18,7 @@
  */
 
 #include "gamesetup.h"
+#include "../util/util.h"
 
 #include <stdlib.h>
 
@@ -30,3 +31,25 @@
 		free(gamesetup);
 	}
 }
+
+flib_gamesetup *flib_gamesetup_copy(flib_gamesetup *setup) {
+	if(!setup) {
+		return NULL;
+	}
+
+	flib_gamesetup *result = flib_calloc(1, sizeof(flib_gamesetup));
+	if(result) {
+		result->script = flib_strdupnull(setup->script);
+		result->gamescheme = flib_cfg_copy(setup->gamescheme);
+		result->map = flib_map_copy(setup->map);
+		result->teamlist = flib_teamlist_copy(setup->teamlist);
+		if((setup->script && !result->script)
+				|| (setup->gamescheme && !result->gamescheme)
+				|| (setup->map && !result->map)
+				|| (setup->teamlist && !result->teamlist)) {
+			flib_gamesetup_destroy(result);
+			result = NULL;
+		}
+	}
+	return result;
+}
--- a/project_files/frontlib/model/gamesetup.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/gamesetup.h	Thu Jul 05 00:33:24 2012 +0200
@@ -39,4 +39,10 @@
 
 void flib_gamesetup_destroy(flib_gamesetup *gamesetup);
 
+/**
+ * Deep-copy of the flib_gamesetup. Copies everything except the weaponsets
+ * of the hogs; those are kept as references.
+ */
+flib_gamesetup *flib_gamesetup_copy(flib_gamesetup *gamesetup);
+
 #endif
--- a/project_files/frontlib/model/map.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/map.c	Thu Jul 05 00:33:24 2012 +0200
@@ -37,66 +37,54 @@
 }
 
 flib_map *flib_map_create_regular(const char *seed, const char *theme, int templateFilter) {
-	flib_map *result = NULL;
-	if(!seed || !theme) {
-		flib_log_e("null parameter in flib_map_create_regular");
-	} else {
-		flib_map newmap = {0};
-		newmap.mapgen = MAPGEN_REGULAR;
-		newmap.name = "+rnd+";
-		newmap.seed = (char*)seed;
-		newmap.theme = (char*)theme;
-		newmap.templateFilter = templateFilter;
-		result = flib_map_copy(&newmap);
+	if(log_badargs_if2(seed==NULL, theme==NULL)) {
+		return NULL;
 	}
-	return result;
+	flib_map newmap = {0};
+	newmap.mapgen = MAPGEN_REGULAR;
+	newmap.name = "+rnd+";
+	newmap.seed = (char*)seed;
+	newmap.theme = (char*)theme;
+	newmap.templateFilter = templateFilter;
+	return flib_map_copy(&newmap);
 }
 
 flib_map *flib_map_create_maze(const char *seed, const char *theme, int mazeSize) {
-	flib_map *result = NULL;
-	if(!seed || !theme) {
-		flib_log_e("null parameter in flib_map_create_maze");
-	} else {
-		flib_map newmap = {0};
-		newmap.mapgen = MAPGEN_MAZE;
-		newmap.name = "+maze+";
-		newmap.seed = (char*)seed;
-		newmap.theme = (char*)theme;
-		newmap.mazeSize = mazeSize;
-		result = flib_map_copy(&newmap);
+	if(log_badargs_if2(seed==NULL, theme==NULL)) {
+		return NULL;
 	}
-	return result;
+	flib_map newmap = {0};
+	newmap.mapgen = MAPGEN_MAZE;
+	newmap.name = "+maze+";
+	newmap.seed = (char*)seed;
+	newmap.theme = (char*)theme;
+	newmap.mazeSize = mazeSize;
+	return flib_map_copy(&newmap);
 }
 
 flib_map *flib_map_create_named(const char *seed, const char *name) {
-	flib_map *result = NULL;
-	if(!seed || !name) {
-		flib_log_e("null parameter in flib_map_create_named");
-	} else {
-		flib_map newmap = {0};
-		newmap.mapgen = MAPGEN_NAMED;
-		newmap.name = (char*)name;
-		newmap.seed = (char*)seed;
-		result = flib_map_copy(&newmap);
+	if(log_badargs_if2(seed==NULL, name==NULL)) {
+		return NULL;
 	}
-	return result;
+	flib_map newmap = {0};
+	newmap.mapgen = MAPGEN_NAMED;
+	newmap.name = (char*)name;
+	newmap.seed = (char*)seed;
+	return flib_map_copy(&newmap);
 }
 
-flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, int drawDataSize) {
-	flib_map *result = NULL;
-	if(!seed || !theme || (!drawData && drawDataSize)) {
-		flib_log_e("null parameter in flib_map_create_drawn");
-	} else {
-		flib_map newmap = {0};
-		newmap.mapgen = MAPGEN_DRAWN;
-		newmap.name = "+drawn+";
-		newmap.seed = (char*)seed;
-		newmap.theme = (char*)theme;
-		newmap.drawData = (uint8_t*) drawData;
-		newmap.drawDataSize = drawDataSize;
-		result = flib_map_copy(&newmap);
+flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize) {
+	if(log_badargs_if3(seed==NULL, theme==NULL, drawData==NULL && drawDataSize>0)) {
+		return NULL;
 	}
-	return result;
+	flib_map newmap = {0};
+	newmap.mapgen = MAPGEN_DRAWN;
+	newmap.name = "+drawn+";
+	newmap.seed = (char*)seed;
+	newmap.theme = (char*)theme;
+	newmap.drawData = (uint8_t*) drawData;
+	newmap.drawDataSize = drawDataSize;
+	return flib_map_copy(&newmap);
 }
 
 flib_map *flib_map_copy(const flib_map *map) {
--- a/project_files/frontlib/model/map.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/map.h	Thu Jul 05 00:33:24 2012 +0200
@@ -20,6 +20,7 @@
 #ifndef MODEL_MAP_H_
 #define MODEL_MAP_H_
 
+#include <stddef.h>
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -57,7 +58,7 @@
 	char *seed;				// Used for all maps
 	char *theme;			// Used for all maps
 	uint8_t *drawData;		// Used for MAPGEN_DRAWN
-	int drawDataSize;		// Used for MAPGEN_DRAWN
+	int drawDataSize;		// Used for MAPGEN_DRAWN TODO size_t
 	int templateFilter;		// Used for MAPGEN_REGULAR
 	int mazeSize;			// Used for MAPGEN_MAZE
 } flib_map;
@@ -99,7 +100,7 @@
  * Create a hand-drawn map. Use flib_map_destroy to free the returned object.
  * No NULL parameters allowed, returns NULL on failure.
  */
-flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, int drawDataSize);
+flib_map *flib_map_create_drawn(const char *seed, const char *theme, const uint8_t *drawData, size_t drawDataSize);
 
 /**
  * Create a deep copy of the map. Returns NULL on failure or if NULL was passed.
--- a/project_files/frontlib/model/mapcfg.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/mapcfg.c	Thu Jul 05 00:33:24 2012 +0200
@@ -38,8 +38,7 @@
 
 int flib_mapcfg_read(const char *dataDirPath, const char *mapname, flib_mapcfg *out) {
 	int result = -1;
-	if(!log_badparams_if(!dataDirPath || !mapname || !out)
-			&& !log_e_if(flib_contains_dir_separator(mapname), "Illegal character in mapname %s", mapname)) {
+	if(!log_badargs_if4(dataDirPath==NULL, mapname==NULL, out==NULL, flib_contains_dir_separator(mapname))) {
 		char *path = flib_asprintf("%sMaps/%s/map.cfg", dataDirPath, mapname);
 		if(path) {
 			FILE *file = fopen(path, "rb");
--- a/project_files/frontlib/model/roomlist.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/roomlist.c	Thu Jul 05 00:33:24 2012 +0200
@@ -86,9 +86,7 @@
 
 int flib_roomlist_add(flib_roomlist *list, char **params) {
 	int result = -1;
-	if(!list || !params) {
-		flib_log_e("null parameter in flib_roomlist_add");
-	} else {
+	if(!log_badargs_if2(list==NULL, params==NULL)) {
 		flib_room *tmpRoom = fillRoomFromParams(params);
 		if(tmpRoom) {
 			if(!insertRoom(&list->rooms, &list->roomCount, tmpRoom, 0)) {
@@ -103,9 +101,7 @@
 
 int flib_roomlist_delete(flib_roomlist *list, const char *name) {
 	int result = -1;
-	if(!list || !name) {
-		flib_log_e("null parameter in flib_roomlist_delete");
-	} else {
+	if(!log_badargs_if2(list==NULL, name==NULL)) {
 		int roomid = findRoom(list, name);
 		if(roomid<0) {
 			flib_log_w("Attempt to delete unknown room %s", name);
@@ -122,9 +118,7 @@
 
 int flib_roomlist_update(flib_roomlist *list, const char *name, char **params) {
 	int result = -1;
-	if(!list || !name || !params) {
-		flib_log_e("null parameter in flib_roomlist_update");
-	} else {
+	if(!log_badargs_if3(list==NULL, name==NULL, params==NULL)) {
 		flib_room *tmpRoom = fillRoomFromParams(params);
 		int roomid = findRoom(list, name);
 		if(tmpRoom && roomid>=0) {
@@ -140,9 +134,7 @@
 
 flib_room *flib_roomlist_find(const flib_roomlist *list, const char *name) {
 	flib_room *result = NULL;
-	if(!list || !name) {
-		flib_log_e("null parameter in flib_roomlist_find");
-	} else {
+	if(!log_badargs_if2(list==NULL, name==NULL)) {
 		int roomid = findRoom(list, name);
 		if(roomid>=0) {
 			result = list->rooms[roomid];
@@ -152,9 +144,7 @@
 }
 
 void flib_roomlist_clear(flib_roomlist *list) {
-	if(!list) {
-		flib_log_e("null parameter in flib_roomlist_clear");
-	} else {
+	if(!log_badargs_if(list==NULL)) {
 		for(int i=0; i<list->roomCount; i++) {
 			flib_roomlist_room_destroy(list->rooms[i]);
 		}
--- a/project_files/frontlib/model/schemelist.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/schemelist.c	Thu Jul 05 00:33:24 2012 +0200
@@ -103,11 +103,11 @@
 }
 
 flib_schemelist *flib_schemelist_from_ini(flib_cfg_meta *meta, const char *filename) {
-	flib_schemelist *list = NULL;
-	if(!meta || !filename) {
-		flib_log_e("null parameter in flib_schemelist_from_ini");
+	if(log_badargs_if2(meta==NULL, filename==NULL)) {
 		return NULL;
 	}
+
+	flib_schemelist *list = NULL;
 	flib_ini *ini = flib_ini_load(filename);
 	if(!ini || flib_ini_enter_section(ini, "schemes")) {
 		flib_log_e("Missing file or missing section \"schemes\" in file %s.", filename);
@@ -164,9 +164,7 @@
 
 int flib_schemelist_to_ini(const char *filename, const flib_schemelist *schemes) {
 	int result = -1;
-	if(!filename || !schemes) {
-		flib_log_e("null parameter in flib_schemelist_to_ini");
-	} else {
+	if(!log_badargs_if2(filename==NULL, schemes==NULL)) {
 		flib_ini *ini = flib_ini_create(NULL);
 		if(ini && !flib_ini_create_section(ini, "schemes")) {
 			bool error = false;
@@ -202,7 +200,7 @@
 }
 
 flib_cfg *flib_schemelist_find(flib_schemelist *list, const char *name) {
-	if(list && name) {
+	if(!log_badargs_if2(list==NULL, name==NULL)) {
 		for(int i=0; i<list->schemeCount; i++) {
 			if(!strcmp(name, list->schemes[i]->name)) {
 				return list->schemes[i];
@@ -216,9 +214,8 @@
 GENERATE_STATIC_LIST_DELETE(deleteScheme, flib_cfg*)
 
 int flib_schemelist_insert(flib_schemelist *list, flib_cfg *cfg, int pos) {
-	if(!list) {
-		flib_log_e("Invalid parameter in flib_schemelist_insert");
-	} else if(!insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) {
+	if(!log_badargs_if2(list==NULL, cfg==NULL)
+			&& !insertScheme(&list->schemes, &list->schemeCount, cfg, pos)) {
 		flib_cfg_retain(cfg);
 		return 0;
 	}
@@ -226,9 +223,7 @@
 }
 
 int flib_schemelist_delete(flib_schemelist *list, int pos) {
-	if(!list) {
-		flib_log_e("Invalid parameter in flib_schemelist_delete");
-	} else {
+	if(!log_badargs_if(list==NULL)) {
 		flib_cfg *elem = list->schemes[pos];
 		if(!deleteScheme(&list->schemes, &list->schemeCount, pos)) {
 			flib_cfg_release(elem);
--- a/project_files/frontlib/model/team.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/team.c	Thu Jul 05 00:33:24 2012 +0200
@@ -34,14 +34,13 @@
 }
 
 flib_team *flib_team_from_ini(const char *filename) {
+	if(log_badargs_if(filename==NULL)) {
+		return NULL;
+	}
+
 	flib_team *result = flib_team_retain(flib_calloc(1, sizeof(flib_team)));
 	flib_ini *ini = NULL;
 
-	if(!filename) {
-		flib_log_e("null parameter in flib_team_from_ini");
-		return from_ini_handleError(result, ini);
-	}
-
 	if(!result) {
 		return from_ini_handleError(result, ini);
 	}
@@ -194,9 +193,7 @@
 
 int flib_team_to_ini(const char *filename, const flib_team *team) {
 	int result = -1;
-	if(!filename || !team) {
-		flib_log_e("null parameter in flib_team_to_ini");
-	} else {
+	if(!log_badargs_if2(filename==NULL, team==NULL)) {
 		flib_ini *ini = flib_ini_create(filename);
 		bool error = false;
 		error |= writeTeamSection(team, ini);
@@ -258,7 +255,7 @@
 	}
 }
 
-char *strdupWithError(const char *in, bool *error) {
+static char *strdupWithError(const char *in, bool *error) {
 	char *out = flib_strdupnull(in);
 	if(in && !out) {
 		*error = true;
--- a/project_files/frontlib/model/teamlist.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/teamlist.c	Thu Jul 05 00:33:24 2012 +0200
@@ -53,9 +53,8 @@
 }
 
 int flib_teamlist_insert(flib_teamlist *list, flib_team *team, int pos) {
-	if(!list || !team) {
-		flib_log_e("null parameter in flib_teamlist_insert");
-	} else if(!insertTeam(&list->teams, &list->teamCount, team, pos)) {
+	if(!log_badargs_if2(list==NULL, team==NULL)
+			&& !insertTeam(&list->teams, &list->teamCount, team, pos)) {
 		flib_team_retain(team);
 		return 0;
 	}
@@ -64,9 +63,7 @@
 
 int flib_teamlist_delete(flib_teamlist *list, const char *name) {
 	int result = -1;
-	if(!list || !name) {
-		flib_log_e("null parameter in flib_teamlist_delete");
-	} else {
+	if(!log_badargs_if2(list==NULL, name==NULL)) {
 		int itemid = findTeam(list, name);
 		if(itemid>=0) {
 			flib_team *team = list->teams[itemid];
@@ -81,9 +78,7 @@
 
 flib_team *flib_teamlist_find(const flib_teamlist *list, const char *name) {
 	flib_team *result = NULL;
-	if(!list || !name) {
-		flib_log_e("null parameter in flib_teamlist_find");
-	} else {
+	if(!log_badargs_if2(list==NULL, name==NULL)) {
 		int itemid = findTeam(list, name);
 		if(itemid>=0) {
 			result = list->teams[itemid];
@@ -93,9 +88,7 @@
 }
 
 void flib_teamlist_clear(flib_teamlist *list) {
-	if(!list) {
-		flib_log_e("null parameter in flib_teamlist_clear");
-	} else {
+	if(!log_badargs_if(list==NULL)) {
 		for(int i=0; i<list->teamCount; i++) {
 			flib_team_release(list->teams[i]);
 		}
@@ -104,3 +97,27 @@
 		list->teamCount = 0;
 	}
 }
+
+flib_teamlist *flib_teamlist_copy(flib_teamlist *list) {
+	if(!list) {
+		return NULL;
+	}
+	flib_teamlist *result = flib_teamlist_create();
+	if(result) {
+		bool error = false;
+		for(int i=0; !error && i<list->teamCount; i++) {
+			flib_team *teamcopy = flib_team_copy(list->teams[i]);
+			if(!teamcopy) {
+				error = true;
+			} else {
+				error |= flib_teamlist_insert(result, teamcopy, i);
+			}
+			flib_team_release(teamcopy);
+		}
+		if(error) {
+			flib_teamlist_destroy(result);
+			result = NULL;
+		}
+	}
+	return result;
+}
--- a/project_files/frontlib/model/teamlist.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/teamlist.h	Thu Jul 05 00:33:24 2012 +0200
@@ -52,4 +52,10 @@
  */
 void flib_teamlist_clear(flib_teamlist *list);
 
+/**
+ * Create a copy of the list and all the teams it contains. Weaponsets are not copied, but
+ * kept as references
+ */
+flib_teamlist *flib_teamlist_copy(flib_teamlist *list);
+
 #endif
--- a/project_files/frontlib/model/weapon.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/model/weapon.c	Thu Jul 05 00:33:24 2012 +0200
@@ -59,9 +59,7 @@
 
 flib_weaponset *flib_weaponset_create(const char *name) {
 	flib_weaponset *result = NULL;
-	if(!name) {
-		flib_log_e("null parameter in flib_weaponset_create_str");
-	} else {
+	if(!log_badargs_if(name==NULL)) {
 		flib_weaponset *newSet = flib_weaponset_retain(flib_calloc(1, sizeof(flib_weaponset)));
 		if(newSet) {
 			newSet->name = flib_strdupnull(name);
@@ -119,9 +117,7 @@
 
 flib_weaponset *flib_weaponset_from_ammostring(const char *name, const char *ammostring) {
 	flib_weaponset *result = NULL;
-	if(!name || !ammostring) {
-		flib_log_e("null parameter in flib_weaponset_from_ammostring");
-	} else {
+	if(!log_badargs_if2(name==NULL, ammostring==NULL)) {
 		result = flib_weaponset_create(name);
 		if(result) {
 			int fieldlen = strlen(ammostring)/4;
@@ -164,9 +160,7 @@
 
 flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename) {
 	flib_weaponsetlist *result = NULL;
-	if(!filename) {
-		flib_log_e("null parameter in flib_weaponsetlist_from_ini");
-	} else {
+	if(!log_badargs_if(filename==NULL)) {
 		flib_ini *ini = flib_ini_load(filename);
 		if(!ini) {
 			flib_log_e("Missing file %s.", filename);
@@ -189,7 +183,6 @@
 static bool needsEscape(char c) {
 	return !((c>='0' && c<='9') || (c>='a' && c <='z'));
 }
-
 
 static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) {
 	int result = -1;
@@ -209,9 +202,7 @@
 
 int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) {
 	int result = -1;
-	if(!filename || !list) {
-		flib_log_e("null parameter in flib_weaponsetlist_to_ini");
-	} else {
+	if(!log_badargs_if2(filename==NULL, list==NULL)) {
 		flib_ini *ini = flib_ini_create(NULL);
 		if(ini && !flib_ini_create_section(ini, "General")) {
 			bool error = false;
@@ -236,9 +227,8 @@
 GENERATE_STATIC_LIST_DELETE(deleteWeaponset, flib_weaponset*)
 
 int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *set, int pos) {
-	if(!list) {
-		flib_log_e("Invalid parameter in flib_weaponsetlist_insert");
-	} else if(!insertWeaponset(&list->weaponsets, &list->weaponsetCount, set, pos)) {
+	if(!log_badargs_if2(list==NULL, set==NULL)
+			&& !insertWeaponset(&list->weaponsets, &list->weaponsetCount, set, pos)) {
 		flib_weaponset_retain(set);
 		return 0;
 	}
@@ -246,9 +236,7 @@
 }
 
 int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) {
-	if(!list) {
-		flib_log_e("Invalid parameter in flib_weaponsetlist_delete");
-	} else {
+	if(!log_badargs_if(list==NULL)) {
 		flib_weaponset *elem = list->weaponsets[pos];
 		if(!deleteWeaponset(&list->weaponsets, &list->weaponsetCount, pos)) {
 			flib_weaponset_release(elem);
--- a/project_files/frontlib/net/netbase.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/net/netbase.c	Thu Jul 05 00:33:24 2012 +0200
@@ -36,6 +36,10 @@
 };
 
 flib_netbase *flib_netbase_create(const char *server, uint16_t port) {
+	if(log_badargs_if2(server==NULL, port==0)) {
+		return NULL;
+	}
+
 	flib_netbase *result = NULL;
 	flib_netbase *newNet =  flib_calloc(1, sizeof(flib_netbase));
 
@@ -62,14 +66,10 @@
 }
 
 bool flib_netbase_connected(flib_netbase *net) {
-	if(!net) {
-		flib_log_e("null parameter in flib_netbase_connected");
-		return false;
-	} else if(net->sock) {
+	if(!log_badargs_if(net==NULL) && net->sock) {
 		return true;
-	} else {
-		return false;
 	}
+	return false;
 }
 
 /**
@@ -135,8 +135,7 @@
 }
 
 flib_netmsg *flib_netbase_recv_message(flib_netbase *net) {
-	if(!net) {
-		flib_log_e("null parameter in flib_netbase_recv_message");
+	if(log_badargs_if(net==NULL)) {
 		return NULL;
 	}
 
@@ -160,8 +159,7 @@
 }
 
 int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len) {
-	if(!net || (!data && len>0)) {
-		flib_log_e("null parameter in flib_netbase_send_raw");
+	if(log_badargs_if2(net==NULL, data==NULL && len>0)) {
 		return -1;
 	}
 	if(!net->sock) {
@@ -181,8 +179,7 @@
 }
 
 int flib_netbase_send_message(flib_netbase *net, flib_netmsg *msg) {
-	if(!net || !msg) {
-		flib_log_e("null parameter in flib_netbase_send_message");
+	if(log_badargs_if2(net==NULL, msg==NULL)) {
 		return -1;
 	}
 
@@ -209,9 +206,7 @@
 
 int flib_netbase_sendf(flib_netbase *net, const char *format, ...) {
 	int result = -1;
-	if(!net || !format) {
-		flib_log_e("null parameter in flib_netbase_sendf");
-	} else {
+	if(!log_badargs_if2(net==NULL, format==NULL)) {
 		va_list argp;
 		va_start(argp, format);
 		char *buffer = flib_vasprintf(format, argp);
@@ -247,9 +242,7 @@
 
 int flib_netmsg_append_part(flib_netmsg *msg, const void *part, size_t partlen) {
 	int result = -1;
-	if(!msg) {
-		flib_log_e("null parameter in flib_netmsg_append_part");
-	} else {
+	if(!log_badargs_if2(msg==NULL, part==NULL && partlen>0)) {
 		char **newParts = realloc(msg->parts, (msg->partCount+1)*sizeof(*msg->parts));
 		if(newParts) {
 			msg->parts = newParts;
--- a/project_files/frontlib/net/netconn.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/net/netconn.c	Thu Jul 05 00:33:24 2012 +0200
@@ -36,9 +36,7 @@
 
 flib_netconn *flib_netconn_create(const char *playerName, flib_cfg_meta *metacfg, const char *dataDirPath, const char *host, uint16_t port) {
 	flib_netconn *result = NULL;
-	if(!playerName || !metacfg || !host) {
-		flib_log_e("null parameter in flib_netconn_create");
-	} else {
+	if(!log_badargs_if3(playerName==NULL, metacfg==NULL, host==NULL)) {
 		flib_netconn *newConn = flib_calloc(1, sizeof(flib_netconn));
 		if(newConn) {
 			newConn->netBase = flib_netbase_create(host, port);
@@ -105,23 +103,17 @@
 }
 
 const flib_roomlist *flib_netconn_get_roomlist(flib_netconn *conn) {
-	const flib_roomlist *result = NULL;
-	if(!conn) {
-		flib_log_e("null parameter in flib_netconn_get_roomlist");
-	} else {
-		result = &conn->roomList;
+	if(!log_badargs_if(conn==NULL)) {
+		return &conn->roomList;
 	}
-	return result;
+	return NULL;
 }
 
 bool flib_netconn_is_chief(flib_netconn *conn) {
-	bool result = false;
-	if(!conn) {
-		flib_log_e("null parameter in flib_netconn_is_chief");
-	} else if(conn->netconnState == NETCONN_STATE_ROOM || conn->netconnState == NETCONN_STATE_INGAME) {
-		result = conn->isChief;
+	if(!log_badargs_if(conn==NULL) && flib_netconn_is_in_room_context(conn)) {
+		return conn->isChief;
 	}
-	return result;
+	return false;
 }
 
 void netconn_leaveRoom(flib_netconn *conn) {
@@ -177,35 +169,30 @@
 
 flib_gamesetup *flib_netconn_create_gamesetup(flib_netconn *conn) {
 	flib_gamesetup *result = NULL;
-	if(!conn) {
-		flib_log_e("null parameter in flib_netconn_create_gameSetup");
-	} else {
+	if(!log_badargs_if(conn==NULL)) {
 		if(conn->teamlist.teamCount==0 || !conn->scheme || !conn->weaponset) {
-			flib_log_e("Incomplete room state to create game setup.");
+			flib_log_e("Incomplete room state");
 		} else {
-			result = flib_calloc(1, sizeof(flib_gamesetup));
-			if(result) {
-				result->gamescheme = flib_cfg_copy(conn->scheme);
-				result->map = flib_map_copy(conn->map);
-				result->script = flib_strdupnull(conn->script);
-				result->teamlist = flib_teamlist_create();
-				for(int i=0; i<conn->teamlist.teamCount; i++) {
-					flib_team *copy = flib_team_copy(conn->teamlist.teams[i]);
-					if(copy) {
-						flib_team_set_weaponset(copy, conn->weaponset);
-						flib_team_set_health(copy, flib_cfg_get_setting(conn->scheme, "health", 100));
-						flib_teamlist_insert(result->teamlist, copy, result->teamlist->teamCount);
-					}
-					flib_team_release(copy);
+			flib_gamesetup stackSetup = {0};
+			stackSetup.gamescheme = conn->scheme;
+			stackSetup.map = conn->map;
+			stackSetup.script = conn->script;
+			stackSetup.teamlist = &conn->teamlist;
+			flib_gamesetup *tmpSetup = flib_gamesetup_copy(&stackSetup);
+			if(tmpSetup) {
+				for(int i=0; i<tmpSetup->teamlist->teamCount; i++) {
+					flib_team_set_weaponset(tmpSetup->teamlist->teams[i], conn->weaponset);
+					flib_team_set_health(tmpSetup->teamlist->teams[i], flib_cfg_get_setting(conn->scheme, "health", 100));
 				}
-				if(result->map->mapgen == MAPGEN_NAMED && result->map->name) {
+				if(tmpSetup->map->mapgen == MAPGEN_NAMED && tmpSetup->map->name) {
 					flib_mapcfg mapcfg;
-					if(!flib_mapcfg_read(conn->dataDirPath, result->map->name, &mapcfg)) {
-						free(result->map->theme);
-						result->map->theme = flib_strdupnull(mapcfg.theme);
+					if(!flib_mapcfg_read(conn->dataDirPath, tmpSetup->map->name, &mapcfg)) {
+						free(tmpSetup->map->theme);
+						tmpSetup->map->theme = flib_strdupnull(mapcfg.theme);
+					} else {
+						flib_log_e("Unable to read map config for map %s", tmpSetup->map->name);
 					}
 				}
-				// TODO handle errors
 			}
 		}
 	}
@@ -640,13 +627,9 @@
 }
 
 void flib_netconn_tick(flib_netconn *conn) {
-	if(!conn) {
-		flib_log_e("null parameter in flib_netconn_tick");
-	} else if(conn->running) {
-		flib_log_w("Call to flib_netconn_tick from a callback");
-	} else if(conn->netconnState == NETCONN_STATE_DISCONNECTED) {
-		flib_log_w("Call to flib_netconn_tick, but we are already done.");
-	} else {
+	if(!log_badargs_if(conn==NULL)
+			&& !log_w_if(conn->running, "Call to flib_netconn_tick from a callback")
+			&& !log_w_if(conn->netconnState == NETCONN_STATE_DISCONNECTED, "We are already done.")) {
 		conn->running = true;
 		flib_netconn_wrappedtick(conn);
 		conn->running = false;
--- a/project_files/frontlib/net/netconn.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/net/netconn.h	Thu Jul 05 00:33:24 2012 +0200
@@ -36,7 +36,7 @@
 
 #define NETCONN_DISCONNECT_NORMAL 0
 #define NETCONN_DISCONNECT_SERVER_TOO_OLD 1
-#define NETCONN_DISCONNECT_AUTH_FAILED 2
+#define NETCONN_DISCONNECT_AUTH_FAILED 2 // TODO can you retry instead?
 #define NETCONN_DISCONNECT_INTERNAL_ERROR 100
 
 #define NETCONN_ROOMLEAVE_ABANDONED 0
--- a/project_files/frontlib/net/netconn_callbacks.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/net/netconn_callbacks.c	Thu Jul 05 00:33:24 2012 +0200
@@ -102,9 +102,7 @@
  */
 #define GENERATE_CB_SETTER(cbName, cbParameterTypes, defaultCb) \
 	void flib_netconn_##cbName(flib_netconn *conn, void (*callback)cbParameterTypes, void *context) { \
-		if(!conn) { \
-			flib_log_e("null parameter in flib_netconn_%s", #cbName); \
-		} else { \
+		if(!log_badargs_if(conn==NULL)) { \
 			conn->cbName##Cb = callback ? callback : &defaultCb; \
 			conn->cbName##Ctx = callback ? context : conn; \
 		} \
--- a/project_files/frontlib/net/netconn_send.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/net/netconn_send.c	Thu Jul 05 00:33:24 2012 +0200
@@ -25,9 +25,11 @@
 #include "../md5/md5.h"
 #include "../base64/base64.h"
 
+#include <zlib.h>
+
 #include <stdlib.h>
 #include <string.h>
-#include <zlib.h>
+#include <limits.h>
 
 // cmdname is always given as literal from functions in this file, so it is never null.
 static int sendVoid(flib_netconn *conn, const char *cmdname) {
@@ -39,7 +41,7 @@
 
 // Testing for !*str prevents sending 0-length parameters (they trip up the protocol)
 static int sendStr(flib_netconn *conn, const char *cmdname, const char *str) {
-	if(log_e_if(!conn || !str || !*str, "Invalid parameter sending %s command", cmdname)) {
+	if(log_e_if(!conn || flib_strempty(str), "Invalid parameter sending %s command", cmdname)) {
 		return -1;
 	}
 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", cmdname, str);
@@ -57,14 +59,14 @@
 }
 
 int flib_netconn_send_chat(flib_netconn *conn, const char *chat) {
-	if(chat && *chat) {
+	if(!flib_strempty(chat)) {
 		return sendStr(conn, "CHAT", chat);
 	}
 	return 0;
 }
 
 int flib_netconn_send_teamchat(flib_netconn *conn, const char *chat) {
-	if(chat && *chat) {
+	if(!flib_strempty(chat)) {
 		return sendStr(conn, "TEAMCHAT", chat);
 	}
 	return 0;
@@ -72,7 +74,7 @@
 
 int flib_netconn_send_nick(flib_netconn *conn, const char *nick) {
 	int result = -1;
-	if(!log_badparams_if(!conn || !nick || !*nick)) {
+	if(!log_badargs_if2(conn==NULL, flib_strempty(nick))) {
 		char *tmpName = flib_strdupnull(nick);
 		if(tmpName) {
 			if(!flib_netbase_sendf(conn->netBase, "%s\n%s\n\n", "NICK", nick)) {
@@ -89,7 +91,7 @@
 
 int flib_netconn_send_password(flib_netconn *conn, const char *passwd) {
 	int result = -1;
-	if(!log_badparams_if(!conn || !passwd)) {
+	if(!log_badargs_if2(conn==NULL, passwd==NULL)) {
 		md5_state_t md5state;
 		uint8_t md5bytes[16];
 		char md5hex[33];
@@ -156,10 +158,10 @@
 
 int flib_netconn_send_addTeam(flib_netconn *conn, const flib_team *team) {
 	int result = -1;
-	if(!log_badparams_if(!conn || !team)) {
-		bool missingInfo = !team->name || !team->grave || !team->fort || !team->voicepack || !team->flag;
+	if(!log_badargs_if2(conn==NULL, team==NULL)) {
+		bool missingInfo = flib_strempty(team->name) || flib_strempty(team->grave) || flib_strempty(team->fort) || flib_strempty(team->voicepack) || flib_strempty(team->flag);
 		for(int i=0; i<HEDGEHOGS_PER_TEAM; i++) {
-			missingInfo |= !team->hogs[i].name || !team->hogs[i].hat;
+			missingInfo |= flib_strempty(team->hogs[i].name) || flib_strempty(team->hogs[i].hat);
 		}
 		if(!log_e_if(missingInfo, "Incomplete team definition")) {
 			flib_vector *vec = flib_vector_create();
@@ -194,7 +196,7 @@
 
 int flib_netconn_send_engineMessage(flib_netconn *conn, const uint8_t *message, size_t size) {
 	int result = -1;
-	if(!log_badparams_if(!conn || (!message && size>0))) {
+	if(!log_badargs_if2(conn==NULL, message==NULL && size>0)) {
 		char *base64encout = NULL;
 		base64_encode_alloc((const char*)message, size, &base64encout);
 		if(base64encout) {
@@ -206,7 +208,7 @@
 }
 
 int flib_netconn_send_teamHogCount(flib_netconn *conn, const char *teamname, int hogcount) {
-	if(!log_badparams_if(!conn || !teamname || hogcount<1 || hogcount>HEDGEHOGS_PER_TEAM)
+	if(!log_badargs_if4(conn==NULL, flib_strempty(teamname), hogcount<1, hogcount>HEDGEHOGS_PER_TEAM)
 			&& !flib_netbase_sendf(conn->netBase, "HH_NUM\n%s\n%i\n\n", teamname, hogcount)) {
 		if(conn->isChief) {
 			flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
@@ -220,7 +222,7 @@
 }
 
 int flib_netconn_send_teamColor(flib_netconn *conn, const char *teamname, int colorIndex) {
-	if(!log_badparams_if(!conn || !teamname)
+	if(!log_badargs_if2(conn==NULL, flib_strempty(teamname))
 			&& !flib_netbase_sendf(conn->netBase, "TEAM_COLOR\n%s\n%i\n\n", teamname, colorIndex)) {
 		if(conn->isChief) {
 			flib_team *team = flib_teamlist_find(&conn->teamlist, teamname);
@@ -234,7 +236,7 @@
 }
 
 int flib_netconn_send_weaponset(flib_netconn *conn, const flib_weaponset *weaponset) {
-	if(!log_badparams_if(!conn || !weaponset)) {
+	if(!log_badargs_if3(conn==NULL, weaponset==NULL, flib_strempty(weaponset->name))) {
 		char ammostring[WEAPONS_COUNT*4+1];
 		strcpy(ammostring, weaponset->loadout);
 		strcat(ammostring, weaponset->crateprob);
@@ -251,7 +253,7 @@
 }
 
 int flib_netconn_send_map(flib_netconn *conn, const flib_map *map) {
-	if(log_badparams_if(!conn || !map)) {
+	if(log_badargs_if2(conn==NULL, map==NULL)) {
 		return -1;
 	}
 	bool error = false;
@@ -348,7 +350,7 @@
 
 int flib_netconn_send_mapDrawdata(flib_netconn *conn, const uint8_t *drawData, size_t size) {
 	int result = -1;
-	if(!log_badparams_if(!conn || (!drawData && size>0) || size>SIZE_MAX/2)) {
+	if(!log_badargs_if3(conn==NULL, drawData==NULL && size>0, size>SIZE_MAX/2)) {
 		uLongf zippedSize = compressBound(size);
 		uint8_t *zipped = flib_malloc(zippedSize+4); // 4 extra bytes for header
 		if(zipped) {
@@ -397,7 +399,7 @@
 
 int flib_netconn_send_scheme(flib_netconn *conn, const flib_cfg *scheme) {
 	int result = -1;
-	if(!log_badparams_if(!conn || !scheme)) {
+	if(!log_badargs_if3(conn==NULL, scheme==NULL, flib_strempty(scheme->name))) {
 		flib_vector *vec = flib_vector_create();
 		if(vec) {
 			bool error = false;
@@ -465,7 +467,7 @@
 }
 
 int flib_netconn_send_setServerVar(flib_netconn *conn, const char *name, const char *value) {
-	if(log_badparams_if(!conn || !name || !value)) {
+	if(log_badargs_if3(conn==NULL, flib_strempty(name), flib_strempty(value))) {
 		return -1;
 	}
 	return flib_netbase_sendf(conn->netBase, "%s\n%s\n%s\n\n", "SET_SERVER_VAR", name, value);
--- a/project_files/frontlib/test.c.nocompile	Wed Jun 27 22:52:19 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,338 +0,0 @@
-/*
- * Hedgewars, a free turn based strategy game
- * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
- 
- #include "frontlib.h"
-#include "util/logging.h"
-#include "util/buffer.h"
-#include "util/util.h"
-#include "util/list.h"
-#include "model/map.h"
-#include "model/weapon.h"
-#include "model/schemelist.h"
-#include "ipc/mapconn.h"
-#include "ipc/gameconn.h"
-#include "net/netconn.h"
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <assert.h>
-#include <string.h>
-
-// Callback function that will be called when the map is rendered
-static void handleMapSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {
-	printf("Drawing map for %i brave little hogs...", numHedgehogs);
-
-	// Draw the map as ASCII art
-	for(int y=0; y<MAPIMAGE_HEIGHT; y++) {
-		for(int x=0; x<MAPIMAGE_WIDTH; x++) {
-			int pixelnum = x + y*MAPIMAGE_WIDTH;
-			bool pixel = bitmap[pixelnum>>3] & (1<<(7-(pixelnum&7)));
-			printf(pixel ? "#" : " ");
-		}
-		printf("\n");
-	}
-
-	// Destroy the connection object (this will end the "tick" loop below)
-	flib_mapconn **connptr = context;
-	flib_mapconn_destroy(*connptr);
-	*connptr = NULL;
-}
-
-static void onDisconnect(void *context, int reason) {
-	flib_log_i("Connection closed. Reason: %i", reason);
-	flib_gameconn **connptr = context;
-	flib_gameconn_destroy(*connptr);
-	*connptr = NULL;
-}
-
-static void onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {
-	flib_log_i("Writing %s (%i bytes)...", isSavegame ? "savegame" : "demo", size);
-	FILE *file = fopen(isSavegame ? "testsave.42.hws" : "testdemo.42.hwd", "wb");
-	fwrite(record, 1, size, file);
-	fclose(file);
-}
-
-// Callback function that will be called on error
-static void handleMapFailure(void *context, const char *errormessage) {
-	flib_log_e("Map rendering failed: %s", errormessage);
-
-	// Destroy the connection object (this will end the "tick" loop below)
-	flib_mapconn **connptr = context;
-	flib_mapconn_destroy(*connptr);
-	*connptr = NULL;
-}
-
-static void startEngineMap(int port) {
-	char commandbuffer[255];
-	const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
-	const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
-	snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s %i landpreview", enginePath, configPath, port);
-	system(commandbuffer);
-}
-
-static void startEngineGame(int port) {
-	char commandbuffer[255];
-	const char *enginePath = "C:\\Programmieren\\Hedgewars\\bin";
-	const char *configPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars";
-	const char *dataPath = "C:\\Programmieren\\Hedgewars\\share\\hedgewars\\Data";
-	snprintf(commandbuffer, 255, "start %s\\hwengine.exe %s 1024 768 32 %i 0 0 0 10 10 %s 0 0 TWVkbzQy 0 0 en.txt", enginePath, configPath, port, dataPath);
-	flib_log_d("Starting engine with CMD: %s", commandbuffer);
-	system(commandbuffer);
-}
-
-void testMapPreview() {
-	// Create a map description and check that there was no error
-	flib_map *map = flib_map_create_maze("This is the seed value", "Jungle", MAZE_SIZE_SMALL_TUNNELS);
-	assert(map);
-
-	// Create a new connection to the engine and check that there was no error
-	flib_mapconn *mapConnection = flib_mapconn_create(map);
-	assert(mapConnection);
-
-	// We don't need the map description anymore
-	flib_map_release(map);
-	map = NULL;
-
-	// Register the callback functions
-	flib_mapconn_onFailure(mapConnection, &handleMapFailure, &mapConnection);
-	flib_mapconn_onSuccess(mapConnection, &handleMapSuccess, &mapConnection);
-
-	// Start the engine process and tell it which port the frontlib is listening on
-	startEngineMap(flib_mapconn_getport(mapConnection));
-
-	// Usually, flib_mapconn_tick will be called in an event loop that runs several
-	// times per second. It handles I/O operations and progress, and calls
-	// callbacks when something interesting happens.
-	while(mapConnection) {
-		flib_mapconn_tick(mapConnection);
-	}
-}
-
-/*void testGame() {
-	flib_cfg_meta *metaconf = flib_cfg_meta_from_ini("metasettings.ini");
-	assert(metaconf);
-	flib_weaponset *weapons = flib_weaponset_create("Defaultweaps");
-	flib_schemelist *schemelist = flib_schemelist_from_ini(metaconf, "schemes.ini");
-
-	flib_gamesetup setup;
-	setup.gamescheme = flib_schemelist_find(schemelist, "Default");
-	setup.map = flib_map_create_maze("asparagus", "Jungle", MAZE_SIZE_MEDIUM_TUNNELS);
-	setup.script = NULL;
-	setup.teamCount = 2;
-	setup.teams = calloc(2, sizeof(flib_team*));
-	setup.teams[0] = calloc(1, sizeof(flib_team));
-	setup.teams[0]->color = 0xffff0000;
-	setup.teams[0]->flag = "australia";
-	setup.teams[0]->fort = "Plane";
-	setup.teams[0]->grave = "Bone";
-	setup.teams[0]->hogsInGame = 2;
-	setup.teams[0]->name = "Team Awesome";
-	setup.teams[0]->voicepack = "British";
-	setup.teams[0]->hogs[0].difficulty = 2;
-	setup.teams[0]->hogs[0].hat = "NoHat";
-	setup.teams[0]->hogs[0].initialHealth = 100;
-	setup.teams[0]->hogs[0].name = "Harry 120";
-	setup.teams[0]->hogs[1].difficulty = 2;
-	setup.teams[0]->hogs[1].hat = "chef";
-	setup.teams[0]->hogs[1].initialHealth = 100;
-	setup.teams[0]->hogs[1].name = "Chefkoch";
-	setup.teams[1] = flib_team_from_ini("Cave Dwellers.hwt");
-	setup.teams[1]->color = 0xFF0000F0;
-	setup.teams[1]->hogsInGame = 8;
-	flib_team_set_weaponset(setup.teams[0], weapons);
-	flib_team_set_weaponset(setup.teams[1], weapons);
-	flib_weaponset_release(weapons);
-
-	flib_gameconn *gameconn = flib_gameconn_create("Medo42", &setup, false);
-	assert(gameconn);
-
-	flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
-	//flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
-
-	startEngineGame(flib_gameconn_getport(gameconn));
-
-	while(gameconn) {
-		flib_gameconn_tick(gameconn);
-	}
-}*/
-
-void testDemo() {
-	FILE *demofile = fopen("testdemo.42.hwd", "rb");
-	assert(demofile);
-	flib_vector *vec = flib_vector_create();
-	uint8_t demobuf[512];
-	int len;
-	while((len=fread(demobuf, 1, 512, demofile))>0) {
-		flib_vector_append(vec, demobuf, len);
-	}
-	fclose(demofile);
-	flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
-	flib_gameconn *gameconn = flib_gameconn_create_playdemo(constbuf.data, constbuf.size);
-	flib_vector_destroy(vec);
-	assert(gameconn);
-	flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
-	flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
-	startEngineGame(flib_gameconn_getport(gameconn));
-
-	while(gameconn) {
-		flib_gameconn_tick(gameconn);
-	}
-}
-
-void testSave() {
-	FILE *demofile = fopen("testsave.42.hws", "rb");
-	assert(demofile);
-	flib_vector *vec = flib_vector_create();
-	uint8_t demobuf[512];
-	int len;
-	while((len=fread(demobuf, 1, 512, demofile))>0) {
-		flib_vector_append(vec, demobuf, len);
-	}
-	fclose(demofile);
-	flib_constbuffer constbuf = flib_vector_as_constbuffer(vec);
-	flib_gameconn *gameconn = flib_gameconn_create_loadgame("Medo42", constbuf.data, constbuf.size);
-	flib_vector_destroy(vec);
-	assert(gameconn);
-	flib_gameconn_onDisconnect(gameconn, &onDisconnect, &gameconn);
-	flib_gameconn_onGameRecorded(gameconn, &onGameRecorded, &gameconn);
-	startEngineGame(flib_gameconn_getport(gameconn));
-
-	while(gameconn) {
-		flib_gameconn_tick(gameconn);
-	}
-}
-
-void handleNetDisconnect(void *context, int reason, const char *message) {
-	flib_log_i("Disconnected: %s", message);
-	flib_netconn_destroy(*(flib_netconn**)context);
-	*(flib_netconn**)context = NULL;
-}
-
-void handleNetConnected(void *context) {
-	const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
-	flib_log_i("List of rooms:");
-	for(int i=0; i<roomlist->roomCount; i++) {
-		flib_roomlist_room *room = roomlist->rooms[i];
-		flib_log_i("%1s %20s %20s %2i %2i %20s %20s %20s", room->inProgress ? "X" : " ", room->name, room->owner, room->playerCount, room->teamCount, room->map, room->scheme, room->weapons);
-	}
-	flib_netconn_send_joinRoom(*(flib_netconn**)context, "frontlib test");
-}
-
-void handleLobbyJoin(void *context, const char *nick) {
-	flib_log_i("%s joined", nick);
-}
-
-void handleChat(void *context, const char *nick, const char *msg) {
-	flib_log_i("%s: %s", nick, msg);
-	if(!memcmp("frontbot ", msg, strlen("frontbot "))) {
-		const char *command = msg+strlen("frontbot ");
-		if(!memcmp("quit", command, strlen("quit"))) {
-			flib_netconn_send_quit(*(flib_netconn**)context, "Yeth Mathter");
-		} else if(!memcmp("describe ", command, strlen("describe "))) {
-			const char *roomname = command+strlen("describe ");
-			const flib_roomlist *roomlist = flib_netconn_get_roomlist(*(flib_netconn**)context);
-			flib_roomlist_room *room = flib_roomlist_find((flib_roomlist*)roomlist, roomname);
-			if(!room) {
-				flib_netconn_send_chat(*(flib_netconn**)context, "Unknown room.");
-			} else {
-				char *text = flib_asprintf(
-						"%s is a room created by %s, where %i players (%i teams) are %s on %s%s, using the %s scheme and %s weaponset.",
-						room->name,
-						room->owner,
-						room->playerCount,
-						room->teamCount,
-						room->inProgress ? "fighting" : "preparing to fight",
-						room->map[0]=='+' ? "" : "the map ",
-						!strcmp("+rnd+", room->map) ? "a random map" :
-								!strcmp("+maze+", room->map) ? "a random maze" :
-								!strcmp("+drawn+", room->map) ? "a hand-drawn map" :
-								room->map,
-						room->scheme,
-						room->weapons);
-				if(text) {
-					flib_netconn_send_chat(*(flib_netconn**)context, text);
-				}
-				free(text);
-			}
-		} else if(!memcmp("join ", command, strlen("join "))) {
-			const char *roomname = command+strlen("join ");
-			flib_netconn_send_joinRoom(*(flib_netconn**)context, roomname);
-		} else if(!memcmp("ready", command, strlen("ready"))) {
-			flib_netconn_send_toggleReady(*(flib_netconn**)context);
-		}
-	}
-}
-
-void handleEnterRoom(void *context, bool isChief) {
-	flib_netconn_send_toggleReady(*(flib_netconn**)context);
-}
-
-flib_gameconn *gameconn = NULL;
-
-void emFromNetHandler(void *context, const char *em, int size) {
-	flib_gameconn_send_enginemsg(gameconn, (const uint8_t*)em, size);
-}
-
-void emFromEngineHandler(void *context, const uint8_t *em, int size) {
-	flib_netconn_send_engineMessage((flib_netconn*)context, em, size);
-}
-
-void handleRunGame(void *context) {
-	flib_gamesetup *gamesetup = flib_netconn_create_gameSetup((flib_netconn*)context);
-	if(gamesetup) {
-		gameconn = flib_gameconn_create("frontbot", gamesetup, true);
-		flib_gameconn_onEngineMessage(gameconn, emFromEngineHandler, context);
-		flib_gameconn_onDisconnect(gameconn, onDisconnect, &gameconn);
-		startEngineGame(flib_gameconn_getport(gameconn));
-	}
-}
-
-int main(int argc, char *argv[]) {
-	flib_init(0);
-	flib_log_setLevel(FLIB_LOGLEVEL_ALL);
-
-	//testMapPreview();
-	//testDemo();
-	//testSave();
-	//testGame();
-
-	flib_cfg_meta *meta = flib_cfg_meta_from_ini("metasettings.ini");
-	assert(meta);
-	flib_netconn *conn = flib_netconn_create("frontbot", meta, "140.247.62.101", 46631);
-	assert(conn);
-	flib_cfg_meta_release(meta);
-
-	flib_netconn_onConnected(conn, handleNetConnected, &conn);
-	flib_netconn_onDisconnected(conn, handleNetDisconnect, &conn);
-	flib_netconn_onLobbyJoin(conn, handleLobbyJoin, &conn);
-	flib_netconn_onChat(conn, handleChat, &conn);
-	flib_netconn_onEnterRoom(conn, handleEnterRoom, conn);
-	flib_netconn_onRunGame(conn, handleRunGame, conn);
-	flib_netconn_onEngineMessage(conn, emFromNetHandler, NULL);
-
-	while(conn) {
-		flib_netconn_tick(conn);
-		if(gameconn) {
-			flib_gameconn_tick(gameconn);
-		}
-	}
-
-	flib_quit();
-	return 0;
-}
--- a/project_files/frontlib/util/buffer.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/buffer.c	Thu Jul 05 00:33:24 2012 +0200
@@ -79,8 +79,7 @@
 }
 
 int flib_vector_resize(flib_vector *vec, size_t newSize) {
-	if(!vec) {
-		flib_log_e("null parameter in flib_vector_resize");
+	if(log_badargs_if(vec==NULL)) {
 		return -1;
 	}
 
@@ -113,7 +112,7 @@
 }
 
 int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
-	if(!log_badparams_if(!vec || (!data && len>0))
+	if(!log_badargs_if2(vec==NULL, data==NULL && len>0)
 			&& !log_oom_if(len > SIZE_MAX-vec->size)) {
 		size_t oldSize = vec->size;
 		if(!log_oom_if(flib_vector_resize(vec, vec->size+len))) {
@@ -126,7 +125,7 @@
 
 int flib_vector_appendf(flib_vector *vec, const char *fmt, ...) {
 	int result = -1;
-	if(!log_badparams_if(!vec || !fmt)) {
+	if(!log_badargs_if2(vec==NULL, fmt==NULL)) {
 		va_list argp;
 		va_start(argp, fmt);
 		char *formatted = flib_vasprintf(fmt, argp);
@@ -142,8 +141,7 @@
 }
 
 flib_buffer flib_vector_as_buffer(flib_vector *vec) {
-	if(!vec) {
-		flib_log_e("null parameter in flib_vector_as_buffer");
+	if(log_badargs_if(vec==NULL)) {
 		flib_buffer result = {NULL, 0};
 		return result;
 	} else {
@@ -153,8 +151,7 @@
 }
 
 flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) {
-	if(!vec) {
-		flib_log_e("null parameter in flib_vector_as_constbuffer");
+	if(log_badargs_if(vec==NULL)) {
 		flib_constbuffer result = {NULL, 0};
 		return result;
 	} else {
@@ -164,8 +161,7 @@
 }
 
 void *flib_vector_data(flib_vector *vec) {
-	if(!vec) {
-		flib_log_e("null parameter in flib_vector_data");
+	if(log_badargs_if(vec==NULL)) {
 		return NULL;
 	} else {
 		return vec->data;
@@ -173,8 +169,7 @@
 }
 
 size_t flib_vector_size(flib_vector *vec) {
-	if(!vec) {
-		flib_log_e("null parameter in flib_vector_size");
+	if(log_badargs_if(vec==NULL)) {
 		return 0;
 	} else {
 		return vec->size;
--- a/project_files/frontlib/util/inihelper.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/inihelper.c	Thu Jul 05 00:33:24 2012 +0200
@@ -73,9 +73,7 @@
 
 flib_ini *flib_ini_load(const char *filename) {
 	flib_ini *result = NULL;
-	if(!filename) {
-		flib_log_e("null parameter in flib_ini_load");
-	} else {
+	if(!log_badargs_if(filename==NULL)) {
 		flib_ini *tmpIni = flib_calloc(1, sizeof(flib_ini));
 		if(tmpIni) {
 			tmpIni->inidict = iniparser_load(filename);
@@ -91,9 +89,7 @@
 
 int flib_ini_save(flib_ini *ini, const char *filename) {
 	int result = INI_ERROR_OTHER;
-	if(!ini || !filename) {
-		flib_log_e("null parameter in flib_ini_save");
-	} else {
+	if(!log_badargs_if2(ini==NULL, filename==NULL)) {
 		FILE *file = fopen(filename, "wb");
 		if(!file) {
 			flib_log_e("Error opening file \"%s\" for writing.", filename);
@@ -125,9 +121,7 @@
 		free(ini->currentSection);
 		ini->currentSection = NULL;
 	}
-	if(!ini || !section) {
-		flib_log_e("null parameter in flib_ini_enter_section");
-	} else {
+	if(!log_badargs_if2(ini==NULL, section==NULL)) {
 		if(!iniparser_find_entry(ini->inidict, section)) {
 			result = INI_ERROR_NOTFOUND;
 		} else {
@@ -145,9 +139,7 @@
 
 int flib_ini_create_section(flib_ini *ini, const char *section) {
 	int result = INI_ERROR_OTHER;
-	if(!ini || !section) {
-		flib_log_e("null parameter in flib_ini_create_section");
-	} else {
+	if(!log_badargs_if2(ini==NULL, section==NULL)) {
 		result = flib_ini_enter_section(ini, section);
 		if(result == INI_ERROR_NOTFOUND) {
 			if(iniparser_set(ini->inidict, section, NULL)) {
@@ -190,9 +182,7 @@
 
 int flib_ini_get_str_opt(flib_ini *ini, char **outVar, const char *key, const char *def) {
 	int result = INI_ERROR_OTHER;
-	if(!ini || !outVar || !key || !ini->currentSection) {
-		flib_log_e("null parameter or no current section in flib_ini_get_str_opt");
-	} else {
+	if(!log_badargs_if4(ini==NULL, ini->currentSection==NULL, outVar==NULL, key==NULL)) {
 		const char *value = findValue(ini->inidict, ini->currentSection, key);
 		if(!value) {
 			value = def;
@@ -266,9 +256,7 @@
 
 int flib_ini_set_str(flib_ini *ini, const char *key, const char *value) {
 	int result = INI_ERROR_OTHER;
-	if(!ini || !key || !value || !ini->currentSection) {
-		flib_log_e("null parameter or no current section in flib_ini_set_str");
-	} else {
+	if(log_badargs_if4(ini==NULL, ini->currentSection==NULL, key==NULL, value==NULL)) {
 		char *dictKey = createDictKey(ini->currentSection, key);
 		if(dictKey) {
 			result = iniparser_set(ini->inidict, dictKey, value);
@@ -293,40 +281,29 @@
 }
 
 int flib_ini_get_sectioncount(flib_ini *ini) {
-	int result = INI_ERROR_OTHER;
-	if(!ini) {
-		flib_log_e("null parameter in flib_ini_get_sectioncount");
-	} else {
-		result = iniparser_getnsec(ini->inidict);
+	if(!log_badargs_if(ini==NULL)) {
+		return iniparser_getnsec(ini->inidict);
 	}
-	return result;
+	return INI_ERROR_OTHER;
 }
 
 char *flib_ini_get_sectionname(flib_ini *ini, int number) {
-	char *result = NULL;
-	if(!ini || number<0) {
-		flib_log_e("bad parameter in flib_ini_get_sectionname");
-	} else {
-		result = flib_strdupnull(iniparser_getsecname(ini->inidict, number));
+	if(!log_badargs_if2(ini==NULL, number<0)) {
+		return flib_strdupnull(iniparser_getsecname(ini->inidict, number));
 	}
-	return result;
+	return NULL;
 }
 
 int flib_ini_get_keycount(flib_ini *ini) {
-	int result = INI_ERROR_OTHER;
-	if(!ini || !ini->currentSection) {
-		flib_log_e("null parameter or no current section in flib_ini_get_keycount");
-	} else {
-		result = iniparser_getsecnkeys(ini->inidict, ini->currentSection);
+	if(!log_badargs_if2(ini==NULL, ini->currentSection==NULL)) {
+		return iniparser_getsecnkeys(ini->inidict, ini->currentSection);
 	}
-	return result;
+	return INI_ERROR_OTHER;
 }
 
 char *flib_ini_get_keyname(flib_ini *ini, int number) {
 	char *result = NULL;
-	if(!ini || number<0 || !ini->currentSection) {
-		flib_log_e("bad parameter or no current section in flib_ini_get_keyname");
-	} else {
+	if(!log_badargs_if3(ini==NULL, ini->currentSection==NULL, number<0)) {
 		int keyCount = iniparser_getsecnkeys(ini->inidict, ini->currentSection);
 		char **keys = iniparser_getseckeys(ini->inidict, ini->currentSection);
 		if(keys && keyCount>number) {
--- a/project_files/frontlib/util/list.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/list.h	Thu Jul 05 00:33:24 2012 +0200
@@ -40,9 +40,7 @@
 #define GENERATE_STATIC_LIST_INSERT(fname, type) \
 	static int fname(type **listptr, int *listSizePtr, type element, int pos) { \
 		int result = -1; \
-		if(!listptr || !listSizePtr || pos < 0 || pos > *listSizePtr) { \
-			flib_log_e("Invalid parameter in "#fname); \
-		} else { \
+		if(!log_badargs_if4(listptr==NULL, listSizePtr==NULL, pos < 0, pos > *listSizePtr)) { \
 			type *newList = flib_realloc(*listptr, ((*listSizePtr)+1)*sizeof(type)); \
 			if(newList) { \
 				memmove(newList + (pos+1), newList + pos, ((*listSizePtr)-pos)*sizeof(type)); \
@@ -65,9 +63,7 @@
 #define GENERATE_STATIC_LIST_DELETE(fname, type) \
 	static int fname(type **listPtr, int *listSizePtr, int pos) { \
 		int result = -1; \
-		if(!listPtr || !listSizePtr || pos < 0 || pos >= *listSizePtr) { \
-			flib_log_e("Invalid parameter in "#fname); \
-		} else { \
+		if(!log_badargs_if4(listPtr==NULL, listSizePtr==NULL, pos < 0, pos >= *listSizePtr)) { \
 			memmove((*listPtr) + pos, (*listPtr) + (pos+1), ((*listSizePtr)-(pos+1))*sizeof(type)); \
 			(*listSizePtr)--; \
 			\
--- a/project_files/frontlib/util/logging.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/logging.c	Thu Jul 05 00:33:24 2012 +0200
@@ -92,10 +92,6 @@
 	return !cond;
 }
 
-bool _flib_assert_params(const char *func, bool cond) {
-	return _flib_fassert(func, FLIB_LOGLEVEL_ERROR, cond, "Invalid parameter to function");
-}
-
 int flib_log_getLevel() {
 	return flib_loglevel;
 }
--- a/project_files/frontlib/util/logging.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/logging.h	Thu Jul 05 00:33:24 2012 +0200
@@ -44,9 +44,31 @@
 #define log_w_if(cond, ...) _flib_fassert(__func__, FLIB_LOGLEVEL_WARNING, !(bool)(cond), __VA_ARGS__)
 
 /**
- * Shorthand for some common error types
+ * Helper macros for log_badargs_if
+ * The t parameters are the textual representation of the c parameters. They need to be passed
+ * explicitly, to prevent them from being expanded in prescan.
  */
-#define log_badparams_if(cond) log_e_if(cond, "Invalid Parameters")
+#define _flib_lbi(c1,t1) log_e_if(c1, "Invalid Argument (%s)", t1)
+#define _flib_lbi2(c1,t1,c2,t2) (_flib_lbi(c1,t1) || _flib_lbi(c2,t2))
+#define _flib_lbi3(c1,t1,c2,t2,c3,t3) (_flib_lbi(c1,t1) || _flib_lbi2(c2,t2,c3,t3))
+#define _flib_lbi4(c1,t1,c2,t2,c3,t3,c4,t4) (_flib_lbi(c1,t1) || _flib_lbi3(c2,t2,c3,t3,c4,t4))
+#define _flib_lbi5(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5) (_flib_lbi(c1,t1) || _flib_lbi4(c2,t2,c3,t3,c4,t4,c5,t5))
+#define _flib_lbi6(c1,t1,c2,t2,c3,t3,c4,t4,c5,t5,c6,t6) (_flib_lbi(c1,t1) || _flib_lbi5(c2,t2,c3,t3,c4,t4,c5,t5,c6,t6))
+
+/**
+ * These macros log an "Invalid Argument" error for the first of their arguments that evaluates to true.
+ * The text of the argument is included in the log message.
+ * The expression returns true if any of its arguments is true (i.e. if an argument error was logged).
+ *
+ * For example, log_badargs_if(x==NULL) will log "Invalid Argument (x==NULL)" and return true if x is NULL.
+ */
+#define log_badargs_if(c1) _flib_lbi(c1,#c1)
+#define log_badargs_if2(c1, c2) _flib_lbi2(c1,#c1,c2,#c2)
+#define log_badargs_if3(c1, c2, c3) _flib_lbi3(c1,#c1,c2,#c2,c3,#c3)
+#define log_badargs_if4(c1, c2, c3, c4) _flib_lbi4(c1,#c1,c2,#c2,c3,#c3,c4,#c4)
+#define log_badargs_if5(c1, c2, c3, c4, c5) _flib_lbi5(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5)
+#define log_badargs_if6(c1, c2, c3, c4, c5, c6) _flib_lbi6(c1,#c1,c2,#c2,c3,#c3,c4,#c4,c5,#c5,c6,#c6)
+
 #define log_oom_if(cond) log_e_if(cond, "Out of Memory")
 
 #define flib_log_e(...) _flib_flog(__func__, FLIB_LOGLEVEL_ERROR, __VA_ARGS__)
@@ -54,7 +76,6 @@
 #define flib_log_i(...) _flib_flog(__func__, FLIB_LOGLEVEL_INFO, __VA_ARGS__)
 #define flib_log_d(...) _flib_flog(__func__, FLIB_LOGLEVEL_DEBUG, __VA_ARGS__)
 
-bool _flib_assert_params(const char *func, bool cond);
 bool _flib_fassert(const char *func, int level, bool cond, const char *fmt, ...);
 void _flib_flog(const char *func, int level, const char *fmt, ...);
 
--- a/project_files/frontlib/util/refcounter.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/refcounter.c	Thu Jul 05 00:33:24 2012 +0200
@@ -22,9 +22,7 @@
 #include "logging.h"
 
 void flib_retain(int *referenceCountPtr, const char *objName) {
-	if(!referenceCountPtr || !objName) {
-		flib_log_e("null parameter to flib_retain");
-	} else {
+	if(!log_badargs_if2(referenceCountPtr==NULL, objName==NULL)) {
 		if((*referenceCountPtr)  >= 0) {
 			(*referenceCountPtr)++;
 			flib_log_d("retaining %s, now %i references", objName, (*referenceCountPtr));
@@ -40,17 +38,17 @@
  */
 bool flib_release(int *referenceCountPtr, const char *objName) {
 	bool result = false;
-	if(!referenceCountPtr) {
-		flib_log_e("null parameter to flib_release");
-	} else if((*referenceCountPtr) > 0) {
-		if(--(*referenceCountPtr) == 0) {
-			flib_log_d("releasing and destroying %s", objName);
-			result = true;
-		} else {
-			flib_log_d("releasing %s, now %i references", objName, (*referenceCountPtr));
+	if(!log_badargs_if2(referenceCountPtr==NULL, objName==NULL)) {
+		if((*referenceCountPtr) > 0) {
+			if(--(*referenceCountPtr) == 0) {
+				flib_log_d("releasing and destroying %s", objName);
+				result = true;
+			} else {
+				flib_log_d("releasing %s, now %i references", objName, *referenceCountPtr);
+			}
+		} else if((*referenceCountPtr) == 0) {
+			flib_log_e("Attempt to release a %s with zero references!", objName);
 		}
-	} else if((*referenceCountPtr) == 0) {
-		flib_log_e("Attempt to release a %s with zero references!", objName);
 	}
 	return result;
 }
--- a/project_files/frontlib/util/util.c	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/util.c	Thu Jul 05 00:33:24 2012 +0200
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <limits.h>
 
 char *flib_asprintf(const char *fmt, ...) {
 	va_list argp;
@@ -37,13 +38,9 @@
 
 char *flib_vasprintf(const char *fmt, va_list args) {
 	char *result = NULL;
-	if(!fmt) {
-		flib_log_e("null parameter in flib_vasprintf");
-	} else {
+	if(!log_badargs_if(fmt==NULL)) {
 		int requiredSize = vsnprintf(NULL, 0, fmt, args)+1;					// Figure out how much memory we need,
-		if(requiredSize<0) {
-			flib_log_e("Error formatting string with template \"%s\" in flib_vasprintf", fmt);
-		} else {
+		if(!log_e_if(requiredSize<0, "Error formatting string with template \"%s\"", fmt)) {
 			char *tmpbuf = flib_malloc(requiredSize);						// allocate it
 			if(tmpbuf && vsnprintf(tmpbuf, requiredSize, fmt, args)>=0) {	// and then do the actual formatting.
 				result = tmpbuf;
@@ -56,41 +53,41 @@
 }
 
 char *flib_join(char **parts, int partCount, const char *delimiter) {
-	size_t totalSize = 1;
-	size_t delimLen = strlen(delimiter);
-	for(int i=0; i<partCount; i++) {
-		totalSize += strlen(parts[i]) + delimLen;
-	}
+	char *result = NULL;
+	if(!log_badargs_if2(parts==NULL, delimiter==NULL)) {
+		size_t totalSize = 1;
+		size_t delimLen = strlen(delimiter);
+		for(int i=0; i<partCount; i++) {
+			totalSize += strlen(parts[i]) + delimLen;
+		}
+		result = flib_malloc(totalSize);
 
-	char *result = flib_malloc(totalSize);
-	if(result) {
-		size_t outpos = 0;
-		for(int i=0; i<partCount; i++) {
-			if(i>0) {
-				strcpy(result+outpos, delimiter);
-				outpos += delimLen;
+		if(result) {
+			size_t outpos = 0;
+			for(int i=0; i<partCount; i++) {
+				if(i>0) {
+					strcpy(result+outpos, delimiter);
+					outpos += delimLen;
+				}
+				strcpy(result+outpos, parts[i]);
+				outpos += strlen(parts[i]);
 			}
-			strcpy(result+outpos, parts[i]);
-			outpos += strlen(parts[i]);
 		}
 	}
 	return result;
 }
 
 char *flib_strdupnull(const char *str) {
-	if(!str) {
-		return NULL;
-	}
-	return flib_asprintf("%s", str);
+	return str==NULL ? NULL : flib_asprintf("%s", str);
 }
 
 void *flib_bufdupnull(const void *buf, size_t size) {
-	if(!buf || size==0) {
-		return NULL;
-	}
-	void *result = flib_malloc(size);
-	if(result) {
-		memcpy(result, buf, size);
+	void *result = NULL;
+	if(!log_badargs_if(buf==NULL && size>0)) {
+		result = flib_malloc(size);
+		if(result) {
+			memcpy(result, buf, size);
+		}
 	}
 	return result;
 }
@@ -127,41 +124,45 @@
 	return flib_urlencode_pred(inbuf, isAsciiAlnum);
 }
 
+static size_t countCharsToEscape(const char *inbuf, bool (*needsEscaping)(char c)) {
+	size_t result = 0;
+	for(const char *c=inbuf; *c; c++) {
+		if(needsEscaping(*c)) {
+			result++;
+		}
+	}
+	return result;
+}
+
 char *flib_urlencode_pred(const char *inbuf, bool (*needsEscaping)(char c)) {
+	char *result = NULL;
+	if(inbuf && !log_badargs_if(needsEscaping == NULL)) {
+		size_t insize = strlen(inbuf);
+		if(!log_e_if(insize > SIZE_MAX/4, "String too long: %zu bytes.", insize)) {
+			size_t escapeCount = countCharsToEscape(inbuf, needsEscaping);
+			result = flib_malloc(insize + escapeCount*2 + 1);
+		}
+		if(result) {
+			char *out = result;
+			for(const char *in = inbuf; *in; in++) {
+				if(!needsEscaping(*in)) {
+					*out = *in;
+					out++;
+				} else {
+					snprintf(out, 4, "%%%02x", (unsigned)(*(uint8_t*)in));
+					out += 3;
+				}
+			}
+			*out = 0;
+		}
+	}
+	return result;
+}
+
+char *flib_urldecode(const char *inbuf) {
 	if(!inbuf) {
 		return NULL;
 	}
-	size_t insize = strlen(inbuf);
-	if(insize > SIZE_MAX/4) {
-		flib_log_e("String too long in flib_urlencode: %zu bytes.", insize);
-		return NULL;
-	}
-
-	char *outbuf = flib_malloc(insize*3+1);
-	if(!outbuf) {
-		return NULL;
-	}
-
-    size_t inpos = 0, outpos = 0;
-    while(inbuf[inpos]) {
-        if(!needsEscaping(inbuf[inpos])) {
-        	outbuf[outpos++] = inbuf[inpos++];
-        } else {
-            if(snprintf(outbuf+outpos, 4, "%%%02X", (unsigned)((uint8_t*)inbuf)[inpos])<0) {
-            	flib_log_e("printf error in flib_urlencode");
-            	free(outbuf);
-            	return NULL;
-            }
-            inpos++;
-            outpos += 3;
-        }
-    }
-    outbuf[outpos] = 0;
-    char *shrunk = realloc(outbuf, outpos+1);
-    return shrunk ? shrunk : outbuf;
-}
-
-char *flib_urldecode(const char *inbuf) {
 	char *outbuf = flib_malloc(strlen(inbuf)+1);
 	if(!outbuf) {
 		return NULL;
@@ -183,7 +184,7 @@
 }
 
 bool flib_contains_dir_separator(const char *str) {
-	if(!log_badparams_if(!str)) {
+	if(!log_badargs_if(!str)) {
 		for(;*str;str++) {
 			if(*str=='\\' || *str=='/') {
 				return true;
@@ -193,6 +194,10 @@
 	return false;
 }
 
+bool flib_strempty(const char *str) {
+	return !str || !*str;
+}
+
 int flib_gets(char *str, size_t strlen) {
 	if(fgets(str, strlen, stdin)) {
 		for(char *s=str; *s; s++) {
--- a/project_files/frontlib/util/util.h	Wed Jun 27 22:52:19 2012 +0200
+++ b/project_files/frontlib/util/util.h	Thu Jul 05 00:33:24 2012 +0200
@@ -112,6 +112,11 @@
  */
 bool flib_contains_dir_separator(const char *str);
 
+/**
+ * Returns true if str is either NULL or points to a 0-length string
+ */
+bool flib_strempty(const char *str);
+
 int flib_gets(char *str, size_t strlen);
 
 #endif