#include <xml/addsnode.h>
#include <xml/nextpcre.h>
#include <string.h>
#include <pcre.h>

#define ___ {
#define ____ }

gboolean
xml_pcre_match_add9 (gchar* text, gssize off, gssize end, 
		     const gchar* txtRE, xml_GNode* tree, const gchar* names[])
{
    if (! txtRE || ! *txtRE || !strcmp (txtRE, "*"))
	return TRUE;
    if (! text || off == end)
	return FALSE;

    ___ pcre* regex; const char* errmsg; int erridx; int ovector[33];
    if (*txtRE == '*' || *txtRE == '+') 
        regex = pcre_compile (txtRE+1, 0, &errmsg, &erridx, 0);
    else if (*txtRE == '?' || *txtRE == '^')
        regex = pcre_compile (txtRE+1, PCRE_ANCHORED, &errmsg, &erridx, 0);
    else
        regex = pcre_compile (txtRE, PCRE_ANCHORED, &errmsg, &erridx, 0);

   if (0< pcre_exec (regex, 0, text, end, 
		      off, PCRE_NOTEMPTY, ovector, 33 ))
    
{
	if (*txtRE == '*' || *txtRE == '+' || ovector[1] == end)
        
{
            xml_tree_add9 (tree, ovector, names);
	    pcre_free (regex);
	    return TRUE;
	}
}
pcre_free (regex); return FALSE; ____; }
gboolean
xml_pcre_match_adds9 (gchar* text, gssize off, gssize end, 
                          const gchar* txtRE, 
                          xml_GNode* tree, const gchar* names[])
{
    if (! txtRE || ! *txtRE || !strcmp (txtRE, "*"))
	return TRUE;
    if (! text || off == end)
	return FALSE;

    ___ pcre* regex; const char* errmsg; int erridx; int ovector[33];
    if (*txtRE == '*' || *txtRE == '+') 
        regex = pcre_compile (txtRE+1, 0, &errmsg, &erridx, 0);
    else if (*txtRE == '?' || *txtRE == '^') 
        regex = pcre_compile (txtRE+1, PCRE_ANCHORED, &errmsg, &erridx, 0);
    else
        regex = pcre_compile (txtRE, PCRE_ANCHORED, &errmsg, &erridx, 0);

    if (0< pcre_exec (regex, 0, text, end, 
		      off, PCRE_NOTEMPTY, ovector, 33 ))
    
{
	if (*txtRE == '*' || *txtRE == '+' || ovector[1] == end)
	
{
            xml_tree_adds9 (tree, ovector, names);
	    pcre_free (regex);
	    return TRUE;
	}
}
pcre_free (regex); return FALSE; ____; }
/* __________ */
gboolean
xml_pcre_match1 (gchar* text, gssize off, gssize end, const gchar* txtRE)
{
    if (! txtRE || ! *txtRE || !strcmp (txtRE, "*"))
	return TRUE;
    if (! text || off == end)
	return FALSE;

    ___ pcre* regex; const char* errmsg; int erridx; int ovector[33];
    if (*txtRE == '*' || *txtRE == '+') 
        regex = pcre_compile (txtRE+1, 0, &errmsg, &erridx, 0);
    else if (*txtRE == '?' || *txtRE == '^') 
        regex = pcre_compile (txtRE+1, PCRE_ANCHORED, &errmsg, &erridx, 0);
    else
        regex = pcre_compile (txtRE, PCRE_ANCHORED, &errmsg, &erridx, 0);

    if (0< pcre_exec (regex, 0, text+off, end-off, 
		      0, PCRE_NOTEMPTY, ovector, 33 ))
    
{
	if (*txtRE == '*' || *txtRE == '+' || ovector[1] == end-off)
	
{
	    pcre_free (regex);
	    return TRUE;
	}
}
pcre_free (regex); return FALSE; ____; }
/* a.k.a. xml_pcre_match_or_empty */
gboolean
xml_pcre_match0 (gchar* text, gssize off, gssize end, const gchar* txtRE)
{
    if (! text || off == end)
	return TRUE;
    return xml_pcre_match1 (text, off, end, txtRE);
}
gboolean
xml_pcre_contains (xml_GNode* node, const gchar* keyRE, const gchar* txtRE)
{
    if (! node || !node->text)
	return FALSE;
    if (! xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
	return FALSE;
    return xml_pcre_match1 (
        node->text->str, node->off, node->end, txtRE);
}
gboolean
xml_pcre_followedby (xml_GNode* node, const gchar* keyRE, const gchar* txtRE)
{
    if (! node || !node->text || !node->name || !node->next)
	return FALSE;
    if (! xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
	return FALSE;
    return xml_pcre_match1 (
        node->text->str, node->end, node->next->off, txtRE);
}
gboolean
xml_pcre_contains0 (xml_GNode* node, const gchar* keyRE, const gchar* txtRE)
{
    if (! node || !node->text)
	return FALSE;
    if (keyRE && ! xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
	return FALSE;
    return xml_pcre_match0 (
        node->text->str, node->off, node->end, txtRE);
}
gboolean
xml_pcre_followedby0 (xml_GNode* node, const gchar* keyRE, const gchar* txtRE)
{
    if (! node || !node->text || !node->name || !node->next)
	return FALSE;
    if (keyRE && ! xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
	return FALSE;
    return xml_pcre_match0 (
        node->text->str, node->end, node->next->off, txtRE);
}
gboolean
xml_pcre_hasnextnode (xml_GNode* node, const gchar* keyRE)
{
    if (! node || !node->next)
	return FALSE;
    if (keyRE && ! xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
	return FALSE;
    return TRUE;
}
xml_GNode*
xml_pcre_next_with_name (xml_GNode* node, const gchar* keyRE)
{
    if (! node) return node;
    if (! keyRE) return node->next;
 again:
    node = node->next;
    if (! node) return node;
    if (xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
        return node;
    goto again;
}
xml_GNode*
xml_pcre_next_or_last (xml_GNode* node, const gchar* keyRE)
{
    if (! node) return node;
    if (! keyRE) return node->next;
 again:
    node = node->next;
    if (! node || ! node->next) return node;
    if (xml_pcre_match1 (
            node->name, 0, strlen (node->name), keyRE))
        return node;
    goto again;
}
/* 
   Local variables:
   c-file-style: "stroustrup"
   End:
 */