#include <xml/gerror.h>
#include <xml/from-xml.h>
#include <xml/attrnode.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <string.h>
#include <errno.h>

#define ___ {
#define ____ }

/**
   returns null on error and sets error info
 */
xml_GNode*
xml_g_markup_parse_file (const xml_GNode* mine, 
			 const gchar* filename, GError** error)
{
    int e;
    xml_GNode* node = 0;
    int f;
    f = open (filename, O_RDONLY);
    if (f < 0) goto _could_not_open_file_;
    ___ struct stat st;
    e = fstat (f, &st);
    if (e < 0) goto _could_not_stat_file_;
    ___ void* p = mmap (0, st.st_size, PROT_READ, MAP_SHARED, f, 0);
    if (p == MAP_FAILED) goto _could_not_mmap_file_;
    node = xml_g_markup_parse_text (mine, p, 0, st.st_size, filename, error);
 _unmap_:
    munmap (p, st.st_size);
    ____;____;
 _close_:
    close (f);
 _return_:
    return node;
 _could_not_open_file_:
    xml_g_set_error (error, errno, "could not open file: '%s': %s", 
		     filename, g_strerror(errno));
    goto _return_;
 _could_not_stat_file_:
    xml_g_set_error (error, errno, "could not stat file: '%s': %s", 
		     filename, g_strerror(errno));
    goto _close_;
 _could_not_mmap_file_:
    xml_g_set_error (error, errno, "could not mmap file: '%s': %s", 
		     filename, g_strerror(errno));
    goto _unmap_;
}
xml_GNode*
xml_tree_node_from_text (const xml_GNode* mine, 
			 const gchar* text, gsize off, gsize end,
			 const gchar* rootfilename)
{
    if (mine && ! mine->text) return 0;
    ___ xml_GNode* node = xml_g_node_new_data (":"); 
    if (rootfilename)
	xml_node_attribute_add (node, "filename", rootfilename);
    if (! mine)
    
{ /* node->off = 0; */
	node->text = g_string_new_len (text+off, end-off);
    }
else
{
	node->off = mine->text->len;
	node->text = g_string_append_len (mine->text, text+off, end-off);
    }
; node->end = node->text->len; return node; ____; }
/**
   returns null on error and sets error info
 */
xml_GNode*
xml_tree_node_from_file (const xml_GNode* mine, 
			 const gchar* file, GError** error)
{
    int e;
    xml_GNode* node = 0;
    if (mine && !mine->text) goto _mine_without_text;
    ___ int f;
    f = open (file, O_RDONLY);
    if (f < 0) goto _could_not_open_file_;
    ___ struct stat st;
    e = fstat (f, &st);
    if (e < 0) goto _could_not_stat_file_;
    ___ void* p = mmap (0, st.st_size, PROT_READ, MAP_SHARED, f, 0);
    if (p == MAP_FAILED) goto _could_not_mmap_file_;
    node = xml_tree_node_from_text (mine, p, 0, st.st_size, file);
    if (node->end - node->off != st.st_size) goto _incomplete_read;
 _unmap_:
    munmap (p, st.st_size);
    ____;____;
 _close_:
    close (f);
    ____;
 _return_:
    return node;
 _mine_without_text:
    xml_g_set_error (error, 0, "elder node without text, a bug?");
    goto _return_;
 _could_not_open_file_:
    xml_g_set_error (error, errno, "could not open file: '%s': %s", 
		     file, g_strerror(errno));
    goto _return_;
 _could_not_stat_file_:
    xml_g_set_error (error, errno, "could not stat file: '%s': %s", 
		     file, g_strerror(errno));
    goto _close_;
 _could_not_mmap_file_:
    xml_g_set_error (error, errno, "could not mmap file: '%s': %s", 
		     file, g_strerror(errno));
    goto _unmap_;
 _incomplete_read:
    xml_g_set_error (error, 0, "could not append file '%s' entirely (OOM?)", 
		     file);
    goto _unmap_;
}
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */