/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/* Header files */
#include "js-utils.h"
#include "js-interpreterdata.h"
#include "js-idenumeration.h"
#include "js-frame.h"
#include "js-runtimeexception.h"
#include "js-exceptionhandler.h"
#include "js-nativeglobal.h"
#include "js-scriptruntime.h"
#ifndef SHELL	/* '03.06.27 by S.Takaoka */
#include "ewb-dbg.h"
#endif

/* Procedures */
void
JSFrame::mark(JSContext *cx)
{
    int i; // avoid compile error on vxWorks

    scope->mark(cx);
    if (thisObj != NULL) thisObj->mark(cx);
    for (i = 0; i < numArgs; ++i) {
	JS_MarkVal(cx, args[i]);
    }
    theData->mark(cx);
    for (i = 0; i <= stackTop; ++i) {
#ifdef TEMPVAL
	if (JS_VAL_IS_DOUBLE(stack[i])) {
	    double *dp = JS_VAL_TO_DOUBLE(stack[i]);

	    if ((dp >= stackTemp) && (dp < stackTemp + theData->itsMaxStack)) {
		continue;
	    }
	}
#endif
	JS_MarkVal(cx, stack[i]);
    }
    for (i = 0; i < theData->itsMaxLocals; ++i) {
#ifdef TEMPVAL
	if (JS_VAL_IS_DOUBLE(local[i])) {
	    double *dp = JS_VAL_TO_DOUBLE(local[i]);

	    if ((dp >= localTemp) && (dp < localTemp + theData->itsMaxLocals)) {
		continue;
	    }
	}
#endif
	JS_MarkVal(cx, local[i]);
    }
    int size = theData->itsVariableTable->size();

    for (i = 0; i < size; ++i) {
#ifdef TEMPVAL
	if (JS_VAL_IS_DOUBLE(vars[i])) {
	    double *dp = JS_VAL_TO_DOUBLE(vars[i]);

	    if ((dp >= varsTemp) && (dp < varsTemp + size)) {
		continue;
	    }
	}
#endif
	JS_MarkVal(cx, vars[i]);
    }
    for (i = 0; i < theData->itsMaxTryDepth; ++i) {
	if (scopeStack[i] != NULL) {
	    scopeStack[i]->mark(cx);
	}
    }
    for (i = 0; i < theData->itsMaxEnums; ++i) {
	if (enums[i] != NULL) {
	    enums[i]->mark(cx);
	}
    }
    if (ex != NULL) {
	ex->mark(cx);
    }
#ifdef TEMPVAL
    int index = numOutArgs - 1;

    for (i = outArgsCount; --i >= 0; ) {
	JS_MarkVal(cx, outArgs[index]);
	index -= 1;
    }
#endif
}
void
JSFrame::destroy(JSContext *cx)
{
    if (stack != NULL) {
	JS_DeleteZoneObj(cx, stack);
    }
    if (local != NULL) {
	JS_DeleteZoneObj(cx, local);
    }
    if (vars != NULL) {
	JS_DeleteZoneObj(cx, vars);
    }
    if (catchStack != NULL) {
	JS_DeleteZoneObj(cx, catchStack);
    }
    if (finallyStack != NULL) {
	JS_DeleteZoneObj(cx, finallyStack);
    }
    if (scopeStack != NULL) {
	JS_DeleteZoneObj(cx, scopeStack);
    }
    if (enums != NULL) {
	JS_DeleteZoneObj(cx, enums);
    }
    JS_DeleteZoneObj(cx, this);
#ifdef TEMPVAL
    if (stackTemp != NULL) {
	JS_DeleteZoneObj(cx, stackTemp);
    }
    if (localTemp != NULL) {
	JS_DeleteZoneObj(cx, localTemp);
    }
    if (varsTemp != NULL) {
	JS_DeleteZoneObj(cx, varsTemp);
    }
#endif
}

JSFrame::JSFrame(JSContext *cx, JSScriptable *scope, JSScriptable *thisObj,
		int numArgs, jsVal_t *args, JSInterpreterData *theData)
{
    this->scope = scope;
    this->thisObj = thisObj;
    this->numArgs = numArgs;
    this->args = args;
    this->theData = theData;

    stackTop = -1;
    if (theData->itsMaxStack > 0) {
        stack = (jsVal_t *) JS_NewZoneObj(cx,
				sizeof (*stack) * theData->itsMaxStack);
    } else {
	stack = NULL;
    }
    if (theData->itsMaxLocals > 0) {
	local = (jsVal_t *) JS_NewZoneObj(cx,
				sizeof (*local) * theData->itsMaxLocals);
	memset(local, 0, sizeof (*local) * theData->itsMaxLocals);
    } else {
	local = NULL;
    }
    int size = theData->itsVariableTable->size();

    if(size >= 255){
	jsString_t message
		= JSScriptRuntime::getMessage(
			cx,
			"<warning>interpreter.local.var.overfrow %s."
			" Please cut down Gloval Variable.\n",
			cx->interpreterSourceFile != NULL ?
				cx->interpreterSourceFile : "" );
#ifdef SHELL
	    printf(message);
#else
	    EwbSetLog(message);
#endif
    }
    if (size > 0) {
        vars = (jsVal_t *) JS_NewZoneObj(cx, sizeof (*vars) * size);

/*
    	const jsVal_t undefined = JS_VAL_VOID;
	int parameterCount = theData->itsVariableTable->getParameterCount();
	int i;

        for (i = 0; i < parameterCount; i++) {
            if (i >= numArgs) {
                vars[i] = undefined;
            } else {
                vars[i] = args[i];    
	    }
        }
        for ( ; i < size; i++) {
            vars[i] = undefined;
	}
*/
    } else {
	vars = NULL;
    }
    if (theData->itsMaxTryDepth > 0) {
        catchStack = (int *) JS_NewZoneObj(cx, sizeof (*catchStack)
					* theData->itsMaxTryDepth);
        finallyStack = (int *) JS_NewZoneObj(cx, sizeof (*finallyStack)
					* theData->itsMaxTryDepth);
        scopeStack = (JSScriptable **) JS_NewZoneObj(cx, sizeof (*scopeStack)
						* theData->itsMaxTryDepth);
        memset(scopeStack, 0, sizeof (*scopeStack) * theData->itsMaxTryDepth);
    } else {
        catchStack = NULL;
        finallyStack = NULL;
        scopeStack = NULL;
    }
    if (theData->itsMaxEnums > 0) {
	enums = (JSIdEnumeration **) JS_NewZoneObj(cx, sizeof (*enums)
						* theData->itsMaxEnums);
	memset(enums, 0, sizeof (*enums) * theData->itsMaxEnums);
    } else {
	enums = NULL;
    }
    ex = NULL;
    tryStackTop = 0;
#ifdef TEMPVAL
    if (theData->itsMaxStack > 0) {
 	stackTemp = (double *) JS_NewZoneObj(cx,
				sizeof (*stackTemp) * theData->itsMaxStack);
    } else {
	stackTemp = NULL;
    }
    if (theData->itsMaxLocals > 0) {
	localTemp = (double *) JS_NewZoneObj(cx,
				sizeof (*localTemp) * theData->itsMaxLocals);
    } else {
	localTemp = NULL;
    }
    if (size > 0) {
        varsTemp = (double *) JS_NewZoneObj(cx, sizeof (*varsTemp) * size);
    } else {
	varsTemp = NULL;
    }
    outArgsCount = 0;
    numOutArgs = 0;
    outArgs = NULL;
#endif
}

