function.cpp
来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 1,022 行 · 第 1/2 页
CPP
1,022 行
// -*- c-basic-offset: 2 -*-/* * This file is part of the KDE libraries * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001,2003 Peter Kelly (pmk@post.com) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "function.h"#include "internal.h"#include "function_object.h"#include "lexer.h"#include "nodes.h"#include "operations.h"#include "debugger.h"#include "context.h"#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <assert.h>#include <string.h>#include <math.h>#include <ctype.h>using namespace KJS;// ------------------------- URI handling functions ---------------------------// ECMA 15.1.3UString encodeURI(ExecState *exec, UString string, UString unescapedSet){ char hexdigits[] = "0123456789ABCDEF"; int encbufAlloc = 2; UChar *encbuf = (UChar*)malloc(encbufAlloc*sizeof(UChar)); int encbufLen = 0; for (int k = 0; k < string.size(); k++) { UChar C = string[k]; if (unescapedSet.find(C) >= 0) { if (encbufLen+1 >= encbufAlloc) encbuf = (UChar*)realloc(encbuf,(encbufAlloc *= 2)*sizeof(UChar)); encbuf[encbufLen++] = C; } else { unsigned char octets[4]; int octets_len = 0; if (C.uc <= 0x007F) { unsigned short zzzzzzz = C.uc; octets[0] = zzzzzzz; octets_len = 1; } else if (C.uc <= 0x07FF) { unsigned short zzzzzz = C.uc & 0x3F; unsigned short yyyyy = (C.uc >> 6) & 0x1F; octets[0] = 0xC0 | yyyyy; octets[1] = 0x80 | zzzzzz; octets_len = 2; } else if (C.uc >= 0xD800 && C.uc <= 0xDBFF) { // we need two chars if (k + 1 >= string.size()) { Object err = Error::create(exec,URIError); exec->setException(err); free(encbuf); return UString(); } unsigned short Cnext = UChar(string[++k]).uc; if (Cnext < 0xDC00 || Cnext > 0xDFFF) { Object err = Error::create(exec,URIError); exec->setException(err); free(encbuf); return UString(); } unsigned short zzzzzz = Cnext & 0x3F; unsigned short yyyy = (Cnext >> 6) & 0x0F; unsigned short xx = C.uc & 0x03; unsigned short wwww = (C.uc >> 2) & 0x0F; unsigned short vvvv = (C.uc >> 6) & 0x0F; unsigned short uuuuu = vvvv+1; octets[0] = 0xF0 | (uuuuu >> 2); octets[1] = 0x80 | ((uuuuu & 0x03) << 4) | wwww; octets[2] = 0x80 | (xx << 4) | yyyy; octets[3] = 0x80 | zzzzzz; octets_len = 4; } else if (C.uc >= 0xDC00 && C.uc <= 0xDFFF) { Object err = Error::create(exec,URIError); exec->setException(err); free(encbuf); return UString(); } else { // 0x0800 - 0xD7FF or 0xE000 - 0xFFFF unsigned short zzzzzz = C.uc & 0x3F; unsigned short yyyyyy = (C.uc >> 6) & 0x3F; unsigned short xxxx = (C.uc >> 12) & 0x0F; octets[0] = 0xE0 | xxxx; octets[1] = 0x80 | yyyyyy; octets[2] = 0x80 | zzzzzz; octets_len = 3; } while (encbufLen+3*octets_len >= encbufAlloc) encbuf = (UChar*)realloc(encbuf,(encbufAlloc *= 2)*sizeof(UChar)); for (int j = 0; j < octets_len; j++) { encbuf[encbufLen++] = '%'; encbuf[encbufLen++] = hexdigits[octets[j] >> 4]; encbuf[encbufLen++] = hexdigits[octets[j] & 0x0F]; } } } UString encoded(encbuf,encbufLen); free(encbuf); return encoded;}static bool decodeHex(UChar hi, UChar lo, unsigned short *val){ *val = 0; if (hi.uc >= '0' && hi.uc <= '9') *val = (hi.uc-'0') << 4; else if (hi.uc >= 'a' && hi.uc <= 'f') *val = 10+(hi.uc-'a') << 4; else if (hi.uc >= 'A' && hi.uc <= 'F') *val = 10+(hi.uc-'A') << 4; else return false; if (lo.uc >= '0' && lo.uc <= '9') *val |= (lo.uc-'0'); else if (lo.uc >= 'a' && lo.uc <= 'f') *val |= 10+(lo.uc-'a'); else if (lo.uc >= 'A' && lo.uc <= 'F') *val |= 10+(lo.uc-'A'); else return false; return true;}UString decodeURI(ExecState *exec, UString string, UString reservedSet){ int decbufAlloc = 2; UChar *decbuf = (UChar*)malloc(decbufAlloc*sizeof(UChar)); int decbufLen = 0; for (int k = 0; k < string.size(); k++) { UChar C = string[k]; if (C != UChar('%')) { // Normal unescaped character if (decbufLen+1 >= decbufAlloc) decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar)); decbuf[decbufLen++] = C; continue; } // We have % escape sequence... expect at least 2 more characters int start = k; if (k+2 >= string.size()) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } unsigned short B; if (!decodeHex(string[k+1],string[k+2],&B)) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } k += 2; if (decbufLen+2 >= decbufAlloc) decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar)); if ((B & 0x80) == 0) { // Single-byte character C = B; } else { // Multi-byte character int n = 0; while (((B << n) & 0x80) != 0) n++; if (n < 2 || n > 4) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } if (k+3*(n-1) >= string.size()) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } unsigned short octets[4]; octets[0] = B; for (int j = 1; j < n; j++) { k++; if ((UChar(string[k]) != UChar('%')) || !decodeHex(string[k+1],string[k+2],&B) || ((B & 0xC0) != 0x80)) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } k += 2; octets[j] = B; } // UTF-8 transform unsigned long V; if (n == 2) { unsigned long yyyyy = octets[0] & 0x1F; unsigned long zzzzzz = octets[1] & 0x3F; V = (yyyyy << 6) | zzzzzz; C = UChar((unsigned short)V); } else if (n == 3) { unsigned long xxxx = octets[0] & 0x0F; unsigned long yyyyyy = octets[1] & 0x3F; unsigned long zzzzzz = octets[2] & 0x3F; V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz; C = UChar((unsigned short)V); } else { assert(n == 4); unsigned long uuuuu = ((octets[0] & 0x07) << 2) | ((octets[1] >> 4) & 0x03); unsigned long vvvv = uuuuu-1; if (vvvv > 0x0F) { Object err = Error::create(exec,URIError); exec->setException(err); free(decbuf); return UString(); } unsigned long wwww = octets[1] & 0x0F; unsigned long xx = (octets[2] >> 4) & 0x03; unsigned long yyyy = octets[2] & 0x0F; unsigned long zzzzzz = octets[3] & 0x3F; unsigned short H = 0xD800 | (vvvv << 6) | (wwww << 2) | xx; unsigned short L = 0xDC00 | (yyyy << 6) | zzzzzz; decbuf[decbufLen++] = UChar(H); decbuf[decbufLen++] = UChar(L); continue; } } if (reservedSet.find(C) < 0) { decbuf[decbufLen++] = C; } else { while (decbufLen+k-start >= decbufAlloc) decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar)); for (int p = start; p < k; p++) decbuf[decbufLen++] = string[p]; } } UString decoded(decbuf,decbufLen); free(decbuf); return decoded;}static UString uriReserved = ";/?:@&=+$,";static UString uriAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";static UString DecimalDigit = "0123456789";static UString uriMark = "-_.!~*'()";static UString uriUnescaped = uriAlpha+DecimalDigit+uriMark;// ----------------------------- FunctionImp ----------------------------------const ClassInfo FunctionImp::info = {"Function", &InternalFunctionImp::info, 0, 0};namespace KJS { class Parameter { public: Parameter(const Identifier &n) : name(n), next(0L) { } ~Parameter() { delete next; } Identifier name; Parameter *next; };}FunctionImp::FunctionImp(ExecState *exec, const Identifier &n) : InternalFunctionImp( static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp()) ), param(0L), line0(-1), line1(-1), sid(-1){ //fprintf(stderr,"FunctionImp::FunctionImp this=%p\n"); ident = n;}FunctionImp::~FunctionImp(){ delete param;}bool FunctionImp::implementsCall() const{ return true;}Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args){ Object &globalObj = exec->dynamicInterpreter()->globalObject(); // enter a new execution context ContextImp ctx(globalObj, exec->dynamicInterpreter()->imp(), thisObj, sid, codeType(), exec->context().imp(), this, &args); ExecState newExec(exec->dynamicInterpreter(), &ctx); newExec.setException(exec->exception()); // could be null // assign user supplied arguments to parameters processParameters(&newExec, args); // add variable declarations (initialized to undefined) processVarDecls(&newExec); ctx.setLines(line0,line0); Debugger *dbg = exec->interpreter()->imp()->debugger(); if (dbg) { if (!dbg->enterContext(&newExec)) { // debugger requested we stop execution dbg->imp()->abort(); return Undefined(); } } Completion comp = execute(&newExec); ctx.setLines(line1,line1); if (dbg) { Object func(this); // ### lineno is inaccurate - we really want the end of the function _body_ here // line1 is suppoed to be the end of the function start, just before the body if (!dbg->exitContext(&newExec,comp)) { // debugger requested we stop execution dbg->imp()->abort(); return Undefined(); } } // if an exception occurred, propogate it back to the previous execution object if (newExec.hadException()) exec->setException(newExec.exception());#ifdef KJS_VERBOSE CString n = ident.isEmpty() ? CString("(internal)") : ident.ustring().cstring(); if (comp.complType() == Throw) { n += " throws"; printInfo(exec, n.c_str(), comp.value()); } else if (comp.complType() == ReturnValue) { n += " returns"; printInfo(exec, n.c_str(), comp.value()); } else fprintf(stderr, "%s returns: undefined\n", n.c_str());#endif if (comp.complType() == Throw) { exec->setException(comp.value()); return comp.value(); } else if (comp.complType() == ReturnValue) return comp.value(); else return Undefined();}void FunctionImp::addParameter(const Identifier &n){ Parameter **p = ¶m; while (*p) p = &(*p)->next; *p = new Parameter(n);}Identifier FunctionImp::parameterProperty(int index) const{ // Find the property name corresponding to the given parameter int pos = 0; Parameter *p; for (p = param; p && pos < index; p = p->next) pos++; if (!p) return Identifier::null(); // Are there any subsequent parameters with the same name? Identifier name = p->name; for (p = p->next; p; p = p->next) if (p->name == name) return Identifier::null(); return name;}UString FunctionImp::parameterString() const{ UString s; const Parameter *p = param; while (p) { if (!s.isEmpty()) s += ", "; s += p->name.ustring(); p = p->next; } return s;}// ECMA 10.1.3qvoid FunctionImp::processParameters(ExecState *exec, const List &args){ Object variable = exec->context().imp()->variableObject();#ifdef KJS_VERBOSE fprintf(stderr, "---------------------------------------------------\n" "processing parameters for %s call\n", name().isEmpty() ? "(internal)" : name().ascii());#endif if (param) { ListIterator it = args.begin(); Parameter *p = param; while (p) { if (it != args.end()) {#ifdef KJS_VERBOSE fprintf(stderr, "setting parameter %s ", p->name.ascii()); printInfo(exec,"to", *it);#endif variable.put(exec, p->name, *it); it++; } else variable.put(exec, p->name, Undefined()); p = p->next; } }#ifdef KJS_VERBOSE else { for (int i = 0; i < args.size(); i++) printInfo(exec,"setting argument", args[i]); }#endif}void FunctionImp::processVarDecls(ExecState * /*exec*/){}Value FunctionImp::get(ExecState *exec, const Identifier &propertyName) const{ // Find the arguments from the closest context. if (propertyName == argumentsPropertyName) {// delme ContextImp *context = exec->context().imp();// fixme// ContextImp *context = exec->_context; while (context) { if (context->function() == this) return static_cast<ActivationImp *> (context->activationObject())->get(exec, propertyName); context = context->callingContext(); } return Null(); } // Compute length of parameters. if (propertyName == lengthPropertyName) { const Parameter * p = param; int count = 0; while (p) { ++count; p = p->next; } return Number(count);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?