wmls.c

来自「WAP browser is based on the Wireless App」· C语言 代码 · 共 1,474 行 · 第 1/3 页

C
1,474
字号
/* 
 * Copyright (c) 2004, TapTarget. All rights reserved.
 * Copyright (c) 2002-2004, Yuri Plaksyuk (york@noir.crocodile.org).
 *
 * http://www.taptarget.com/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *      - Redistributions of source code must retain the above
 *      copyright notice, this list of conditions and the following
 *      disclaimer.
 * 
 *      - 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.
 * 
 *      - All advertising materials mentioning features or use of this
 *      software must display the following acknowledgement: This
 *      product includes software developed by TapTarget.
 * 
 *      - The name of TapTarget may not be used to endorse or
 *      promote products derived from this software without specific
 *      prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY TAPTARGET "AS IS" AND ANY EXPRESS
 * 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 TAPTARGET 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.
 * 
 * $Id: wmls.c,v 1.4 2004/05/13 10:19:24 york Exp $ 
 */

#include "wmls.h"
#include "wmlscode.h"
#include "MathLib.h"

static ScriptModule *ScriptLoadModule(ScriptLibGlobals *gP, const Char *uri, UInt16 len, Err *errP);
static Int16 ScriptFindFunc(ScriptModule *m, Char *str, UInt16 strlen);
static Err   ScriptFuncCall(ScriptLibGlobals *gP, ScriptModule *m, UInt8 findex);
static Err   ScriptLibFuncCall(ScriptLibGlobals *gP, UInt16 lindex, UInt8 findex);
static Err   ScriptUrlFuncCall(ScriptLibGlobals *gP, UInt16 uindex, UInt8 findex);
static Int32 ReadIntMB(UInt8 *buf, UInt16 *offsetP);


Err ScriptExecute(ScriptLibGlobals *gP, const Char *uri, ScriptSlot *rs)
{
    Int16 findex;
    UInt8 argc = 0;
    Char *str, *ptr;
    Err err = errNone;

    ScriptModule *m;
    ScriptSlot *stack;
    ScriptFunction *fp;


    str = StrChr(uri, '#');
    if(str == NULL) return scriptErrInvalidURI;

    m = ScriptLoadModule(gP, uri, str - uri, &err);
    if(m == NULL) return err;

    ptr = StrChr(++str, '(');
    if(ptr == NULL) return scriptErrInvalidURI;

    findex = ScriptFindFunc(m, str, ptr - str);
    if(findex < 0) return scriptErrFunctionNotFound;

    stack = MemPtrNew(sizeof(ScriptSlot) * gP->stackSize);
    if(stack == NULL) return scriptErrMemory;

    gP->sp = stack + gP->stackSize; // initialize stack pointer

    while(1)
    {
        // push function parameters into the stack
        ptr++;

        while(*ptr == ' ') ptr++; // skip spaces

        if(*ptr == ')') break;

        ptr = SlotParseConst(--gP->sp, ptr), argc++;
        if(ptr == NULL) { err = scriptErrSyntax; goto __cleanup; }

        while(*ptr == ' ') ptr++; // skip spaces

        if(*ptr == ')') break;
        if(*ptr != ',') { err = scriptErrSyntax; goto __cleanup; }
    }


    // check number of parameters
    fp = m->func_table + findex;
    if(argc != fp->arg_count)
    {
        err = scriptErrVerificationFailed;
        goto __cleanup;
    }

    // execute function
    err = ScriptFuncCall(gP, m, findex);
    if(err) goto __cleanup;

    // save result into result slot
    rs->type     = gP->sp->type;
    rs->value.a  = gP->sp->value.a;
    SLOT_FREE(gP->sp);

__cleanup:
    while(gP->sp < stack + gP->stackSize) { SLOT_POP(gP->sp); }
    MemPtrFree(stack);

    return err;
}

