#include <stdio.h>
+#include <stdlib.h>
 #include <glib.h>
 #include "xmlparser.h"
 
@@ -19,8 +20,8 @@ XmlTag xml_tag_new(XmlTag parent) { 
     tag->children = g_array_new(FALSE, FALSE, sizeof(XmlTag));
     tag->parent = parent;
     tag->value = g_string_new(NULL);
-    tag->attributes = g_malloc(sizeof(GData *));
-    g_datalist_init(tag->attributes);
+    //tag->attributes = g_malloc(sizeof(GData *));
+    //g_datalist_init(tag->attributes);
 
     return tag;
 }
@@ -32,8 +33,22 @@ void xml_tag_free(XmlTag tag) { 
     g_string_free(tag->name, TRUE);
     g_array_free(tag->children, TRUE);
     g_string_free(tag->value, TRUE);
-    g_dataset_destroy(tag->attributes);
+    //g_dataset_destroy(tag->attributes);
+    //g_free(tag->attributes);
     g_free(tag);
+    return;
+}
+
+// Frees an entire tree of XmlTags
+// Arguments:
+// * root: the root of the tree you wish to free
+void xml_tree_free(XmlTag root) {
+    int i;
+    for (i = 0; i < root->children->len; i++) {
+        xml_tree_free(g_array_index(root->children, XmlTag, i));
+    }
+    xml_tag_free(root);
+    return;
 }
 
 void xml_print_tree_helper(XmlTag tag) {
@@ -52,16 +67,18 @@ void xml_print_tree_helper(XmlTag tag) { 
         xml_print_tree_helper(g_array_index(tag->children, XmlTag, i));
     }
     depth--;
+    return;
 }
 
 // Prints the tag tree
 // Arguments:
 // * tag: This should be the root of the tree, and it won't be printed.
