Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

decompile.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * decompile.c - A program to test the WML compiler. This tool was written
00059  *               from the WBXML 1.2 and WML 1.1 specs.
00060  *
00061  * Author: Chris Wulff, Vanteon (cwulff@vanteon.com)
00062  *
00063  */
00064 
00065 #include <stdio.h>
00066 #include <stdlib.h>
00067 #include <memory.h>
00068 #include <string.h>
00069 
00070 #include "decompile.h"
00071 
00072 const WBXML_MB_U_INT32 ZERO_WBXML_MB_U_INT32 = {0,0,0,0};
00073 long dtd_id;
00074 
00075 #define INDENT_SIZE     4
00076 
00077 DTD_TYPE_LIST DTDTypeList[] =
00078 {
00079     {1, "UNKNOWN"},
00080     {2, "-//WAPFORUM//DTD WML 1.0//EN\"\n"
00081      "\"http://www.wapforum.org/DTD/wml.xml"},
00082     {3, "-//WAPFORUM//DTD WTA 1.0//EN"},
00083     {4, "-//WAPFORUM//DTD WML 1.1//EN\"\n"
00084      "\"http://www.wapforum.org/DTD/wml_1.1.xml"},
00085     {5, "-//WAPFORUM//DTD SI 1.0//EN\"\n"
00086      "\"http://www.wapforum.org/DTD/si.dtd"},
00087     {6, "-//WAPFORUM//DTD SL 1.0//EN\"\n"
00088      "\"http://www.wapforum.org/DTD/sl.dtd"},
00089     {7, "-//WAPFORUM//DTD CO 1.0//EN"},
00090     {8, "-//WAPFORUM//DTD CHANNEL 1.1//EN"},
00091     {9, "-//WAPFORUM//DTD WML 1.2//EN\"\n"
00092      "\"http://www.wapforum.org/DTD/wml12.dtd"},
00093     {0, NULL}
00094 };
00095 
00096 
00097 /**************************************
00098  * DTD Public Type 4 (WML 1.1) Tables *
00099  **************************************/
00100 
00101 CODEPAGE_TAG_NAME_LIST CodepageTagNames[] =
00102 {
00103     {4, "a",         0, 0x1c},
00104     {4, "anchor",    0, 0x22},
00105     {4, "access",    0, 0x23},
00106     {4, "b",         0, 0x24},
00107     {4, "big",       0, 0x25},
00108     {4, "br",        0, 0x26},
00109     {4, "card",      0, 0x27},
00110     {4, "do",        0, 0x28},
00111     {4, "em",        0, 0x29},
00112     {4, "fieldset",  0, 0x2a},
00113     {4, "go",        0, 0x2b},
00114     {4, "head",      0, 0x2c},
00115     {4, "i",         0, 0x2d},
00116     {4, "img",       0, 0x2e},
00117     {4, "input",     0, 0x2f},
00118     {4, "meta",      0, 0x30},
00119     {4, "noop",      0, 0x31},
00120     {4, "p",         0, 0x20},
00121     {4, "postfield", 0, 0x21},
00122     {4, "pre",       0, 0x1b},
00123     {4, "prev",      0, 0x32},
00124     {4, "onevent",   0, 0x33},
00125     {4, "optgroup",  0, 0x34},
00126     {4, "option",    0, 0x35},
00127     {4, "refresh",   0, 0x36},
00128     {4, "select",    0, 0x37},
00129     {4, "setvar",    0, 0x3e},
00130     {4, "small",     0, 0x38},
00131     {4, "strong",    0, 0x39},
00132     {4, "table",     0, 0x1f},
00133     {4, "td",        0, 0x1d},
00134     {4, "template",  0, 0x3b},
00135     {4, "timer",     0, 0x3c},
00136     {4, "tr",        0, 0x1e},
00137     {4, "u",         0, 0x3d},
00138     {4, "wml",       0, 0x3f},
00139 
00140     {6, "TAG_05",    1, 0x05},
00141     {6, "TAG_06",    1, 0x06},
00142     {6, "TAG_07",    1, 0x07},
00143 
00144     {0, NULL, 0, 0}
00145 };
00146 
00147 CODEPAGE_ATTRSTART_NAME_LIST CodepageAttrstartNames[] =
00148 {
00149     {4, "accept-charset",  NULL,                                0, 0x05},
00150     {4, "accesskey",       NULL,                                0, 0x5e},
00151     {4, "align",           NULL,                                0, 0x52},
00152     {4, "align",           "bottom",                            0, 0x06},
00153     {4, "align",           "center",                            0, 0x07},
00154     {4, "align",           "left",                              0, 0x08},
00155     {4, "align",           "middle",                            0, 0x09},
00156     {4, "align",           "right",                             0, 0x0a},
00157     {4, "align",           "top",                               0, 0x0b},
00158     {4, "alt",             NULL,                                0, 0x0c},
00159     {4, "class",           NULL,                                0, 0x54},
00160     {4, "columns",         NULL,                                0, 0x53},
00161     {4, "content",         NULL,                                0, 0x0d},
00162     {4, "content",         "application/vnd.wap.wmlc;charset=", 0, 0x5c},
00163     {4, "domain",          NULL,                                0, 0x0f},
00164     {4, "emptyok",         "false",                             0, 0x10},
00165     {4, "emptyok",         "true",                              0, 0x11},
00166     {4, "enctype",         NULL,                                0, 0x5f},
00167     {4, "enctype",         "application/x-www-form-urlencoded", 0, 0x60},
00168     {4, "enctype",         "multipart/form-data",               0, 0x61},
00169     {4, "format",          NULL,                                0, 0x12},
00170     {4, "forua",           "false",                             0, 0x56},
00171     {4, "forua",           "true",                              0, 0x57},
00172     {4, "height",          NULL,                                0, 0x13},
00173     {4, "href",            NULL,                                0, 0x4a},
00174     {4, "href",            "http://",                           0, 0x4b},
00175     {4, "href",            "https://",                          0, 0x4c},
00176     {4, "hspace",          NULL,                                0, 0x14},
00177     {4, "http-equiv",      NULL,                                0, 0x5a},
00178     {4, "http-equiv",      "Content-Type",                      0, 0x5b},
00179     {4, "http-equiv",      "Expires",                           0, 0x5d},
00180     {4, "id",              NULL,                                0, 0x55},
00181     {4, "ivalue",          NULL,                                0, 0x15},
00182     {4, "iname",           NULL,                                0, 0x16},
00183     {4, "label",           NULL,                                0, 0x18},
00184     {4, "localsrc",        NULL,                                0, 0x19},
00185     {4, "maxlength",       NULL,                                0, 0x1a},
00186     {4, "method",          "get",                               0, 0x1b},
00187     {4, "method",          "post",                              0, 0x1c},
00188     {4, "mode",            "nowrap",                            0, 0x1d},
00189     {4, "mode",            "wrap",                              0, 0x1e},
00190     {4, "multiple",        "false",                             0, 0x1f},
00191     {4, "multiple",        "true",                              0, 0x20},
00192     {4, "name",            NULL,                                0, 0x21},
00193     {4, "newcontext",      "false",                             0, 0x22},
00194     {4, "newcontext",      "true",                              0, 0x23},
00195     {4, "onenterbackward", NULL,                                0, 0x25},
00196     {4, "onenterforward",  NULL,                                0, 0x26},
00197     {4, "onpick",          NULL,                                0, 0x24},
00198     {4, "ontimer",         NULL,                                0, 0x27},
00199     {4, "optional",        "false",                             0, 0x28},
00200     {4, "optional",        "true",                              0, 0x29},
00201     {4, "path",            NULL,                                0, 0x2a},
00202     {4, "scheme",          NULL,                                0, 0x2e},
00203     {4, "sendreferer",     "false",                             0, 0x2f},
00204     {4, "sendreferer",     "true",                              0, 0x30},
00205     {4, "size",            NULL,                                0, 0x31},
00206     {4, "src",             NULL,                                0, 0x32},
00207     {4, "src",             "http://",                           0, 0x58},
00208     {4, "src",             "https://",                          0, 0x59},
00209     {4, "ordered",         "true",                              0, 0x33},
00210     {4, "ordered",         "false",                             0, 0x34},
00211     {4, "tabindex",        NULL,                                0, 0x35},
00212     {4, "title",           NULL,                                0, 0x36},
00213     {4, "type",            NULL,                                0, 0x37},
00214     {4, "type",            "accept",                            0, 0x38},
00215     {4, "type",            "delete",                            0, 0x39},
00216     {4, "type",            "help",                              0, 0x3a},
00217     {4, "type",            "password",                          0, 0x3b},
00218     {4, "type",            "onpick",                            0, 0x3c},
00219     {4, "type",            "onenterbackward",                   0, 0x3d},
00220     {4, "type",            "onenterforward",                    0, 0x3e},
00221     {4, "type",            "ontimer",                           0, 0x3f},
00222     {4, "type",            "options",                           0, 0x45},
00223     {4, "type",            "prev",                              0, 0x46},
00224     {4, "type",            "reset",                             0, 0x47},
00225     {4, "type",            "text",                              0, 0x48},
00226     {4, "type",            "vnd.",                              0, 0x49},
00227     {4, "value",           NULL,                                0, 0x4d},
00228     {4, "vspace",          NULL,                                0, 0x4e},
00229     {4, "width",           NULL,                                0, 0x4f},
00230     {4, "xml:lang",        NULL,                                0, 0x50},
00231 
00232     {6, "ATTR_06",         NULL,                                1, 0x06},
00233     {6, "ATTR_07",         NULL,                                1, 0x07},
00234     {6, "ATTR_08",         NULL,                                1, 0x08},
00235     {6, "ATTR_11",         NULL,                                1, 0x11},
00236     {6, "ATTR_12",         NULL,                                1, 0x12},
00237     {6, "ATTR_13",         NULL,                                1, 0x13},
00238     {6, "ATTR_14",         NULL,                                1, 0x14},
00239     {6, "ATTR_15",         NULL,                                1, 0x15},
00240     {6, "ATTR_21",         NULL,                                1, 0x21},
00241     {6, "ATTR_22",         NULL,                                1, 0x22},
00242     {6, "ATTR_23",         NULL,                                1, 0x23},
00243     {6, "ATTR_24",         NULL,                                1, 0x24},
00244     {6, "ATTR_28",         NULL,                                1, 0x28},
00245     {6, "ATTR_29",         NULL,                                1, 0x29},
00246     {6, "ATTR_45",         NULL,                                1, 0x45},
00247     {6, "ATTR_61",         NULL,                                1, 0x61},
00248     {6, "ATTR_62",         NULL,                                1, 0x62},
00249     {6, "ATTR_63",         NULL,                                1, 0x63},
00250     {6, "ATTR_64",         NULL,                                1, 0x64},
00251     {6, "ATTR_6A",         NULL,                                1, 0x6A},
00252     {6, "ATTR_6B",         NULL,                                1, 0x6B},
00253     {6, "ATTR_6C",         NULL,                                1, 0x6C},
00254     {6, "ATTR_70",         NULL,                                1, 0x70},
00255     {6, "ATTR_71",         NULL,                                1, 0x71},
00256     {6, "ATTR_73",         NULL,                                1, 0x73},
00257     {6, "ATTR_74",         NULL,                                1, 0x74},
00258 
00259     {0, NULL,              NULL,                                0, 0}
00260 };
00261 
00262 CODEPAGE_ATTRVALUE_NAME_LIST CodepageAttrvalueNames[] =
00263 {
00264     {4, ".com/",           0, 0x85},
00265     {4, ".edu/",           0, 0x86},
00266     {4, ".net/",           0, 0x87},
00267     {4, ".org/",           0, 0x88},
00268     {4, "accept",          0, 0x89},
00269     {4, "bottom",          0, 0x8a},
00270     {4, "clear",           0, 0x8b},
00271     {4, "delete",          0, 0x8c},
00272     {4, "help",            0, 0x8d},
00273     {4, "http://",         0, 0x8e},
00274     {4, "http://www.",     0, 0x8f},
00275     {4, "https://",        0, 0x90},
00276     {4, "https://www.",    0, 0x91},
00277     {4, "middle",          0, 0x93},
00278     {4, "nowrap",          0, 0x94},
00279     {4, "onenterbackward", 0, 0x96},
00280     {4, "onenterforward",  0, 0x97},
00281     {4, "onpick",          0, 0x95},
00282     {4, "ontimer",         0, 0x98},
00283     {4, "options",         0, 0x99},
00284     {4, "password",        0, 0x9a},
00285     {4, "reset",           0, 0x9b},
00286     {4, "text",            0, 0x9d},
00287     {4, "top",             0, 0x9e},
00288     {4, "unknown",         0, 0x9f},
00289     {4, "wrap",            0, 0xa0},
00290     {4, "www.",            0, 0xa1},
00291     {0, NULL, 0, 0}
00292 };
00293 
00294 
00295 /**************************
00296  * Node Tree Construction *
00297  **************************/
00298 
00299 /*
00300  * Function: NewNode
00301  *
00302  * Description:
00303  *
00304  *  Allocate and initialize a new node. This links the new node
00305  *  as the first child of the current node in the buffer. This causes
00306  *  child nodes to be linked in reverse order. If there is no current
00307  *  node, then the new node will be linked in as the first child at the
00308  *  top of the tree.
00309  *
00310  * Parameters:
00311  *
00312  *  buffer - WBXML buffer to link the new node into
00313  *  type   - Type of node to allocate
00314  *
00315  * Return value:
00316  *
00317  *  P_WBXML_NODE - A pointer to the newly allocated node.
00318  *
00319  */
00320 static P_WBXML_NODE NewNode(P_WBXML_INFO buffer, WBXML_NODE_TYPE type)
00321 {
00322     if (buffer)
00323     {
00324         P_WBXML_NODE newnode = malloc(sizeof(WBXML_NODE));
00325 
00326         if (newnode)
00327         {
00328             newnode->m_prev = NULL;
00329             newnode->m_child = NULL;
00330 
00331             if (buffer->m_curnode)
00332             {
00333                 /* Insert this node as the first child of the current node */
00334                 newnode->m_parent = buffer->m_curnode;
00335                 newnode->m_next = buffer->m_curnode->m_child;
00336 
00337                 if (buffer->m_curnode->m_child)
00338                 {
00339                     ((P_WBXML_NODE)buffer->m_curnode->m_child)->m_prev = newnode;
00340                 }
00341 
00342                 buffer->m_curnode->m_child = newnode;
00343             }
00344             else
00345             {
00346                 /* Insert this node at the top of the tree */
00347                 newnode->m_parent = NULL;
00348                 newnode->m_next = buffer->m_tree;
00349                 
00350                 if (buffer->m_tree)
00351                 {
00352                     buffer->m_tree->m_prev = newnode;
00353                 }
00354 
00355                 buffer->m_tree = newnode;
00356             }
00357 
00358             newnode->m_page = buffer->m_curpage;
00359             newnode->m_type = type;
00360             newnode->m_data = NULL;
00361         }
00362         else
00363         {
00364             ParseError(ERR_NOT_ENOUGH_MEMORY);
00365         }
00366 
00367         return newnode;
00368     }
00369     else
00370     {
00371         ParseError(ERR_INTERNAL_BAD_PARAM);
00372     }
00373 
00374     return NULL;
00375 }
00376 
00377 /*
00378  * Function: FreeNode
00379  *
00380  * Description:
00381  *
00382  *  Free a node, all its children and forward siblings.
00383  *
00384  * Parameters:
00385  *
00386  *  node - The node to free
00387  *
00388  */
00389 static void FreeNode(P_WBXML_NODE node)
00390 {
00391     if (node)
00392     {
00393         if (node->m_child)
00394         {
00395             FreeNode(node->m_child);
00396         }
00397 
00398         if (node->m_next)
00399         {
00400             FreeNode(node->m_next);
00401         }
00402 
00403         free(node);
00404     }
00405 }
00406 
00407 static void AddDTDNode(P_WBXML_INFO buffer, const WBXML_DTD_TYPE dtdnum, const WBXML_MB_U_INT32 index)
00408 {
00409     P_WBXML_NODE newnode = NewNode(buffer, NODE_DTD_TYPE);
00410     newnode->m_data = malloc(sizeof(DTD_NODE_DATA));
00411     memcpy( &( ((DTD_NODE_DATA*)newnode->m_data)->m_dtdnum ), &(dtdnum[0]), sizeof(WBXML_MB_U_INT32) );
00412     memcpy( &( ((DTD_NODE_DATA*)newnode->m_data)->m_index ), &(index[0]), sizeof(WBXML_MB_U_INT32) );
00413     dtd_id = (long) dtdnum[0];
00414 }
00415 
00416 static void AddStringTableNode(P_WBXML_INFO buffer, const P_WBXML_STRING_TABLE strings)
00417 {
00418     P_WBXML_NODE newnode = NewNode(buffer, NODE_STRING_TABLE);
00419     newnode->m_data = malloc(sizeof(WBXML_STRING_TABLE));
00420     memcpy( newnode->m_data, strings, sizeof(WBXML_STRING_TABLE) );
00421 }
00422 
00423 static void AddCodepageTagNode(P_WBXML_INFO buffer, WBXML_TAG tag)
00424 {
00425     P_WBXML_NODE newnode = NewNode(buffer, NODE_CODEPAGE_TAG);
00426     newnode->m_data = malloc(sizeof(WBXML_TAG));
00427     *((P_WBXML_TAG)newnode->m_data) = tag;
00428 }
00429 
00430 static void AddCodepageLiteralTagNode(P_WBXML_INFO buffer, WBXML_MB_U_INT32 index)
00431 {
00432     P_WBXML_NODE newnode = NewNode(buffer, NODE_CODEPAGE_LITERAL_TAG);
00433     newnode->m_data = malloc(sizeof(WBXML_MB_U_INT32));
00434     memcpy( ((P_WBXML_MB_U_INT32)newnode->m_data), &index, sizeof(WBXML_MB_U_INT32) );
00435 }
00436 
00437 static void AddAttrStartNode(P_WBXML_INFO buffer, WBXML_TAG tag)
00438 {
00439     P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRSTART);
00440     newnode->m_data = malloc(sizeof(WBXML_TAG));
00441     *((P_WBXML_TAG)newnode->m_data) = tag;
00442 }
00443 
00444 static void AddAttrStartLiteralNode(P_WBXML_INFO buffer, WBXML_MB_U_INT32 index)
00445 {
00446     P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRSTART_LITERAL);
00447     newnode->m_data = malloc(sizeof(WBXML_MB_U_INT32));
00448     memcpy( ((P_WBXML_MB_U_INT32)newnode->m_data), &index, sizeof(WBXML_MB_U_INT32) );
00449 }
00450 
00451 static void AddAttrValueNode(P_WBXML_INFO buffer, WBXML_TAG tag)
00452 {
00453     P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTRVALUE);
00454     newnode->m_data = malloc(sizeof(WBXML_TAG));
00455     *((P_WBXML_TAG)newnode->m_data) = tag;
00456 }
00457 
00458 static void AddAttrEndNode(P_WBXML_INFO buffer)
00459 {
00460     P_WBXML_NODE newnode = NewNode(buffer, NODE_ATTREND);
00461     newnode->m_data = NULL;
00462 }
00463 
00464 static void AddStringNode(P_WBXML_INFO buffer, char* string)
00465 {
00466     P_WBXML_NODE newnode = NewNode(buffer, NODE_STRING);
00467     newnode->m_data = strdup(string);
00468 }
00469 
00470 static void AddVariableStringNode(P_WBXML_INFO buffer, char* string, WBXML_VARIABLE_TYPE type)
00471 {
00472     /* TODO: add this node */
00473 }
00474 
00475 static void AddVariableIndexNode(P_WBXML_INFO buffer, char* string, WBXML_VARIABLE_TYPE type)
00476 {
00477     /* TODO: add this node */
00478 }
00479 
00480 
00481 /****************
00482  * Flow Control *
00483  ****************/
00484 
00485 void Message(char* msg)
00486 {
00487   printf("%s\n", msg);
00488 }
00489 
00490 void ParseError(WBXML_PARSE_ERROR error)
00491 {
00492   switch (error)
00493   {
00494     case ERR_END_OF_DATA:
00495       Message("Input stream is incomplete (EOF).");
00496       break;
00497 
00498     case ERR_INTERNAL_BAD_PARAM:
00499       Message("Internal error: Bad parameter.");
00500       break;
00501 
00502     case ERR_TAG_NOT_FOUND:
00503       Message("Tag not found.");
00504       break;
00505         
00506     case ERR_FILE_NOT_FOUND:
00507       Message("File not found.");
00508       break;
00509 
00510     case ERR_FILE_NOT_READ:
00511       Message("File read error.");
00512       break;
00513 
00514     case ERR_NOT_ENOUGH_MEMORY:
00515       Message("Not enough memory");
00516       break;
00517 
00518     default:
00519       Message("Unknown error.");
00520       break;
00521   }
00522 
00523   exit(error);
00524 }
00525 
00526 void ParseWarning(WBXML_PARSE_WARNING warning)
00527 {
00528   switch (warning)
00529   {
00530     case WARN_FUTURE_EXPANSION_EXT_0:
00531       Message("Token EXT_0 encountered. This token is reserved for future expansion.");
00532       break;
00533 
00534     case WARN_FUTURE_EXPANSION_EXT_1:
00535       Message("Token EXT_1 encountered. This token is reserved for future expansion.");
00536       break;
00537 
00538     case WARN_FUTURE_EXPANSION_EXT_2:
00539       Message("Token EXT_2 encountered. This token is reserved for future expansion.");
00540       break;
00541 
00542     default:
00543       Message("Unknown warning.");
00544       break;
00545   }
00546 }
00547 
00548 WBXML_LENGTH BytesLeft(P_WBXML_INFO buffer)
00549 {
00550   if (buffer)
00551   {
00552     WBXML_LENGTH bytesRead = (buffer->m_curpos - buffer->m_start);
00553     if (bytesRead >= buffer->m_length)
00554     {
00555       return 0;
00556     }
00557     else
00558     {
00559       return (buffer->m_length - bytesRead);
00560     }
00561   }
00562   else
00563   {
00564     ParseError(ERR_INTERNAL_BAD_PARAM);
00565   }
00566 
00567   return 0;
00568 }
00569 
00570 BOOL IsTag(P_WBXML_INFO buffer, WBXML_TAG tag)
00571 {
00572   BOOL result = FALSE;
00573 
00574   if (buffer)
00575   {
00576     if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
00577     {
00578       result = ((*((WBXML_TAG*) buffer->m_curpos)) == tag);
00579     }
00580     else
00581     {
00582         /* No more data, so nope, not this tag */
00583       result = FALSE;
00584     }
00585   }
00586   else
00587   {
00588     ParseError(ERR_INTERNAL_BAD_PARAM);
00589   }
00590 
00591   return result;
00592 }
00593 
00594 BOOL IsCodepageTag(P_WBXML_INFO buffer, CP_TAG_TYPE type)
00595 {
00596     WBXML_U_INT8 result = *(buffer->m_curpos);
00597 
00598     /* NOTE THAT THESE ARE NOT UNIQUE! */
00599     switch (type)
00600     {
00601         case CP_TAG_TAG:
00602             return TRUE;
00603         case CP_TAG_ATTRSTART:
00604             return ((result & 0x80) != 0x80);
00605         case CP_TAG_ATTRVALUE:
00606             return ((result & 0x80) == 0x80);
00607         default:
00608             return FALSE;
00609     }
00610 }
00611 
00612 BOOL Is_attrValue  (P_WBXML_INFO buffer)
00613 {
00614     WBXML_INFO tmpbuffer;
00615     memcpy(&tmpbuffer, buffer, sizeof(WBXML_INFO));
00616     tmpbuffer.m_curpos += SWITCHPAGE_SIZE;
00617 
00618     return ((Is_switchPage(buffer) && IsCodepageTag(&tmpbuffer, CP_TAG_ATTRVALUE)) ||
00619             IsCodepageTag(buffer, CP_TAG_ATTRVALUE) ||
00620             Is_string(buffer) ||
00621             Is_extension(buffer) ||
00622             Is_entity(buffer) ||
00623             Is_pi(buffer) ||
00624             Is_opaque(buffer));
00625 }
00626 
00627 BOOL Is_extension  (P_WBXML_INFO buffer)
00628 {
00629     WBXML_INFO tmpbuffer;
00630     memcpy(&tmpbuffer, buffer, sizeof(WBXML_INFO));
00631     tmpbuffer.m_curpos += SWITCHPAGE_SIZE;
00632 
00633     return ((Is_switchPage(buffer) &&
00634              (IsTag(&tmpbuffer, TAG_EXT_0) ||
00635               IsTag(&tmpbuffer, TAG_EXT_1) ||
00636               IsTag(&tmpbuffer, TAG_EXT_2) ||
00637               IsTag(&tmpbuffer, TAG_EXT_T_0) ||
00638               IsTag(&tmpbuffer, TAG_EXT_T_1) ||
00639               IsTag(&tmpbuffer, TAG_EXT_T_2) ||
00640               IsTag(&tmpbuffer, TAG_EXT_I_0) ||
00641               IsTag(&tmpbuffer, TAG_EXT_I_1) ||
00642               IsTag(&tmpbuffer, TAG_EXT_I_2))) ||
00643             (IsTag(buffer, TAG_EXT_0) ||
00644              IsTag(buffer, TAG_EXT_1) ||
00645              IsTag(buffer, TAG_EXT_2) ||
00646              IsTag(buffer, TAG_EXT_T_0) ||
00647              IsTag(buffer, TAG_EXT_T_1) ||
00648              IsTag(buffer, TAG_EXT_T_2) ||
00649              IsTag(buffer, TAG_EXT_I_0) ||
00650              IsTag(buffer, TAG_EXT_I_1) ||
00651              IsTag(buffer, TAG_EXT_I_2)));
00652 }
00653 
00654 BOOL Is_string     (P_WBXML_INFO buffer)
00655 {
00656     return (Is_inline(buffer) ||
00657             Is_tableref(buffer));
00658 }
00659 
00660 BOOL Is_switchPage (P_WBXML_INFO buffer)
00661 {
00662     return IsTag(buffer, TAG_SWITCH_PAGE);
00663 }
00664 
00665 BOOL Is_inline     (P_WBXML_INFO buffer)
00666 {
00667     return IsTag(buffer, TAG_STR_I);
00668 }
00669 
00670 BOOL Is_tableref   (P_WBXML_INFO buffer)
00671 {
00672     return IsTag(buffer, TAG_STR_T);
00673 }
00674 
00675 BOOL Is_entity     (P_WBXML_INFO buffer)
00676 {
00677     return IsTag(buffer, TAG_ENTITY);
00678 }
00679 
00680 BOOL Is_pi         (P_WBXML_INFO buffer)
00681 {
00682     return IsTag(buffer, TAG_PI);
00683 }
00684 
00685 BOOL Is_opaque     (P_WBXML_INFO buffer)
00686 {
00687     return IsTag(buffer, TAG_OPAQUE);
00688 }
00689 
00690 BOOL Is_zero(P_WBXML_INFO buffer)
00691 {
00692   BOOL result = FALSE;
00693 
00694   if (buffer) 
00695   {
00696     if (BytesLeft(buffer) >= 1) 
00697     {
00698       result = ((*buffer->m_curpos) == 0);
00699     }
00700     else
00701     {
00702       ParseError(ERR_END_OF_DATA);
00703     }
00704   }
00705   else
00706   {
00707     ParseError(ERR_INTERNAL_BAD_PARAM);
00708   }
00709 
00710   return result;
00711 }
00712 
00713 
00714 /***********************
00715  * Basic Type Decoders *
00716  ***********************/
00717 
00718 void Read_u_int8(P_WBXML_INFO buffer, P_WBXML_U_INT8 result)
00719 {
00720   if (buffer && result)
00721   {
00722     if (BytesLeft(buffer) >= 1) 
00723     {
00724       *result = *(buffer->m_curpos);
00725       (buffer->m_curpos)++;
00726     }
00727     else
00728     {
00729       ParseError(ERR_END_OF_DATA);
00730     }
00731   }
00732   else
00733   {
00734     ParseError(ERR_INTERNAL_BAD_PARAM);
00735   }
00736 }
00737 
00738 void Read_mb_u_int32(P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
00739 {
00740   if (buffer && result)
00741   {
00742     int i;
00743     for (i = 0; i < MAX_MB_U_INT32_BYTES; i++)
00744     {
00745       if (BytesLeft(buffer) >= 1)
00746       {
00747         (*result)[i] = *(buffer->m_curpos);
00748         (buffer->m_curpos)++;
00749 
00750         if ( !( (*result)[i] & 0x80 ) )
00751           break;
00752       }
00753       else
00754       {
00755         ParseError(ERR_END_OF_DATA);
00756       }
00757     }
00758   }
00759   else
00760   {
00761     ParseError(ERR_INTERNAL_BAD_PARAM);
00762   }
00763 }
00764 
00765 void Read_bytes(P_WBXML_INFO buffer, WBXML_LENGTH length, P_WBXML_BYTES result)
00766 {
00767   if (buffer && result)
00768   {
00769     if (BytesLeft(buffer) >= length) 
00770     {
00771       *result = (WBXML_BYTES) malloc(length*sizeof(unsigned char));
00772       memcpy(*result, buffer->m_curpos, length);
00773       buffer->m_curpos += length;
00774     }
00775     else
00776     {
00777       ParseError(ERR_END_OF_DATA);
00778     }
00779   }
00780   else
00781   {
00782     ParseError(ERR_INTERNAL_BAD_PARAM);
00783   }
00784 }
00785 
00786 void ReadFixedTag(P_WBXML_INFO buffer, WBXML_TAG tag)
00787 {
00788   if (buffer)
00789   {
00790     if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
00791     {
00792       if ((*((WBXML_TAG*) buffer->m_curpos)) == tag)
00793       {
00794         buffer->m_curpos += sizeof(WBXML_TAG);
00795       }
00796       else
00797       {
00798         ParseError(ERR_TAG_NOT_FOUND);
00799       }
00800     }
00801     else
00802     {
00803       ParseError(ERR_END_OF_DATA);
00804     }
00805   }
00806   else
00807   {
00808     ParseError(ERR_INTERNAL_BAD_PARAM);
00809   }
00810 }
00811 
00812 WBXML_TAG ReadCodepageTag (P_WBXML_INFO buffer, CP_TAG_TYPE type)
00813 {
00814   WBXML_TAG tag = 0;
00815 
00816   if (buffer)
00817   {
00818     if (BytesLeft(buffer) >= sizeof(WBXML_TAG))
00819     {
00820       tag = *((WBXML_TAG*) buffer->m_curpos);
00821 
00822       switch (type)
00823       {
00824         case CP_TAG_TAG:
00825           buffer->m_curpos += sizeof(WBXML_TAG);
00826           break;
00827 
00828         case CP_TAG_ATTRSTART:
00829           if ((tag & 0x80) != 0x80)
00830           {
00831             buffer->m_curpos += sizeof(WBXML_TAG);
00832           }
00833           else
00834           {
00835               ParseError(ERR_TAG_NOT_FOUND);
00836           }
00837           break;
00838 
00839         case CP_TAG_ATTRVALUE:
00840           if ((tag & 0x80) == 0x80)
00841           {
00842             buffer->m_curpos += sizeof(WBXML_TAG);
00843           }
00844           else
00845           {
00846               ParseError(ERR_TAG_NOT_FOUND);
00847           }
00848           break;
00849 
00850         default:
00851           ParseError(ERR_TAG_NOT_FOUND);
00852           break;
00853       }
00854     }
00855     else
00856     {
00857       ParseError(ERR_END_OF_DATA);
00858     }
00859   }
00860   else
00861   {
00862     ParseError(ERR_INTERNAL_BAD_PARAM);
00863   }
00864 
00865   return tag;
00866 }
00867 
00868 
00869 /**************************
00870  * Basic Type Conversions *
00871  **************************/
00872 
00873 long mb_u_int32_to_long(P_WBXML_MB_U_INT32 value)
00874 {
00875   long result = 0;
00876 
00877   if (value)
00878   {
00879     int i;
00880     for (i = 0; i < MAX_MB_U_INT32_BYTES; i++)
00881     {
00882       result <<= 7;
00883       result |= ((*value)[i] & 0x7f);
00884 
00885       if ( !( (*value)[i] & 0x80 ) )
00886         break;
00887     }
00888   }
00889   else
00890   {
00891     ParseError(ERR_INTERNAL_BAD_PARAM);
00892   }
00893 
00894   return result;
00895 }
00896 
00897 static void OutputEncodedString(const unsigned char* str)
00898 {
00899     /* Work our way down the string looking for illegal chars */
00900     while (*str != 0)
00901     {
00902         if ((*str < 0x20) || (*str > 0x7F))
00903         {
00904             /* Out of range... encode */
00905             printf("&#x%02x;", *str);
00906         }
00907         else
00908         {
00909             switch (*str)
00910             {
00911                 case '<':
00912                 case '>':
00913                 case '&':
00914                 case '\'':
00915                 case '\"':
00916                     /* Special symbol... encode */
00917                     printf("&#x%2x", *str);
00918                     break;
00919 
00920                 default:
00921                     printf("%c", *str);
00922                     break;
00923             }
00924         }
00925 
00926         str++;
00927     }
00928 }
00929 
00930 
00931 /*******************************
00932  * Document Structure Decoders *
00933  *******************************/
00934 
00935 void Read_start      (P_WBXML_INFO buffer)
00936 {
00937   Read_version(buffer);
00938   Read_publicid(buffer);
00939   Read_charset(buffer);
00940   Read_strtbl(buffer);
00941   Read_body(buffer);
00942 }
00943 
00944 void Read_strtbl     (P_WBXML_INFO buffer)
00945 {
00946   WBXML_STRING_TABLE result;
00947   Read_mb_u_int32(buffer, &(result.m_length));
00948   Read_bytes(buffer, mb_u_int32_to_long(&(result.m_length)), &(result.m_strings));
00949 
00950   AddStringTableNode(buffer, &result);
00951 }
00952 
00953 void Read_body       (P_WBXML_INFO buffer)
00954 {
00955   while (Is_pi(buffer))
00956   {
00957     Read_pi(buffer);
00958   }
00959 
00960   Read_element(buffer);
00961 
00962   while (Is_pi(buffer))
00963   {
00964     Read_pi(buffer);
00965   }
00966 }
00967 
00968 void Read_element    (P_WBXML_INFO buffer)
00969 {
00970   WBXML_TAG stagvalue = 0;
00971 
00972   if (Is_switchPage(buffer))
00973   {
00974     Read_switchPage(buffer);
00975   }
00976 
00977   stagvalue = Read_stag(buffer);
00978 
00979   /* move the current node down to this one in the tree */
00980   if (buffer->m_curnode)
00981       buffer->m_curnode = buffer->m_curnode->m_child;
00982   else buffer->m_curnode = buffer->m_tree;
00983 
00984   if ((stagvalue & CODEPAGE_TAG_HAS_ATTRS) == CODEPAGE_TAG_HAS_ATTRS)
00985   {
00986     do
00987     {
00988       Read_attribute(buffer);
00989 
00990     } while (!IsTag(buffer, TAG_END));
00991 
00992     ReadFixedTag(buffer, TAG_END);
00993 
00994     AddAttrEndNode(buffer);
00995   }
00996 
00997   if ((stagvalue & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
00998   {
00999     while (!IsTag(buffer, TAG_END))
01000     {
01001       Read_content(buffer);
01002     }
01003 
01004     ReadFixedTag(buffer, TAG_END);
01005   }
01006 
01007   /* move the current node back up one */
01008   buffer->m_curnode = buffer->m_curnode->m_parent;
01009 }
01010 
01011 void Read_content    (P_WBXML_INFO buffer)
01012 {
01013     if (Is_string(buffer))
01014     {
01015         Read_string(buffer);
01016     }
01017     else if (Is_extension(buffer))
01018     {
01019         Read_extension(buffer);
01020     }
01021     else if (Is_entity(buffer))
01022     {
01023         Read_entity(buffer);
01024     }
01025     else if (Is_pi(buffer))
01026     {
01027         Read_pi(buffer);
01028     }
01029     else if (Is_opaque(buffer))
01030     {
01031         Read_opaque(buffer);
01032     }
01033     else
01034     {
01035         /* Assume it is an element */
01036         Read_element(buffer);
01037     }
01038 }
01039 
01040 WBXML_TAG Read_stag       (P_WBXML_INFO buffer)
01041 {
01042     if (IsCodepageTag(buffer, CP_TAG_TAG))
01043     {
01044         WBXML_TAG tag = ReadCodepageTag(buffer, CP_TAG_TAG);
01045 
01046         AddCodepageTagNode(buffer, tag);
01047 
01048         return tag;
01049     }
01050     else if (IsTag(buffer, TAG_LITERAL))
01051     {
01052         WBXML_MB_U_INT32 index;
01053 
01054         ReadFixedTag(buffer, TAG_LITERAL);
01055         Read_index(buffer, &index);
01056 
01057         AddCodepageLiteralTagNode(buffer, index);
01058     }
01059     else
01060     {
01061         ParseError(ERR_TAG_NOT_FOUND);
01062     }
01063 
01064     return 0;
01065 }
01066 
01067 void Read_attribute  (P_WBXML_INFO buffer)
01068 {
01069     Read_attrStart(buffer);
01070 
01071     while (Is_attrValue(buffer))
01072     {
01073         Read_attrValue(buffer);
01074     }
01075 }
01076 
01077 void Read_attrStart  (P_WBXML_INFO buffer)
01078 {
01079   if (Is_switchPage(buffer))
01080   {
01081     WBXML_TAG tag;
01082     Read_switchPage(buffer);
01083     tag = ReadCodepageTag(buffer, CP_TAG_ATTRSTART);
01084 
01085     AddAttrStartNode(buffer, tag);
01086   }
01087   else if (IsCodepageTag(buffer, CP_TAG_ATTRSTART))
01088   {
01089     WBXML_TAG tag;
01090     tag = ReadCodepageTag(buffer, CP_TAG_ATTRSTART);
01091 
01092     AddAttrStartNode(buffer, tag);
01093   }
01094   else if (IsTag(buffer, TAG_LITERAL))
01095   {
01096     WBXML_MB_U_INT32 index;
01097 
01098     ReadFixedTag(buffer, TAG_LITERAL);
01099     Read_index(buffer, &index);
01100 
01101     AddAttrStartLiteralNode(buffer, index);
01102   }
01103   else
01104   {
01105     ParseError(ERR_TAG_NOT_FOUND);
01106   }
01107 }
01108 
01109 void Read_attrValue  (P_WBXML_INFO buffer)
01110 {
01111   if (Is_switchPage(buffer))
01112   {
01113     WBXML_TAG tag;
01114     Read_switchPage(buffer);
01115     tag = ReadCodepageTag(buffer, CP_TAG_ATTRVALUE);
01116     AddAttrValueNode(buffer, tag);
01117   }
01118   else if (IsCodepageTag(buffer, CP_TAG_ATTRVALUE))
01119   {
01120     WBXML_TAG tag;
01121     tag = ReadCodepageTag(buffer, CP_TAG_ATTRVALUE);
01122     AddAttrValueNode(buffer, tag);
01123   }
01124   else if (Is_string(buffer))
01125   {
01126     Read_string(buffer);
01127   }
01128   else if (Is_extension(buffer))
01129   {
01130     Read_extension(buffer);
01131   }
01132   else if (Is_entity(buffer))
01133   {
01134     Read_entity(buffer);
01135   }
01136   else if (Is_opaque(buffer))
01137   {
01138     Read_opaque(buffer);
01139   }
01140   else
01141   {
01142     ParseError(ERR_TAG_NOT_FOUND);
01143   }
01144 }
01145 
01146 void Read_extension  (P_WBXML_INFO buffer)
01147 {
01148     if (Is_switchPage(buffer))
01149     {
01150         Read_switchPage(buffer);
01151     }
01152 
01153     if (IsTag(buffer, TAG_EXT_I_0))
01154     {
01155         char* str = NULL;
01156 
01157         ReadFixedTag(buffer, TAG_EXT_I_0);
01158         Read_termstr_rtn(buffer, &str);
01159 
01160         AddVariableStringNode(buffer, str, VAR_ESCAPED); 
01161     }
01162     else if (IsTag(buffer, TAG_EXT_I_1))
01163     {
01164         char* str = NULL;
01165 
01166         ReadFixedTag(buffer, TAG_EXT_I_1);
01167         Read_termstr_rtn(buffer, &str);
01168 
01169         AddVariableStringNode(buffer, str, VAR_UNESCAPED); 
01170     }
01171     else if (IsTag(buffer, TAG_EXT_I_2))
01172     {
01173         char* str = NULL;
01174 
01175         ReadFixedTag(buffer, TAG_EXT_I_2);
01176         Read_termstr_rtn(buffer, &str);
01177 
01178         AddVariableStringNode(buffer, str, VAR_UNCHANGED); 
01179     }
01180     else if (IsTag(buffer, TAG_EXT_T_0))
01181     {
01182         WBXML_MB_U_INT32 index;
01183 
01184         ReadFixedTag(buffer, TAG_EXT_T_0);
01185         Read_index(buffer, &index);
01186 
01187         AddVariableIndexNode(buffer, index, VAR_ESCAPED);
01188     }
01189     else if (IsTag(buffer, TAG_EXT_T_1))
01190     {
01191         WBXML_MB_U_INT32 index;
01192 
01193         ReadFixedTag(buffer, TAG_EXT_T_1);
01194         Read_index(buffer, &index);
01195 
01196         AddVariableIndexNode(buffer, index, VAR_UNESCAPED);
01197     }
01198     else if (IsTag(buffer, TAG_EXT_T_2))
01199     {
01200         WBXML_MB_U_INT32 index;
01201 
01202         ReadFixedTag(buffer, TAG_EXT_T_2);
01203         Read_index(buffer, &index);
01204 
01205         AddVariableIndexNode(buffer, index, VAR_UNCHANGED);
01206     }
01207     else if (IsTag(buffer, TAG_EXT_0))
01208     {
01209         ReadFixedTag(buffer, TAG_EXT_0);
01210 
01211         ParseWarning(WARN_FUTURE_EXPANSION_EXT_0);
01212     }
01213     else if (IsTag(buffer, TAG_EXT_1))
01214     {
01215         ReadFixedTag(buffer, TAG_EXT_1);
01216 
01217         ParseWarning(WARN_FUTURE_EXPANSION_EXT_1);
01218     }
01219     else if (IsTag(buffer, TAG_EXT_2))
01220     {
01221         ReadFixedTag(buffer, TAG_EXT_2);
01222 
01223         ParseWarning(WARN_FUTURE_EXPANSION_EXT_2);
01224     }
01225     else
01226     {
01227         ParseError(ERR_TAG_NOT_FOUND);
01228     }
01229 }
01230 
01231 void Read_string     (P_WBXML_INFO buffer)
01232 {
01233     if (Is_inline(buffer))
01234     {
01235         Read_inline(buffer);
01236     }
01237     else if (Is_tableref(buffer))
01238     {
01239         Read_tableref(buffer);
01240     }
01241     else
01242     {
01243         ParseError(ERR_TAG_NOT_FOUND);
01244     }
01245 }
01246 
01247 void Read_switchPage (P_WBXML_INFO buffer)
01248 {
01249   WBXML_U_INT8 pageindex;
01250 
01251   ReadFixedTag(buffer, TAG_SWITCH_PAGE);
01252   Read_pageindex(buffer, &pageindex);
01253 
01254   /* Use the new codepage */
01255   buffer->m_curpage = pageindex;
01256 }
01257 
01258 void Read_inline     (P_WBXML_INFO buffer)
01259 {
01260     ReadFixedTag(buffer, TAG_STR_I);
01261     Read_termstr(buffer);
01262 }
01263 
01264 void Read_tableref   (P_WBXML_INFO buffer)
01265 {
01266   WBXML_MB_U_INT32 index;
01267 
01268   ReadFixedTag(buffer, TAG_STR_T);
01269   Read_index(buffer, &index);
01270 }
01271 
01272 void Read_entity     (P_WBXML_INFO buffer)
01273 {
01274     ReadFixedTag(buffer, TAG_ENTITY);
01275     Read_entcode(buffer);
01276 }
01277 
01278 void Read_entcode    (P_WBXML_INFO buffer)
01279 {
01280     WBXML_MB_U_INT32 result;
01281     Read_mb_u_int32(buffer, &result);
01282 }
01283 
01284 void Read_pi         (P_WBXML_INFO buffer)
01285 {
01286   ReadFixedTag(buffer, TAG_PI);
01287   Read_attrStart(buffer);
01288   
01289   while (Is_attrValue(buffer))
01290   {
01291     Read_attrValue(buffer);
01292   }
01293 
01294   ReadFixedTag(buffer, TAG_END);
01295 }
01296 
01297 void Read_opaque     (P_WBXML_INFO buffer)
01298 {
01299   WBXML_MB_U_INT32 length;
01300   WBXML_BYTES      data;
01301 
01302   ReadFixedTag(buffer, TAG_OPAQUE);
01303   Read_length(buffer, &length);
01304   Read_bytes(buffer, mb_u_int32_to_long(&length), &data);
01305 }
01306 
01307 void Read_version    (P_WBXML_INFO buffer)
01308 {
01309   WBXML_U_INT8 result;
01310 
01311   Read_u_int8(buffer, &result);
01312 }
01313 
01314 void Read_publicid   (P_WBXML_INFO buffer)
01315 {
01316   if (Is_zero(buffer))
01317   {
01318     WBXML_MB_U_INT32 index;
01319 
01320     Read_index(buffer, &index);
01321 
01322     AddDTDNode(buffer, ZERO_WBXML_MB_U_INT32, index);
01323   }
01324   else
01325   {
01326     WBXML_MB_U_INT32 result;
01327 
01328     Read_mb_u_int32(buffer, &result);
01329 
01330     AddDTDNode(buffer, result, ZERO_WBXML_MB_U_INT32);
01331   }
01332 }
01333 
01334 void Read_charset    (P_WBXML_INFO buffer)
01335 {
01336   WBXML_MB_U_INT32 result;
01337 
01338   Read_mb_u_int32(buffer, &result);
01339 }
01340 
01341 void Read_termstr_rtn(P_WBXML_INFO buffer, char** result)
01342 {
01343 
01344 #define STRING_BLOCK_SIZE 256
01345 
01346     int buflen = STRING_BLOCK_SIZE;
01347     char* strbuf = (char*) malloc(buflen);
01348     BOOL doubled = FALSE;
01349     int i = 0;
01350 
01351     if (!result)
01352         ParseError(ERR_INTERNAL_BAD_PARAM);
01353 
01354     while ( (BytesLeft(buffer) >= 1) && (*(buffer->m_curpos) != 0) )
01355     {
01356         if (i>=buflen)
01357         {
01358             buflen += STRING_BLOCK_SIZE;
01359             strbuf = realloc(strbuf, buflen);
01360         }
01361 
01362         if (*(buffer->m_curpos) != '$' || doubled == TRUE)
01363         {
01364             strbuf[i] = *(buffer->m_curpos);
01365             buffer->m_curpos++;
01366             i++;
01367             if (doubled == TRUE)
01368                 doubled = FALSE;
01369         }
01370         else
01371         {
01372             strbuf[i] = *(buffer->m_curpos);
01373             i++;
01374             doubled = TRUE;
01375         }
01376     }
01377 
01378     strbuf[i] = 0;
01379     buffer->m_curpos++;
01380 
01381     if (*result)
01382         free(*result);
01383 
01384     *result = strbuf;
01385 }
01386 
01387 void Read_termstr    (P_WBXML_INFO buffer)
01388 {
01389     char* strbuf = NULL;
01390 
01391     Read_termstr_rtn(buffer, &strbuf);
01392 
01393     AddStringNode(buffer, strbuf);
01394 
01395     free(strbuf);
01396 }
01397 
01398 void Read_index      (P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
01399 {
01400   Read_mb_u_int32(buffer, result);
01401 }
01402 
01403 void Read_length     (P_WBXML_INFO buffer, P_WBXML_MB_U_INT32 result)
01404 {
01405   Read_mb_u_int32(buffer, result);
01406 }
01407 
01408 void Read_zero       (P_WBXML_INFO buffer)
01409 {
01410   WBXML_U_INT8 result;
01411 
01412   Read_u_int8(buffer, &result);
01413 
01414   if (result != (WBXML_U_INT8) 0)
01415   {
01416     ParseError(ERR_TAG_NOT_FOUND);
01417   }
01418 }
01419 
01420 void Read_pageindex  (P_WBXML_INFO buffer, P_WBXML_U_INT8 result)
01421 {
01422   Read_u_int8(buffer, result);
01423 }
01424 
01425 static void Init(P_WBXML_INFO buffer)
01426 {
01427     buffer->m_start = NULL;
01428     buffer->m_curpos = NULL;
01429     buffer->m_length = 0;
01430     buffer->m_tree = NULL;
01431     buffer->m_curnode = NULL;
01432     buffer->m_curpage = 0;
01433 }
01434 
01435 static size_t BufferLength(P_WBXML_INFO buffer)
01436 {
01437     size_t ret;
01438 
01439     while (buffer->m_curpos != '\0')
01440         buffer->m_curpos++;
01441 
01442     ret = buffer->m_curpos - buffer->m_start;
01443     buffer->m_curpos = buffer->m_start;
01444     return ret;
01445 }
01446 
01447 static void Free(P_WBXML_INFO buffer)
01448 {
01449     if (buffer->m_start)
01450     {
01451         free(buffer->m_start);
01452         buffer->m_start = NULL;
01453     }
01454 
01455     buffer->m_curpos = NULL;
01456     buffer->m_length = 0;
01457 
01458     FreeNode(buffer->m_tree);
01459     buffer->m_tree = NULL;
01460 }
01461 
01462 static long FileSize(FILE* file)
01463 {
01464     long curpos = ftell(file);
01465     long endpos;
01466     fseek(file, 0, SEEK_END);
01467     endpos = ftell(file);
01468     fseek(file, curpos, SEEK_SET);
01469 
01470     return endpos;
01471 }
01472 
01473 static void ReadBinary(P_WBXML_INFO buffer, FILE* file)
01474 {
01475     char buf[4096];
01476     int m = 1;
01477     long n;
01478 
01479     if (buffer && file)
01480     {
01481         if (file != stdin)
01482         {
01483             buffer->m_length = FileSize(file);
01484             buffer->m_start = (P_WBXML) malloc(buffer->m_length);
01485             buffer->m_curpos = buffer->m_start;
01486 
01487             if (!buffer->m_start)
01488             {
01489                 fclose(file);
01490                 ParseError(ERR_NOT_ENOUGH_MEMORY);
01491             }
01492 
01493             if (fread(buffer->m_start, 1, buffer->m_length, file) != buffer->m_length)
01494             {
01495                 fclose(file);
01496                 ParseError(ERR_FILE_NOT_READ);
01497             }
01498             else
01499             {
01500                 fclose(file);
01501             }
01502         }
01503         else
01504         {
01505             while ((n = fread(buf, 1, sizeof(buf), file)) > 0)
01506             {
01507                 buffer->m_start = (P_WBXML) realloc(buffer->m_start, sizeof(buf) * m);
01508                 memcpy(buffer->m_start + (sizeof(buf) * (m - 1)), buf, sizeof(buf));
01509                 m++;
01510             }
01511             buffer->m_length = BufferLength(buffer);
01512             buffer->m_curpos = buffer->m_start;
01513         }
01514                 
01515     }
01516     else
01517     {
01518         ParseError(ERR_INTERNAL_BAD_PARAM);
01519     }
01520 }
01521 
01522 static const char* DTDTypeName(long dtdnum)
01523 {
01524     int i = 0;
01525 
01526     /* Search the DTD list for a match */
01527     while (DTDTypeList[i].m_name)
01528     {
01529         if (DTDTypeList[i].m_id == dtdnum)
01530         {
01531             break;
01532         }
01533 
01534         i++;
01535     }
01536 
01537     return DTDTypeList[i].m_name;
01538 }
01539 
01540 static const char* CodepageTagName(WBXML_CODEPAGE page, WBXML_TAG tag)
01541 {
01542     int i = 0;
01543 
01544     /* Strip flags off of the tag */
01545     tag = (WBXML_TAG) (tag & CODEPAGE_TAG_MASK);
01546 
01547     /* Search the tag list for a match */
01548     while (CodepageTagNames[i].m_name)
01549     {
01550         if ((CodepageTagNames[i].m_dtd_id == dtd_id) &&
01551             (CodepageTagNames[i].m_page == page) &&
01552             (CodepageTagNames[i].m_tag == tag))
01553         {
01554             break;
01555         }
01556 
01557         i++;
01558     }
01559 
01560     return CodepageTagNames[i].m_name;
01561 }
01562 
01563 static const char* CodepageAttrstartName(WBXML_CODEPAGE page, WBXML_TAG tag, char** value)
01564 {
01565     int i = 0;
01566 
01567     /* Check Parameters */
01568     if (!value)
01569     {
01570         ParseError(ERR_INTERNAL_BAD_PARAM);
01571     }
01572 
01573     /* Search the tag list for a match */
01574     while (CodepageAttrstartNames[i].m_name)
01575     {
01576         if ((CodepageAttrstartNames[i].m_dtd_id == dtd_id) &&
01577             (CodepageAttrstartNames[i].m_page == page) &&
01578             (CodepageAttrstartNames[i].m_tag == tag))
01579         {
01580             break;
01581         }
01582 
01583         i++;
01584     }
01585 
01586     /* Duplicate the value because it may be concatenated to */
01587     if (CodepageAttrstartNames[i].m_valueprefix)
01588     {
01589         *value = strdup(CodepageAttrstartNames[i].m_valueprefix);
01590     }
01591     else
01592     {
01593         *value = NULL;
01594     }
01595 
01596     /* Return the tag name */
01597     return CodepageAttrstartNames[i].m_name;
01598 }
01599 
01600 static void CodepageAttrvalueName(WBXML_CODEPAGE page, WBXML_TAG tag, char** value)
01601 {
01602     int i = 0;
01603 
01604     /* Check Parameters */
01605     if (!value)
01606     {
01607         ParseError(ERR_INTERNAL_BAD_PARAM);
01608     }
01609 
01610     /* Search the tag list for a match */
01611     while (CodepageAttrvalueNames[i].m_name)
01612     {
01613         if ((CodepageAttrvalueNames[i].m_dtd_id == dtd_id) &&
01614             (CodepageAttrvalueNames[i].m_page == page) &&
01615             (CodepageAttrvalueNames[i].m_tag == tag))
01616         {
01617             break;
01618         }
01619 
01620         i++;
01621     }
01622 
01623     /* concatenate the value */
01624     if (CodepageAttrvalueNames[i].m_name)
01625     {
01626         if (*value)
01627         {
01628             *value = realloc(*value, strlen(*value) + strlen(CodepageAttrvalueNames[i].m_name) + 1);
01629             strcat(*value, CodepageAttrvalueNames[i].m_name);
01630         }
01631         else
01632         {
01633             *value = strdup(CodepageAttrvalueNames[i].m_name);
01634         }
01635     }
01636 }
01637 
01638 static const char* GetStringTableString(P_WBXML_NODE node, long index)
01639 {
01640     /* Find the string table node */
01641 
01642     P_WBXML_NODE pStringsNode = node;
01643 
01644     while (pStringsNode->m_parent)
01645     {
01646         pStringsNode = pStringsNode->m_parent;
01647     }
01648 
01649     while (pStringsNode->m_next)
01650     {
01651         pStringsNode = pStringsNode->m_next;
01652     }
01653 
01654     while (pStringsNode->m_prev && pStringsNode->m_type != NODE_STRING_TABLE)
01655     {
01656         pStringsNode = pStringsNode->m_prev;
01657     }
01658 
01659     if (pStringsNode->m_type != NODE_STRING_TABLE)
01660     {
01661         return "!!NO STRING TABLE!!";
01662     }
01663 
01664     /* Find the indexed string */
01665 
01666     if ((index >= 0) && (index < mb_u_int32_to_long(&((P_WBXML_STRING_TABLE)pStringsNode->m_data)->m_length)))
01667     {
01668         return (const char*) &(((P_WBXML_STRING_TABLE)pStringsNode->m_data)->m_strings[index]);
01669     }
01670     else
01671     {
01672         return "!!STRING TABLE INDEX TOO LARGE!!";
01673     }
01674 }
01675 
01676 static void DumpNode(P_WBXML_NODE node, int indent, BOOL *inattrs, BOOL hascontent, char** value)
01677 {
01678     P_WBXML_NODE curnode = node->m_child;
01679 
01680     WBXML_TAG nodetype = 0;
01681     long dtdnum = 0;
01682 
01683     BOOL bAttributesFollow = FALSE;
01684     BOOL bHasContent = FALSE;
01685 
01686     int i;
01687 
01688     if (!(*inattrs))
01689     {
01690         for (i=0; i<indent; i++)
01691         {
01692             printf(" ");
01693         }
01694     }
01695     else
01696     {
01697         if ((node->m_type != NODE_ATTRVALUE) && (*value))
01698         {
01699             printf("=\"");
01700             OutputEncodedString((unsigned char*) *value);
01701             printf("\"");
01702             free(*value);
01703             *value = NULL;
01704         }
01705     }
01706 
01707     switch (node->m_type)
01708     {
01709         case NODE_DTD_TYPE:
01710             printf("<?xml version=\"1.0\"?>\n<!DOCTYPE wml PUBLIC ");
01711 
01712             dtdnum = mb_u_int32_to_long( &((DTD_NODE_DATA*)node->m_data)->m_dtdnum );
01713             if ( dtdnum == 0)
01714             {
01715                 printf("\"%s\">\n\n", GetStringTableString(node, mb_u_int32_to_long(&((DTD_NODE_DATA*)node->m_data)->m_index)) );
01716             }
01717             else
01718             {
01719                 printf("\"%s\">\n\n", DTDTypeName(dtdnum) );
01720             }
01721             break;
01722 
01723         case NODE_CODEPAGE_TAG:
01724             nodetype = *((P_WBXML_TAG)node->m_data);
01725             if ((nodetype & CODEPAGE_TAG_MASK) == nodetype)
01726             {
01727                 printf("<%s/>\n", CodepageTagName(node->m_page, nodetype));
01728             }
01729             else
01730             {
01731                 if ((nodetype & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
01732                 {
01733                     bHasContent = TRUE;
01734                 }
01735 
01736                 if ((nodetype & CODEPAGE_TAG_HAS_ATTRS) == CODEPAGE_TAG_HAS_ATTRS)
01737                 {
01738                     printf("<%s", CodepageTagName(node->m_page, nodetype));
01739                     bAttributesFollow = TRUE;
01740                 }
01741                 else
01742                 {
01743                     printf("<%s>\n", CodepageTagName(node->m_page, nodetype));
01744                 }
01745             }
01746             break;
01747 
01748         case NODE_CODEPAGE_LITERAL_TAG:
01749             printf("<%s>\n", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
01750             break;
01751 
01752         case NODE_ATTRSTART:
01753             printf(" %s", CodepageAttrstartName(node->m_page, *((P_WBXML_TAG)node->m_data), value) );
01754             break;
01755 
01756         case NODE_ATTRSTART_LITERAL:
01757             printf(" %s", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
01758             break;
01759 
01760         case NODE_ATTRVALUE:
01761             CodepageAttrvalueName(node->m_page, *((P_WBXML_TAG)node->m_data), value);
01762             break;
01763 
01764         case NODE_ATTREND:
01765             if (!hascontent)
01766             {
01767                 printf("/");
01768             }
01769             printf(">\n");
01770             *inattrs = FALSE;
01771             break;
01772 
01773         case NODE_STRING:
01774             if (*inattrs)
01775             {
01776                 /* concatenate the value */
01777                 if (*value)
01778                 {
01779                     if (node->m_data)
01780                     {
01781                         *value = realloc(*value, strlen(*value) + strlen((char*) node->m_data) + 1);
01782                         strcat(*value, (char*) node->m_data);
01783                     }
01784                 }
01785                 else
01786                 {
01787                     if (node->m_data)
01788                     {
01789                         *value = strdup((char*) node->m_data);
01790                     }
01791                 }
01792             }
01793             else
01794             {
01795                 OutputEncodedString((unsigned char*) node->m_data);
01796                 printf("\n");
01797             }
01798             break;
01799 
01800         case NODE_VARIABLE_STRING:
01801             /* TODO: output variable string */
01802             break;
01803 
01804         case NODE_VARIABLE_INDEX:
01805             /* TODO: output variable string */
01806             break;
01807 
01808         default:
01809             break;
01810     }
01811 
01812     indent += INDENT_SIZE;
01813 
01814     if (curnode)
01815     {
01816         while (curnode->m_next) curnode = curnode->m_next;
01817 
01818         while (curnode)
01819         {
01820             DumpNode(curnode, indent, &bAttributesFollow, bHasContent, value);
01821             curnode = curnode->m_prev;
01822         }
01823     }
01824 
01825     indent -= INDENT_SIZE;
01826 
01827     /* Output the element end if we have one */
01828     if ((nodetype & CODEPAGE_TAG_HAS_CONTENT) == CODEPAGE_TAG_HAS_CONTENT)
01829     {
01830         for (i=0; i<indent; i++)
01831         {
01832             printf(" ");
01833         }
01834 
01835         switch (node->m_type)
01836         {
01837             case NODE_CODEPAGE_TAG:
01838                 printf("</%s>\n", CodepageTagName(node->m_page, *((P_WBXML_TAG)node->m_data)) );
01839                 break;
01840 
01841             case NODE_CODEPAGE_LITERAL_TAG:
01842                 printf("</%s>\n", GetStringTableString(node, mb_u_int32_to_long(((P_WBXML_MB_U_INT32)node->m_data))) );
01843                 break;
01844 
01845             default:
01846                 break;
01847         }
01848     }
01849 }
01850 
01851 static void DumpNodes(P_WBXML_INFO buffer)
01852 {
01853     P_WBXML_NODE curnode = buffer->m_tree;
01854     BOOL bAttrsFollow = FALSE;
01855     char* value = NULL;
01856 
01857     if (curnode)
01858     {
01859         while (curnode->m_next) curnode = curnode->m_next;
01860 
01861         while (curnode)
01862         {
01863             DumpNode(curnode, 0, &bAttrsFollow, FALSE, &value);
01864             curnode = curnode->m_prev;
01865         }
01866     }
01867 }
01868 
01869 int main(int argc, char** argv)
01870 {
01871     WBXML_INFO buffer;
01872     FILE* file;
01873 
01874     if (argc < 2)
01875     {
01876         file = stdin;
01877     }
01878     else
01879     {
01880             file = fopen(argv[1], "r");
01881         if (!file)
01882         {
01883             ParseError(ERR_FILE_NOT_FOUND);
01884         }
01885     }
01886 
01887     Init(&buffer);
01888     ReadBinary(&buffer, file);
01889     Read_start(&buffer);
01890     DumpNodes(&buffer);
01891     Free(&buffer);
01892 
01893     return 0;
01894 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.