/* ====================================================================
* The Kannel Software License, Version 1.0
*
* Copyright (c) 2001-2005 Kannel Group
* Copyright (c) 1998-2001 WapIT Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Kannel Group (http://www.kannel.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Kannel" and "Kannel Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please
* contact org@kannel.org.
*
* 5. Products derived from this software may not be called "Kannel",
* nor may "Kannel" appear in their name, without prior written
* permission of the Kannel Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Kannel Group. For more information on
* the Kannel Group, please see .
*
* Portions of this software are based upon software originally written at
* WapIT Ltd., Helsinki, Finland for the Kannel project.
*/
/*
* decompile.c - A program to test the WML compiler. This tool was written
* from the WBXML 1.2 and WML 1.1 specs.
*
* Author: Chris Wulff, Vanteon (cwulff@vanteon.com)
*
*/
#include
#include
#include
#include
#include "decompile.h"
const WBXML_MB_U_INT32 ZERO_WBXML_MB_U_INT32 = {0,0,0,0};
long dtd_id;
#define INDENT_SIZE 4
DTD_TYPE_LIST DTDTypeList[] =
{
{1, "UNKNOWN"},
{2, "-//WAPFORUM//DTD WML 1.0//EN\"\n"
"\"http://www.wapforum.org/DTD/wml.xml"},
{3, "-//WAPFORUM//DTD WTA 1.0//EN"},
{4, "-//WAPFORUM//DTD WML 1.1//EN\"\n"
"\"http://www.wapforum.org/DTD/wml_1.1.xml"},
{5, "-//WAPFORUM//DTD SI 1.0//EN\"\n"
"\"http://www.wapforum.org/DTD/si.dtd"},
{6, "-//WAPFORUM//DTD SL 1.0//EN\"\n"
"\"http://www.wapforum.org/DTD/sl.dtd"},
{7, "-//WAPFORUM//DTD CO 1.0//EN"},
{8, "-//WAPFORUM//DTD CHANNEL 1.1//EN"},
{9, "-//WAPFORUM//DTD WML 1.2//EN\"\n"
"\"http://www.wapforum.org/DTD/wml12.dtd"},
{0, NULL}
};
/**************************************
* DTD Public Type 4 (WML 1.1) Tables *
**************************************/
CODEPAGE_TAG_NAME_LIST CodepageTagNames[] =
{
{4, "a", 0, 0x1c},
{4, "anchor", 0, 0x22},
{4, "access", 0, 0x23},
{4, "b", 0, 0x24},
{4, "big", 0, 0x25},
{4, "br", 0, 0x26},
{4, "card", 0, 0x27},
{4, "do", 0, 0x28},
{4, "em", 0, 0x29},
{4, "fieldset", 0, 0x2a},
{4, "go", 0, 0x2b},
{4, "head", 0, 0x2c},
{4, "i", 0, 0x2d},
{4, "img", 0, 0x2e},
{4, "input", 0, 0x2f},
{4, "meta", 0, 0x30},
{4, "noop", 0, 0x31},
{4, "p", 0, 0x20},
{4, "postfield", 0, 0x21},
{4, "pre", 0, 0x1b},
{4, "prev", 0, 0x32},
{4, "onevent", 0, 0x33},
{4, "optgroup", 0, 0x34},
{4, "option", 0, 0x35},
{4, "refresh", 0, 0x36},
{4, "select", 0, 0x37},
{4, "setvar", 0, 0x3e},
{4, "small", 0, 0x38},
{4, "strong", 0, 0x39},
{4, "table", 0, 0x1f},
{4, "td", 0, 0x1d},
{4, "template", 0, 0x3b},
{4, "timer", 0, 0x3c},
{4, "tr", 0, 0x1e},
{4, "u", 0, 0x3d},
{4, "wml", 0, 0x3f},
{6, "TAG_05", 1, 0x05},
{6, "TAG_06", 1, 0x06},
{6, "TAG_07", 1, 0x07},
{0, NULL, 0, 0}
};
CODEPAGE_ATTRSTART_NAME_LIST CodepageAttrstartNames[] =
{
{4, "accept-charset", NULL, 0, 0x05},
{4, "accesskey", NULL, 0, 0x5e},
{4, "align", NULL, 0, 0x52},
{4, "align", "bottom", 0, 0x06},
{4, "align", "center", 0, 0x07},
{4, "align", "left", 0, 0x08},
{4, "align", "middle", 0, 0x09},
{4, "align", "right", 0, 0x0a},
{4, "align", "top", 0, 0x0b},
{4, "alt", NULL, 0, 0x0c},
{4, "class", NULL, 0, 0x54},
{4, "columns", NULL, 0, 0x53},
{4, "content", NULL, 0, 0x0d},
{4, "content", "application/vnd.wap.wmlc;charset=", 0, 0x5c},
{4, "domain", NULL, 0, 0x0f},
{4, "emptyok", "false", 0, 0x10},
{4, "emptyok", "true", 0, 0x11},
{4, "enctype", NULL, 0, 0x5f},
{4, "enctype", "application/x-www-form-urlencoded", 0, 0x60},
{4, "enctype", "multipart/form-data", 0, 0x61},
{4, "format", NULL, 0, 0x12},
{4, "forua", "false", 0, 0x56},
{4, "forua", "true", 0, 0x57},
{4, "height", NULL, 0, 0x13},
{4, "href", NULL, 0, 0x4a},
{4, "href", "http://", 0, 0x4b},
{4, "href", "https://", 0, 0x4c},
{4, "hspace", NULL, 0, 0x14},
{4, "http-equiv", NULL, 0, 0x5a},
{4, "http-equiv", "Content-Type", 0, 0x5b},
{4, "http-equiv", "Expires", 0, 0x5d},
{4, "id", NULL, 0, 0x55},
{4, "ivalue", NULL, 0, 0x15},
{4, "iname", NULL, 0, 0x16},
{4, "label", NULL, 0, 0x18},
{4, "localsrc", NULL, 0, 0x19},
{4, "maxlength", NULL, 0, 0x1a},
{4, "method", "get", 0, 0x1b},
{4, "method", "post", 0, 0x1c},
{4, "mode", "nowrap", 0, 0x1d},
{4, "mode", "wrap", 0, 0x1e},
{4, "multiple", "false", 0, 0x1f},
{4, "multiple", "true", 0, 0x20},
{4, "name", NULL, 0, 0x21},
{4, "newcontext", "false", 0, 0x22},
{4, "newcontext", "true", 0, 0x23},
{4, "onenterbackward", NULL, 0, 0x25},
{4, "onenterforward", NULL, 0, 0x26},
{4, "onpick", NULL, 0, 0x24},
{4, "ontimer", NULL, 0, 0x27},
{4, "optional", "false", 0, 0x28},
{4, "optional", "true", 0, 0x29},
{4, "path", NULL, 0, 0x2a},
{4, "scheme", NULL, 0, 0x2e},
{4, "sendreferer", "false", 0, 0x2f},
{4, "sendreferer", "true", 0, 0x30},
{4, "size", NULL, 0, 0x31},
{4, "src", NULL, 0, 0x32},
{4, "src", "http://", 0, 0x58},
{4, "src", "https://", 0, 0x59},
{4, "ordered", "true", 0, 0x33},
{4, "ordered", "false", 0, 0x34},
{4, "tabindex", NULL, 0, 0x35},
{4, "title", NULL, 0, 0x36},
{4, "type", NULL, 0, 0x37},
{4, "type", "accept", 0, 0x38},
{4, "type", "delete", 0, 0x39},
{4, "type", "help", 0, 0x3a},
{4, "type", "password", 0, 0x3b},
{4, "type", "onpick", 0, 0x3c},
{4, "type", "onenterbackward", 0, 0x3d},
{4, "type", "onenterforward", 0, 0x3e},
{4, "type", "ontimer", 0, 0x3f},
{4, "type", "options", 0, 0x45},
{4, "type", "prev", 0, 0x46},
{4, "type", "reset", 0, 0x47},
{4, "type", "text", 0, 0x48},
{4, "type", "vnd.", 0, 0x49},
{4, "value", NULL, 0, 0x4d},
{4, "vspace", NULL, 0, 0x4e},
{4, "width", NULL, 0, 0x4f},
{4, "xml:lang", NULL, 0, 0x50},
{6, "ATTR_06", NULL, 1, 0x06},
{6, "ATTR_07", NULL, 1, 0x07},
{6, "ATTR_08", NULL, 1, 0x08},
{6, "ATTR_11", NULL, 1, 0x11},
{6, "ATTR_12", NULL, 1, 0x12},
{6, "ATTR_13", NULL, 1, 0x13},
{6, "ATTR_14", NULL, 1, 0x14},
{6, "ATTR_15", NULL, 1, 0x15},
{6, "ATTR_21", NULL, 1, 0x21},
{6, "ATTR_22", NULL, 1, 0x22},
{6, "ATTR_23", NULL, 1, 0x23},
{6, "ATTR_24", NULL, 1, 0x24},
{6, "ATTR_28", NULL, 1, 0x28},
{6, "ATTR_29", NULL, 1, 0x29},
{6, "ATTR_45", NULL, 1, 0x45},
{6, "ATTR_61", NULL, 1, 0x61},
{6, "ATTR_62", NULL, 1, 0x62},
{6, "ATTR_63", NULL, 1, 0x63},
{6, "ATTR_64", NULL, 1, 0x64},
{6, "ATTR_6A", NULL, 1, 0x6A},
{6, "ATTR_6B", NULL, 1, 0x6B},
{6, "ATTR_6C", NULL, 1, 0x6C},
{6, "ATTR_70", NULL, 1, 0x70},
{6, "ATTR_71", NULL, 1, 0x71},
{6, "ATTR_73", NULL, 1, 0x73},
{6, "ATTR_74", NULL, 1, 0x74},
{0, NULL, NULL, 0, 0}
};
CODEPAGE_ATTRVALUE_NAME_LIST CodepageAttrvalueNames[] =
{
{4, ".com/", 0, 0x85},
{4, ".edu/", 0, 0x86},
{4, ".net/", 0, 0x87},
{4, ".org/", 0, 0x88},
{4, "accept", 0, 0x89},
{4, "bottom", 0, 0x8a},
{4, "clear", 0, 0x8b},
{4, "delete", 0, 0x8c},
{4, "help", 0, 0x8d},
{4, "http://", 0, 0x8e},
{4, "http://www.", 0, 0x8f},
{4, "https://", 0, 0x90},
{4, "https://www.", 0, 0x91},
{4, "middle", 0, 0x93},
{4, "nowrap", 0, 0x94},
{4, "onenterbackward", 0, 0x96},
{4, "onenterforward", 0, 0x97},
{4, "onpick", 0, 0x95},
{4, "ontimer", 0, 0x98},
{4, "options", 0, 0x99},
{4, "password", 0, 0x9a},
{4, "reset", 0, 0x9b},
{4, "text", 0, 0x9d},
{4, "top", 0, 0x9e},
{4, "unknown", 0, 0x9f},
{4, "wrap", 0, 0xa0},
{4, "www.", 0, 0xa1},
{0, NULL, 0, 0}
};
/**************************
* Node Tree Construction *
**************************/
/*
* Function: NewNode
*
* Description:
*
* Allocate and initialize a new node. This links the new node
* as the first child of the current node in the buffer. This causes
* child nodes to be linked in reverse order. If there is no current
* node, then the new node will be linked in as the first child at the
* top of the tree.
*
* Parameters:
*
* buffer - WBXML buffer to link the new node into
* type - Type of node to allocate
*
* Return value:
*
* P_WBXML_NODE - A pointer to the newly allocated node.
*
*/
static P_WBXML_NODE NewNode(P_WBXML_INFO buffer, WBXML_NODE_TYPE type)
{
if (buffer)
{
P_WBXML_NODE newnode = malloc(sizeof(WBXML_NODE));
if (newnode)
{
newnode->m_prev = NULL;
newnode->m_child = NULL;
if (buffer->m_curnode)
{
/* Insert this node as the first child of the current node */
newnode->m_parent = buffer->m_curnode;
newnode->m_next = buffer->m_curnode->m_child;
if (buffer->m_curnode->m_child)
{
((P_WBXML_NODE)buffer->m_curnode->m_child)->m_prev = newnode;
}
buffer->m_curnode->m_child = newnode;
}
else
{
/* Insert this node at the top of the tree */
newnode->m_parent = NULL;
newnode->m_next = buffer->m_tree;
if (buffer->m_tree)
{
buffer->m_tree->m_prev = newnode;
}
buffer->m_tree = newnode;
}
newnode->m_page = buffer->m_curpage;
newnode->m_type = type;
newnode->m_data = NULL;
}
else
{
ParseError(ERR_NOT_ENOUGH_MEMORY);
}
return newnode;
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return NULL;
}
/*
* Function: FreeNode
*
* Description:
*
* Free a node, all its children and forward siblings.
*
* Parameters:
*
* node - The node to free
*
*/
static void FreeNode(P_WBXML_NODE node)
{
if (node)
{
if (node->m_child)
{
FreeNode(node->m_child);
}
if (node->m_next)
{
FreeNode(node->m_next);
}
free(node);
}
}
static void AddDTDNode(P_WBXML_INFO buffer, const WBXML_DTD_TYPE dtdnum, const WBXML_MB_U_INT32 index)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_DTD_TYPE);
newnode->m_data = malloc(sizeof(DTD_NODE_DATA));
memcpy( &( ((DTD_NODE_DATA*)newnode->m_data)->m_dtdnum ), &(dtdnum[0]), sizeof(WBXML_MB_U_INT32) );
memcpy( &( ((DTD_NODE_DATA*)newnode->m_data)->m_index ), &(index[0]), sizeof(WBXML_MB_U_INT32) );
dtd_id = (long) dtdnum[0];
}
static void AddStringTableNode(P_WBXML_INFO buffer, const P_WBXML_STRING_TABLE strings)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_STRING_TABLE);
newnode->m_data = malloc(sizeof(WBXML_STRING_TABLE));
memcpy( newnode->m_data, strings, sizeof(WBXML_STRING_TABLE) );
}
static void AddCodepageTagNode(P_WBXML_INFO buffer, WBXML_TAG tag)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_CODEPAGE_TAG);
newnode->m_data = malloc(sizeof(WBXML_TAG));
*((P_WBXML_TAG)newnode->m_data) = tag;
}
static void AddCodepageLiteralTagNode(P_WBXML_INFO buffer, WBXML_MB_U_INT32 index)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_CODEPAGE_LITERAL_TAG);
newnode->m_data = malloc(sizeof(WBXML_MB_U_INT32));
memcpy( ((P_WBXML_MB_U_INT32)newnode->m_data), &index, sizeof(WBXML_MB_U_INT32) );
}
static void AddAttrStartNode(P_WBXML_INFO buffer, WBXML_TAG tag)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRSTART);
newnode->m_data = malloc(sizeof(WBXML_TAG));
*((P_WBXML_TAG)newnode->m_data) = tag;
}
static void AddAttrStartLiteralNode(P_WBXML_INFO buffer, WBXML_MB_U_INT32 index)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRSTART_LITERAL);
newnode->m_data = malloc(sizeof(WBXML_MB_U_INT32));
memcpy( ((P_WBXML_MB_U_INT32)newnode->m_data), &index, sizeof(WBXML_MB_U_INT32) );
}
static void AddAttrValueNode(P_WBXML_INFO buffer, WBXML_TAG tag)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRVALUE);
newnode->m_data = malloc(sizeof(WBXML_TAG));
*((P_WBXML_TAG)newnode->m_data) = tag;
}
static void AddAttrEndNode(P_WBXML_INFO buffer)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTREND);
newnode->m_data = NULL;
}
static void AddStringNode(P_WBXML_INFO buffer, char* string)
{
P_WBXML_NODE newnode = NewNode(buffer, NODE_STRING);
newnode->m_data = strdup(string);
}
static void AddVariableStringNode(P_WBXML_INFO buffer, char* string, WBXML_VARIABLE_TYPE type)
{
/* TODO: add this node */
}
static void AddVariableIndexNode(P_WBXML_INFO buffer, char* string, WBXML_VARIABLE_TYPE type)
{
/* TODO: add this node */
}
/****************
* Flow Control *
****************/
void Message(char* msg)
{
printf("%s\n", msg);
}
void ParseError(WBXML_PARSE_ERROR error)
{
switch (error)
{
case ERR_END_OF_DATA:
Message("Input stream is incomplete (EOF).");
break;
case ERR_INTERNAL_BAD_PARAM:
Message("Internal error: Bad parameter.");
break;
case ERR_TAG_NOT_FOUND:
Message("Tag not found.");
break;
case ERR_FILE_NOT_FOUND:
Message("File not found.");
break;
case ERR_FILE_NOT_READ:
Message("File read error.");
break;
case ERR_NOT_ENOUGH_MEMORY:
Message("Not enough memory");
break;
default:
Message("Unknown error.");
break;
}
exit(error);
}
void ParseWarning(WBXML_PARSE_WARNING warning)
{
switch (warning)
{
case WARN_FUTURE_EXPANSION_EXT_0:
Message("Token EXT_0 encountered. This token is reserved for future expansion.");
break;
case WARN_FUTURE_EXPANSION_EXT_1:
Message("Token EXT_1 encountered. This token is reserved for future expansion.");
break;
case WARN_FUTURE_EXPANSION_EXT_2:
Message("Token EXT_2 encountered. This token is reserved for future expansion.");
break;
default:
Message("Unknown warning.");
break;
}
}
WBXML_LENGTH BytesLeft(P_WBXML_INFO buffer)
{
if (buffer)
{
WBXML_LENGTH bytesRead = (buffer->m_curpos - buffer->m_start);
if (bytesRead >= buffer->m_length)
{
return 0;
}
else
{
return (buffer->m_length - bytesRead);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return 0;
}
BOOL IsTag(P_WBXML_INFO buffer, WBXML_TAG tag)
{
BOOL result = FALSE;
if (buffer)
{
if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
{
result = ((*((WBXML_TAG*) buffer->m_curpos)) == tag);
}
else
{
/* No more data, so nope, not this tag */
result = FALSE;
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return result;
}
BOOL IsCodepageTag(P_WBXML_INFO buffer, CP_TAG_TYPE type)
{
WBXML_U_INT8 result = *(buffer->m_curpos);
/* NOTE THAT THESE ARE NOT UNIQUE! */
switch (type)
{
case CP_TAG_TAG:
return TRUE;
case CP_TAG_ATTRSTART:
return ((result & 0x80) != 0x80);
case CP_TAG_ATTRVALUE:
return ((result & 0x80) == 0x80);
default:
return FALSE;
}
}
BOOL Is_attrValue (P_WBXML_INFO buffer)
{
WBXML_INFO tmpbuffer;
memcpy(&tmpbuffer, buffer, sizeof(WBXML_INFO));
tmpbuffer.m_curpos += SWITCHPAGE_SIZE;
return ((Is_switchPage(buffer) && IsCodepageTag(&tmpbuffer, CP_TAG_ATTRVALUE)) ||
IsCodepageTag(buffer, CP_TAG_ATTRVALUE) ||
Is_string(buffer) ||
Is_extension(buffer) ||
Is_entity(buffer) ||
Is_pi(buffer) ||
Is_opaque(buffer));
}
BOOL Is_extension (P_WBXML_INFO buffer)
{
WBXML_INFO tmpbuffer;
memcpy(&tmpbuffer, buffer, sizeof(WBXML_INFO));
tmpbuffer.m_curpos += SWITCHPAGE_SIZE;
return ((Is_switchPage(buffer) &&
(IsTag(&tmpbuffer, TAG_EXT_0) ||
IsTag(&tmpbuffer, TAG_EXT_1) ||
IsTag(&tmpbuffer, TAG_EXT_2) ||
IsTag(&tmpbuffer, TAG_EXT_T_0) ||
IsTag(&tmpbuffer, TAG_EXT_T_1) ||
IsTag(&tmpbuffer, TAG_EXT_T_2) ||
IsTag(&tmpbuffer, TAG_EXT_I_0) ||
IsTag(&tmpbuffer, TAG_EXT_I_1) ||
IsTag(&tmpbuffer, TAG_EXT_I_2))) ||
(IsTag(buffer, TAG_EXT_0) ||
IsTag(buffer, TAG_EXT_1) ||
IsTag(buffer, TAG_EXT_2) ||
IsTag(buffer, TAG_EXT_T_0) ||
IsTag(buffer, TAG_EXT_T_1) ||
IsTag(buffer, TAG_EXT_T_2) ||
IsTag(buffer, TAG_EXT_I_0) ||
IsTag(buffer, TAG_EXT_I_1) ||
IsTag(buffer, TAG_EXT_I_2)));
}
BOOL Is_string (P_WBXML_INFO buffer)
{
return (Is_inline(buffer) ||
Is_tableref(buffer));
}
BOOL Is_switchPage (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_SWITCH_PAGE);
}
BOOL Is_inline (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_STR_I);
}
BOOL Is_tableref (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_STR_T);
}
BOOL Is_entity (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_ENTITY);
}
BOOL Is_pi (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_PI);
}
BOOL Is_opaque (P_WBXML_INFO buffer)
{
return IsTag(buffer, TAG_OPAQUE);
}
BOOL Is_zero(P_WBXML_INFO buffer)
{
BOOL result = FALSE;
if (buffer)
{
if (BytesLeft(buffer) >= 1)
{
result = ((*buffer->m_curpos) == 0);
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return result;
}
/***********************
* Basic Type Decoders *
***********************/
void Read_u_int8(P_WBXML_INFO buffer, P_WBXML_U_INT8 result)
{
if (buffer && result)
{
if (BytesLeft(buffer) >= 1)
{
*result = *(buffer->m_curpos);
(buffer->m_curpos)++;
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
}
void Read_mb_u_int32(P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
{
if (buffer && result)
{
int i;
for (i = 0; i < MAX_MB_U_INT32_BYTES; i++)
{
if (BytesLeft(buffer) >= 1)
{
(*result)[i] = *(buffer->m_curpos);
(buffer->m_curpos)++;
if ( !( (*result)[i] & 0x80 ) )
break;
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
}
void Read_bytes(P_WBXML_INFO buffer, WBXML_LENGTH length, P_WBXML_BYTES result)
{
if (buffer && result)
{
if (BytesLeft(buffer) >= length)
{
*result = (WBXML_BYTES) malloc(length*sizeof(unsigned char));
memcpy(*result, buffer->m_curpos, length);
buffer->m_curpos += length;
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
}
void ReadFixedTag(P_WBXML_INFO buffer, WBXML_TAG tag)
{
if (buffer)
{
if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
{
if ((*((WBXML_TAG*) buffer->m_curpos)) == tag)
{
buffer->m_curpos += sizeof(WBXML_TAG);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
}
WBXML_TAG ReadCodepageTag (P_WBXML_INFO buffer, CP_TAG_TYPE type)
{
WBXML_TAG tag = 0;
if (buffer)
{
if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
{
tag = *((WBXML_TAG*) buffer->m_curpos);
switch (type)
{
case CP_TAG_TAG:
buffer->m_curpos += sizeof(WBXML_TAG);
break;
case CP_TAG_ATTRSTART:
if ((tag & 0x80) != 0x80)
{
buffer->m_curpos += sizeof(WBXML_TAG);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
break;
case CP_TAG_ATTRVALUE:
if ((tag & 0x80) == 0x80)
{
buffer->m_curpos += sizeof(WBXML_TAG);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
break;
default:
ParseError(ERR_TAG_NOT_FOUND);
break;
}
}
else
{
ParseError(ERR_END_OF_DATA);
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return tag;
}
/**************************
* Basic Type Conversions *
**************************/
long mb_u_int32_to_long(P_WBXML_MB_U_INT32 value)
{
long result = 0;
if (value)
{
int i;
for (i = 0; i < MAX_MB_U_INT32_BYTES; i++)
{
result <<= 7;
result |= ((*value)[i] & 0x7f);
if ( !( (*value)[i] & 0x80 ) )
break;
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
return result;
}
static void OutputEncodedString(const unsigned char* str)
{
/* Work our way down the string looking for illegal chars */
while (*str != 0)
{
if ((*str < 0x20) || (*str > 0x7F))
{
/* Out of range... encode */
printf("%02x;", *str);
}
else
{
switch (*str)
{
case '<':
case '>':
case '&':
case '\'':
case '\"':
/* Special symbol... encode */
printf("%2x", *str);
break;
default:
printf("%c", *str);
break;
}
}
str++;
}
}
/*******************************
* Document Structure Decoders *
*******************************/
void Read_start (P_WBXML_INFO buffer)
{
Read_version(buffer);
Read_publicid(buffer);
Read_charset(buffer);
Read_strtbl(buffer);
Read_body(buffer);
}
void Read_strtbl (P_WBXML_INFO buffer)
{
WBXML_STRING_TABLE result;
Read_mb_u_int32(buffer, &(result.m_length));
Read_bytes(buffer, mb_u_int32_to_long(&(result.m_length)), &(result.m_strings));
AddStringTableNode(buffer, &result);
}
void Read_body (P_WBXML_INFO buffer)
{
while (Is_pi(buffer))
{
Read_pi(buffer);
}
Read_element(buffer);
while (Is_pi(buffer))
{
Read_pi(buffer);
}
}
void Read_element (P_WBXML_INFO buffer)
{
WBXML_TAG stagvalue = 0;
if (Is_switchPage(buffer))
{
Read_switchPage(buffer);
}
stagvalue = Read_stag(buffer);
/* move the current node down to this one in the tree */
if (buffer->m_curnode)
buffer->m_curnode = buffer->m_curnode->m_child;
else buffer->m_curnode = buffer->m_tree;
if ((stagvalue & CODEPAGE_TAG_HAS_ATTRS) == CODEPAGE_TAG_HAS_ATTRS)
{
do
{
Read_attribute(buffer);
} while (!IsTag(buffer, TAG_END));
ReadFixedTag(buffer, TAG_END);
AddAttrEndNode(buffer);
}
if ((stagvalue & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
{
while (!IsTag(buffer, TAG_END))
{
Read_content(buffer);
}
ReadFixedTag(buffer, TAG_END);
}
/* move the current node back up one */
buffer->m_curnode = buffer->m_curnode->m_parent;
}
void Read_content (P_WBXML_INFO buffer)
{
if (Is_string(buffer))
{
Read_string(buffer);
}
else if (Is_extension(buffer))
{
Read_extension(buffer);
}
else if (Is_entity(buffer))
{
Read_entity(buffer);
}
else if (Is_pi(buffer))
{
Read_pi(buffer);
}
else if (Is_opaque(buffer))
{
Read_opaque(buffer);
}
else
{
/* Assume it is an element */
Read_element(buffer);
}
}
WBXML_TAG Read_stag (P_WBXML_INFO buffer)
{
if (IsCodepageTag(buffer, CP_TAG_TAG))
{
WBXML_TAG tag = ReadCodepageTag(buffer, CP_TAG_TAG);
AddCodepageTagNode(buffer, tag);
return tag;
}
else if (IsTag(buffer, TAG_LITERAL))
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_LITERAL);
Read_index(buffer, &index);
AddCodepageLiteralTagNode(buffer, index);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
return 0;
}
void Read_attribute (P_WBXML_INFO buffer)
{
Read_attrStart(buffer);
while (Is_attrValue(buffer))
{
Read_attrValue(buffer);
}
}
void Read_attrStart (P_WBXML_INFO buffer)
{
if (Is_switchPage(buffer))
{
WBXML_TAG tag;
Read_switchPage(buffer);
tag = ReadCodepageTag(buffer, CP_TAG_ATTRSTART);
AddAttrStartNode(buffer, tag);
}
else if (IsCodepageTag(buffer, CP_TAG_ATTRSTART))
{
WBXML_TAG tag;
tag = ReadCodepageTag(buffer, CP_TAG_ATTRSTART);
AddAttrStartNode(buffer, tag);
}
else if (IsTag(buffer, TAG_LITERAL))
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_LITERAL);
Read_index(buffer, &index);
AddAttrStartLiteralNode(buffer, index);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
void Read_attrValue (P_WBXML_INFO buffer)
{
if (Is_switchPage(buffer))
{
WBXML_TAG tag;
Read_switchPage(buffer);
tag = ReadCodepageTag(buffer, CP_TAG_ATTRVALUE);
AddAttrValueNode(buffer, tag);
}
else if (IsCodepageTag(buffer, CP_TAG_ATTRVALUE))
{
WBXML_TAG tag;
tag = ReadCodepageTag(buffer, CP_TAG_ATTRVALUE);
AddAttrValueNode(buffer, tag);
}
else if (Is_string(buffer))
{
Read_string(buffer);
}
else if (Is_extension(buffer))
{
Read_extension(buffer);
}
else if (Is_entity(buffer))
{
Read_entity(buffer);
}
else if (Is_opaque(buffer))
{
Read_opaque(buffer);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
void Read_extension (P_WBXML_INFO buffer)
{
if (Is_switchPage(buffer))
{
Read_switchPage(buffer);
}
if (IsTag(buffer, TAG_EXT_I_0))
{
char* str = NULL;
ReadFixedTag(buffer, TAG_EXT_I_0);
Read_termstr_rtn(buffer, &str);
AddVariableStringNode(buffer, str, VAR_ESCAPED);
}
else if (IsTag(buffer, TAG_EXT_I_1))
{
char* str = NULL;
ReadFixedTag(buffer, TAG_EXT_I_1);
Read_termstr_rtn(buffer, &str);
AddVariableStringNode(buffer, str, VAR_UNESCAPED);
}
else if (IsTag(buffer, TAG_EXT_I_2))
{
char* str = NULL;
ReadFixedTag(buffer, TAG_EXT_I_2);
Read_termstr_rtn(buffer, &str);
AddVariableStringNode(buffer, str, VAR_UNCHANGED);
}
else if (IsTag(buffer, TAG_EXT_T_0))
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_EXT_T_0);
Read_index(buffer, &index);
AddVariableIndexNode(buffer, index, VAR_ESCAPED);
}
else if (IsTag(buffer, TAG_EXT_T_1))
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_EXT_T_1);
Read_index(buffer, &index);
AddVariableIndexNode(buffer, index, VAR_UNESCAPED);
}
else if (IsTag(buffer, TAG_EXT_T_2))
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_EXT_T_2);
Read_index(buffer, &index);
AddVariableIndexNode(buffer, index, VAR_UNCHANGED);
}
else if (IsTag(buffer, TAG_EXT_0))
{
ReadFixedTag(buffer, TAG_EXT_0);
ParseWarning(WARN_FUTURE_EXPANSION_EXT_0);
}
else if (IsTag(buffer, TAG_EXT_1))
{
ReadFixedTag(buffer, TAG_EXT_1);
ParseWarning(WARN_FUTURE_EXPANSION_EXT_1);
}
else if (IsTag(buffer, TAG_EXT_2))
{
ReadFixedTag(buffer, TAG_EXT_2);
ParseWarning(WARN_FUTURE_EXPANSION_EXT_2);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
void Read_string (P_WBXML_INFO buffer)
{
if (Is_inline(buffer))
{
Read_inline(buffer);
}
else if (Is_tableref(buffer))
{
Read_tableref(buffer);
}
else
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
void Read_switchPage (P_WBXML_INFO buffer)
{
WBXML_U_INT8 pageindex;
ReadFixedTag(buffer, TAG_SWITCH_PAGE);
Read_pageindex(buffer, &pageindex);
/* Use the new codepage */
buffer->m_curpage = pageindex;
}
void Read_inline (P_WBXML_INFO buffer)
{
ReadFixedTag(buffer, TAG_STR_I);
Read_termstr(buffer);
}
void Read_tableref (P_WBXML_INFO buffer)
{
WBXML_MB_U_INT32 index;
ReadFixedTag(buffer, TAG_STR_T);
Read_index(buffer, &index);
}
void Read_entity (P_WBXML_INFO buffer)
{
ReadFixedTag(buffer, TAG_ENTITY);
Read_entcode(buffer);
}
void Read_entcode (P_WBXML_INFO buffer)
{
WBXML_MB_U_INT32 result;
Read_mb_u_int32(buffer, &result);
}
void Read_pi (P_WBXML_INFO buffer)
{
ReadFixedTag(buffer, TAG_PI);
Read_attrStart(buffer);
while (Is_attrValue(buffer))
{
Read_attrValue(buffer);
}
ReadFixedTag(buffer, TAG_END);
}
void Read_opaque (P_WBXML_INFO buffer)
{
WBXML_MB_U_INT32 length;
WBXML_BYTES data;
ReadFixedTag(buffer, TAG_OPAQUE);
Read_length(buffer, &length);
Read_bytes(buffer, mb_u_int32_to_long(&length), &data);
}
void Read_version (P_WBXML_INFO buffer)
{
WBXML_U_INT8 result;
Read_u_int8(buffer, &result);
}
void Read_publicid (P_WBXML_INFO buffer)
{
if (Is_zero(buffer))
{
WBXML_MB_U_INT32 index;
Read_index(buffer, &index);
AddDTDNode(buffer, ZERO_WBXML_MB_U_INT32, index);
}
else
{
WBXML_MB_U_INT32 result;
Read_mb_u_int32(buffer, &result);
AddDTDNode(buffer, result, ZERO_WBXML_MB_U_INT32);
}
}
void Read_charset (P_WBXML_INFO buffer)
{
WBXML_MB_U_INT32 result;
Read_mb_u_int32(buffer, &result);
}
void Read_termstr_rtn(P_WBXML_INFO buffer, char** result)
{
#define STRING_BLOCK_SIZE 256
int buflen = STRING_BLOCK_SIZE;
char* strbuf = (char*) malloc(buflen);
BOOL doubled = FALSE;
int i = 0;
if (!result)
ParseError(ERR_INTERNAL_BAD_PARAM);
while ( (BytesLeft(buffer) >= 1) && (*(buffer->m_curpos) != 0) )
{
if (i>=buflen)
{
buflen += STRING_BLOCK_SIZE;
strbuf = realloc(strbuf, buflen);
}
if (*(buffer->m_curpos) != '$' || doubled == TRUE)
{
strbuf[i] = *(buffer->m_curpos);
buffer->m_curpos++;
i++;
if (doubled == TRUE)
doubled = FALSE;
}
else
{
strbuf[i] = *(buffer->m_curpos);
i++;
doubled = TRUE;
}
}
strbuf[i] = 0;
buffer->m_curpos++;
if (*result)
free(*result);
*result = strbuf;
}
void Read_termstr (P_WBXML_INFO buffer)
{
char* strbuf = NULL;
Read_termstr_rtn(buffer, &strbuf);
AddStringNode(buffer, strbuf);
free(strbuf);
}
void Read_index (P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
{
Read_mb_u_int32(buffer, result);
}
void Read_length (P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
{
Read_mb_u_int32(buffer, result);
}
void Read_zero (P_WBXML_INFO buffer)
{
WBXML_U_INT8 result;
Read_u_int8(buffer, &result);
if (result != (WBXML_U_INT8) 0)
{
ParseError(ERR_TAG_NOT_FOUND);
}
}
void Read_pageindex (P_WBXML_INFO buffer, P_WBXML_U_INT8 result)
{
Read_u_int8(buffer, result);
}
static void Init(P_WBXML_INFO buffer)
{
buffer->m_start = NULL;
buffer->m_curpos = NULL;
buffer->m_length = 0;
buffer->m_tree = NULL;
buffer->m_curnode = NULL;
buffer->m_curpage = 0;
}
static size_t BufferLength(P_WBXML_INFO buffer)
{
size_t ret;
while (buffer->m_curpos != '\0')
buffer->m_curpos++;
ret = buffer->m_curpos - buffer->m_start;
buffer->m_curpos = buffer->m_start;
return ret;
}
static void Free(P_WBXML_INFO buffer)
{
if (buffer->m_start)
{
free(buffer->m_start);
buffer->m_start = NULL;
}
buffer->m_curpos = NULL;
buffer->m_length = 0;
FreeNode(buffer->m_tree);
buffer->m_tree = NULL;
}
static long FileSize(FILE* file)
{
long curpos = ftell(file);
long endpos;
fseek(file, 0, SEEK_END);
endpos = ftell(file);
fseek(file, curpos, SEEK_SET);
return endpos;
}
static void ReadBinary(P_WBXML_INFO buffer, FILE* file)
{
char buf[4096];
int m = 1;
long n;
if (buffer && file)
{
if (file != stdin)
{
buffer->m_length = FileSize(file);
buffer->m_start = (P_WBXML) malloc(buffer->m_length);
buffer->m_curpos = buffer->m_start;
if (!buffer->m_start)
{
fclose(file);
ParseError(ERR_NOT_ENOUGH_MEMORY);
}
if (fread(buffer->m_start, 1, buffer->m_length, file) != buffer->m_length)
{
fclose(file);
ParseError(ERR_FILE_NOT_READ);
}
else
{
fclose(file);
}
}
else
{
while ((n = fread(buf, 1, sizeof(buf), file)) > 0)
{
buffer->m_start = (P_WBXML) realloc(buffer->m_start, sizeof(buf) * m);
memcpy(buffer->m_start + (sizeof(buf) * (m - 1)), buf, sizeof(buf));
m++;
}
buffer->m_length = BufferLength(buffer);
buffer->m_curpos = buffer->m_start;
}
}
else
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
}
static const char* DTDTypeName(long dtdnum)
{
int i = 0;
/* Search the DTD list for a match */
while (DTDTypeList[i].m_name)
{
if (DTDTypeList[i].m_id == dtdnum)
{
break;
}
i++;
}
return DTDTypeList[i].m_name;
}
static const char* CodepageTagName(WBXML_CODEPAGE page, WBXML_TAG tag)
{
int i = 0;
/* Strip flags off of the tag */
tag = (WBXML_TAG) (tag & CODEPAGE_TAG_MASK);
/* Search the tag list for a match */
while (CodepageTagNames[i].m_name)
{
if ((CodepageTagNames[i].m_dtd_id == dtd_id) &&
(CodepageTagNames[i].m_page == page) &&
(CodepageTagNames[i].m_tag == tag))
{
break;
}
i++;
}
return CodepageTagNames[i].m_name;
}
static const char* CodepageAttrstartName(WBXML_CODEPAGE page, WBXML_TAG tag, char** value)
{
int i = 0;
/* Check Parameters */
if (!value)
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
/* Search the tag list for a match */
while (CodepageAttrstartNames[i].m_name)
{
if ((CodepageAttrstartNames[i].m_dtd_id == dtd_id) &&
(CodepageAttrstartNames[i].m_page == page) &&
(CodepageAttrstartNames[i].m_tag == tag))
{
break;
}
i++;
}
/* Duplicate the value because it may be concatenated to */
if (CodepageAttrstartNames[i].m_valueprefix)
{
*value = strdup(CodepageAttrstartNames[i].m_valueprefix);
}
else
{
*value = NULL;
}
/* Return the tag name */
return CodepageAttrstartNames[i].m_name;
}
static void CodepageAttrvalueName(WBXML_CODEPAGE page, WBXML_TAG tag, char** value)
{
int i = 0;
/* Check Parameters */
if (!value)
{
ParseError(ERR_INTERNAL_BAD_PARAM);
}
/* Search the tag list for a match */
while (CodepageAttrvalueNames[i].m_name)
{
if ((CodepageAttrvalueNames[i].m_dtd_id == dtd_id) &&
(CodepageAttrvalueNames[i].m_page == page) &&
(CodepageAttrvalueNames[i].m_tag == tag))
{
break;
}
i++;
}
/* concatenate the value */
if (CodepageAttrvalueNames[i].m_name)
{
if (*value)
{
*value = realloc(*value, strlen(*value) + strlen(CodepageAttrvalueNames[i].m_name) + 1);
strcat(*value, CodepageAttrvalueNames[i].m_name);
}
else
{
*value = strdup(CodepageAttrvalueNames[i].m_name);
}
}
}
static const char* GetStringTableString(P_WBXML_NODE node, long index)
{
/* Find the string table node */
P_WBXML_NODE pStringsNode = node;
while (pStringsNode->m_parent)
{
pStringsNode = pStringsNode->m_parent;
}
while (pStringsNode->m_next)
{
pStringsNode = pStringsNode->m_next;
}
while (pStringsNode->m_prev && pStringsNode->m_type != NODE_STRING_TABLE)
{
pStringsNode = pStringsNode->m_prev;
}
if (pStringsNode->m_type != NODE_STRING_TABLE)
{
return "!!NO STRING TABLE!!";
}
/* Find the indexed string */
if ((index >= 0) && (index < mb_u_int32_to_long(&((P_WBXML_STRING_TABLE)pStringsNode->m_data)->m_length)))
{
return (const char*) &(((P_WBXML_STRING_TABLE)pStringsNode->m_data)->m_strings[index]);
}
else
{
return "!!STRING TABLE INDEX TOO LARGE!!";
}
}
static void DumpNode(P_WBXML_NODE node, int indent, BOOL *inattrs, BOOL hascontent, char** value)
{
P_WBXML_NODE curnode = node->m_child;
WBXML_TAG nodetype = 0;
long dtdnum = 0;
BOOL bAttributesFollow = FALSE;
BOOL bHasContent = FALSE;
int i;
if (!(*inattrs))
{
for (i=0; im_type != NODE_ATTRVALUE) && (*value))
{
printf("=\"");
OutputEncodedString((unsigned char*) *value);
printf("\"");
free(*value);
*value = NULL;
}
}
switch (node->m_type)
{
case NODE_DTD_TYPE:
printf("\n\n\n", GetStringTableString(node, mb_u_int32_to_long(&((DTD_NODE_DATA*)node->m_data)->m_index)) );
}
else
{
printf("\"%s\">\n\n", DTDTypeName(dtdnum) );
}
break;
case NODE_CODEPAGE_TAG:
nodetype = *((P_WBXML_TAG)node->m_data);
if ((nodetype & CODEPAGE_TAG_MASK) == nodetype)
{
printf("<%s/>\n", CodepageTagName(node->m_page, nodetype));
}
else
{
if ((nodetype & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
{
bHasContent = TRUE;
}
if ((nodetype & CODEPAGE_TAG_HAS_ATTRS) == CODEPAGE_TAG_HAS_ATTRS)
{
printf("<%s", CodepageTagName(node->m_page, nodetype));
bAttributesFollow = TRUE;
}
else
{
printf("<%s>\n", CodepageTagName(node->m_page, nodetype));
}
}
break;
case NODE_CODEPAGE_LITERAL_TAG:
printf("<%s>\n", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
break;
case NODE_ATTRSTART:
printf(" %s", CodepageAttrstartName(node->m_page, *((P_WBXML_TAG)node->m_data), value) );
break;
case NODE_ATTRSTART_LITERAL:
printf(" %s", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
break;
case NODE_ATTRVALUE:
CodepageAttrvalueName(node->m_page, *((P_WBXML_TAG)node->m_data), value);
break;
case NODE_ATTREND:
if (!hascontent)
{
printf("/");
}
printf(">\n");
*inattrs = FALSE;
break;
case NODE_STRING:
if (*inattrs)
{
/* concatenate the value */
if (*value)
{
if (node->m_data)
{
*value = realloc(*value, strlen(*value) + strlen((char*) node->m_data) + 1);
strcat(*value, (char*) node->m_data);
}
}
else
{
if (node->m_data)
{
*value = strdup((char*) node->m_data);
}
}
}
else
{
OutputEncodedString((unsigned char*) node->m_data);
printf("\n");
}
break;
case NODE_VARIABLE_STRING:
/* TODO: output variable string */
break;
case NODE_VARIABLE_INDEX:
/* TODO: output variable string */
break;
default:
break;
}
indent += INDENT_SIZE;
if (curnode)
{
while (curnode->m_next) curnode = curnode->m_next;
while (curnode)
{
DumpNode(curnode, indent, &bAttributesFollow, bHasContent, value);
curnode = curnode->m_prev;
}
}
indent -= INDENT_SIZE;
/* Output the element end if we have one */
if ((nodetype & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
{
for (i=0; im_type)
{
case NODE_CODEPAGE_TAG:
printf("%s>\n", CodepageTagName(node->m_page, *((P_WBXML_TAG)node->m_data)) );
break;
case NODE_CODEPAGE_LITERAL_TAG:
printf("%s>\n", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
break;
default:
break;
}
}
}
static void DumpNodes(P_WBXML_INFO buffer)
{
P_WBXML_NODE curnode = buffer->m_tree;
BOOL bAttrsFollow = FALSE;
char* value = NULL;
if (curnode)
{
while (curnode->m_next) curnode = curnode->m_next;
while (curnode)
{
DumpNode(curnode, 0, &bAttrsFollow, FALSE, &value);
curnode = curnode->m_prev;
}
}
}
int main(int argc, char** argv)
{
WBXML_INFO buffer;
FILE* file;
if (argc < 2)
{
file = stdin;
}
else
{
file = fopen(argv[1], "r");
if (!file)
{
ParseError(ERR_FILE_NOT_FOUND);
}
}
Init(&buffer);
ReadBinary(&buffer, file);
Read_start(&buffer);
DumpNodes(&buffer);
Free(&buffer);
return 0;
}