Added X-Macros example.
Simplified INIReaderTest.cpp.
diff --git a/cpp/INIReaderTest.cpp b/cpp/INIReaderTest.cpp
index d0dc0af..bc1415d 100644
--- a/cpp/INIReaderTest.cpp
+++ b/cpp/INIReaderTest.cpp
@@ -1,25 +1,19 @@
-// INIReader.h example that shows simple usage of the INIReader class
+// Example that shows simple usage of the INIReader class
 
 #include <iostream>
 #include "INIReader.h"
 
-using std::cout;
-
 int main()
 {
     INIReader reader("../examples/test.ini");
 
     if (reader.ParseError() < 0) {
-        cout << "Couldn't read INI file!\n";
+        std::cout << "Can't load 'test.ini'\n";
         return 1;
     }
-
-    cout << "Valid config:";
-    cout << " user_name='" << reader.Get("user", "name", "UNKNOWN") << "'";
-    cout << " user_email='" << reader.Get("user", "email", "UNKNOWN") << "'";
-    cout << " protocol_version="
-         << reader.GetInteger("protocol", "version", -1);
-    cout << "\n";
-
+    std::cout << "Config loaded from 'test.ini': version="
+              << reader.GetInteger("protocol", "version", -1) << ", name="
+              << reader.Get("user", "name", "UNKNOWN") << ", email="
+              << reader.Get("user", "email", "UNKNOWN") << "\n";
     return 0;
 }
diff --git a/examples/config.def b/examples/config.def
new file mode 100644
index 0000000..f5c7ed5
--- /dev/null
+++ b/examples/config.def
@@ -0,0 +1,8 @@
+// CFG(section, name, default)

+

+CFG(protocol, version, "0")

+

+CFG(user, name, "Fatty Lumpkin")

+CFG(user, email, "fatty@lumpkin.com")

+

+#undef CFG

diff --git a/examples/ini_xmacros.c b/examples/ini_xmacros.c
new file mode 100644
index 0000000..f2b7285
--- /dev/null
+++ b/examples/ini_xmacros.c
@@ -0,0 +1,46 @@
+/* Parse a configuration file into a struct using X-Macros */
+
+#include <stdio.h>
+#include <string.h>
+#include "../ini.h"
+
+/* define the config struct type */
+typedef struct {
+    #define CFG(s, n, default) char *s##_##n;
+    #include "config.def"
+} config;
+
+/* create one and fill in its default values */
+config Config = {
+    #define CFG(s, n, default) default,
+    #include "config.def"
+};
+
+/* process a line of the INI file, storing valid values into config struct */
+int handler(void *user, const char *section, const char *name,
+            const char *value)
+{
+    config *cfg = (config *)user;
+
+    if (0) ;
+    #define CFG(s, n, default) else if (stricmp(section, #s)==0 && \
+        stricmp(name, #n)==0) cfg->s##_##n = strdup(value);
+    #include "config.def"
+
+    return 1;
+}
+
+/* print all the variables in the config, one per line */
+void dump_config(config *cfg)
+{
+    #define CFG(s, n, default) printf("%s_%s = %s\n", #s, #n, cfg->s##_##n);
+    #include "config.def"
+}
+
+int main(int argc, char* argv[])
+{
+    if (ini_parse("test.ini", handler, &Config) < 0)
+        printf("Can't load 'test.ini', using defaults\n");
+    dump_config(&Config);
+    return 0;
+}