Err ScriptUnloadModules(ScriptLibGlobals *gP)
{
    ScriptModule *m = gP->modules, *p;
    UInt16 i;

    while(m)
    {
        if(m->uri)
            MemPtrFree(m->uri);

        if(m->const_pool)
        {
            for(i = 0; i < m->const_count; i++)
                SlotFree(m->const_pool + i);
            MemPtrFree(m->const_pool);
        }

        if(m->func_table)
            MemPtrFree(m->func_table);

        p = m, m = m->next;

        gP->hostP->UnloadModule(p->moduleP);
        MemPtrFree(p);
    }

    gP->modules = NULL;
    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////

static ScriptModule *ScriptLoadModule(ScriptLibGlobals *gP, const Char *uri, UInt16 len, Err *errP)
{
    ScriptModule *m;
    UInt16 offset, i;
    UInt8 *moduleP;

    *errP = 0;

    // find it among already loaded modules
    for(m = gP->modules; m; m = m->next)
    {
        if(StrNCompare(m->uri, uri, len) == 0 && m->uri[len] == 0)
            return m;
    }

    // load module from the host
    *errP = gP->hostP->LoadModule(uri, len, (void**)&moduleP, &offset);
    if(*errP) return NULL;

    // parse module
    m = MemPtrNew(sizeof(ScriptModule));
    if(m == NULL) { *errP = scriptErrMemory; return NULL; }

    offset++; // skip version info

    MemSet(m, sizeof(ScriptModule), 0);
    m->uri           = ScriptStrCopyEx(uri, len);
    m->moduleP       = moduleP;
    m->code_size     = ReadIntMB(moduleP, &offset);
    m->const_count   = ReadIntMB(moduleP, &offset);
    m->const_charset = ReadIntMB(moduleP, &offset);

    if(m->const_count)
    {
        m->const_pool = MemPtrNew(sizeof(ScriptSlot) * m->const_count);
        if(m->const_pool == NULL) { *errP = scriptErrMemory; return NULL; }

        for(i = 0; i < m->const_count; i++)
            SlotLoadConst(m->const_pool + i, moduleP, &offset);
    }

    // pragma pool
    m->pragma_count = ReadIntMB(moduleP, &offset);
    for(i = 0; i < m->pragma_count; i++)
        switch(moduleP[offset++])
        {
        case 0: // Access Domain
        case 1: // Access Path
            ReadIntMB(moduleP, &offset);
            break;

        case 2: // User Agent Property
            ReadIntMB(moduleP, &offset);
            ReadIntMB(moduleP, &offset);
            break;

        case 3: // User Agent Property and Scheme
            ReadIntMB(moduleP, &offset);
            ReadIntMB(moduleP, &offset);
            ReadIntMB(moduleP, &offset);
            break;
        }

    // function pool
    m->func_count   = moduleP[offset++];
    m->export_count = moduleP[offset++];
    m->export_table = moduleP + offset;

    // skip exported function names
    for(i = 0; i < m->export_count; i++)
        offset += moduleP[offset + 1] + 2;

    m->func_table = MemPtrNew(sizeof(ScriptFunction) * m->func_count);
    if(m->func_table == NULL) { *errP = scriptErrMemory; return NULL; }

    for(i = 0; i < m->func_count; i++)
    {
        ScriptFunction *fp = m->func_table + i;

        fp->arg_count = moduleP[offset++];
        fp->var_count = moduleP[offset++];
        fp->code_size = ReadIntMB(moduleP, &offset);
        fp->code      = moduleP + offset;

        offset += fp->code_size;
    }

    return m->next = gP->modules, gP->modules = m;
}

static Int16 ScriptFindFunc(ScriptModule *m, Char *str, UInt16 strlen)
{
    UInt16 i;

    UInt8 *ptr = m->export_table;
    UInt8 findex, length;

    for(i = 0; i < m->export_count; i++)
    {
        findex = *ptr++; // exported function index
        length = *ptr++; // exported function name length

        if(length == strlen && StrNCompare(ptr, str, strlen) == 0)
            return findex;

        ptr += length;   // go to next name entry
    }

    return -1;
}

static Err ScriptFuncCall(ScriptLibGlobals *gP, ScriptModule *m, UInt8 findex)
{
    ScriptFunction *fp;
    ScriptSlot *bp, *xp, *tp;
    UInt8 *ip, *code_end;
    UInt16 i;
    Err err;
    FlpCompDouble flpArg1;
    FlpCompDouble flpArg2;
    FlpCompDouble theCompFloat;

    if(findex >= m->func_count)
        goto __verification_failed; 

    fp = m->func_table + findex;
    bp = gP->sp + fp->arg_count - 1; // TODO: check for stack underflow!!!
    ip = fp->code;

    for(i = 0; i < fp->var_count; i++)
    {
        SLOT_PUSH_STRING(gP->sp, NULL);
    }

    code_end = ip + fp->code_size;
    while(ip < code_end)
    {
        switch(*ip)
        {
        case RESERVED_00:
            goto __illegal_instruction;

        case JUMP_FW:
            ip += *(++ip);
            break;

        case JUMP_FW_W:
            ip += *(UInt16*)(++ip) + 1;
            break;

        case JUMP_BW:
            ip -= *(ip + 1);
            continue;

        case JUMP_BW_W:
            ip -= *(UInt16*)(ip + 1);
            continue;

        case TJUMP_FW:
            if(SLOT_IS_FALSE(gP->sp)) ip += *(++ip);
            SLOT_POP(gP->sp);
            break;
            
        case TJUMP_FW_W:
            if(SLOT_IS_FALSE(gP->sp)) ip += *(UInt16*)(++ip) + 1;
            SLOT_POP(gP->sp);
            break;
            
        case TJUMP_BW:
            if(SLOT_IS_FALSE(gP->sp)) ip -= *(ip + 1);
            SLOT_POP(gP->sp);
            continue;

        case TJUMP_BW_W:
            if(SLOT_IS_FALSE(gP->sp)) ip -= *(UInt16*)(ip + 1);
            SLOT_POP(gP->sp);
            break;

        case CALL:
            err = ScriptFuncCall(gP, m, *(++ip));
            if(err) return err;
            break;

        case CALL_LIB:
            err = ScriptLibFuncCall(gP, *(++ip), *(++ip));
            if(err) return err;

            break;

        case CALL_LIB_W:
            err = ScriptLibFuncCall(gP, *(UInt16*)(++ip), *(++ip));
            if(err) return err;

            ++ip;
            break;

        case CALL_URL:
            err = ScriptUrlFuncCall(gP, *(++ip), *(++ip));
            if(err) return err;

            break;

        case CALL_URL_W:
            err = ScriptUrlFuncCall(gP, *(UInt16*)(++ip), *(++ip));
            if(err) return err;

            ++ip;
            break;

        case LOAD_VAR:
            SLOT_PUSH_VAR(gP->sp, bp - *(++ip));
            break;

        case STORE_VAR:
            SLOT_SAVE_VAR(gP->sp, bp - *(++ip));
            break;

        case INCR_VAR:
	    tp = bp - *(++ip);
	    if (tp->type == scriptTypeInteger) {
            	SLOT_TO_INTEGER(tp);
            	xp->value.n++;
	    }
	    else {
            	SLOT_TO_FLOAT(tp);
	    	//xp->value.f++;
		flpArg1.d = xp->value.f;
		flpArg2.d = 1.0;
		FlpBufferCorrectedAdd(&theCompFloat.fd, flpArg1.fd, flpArg2.fd, kDefAccuracy); 
		xp->value.f = theCompFloat.d;
	    }
            break;

        case DECR_VAR:
	    tp = bp - *(++ip);
	    if (tp->type == scriptTypeInteger) {
            	SLOT_TO_INTEGER(tp);
            	xp->value.n--;
	    }
	    else {
	    	SLOT_TO_FLOAT(tp);
            	//xp->value.f--;
		flpArg1.d = xp->value.f;
		flpArg2.d = 1.0;
		FlpBufferCorrectedSub(&theCompFloat.fd, flpArg1.fd, flpArg2.fd, kDefAccuracy); 
		xp->value.f = theCompFloat.d;
	    }
            break;

        case LOAD_CONST:
            SLOT_PUSH_VAR(gP->sp, m->const_pool + *(++ip));
            break;

        case LOAD_CONST_W:
            SLOT_PUSH_VAR(gP->sp, m->const_pool + *(UInt16*)(++ip));
            ++ip;
            break;

        case CONST_0:
            SLOT_PUSH_INTEGER(gP->sp, 0);
            break;

        case CONST_1:
            SLOT_PUSH_INTEGER(gP->sp, 1);
            break;

        case CONST_M1:
            SLOT_PUSH_INTEGER(gP->sp, -1);
            break;

        case CONST_ES:
            SLOT_PUSH_STRING(gP->sp, NULL);
            break;

        case CONST_INVALID:
            SLOT_PUSH_INVALID(gP->sp);
            break;

        case CONST_TRUE:
            SLOT_PUSH_TRUE(gP->sp);
            break;

        case CONST_FALSE:
            SLOT_PUSH_FALSE(gP->sp);
            break;

        case INCR:
	    if (gP->sp->type == scriptTypeInteger) {
            	SLOT_TO_INTEGER(gP->sp);
            	xp->value.n++;
	    }
	    else {
		SLOT_TO_FLOAT(gP->sp);
		//xp->value.f++;
		flpArg1.d = xp->value.f;
		flpArg2.d = 1.0;
		FlpBufferCorrectedAdd(&theCompFloat.fd, flpArg1.fd, flpArg2.fd, kDefAccuracy); 
		xp->value.f = theCompFloat.d;
	    }
            break;

        case DECR:
	    if (gP->sp->type == scriptTypeInteger) {
            	SLOT_TO_INTEGER(gP->sp);
            	xp->value.n--;
	    }
	    else {
		SLOT_TO_FLOAT(gP->sp);
		//xp->value.f--;
		flpArg1.d = xp->value.f;
		flpArg2.d = 1.0;
		FlpBufferCorrectedSub(&theCompFloat.fd, flpArg1.fd, flpArg2.fd, kDefAccuracy); 
		xp->value.f = theCompFloat.d;
	    }
            break;

        case ADD_ASG:
            switch(SlotMixedOp(xp = bp - *(++ip), gP->sp))
            {
            case scriptTypeString:
                SlotStrAppend(xp, gP->sp->value.s, StrLen(gP->sp->value.s));
                break;

            case scriptTypeInteger:
                xp->value.n += gP->sp->value.n;
                break;

            case scriptTypeFloat:
                //xp->value.f += gP->sp->value.f;
		flpArg1.d = xp->value.f;
		flpArg2.d = gP->sp->value.f;
		FlpBufferCorrectedAdd(&theCompFloat.fd, flpArg1.fd, flpArg2.fd, kDefAccuracy); 
		xp->value.f = theCompFloat.d;
                break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?