-void xml_print_tree(XmlTag tag) {
+void xml_tree_print(XmlTag tag) {
     int i;
     for (i = 0; i < tag->children->len; i++) {
         xml_print_tree_helper(g_array_index(tag->children, XmlTag, i));
     }
+    return;
 }
 
 // Strips whitespace from a GString
@@ -72,7 +89,7 @@ void xml_print_tree(XmlTag tag) { 
 //  or if string was NULL, the amount of whitespace stripped off the
 //  beginning of the last stripped string.
 int g_string_strip(GString *string) {
-    static int i;
+    static int i = 0;
     if (string == NULL) {
         return i;
     }
@@ -100,8 +117,9 @@ int g_string_strip(GString *string) { 
 // * message: the error message to print
 // * line: the line at which the error occurred
 // * col: the column at which the error occurred
-void xml_error(const char *message, int line, int col) {
-    printf("ERROR (%d,%d): %s\n", line, col + g_string_strip(NULL) + 1, message);
+void xml_error(const char *message, unsigned int line, int col) {
+    printf("ERROR (%u,%d): %s\n", line, col + g_string_strip(NULL) + 1, message);
+    return;
 }
 
 // Checks a tag for validity
@@ -112,7 +130,7 @@ void xml_error(const char *message, int line, int col) { 
 // Returns:
 // TRUE if the tag has a nonzero length name
 // FALSE if the tag has a zero length name
-gboolean check_tag(XmlTag tag, int line, int col) {
+gboolean xml_tag_check(XmlTag tag, int line, int col) {
     if (tag->name->len == 0) {
         XML_STATUS = XML_UNNAMED_TAG;
         xml_error(XML_E_UNNAMED_TAG, line, col);
@@ -123,6 +141,7 @@ gboolean check_tag(XmlTag tag, int line, int col) { 
 
 // This will parse the tagname to extract attributes from it
 void xml_tag_parse_attributes(XmlTag tag) {
+    return;
 }
 
 // Parses an XML file
@@ -150,7 +169,7 @@ XmlTag xml_parse(char *path_to_file) { 
     gboolean escape = FALSE;
     
     int i;
-    int line = 1;
+    unsigned int line = 1;
     char c;
     while (g_io_channel_read_line_string(input, buffer, NULL, NULL) == G_IO_STATUS_NORMAL) {
         g_string_strip(buffer);
@@ -164,26 +183,40 @@ XmlTag xml_parse(char *path_to_file) { 
                         break;
                     }
                 case '<':
-                    if (opentag) {
-                        XML_STATUS = XML_INVALID_CHAR;
-                        xml_error(XML_E_INVALID_CHAR, line, i);
-                        return NULL;
+                    if (!escape) {
+                        if (opentag) {
+                            XML_STATUS = XML_INVALID_CHAR;
+                            xml_error(XML_E_INVALID_CHAR, line, i);
+                            g_string_free(buffer, TRUE);
+                            g_io_channel_shutdown(input, TRUE, NULL);
+                            g_io_channel_unref(input);
+                            xml_tree_free(head);
+                            return NULL;
+                        }
+                        opentag = TRUE;
+                        currenttag = xml_tag_new(currenttag);
+                        g_array_append_val(currenttag->parent->children, currenttag);
+                        break;
                     }
-                    opentag = TRUE;
-                    currenttag = xml_tag_new(currenttag);
-                    g_array_append_val(currenttag->parent->children, currenttag);
-                    break;
                 case '>':
                     if (opentag) opentag = FALSE;
                     else {
                         XML_STATUS = XML_INVALID_CLOSING;
                         xml_error(XML_E_INVALID_CLOSING, line, i);
+                        g_string_free(buffer, TRUE);
+                        g_io_channel_shutdown(input, TRUE, NULL);
+                        g_io_channel_unref(input);
+                        xml_tree_free(head);
                         return NULL;
                     }
                     if (g_str_has_prefix(currenttag->name->str, "/")) {
                         if (g_strcmp0(currenttag->name->str + 1, currenttag->parent->name->str)) {
                             XML_STATUS = XML_INVALID_CLOSING;
                             xml_error(XML_E_INVALID_CLOSING, line, i-currenttag->name->len - 1);
+                            g_string_free(buffer, TRUE);
+                            g_io_channel_shutdown(input, TRUE, NULL);
+                            g_io_channel_unref(input);
+                            xml_tree_free(head);
                             return NULL;
                         }
                         g_array_remove_index(currenttag->parent->children, currenttag->parent->children->len-1);
@@ -192,12 +225,20 @@ XmlTag xml_parse(char *path_to_file) { 
                         xml_tag_free(temp);
                     } else if (g_str_has_suffix(currenttag->name->str, " /")) {
                         g_string_truncate(currenttag->name, currenttag->name->len - 2);
-                        if (!check_tag(currenttag, line, i)) {
+                        if (!xml_tag_check(currenttag, line, i)) {
+                            g_string_free(buffer, TRUE);
+                            g_io_channel_shutdown(input, TRUE, NULL);
+                            g_io_channel_unref(input);
+                            xml_tree_free(head);
                             return NULL;
                         }
                         currenttag = currenttag->parent;
                     } else {
-                        if (!check_tag(currenttag, line, i)) {
+                        if (!xml_tag_check(currenttag, line, i)) {
+                            g_string_free(buffer, TRUE);
+                            g_io_channel_shutdown(input, TRUE, NULL);
+                            g_io_channel_unref(input);
+                            xml_tree_free(head);
                             return NULL;
                         }
                     }
@@ -206,6 +247,10 @@ XmlTag xml_parse(char *path_to_file) { 
                     if (currenttag == head) {
                         XML_STATUS = XML_VALUE_NO_PARENT;
                         xml_error(XML_E_VALUE_NO_PARENT, line, i);
+                        g_string_free(buffer, TRUE);
+                        g_io_channel_shutdown(input, TRUE, NULL);
+                        g_io_channel_unref(input);
+                        xml_tree_free(head);
                         return NULL;
                     }
                     if (opentag) {
@@ -221,8 +266,15 @@ XmlTag xml_parse(char *path_to_file) { 
     if (currenttag != head) {
         XML_STATUS = XML_UNCLOSED_TAGS;
         xml_error(XML_E_UNCLOSED_TAGS, 0, 0);
+        g_string_free(buffer, TRUE);
+        g_io_channel_shutdown(input, TRUE, NULL);
+        g_io_channel_unref(input);
+        xml_tree_free(head);
         return NULL;
     }
 
+    g_string_free(buffer, TRUE);
+    g_io_channel_shutdown(input, TRUE, NULL);
+    g_io_channel_unref(input);
     return head;
 }