30#include <kjs/object.h>
31#include <kjs/lookup.h>
32#include <kjs/function.h>
33#include <kjs/interpreter.h>
34#include <kjs/string_object.h>
35#include <kjs/error_object.h>
95class Scriptface :
public JSObject
171 const ClassInfo* classInfo()
const {
return &info; }
217#define DBGP "KTranscript: "
225template <
typename T1>
233template <
typename T1,
typename T2>
241template <
typename T1,
typename T2,
typename T3>
250#define WARNP "KTranscript: "
254template <
typename T1>
262UString::UString(
const QString &d)
264 unsigned int len = d.length();
267 m_rep = UString::Rep::create(
dat, len);
269QString UString::qstring()
const
271 return QString((QChar*) data(), size());
279 if (
expt->isObject()
280 &&
expt->getObject()->hasProperty(exec,
"message"))
282 JSValue *msg =
expt->getObject()->get(exec,
"message");
283 return QString::fromLatin1(
"Error: %1").arg(msg->getString().qstring());
288 return QString::fromLatin1(
"Caught exception: %1").arg(
strexpt);
298 int len =
s.length();
299 for (
int i = 0; i < p && i < len; ++i) {
318 int len = key.length();
320 for (
int i = 0; i < len; ++i) {
350 int len =
raw.length();
368 return raw.mid(is + 1,
ie - is - 1);
376 if (
vtype == QVariant::String)
378 else if (
vtype == QVariant::Double \
379 ||
vtype == QVariant::Int ||
vtype == QVariant::UInt \
380 ||
vtype == QVariant::LongLong ||
vtype == QVariant::ULongLong)
398 if (!file.open(QIODevice::ReadOnly)) {
402 stream.setCodec(
"UTF-8");
403 while (!stream.atEnd()) {
404 QString line = stream.readLine();
410 line = line.left(
p1);
412 line = line.trimmed();
413 if (line.isEmpty()) {
437 QString value = line.mid(
p1 + 1).trimmed();
438 if (!
field.isEmpty()) {
439 (*configGroup)[
field] = value;
462KTranscriptImp::KTranscriptImp ()
469KTranscriptImp::~KTranscriptImp ()
505 error =
"Security block: trying to execute a script in suid environment.";
513 loadModules(
mods, error);
515 if (!error.isEmpty())
523 if (!m_sface.contains(
lang))
524 setupInterpreter(
lang);
529 JSObject *
gobj =
sface->jsi->globalObject();
532 sface->msgctxt = &msgctxt;
533 sface->dynctxt = &dynctxt;
534 sface->msgid = &msgid;
537 sface->final = &
final;
538 sface->fallback = &fallback;
553 error = QString::fromLatin1(
"Unregistered call to '%1'.").arg(
funcName);
565 for (
int i = 1; i <
argc; ++i)
568 if (
fval->isObject())
577 if (exec->hadException())
578 exec->clearException();
582 else if (!exec->hadException())
588 return val->getString().qstring();
594 error = QString::fromLatin1(
"Non-string return value: %1").arg(
strval);
603 exec->clearException();
613 if (!m_sface.contains(
lang))
619 return sface->nameForalls;
633 if (!m_sface.contains(
mlang))
634 setupInterpreter(
mlang);
641 modErrors.append(QString::fromLatin1(
"Funny module path '%1', skipping.")
658 if (exec->hadException())
661 exec->clearException();
666 currentModulePath.clear();
675void KTranscriptImp::setupInterpreter (
const QString &
lang)
678 Interpreter *jsi =
new Interpreter;
680 jsi->initGlobalObject();
686 Scriptface *
sface =
new Scriptface(jsi->globalExec(), config[
lang]);
687 jsi->globalObject()->put(jsi->globalExec(),
SFNAME,
sface,
699#include "ktranscript.lut.h"
746Scriptface::~Scriptface ()
760 dbgout(
"Scriptface::getValueProperty: Unknown property id %1",
token);
774 dbgout(
"Scriptface::putValueProperty: Unknown property id %1",
token);
778#define CALLARG(i) (args.size() > i ? args[i] : jsNull())
781 if (!
thisObj->inherits(&Scriptface::info)) {
784 Scriptface *obj =
static_cast<Scriptface*
>(
thisObj);
786 case Scriptface::Load:
787 return obj->loadf(exec, args);
788 case Scriptface::Setcall:
790 case Scriptface::Hascall:
791 return obj->hascallf(exec,
CALLARG(0));
792 case Scriptface::Acall:
793 return obj->acallf(exec, args);
794 case Scriptface::SetcallForall:
796 case Scriptface::Fallback:
797 return obj->fallbackf(exec);
798 case Scriptface::Nsubs:
799 return obj->nsubsf(exec);
800 case Scriptface::Subs:
801 return obj->subsf(exec,
CALLARG(0));
802 case Scriptface::Vals:
803 return obj->valsf(exec,
CALLARG(0));
804 case Scriptface::Msgctxt:
805 return obj->msgctxtf(exec);
806 case Scriptface::Dynctxt:
807 return obj->dynctxtf(exec,
CALLARG(0));
808 case Scriptface::Msgid:
809 return obj->msgidf(exec);
810 case Scriptface::Msgkey:
811 return obj->msgkeyf(exec);
812 case Scriptface::Msgstrf:
813 return obj->msgstrff(exec);
814 case Scriptface::Dbgputs:
815 return obj->dbgputsf(exec,
CALLARG(0));
816 case Scriptface::Warnputs:
817 return obj->warnputsf(exec,
CALLARG(0));
818 case Scriptface::LocaleCountry:
819 return obj->localeCountryf(exec);
820 case Scriptface::NormKey:
821 return obj->normKeyf(exec,
CALLARG(0));
822 case Scriptface::LoadProps:
823 return obj->loadPropsf(exec, args);
824 case Scriptface::GetProp:
826 case Scriptface::SetProp:
828 case Scriptface::ToUpperFirst:
830 case Scriptface::ToLowerFirst:
832 case Scriptface::GetConfString:
834 case Scriptface::GetConfBool:
836 case Scriptface::GetConfNumber:
845#define SPREF SFNAME"."
849 if (
globalKTI->currentModulePath.isEmpty())
851 SPREF"load: no current module path, aiiie...");
853 for (
int i = 0; i <
fnames.size(); ++i)
856 SPREF"load: expected string as file name");
858 for (
int i = 0; i <
fnames.size(); ++i)
864 if (!file.open(QIODevice::ReadOnly))
866 QString::fromLatin1(
SPREF"load: cannot read file '%1'") \
870 stream.setCodec(
"UTF-8");
871 QString source = stream.readAll();
887 line = QString::number(
lval->toInt32(exec));
891 QString::fromLatin1(
"at %1:%2: %3")
903 if (!name->isString())
905 SPREF"setcall: expected string as first argument");
906 if ( !
func->isObject()
907 || !
func->getObject()->implementsCall())
909 SPREF"setcall: expected function as second argument");
910 if (!(
fval->isObject() ||
fval->isNull()))
912 SPREF"setcall: expected object or null as third argument");
931 if (!name->isString())
933 SPREF"hascall: expected string as first argument");
941 if (
argv.size() < 1) {
943 SPREF"acall: expected at least one argument (call name)");
947 SPREF"acall: expected string as first argument (call name)");
954 QString::fromLatin1(
SPREF"acall: unregistered call to '%1'").arg(
callname));
965 for (
int i = 1; i <
argv.size(); ++i)
968 if (
fval->isObject()) {
982 if (!name->isString())
984 SPREF"setcallForall: expected string as first argument");
985 if ( !
func->isObject()
986 || !
func->getObject()->implementsCall())
988 SPREF"setcallForall: expected function as second argument");
989 if (!(
fval->isObject() ||
fval->isNull()))
991 SPREF"setcallForall: expected object or null as third argument");
1006 nameForalls.append(
qname);
1014 if (fallback !=
NULL)
1027 if (!index->isNumber())
1029 SPREF"subs: expected number as first argument");
1031 int i =
qRound(index->getNumber());
1034 SPREF"subs: index out of range");
1041 if (!index->isNumber())
1043 SPREF"vals: expected number as first argument");
1045 int i =
qRound(index->getNumber());
1048 SPREF"vals: index out of range");
1061 if (!key->isString())
1063 SPREF"dynctxt: expected string as first argument");
1066 if (dynctxt->contains(
qkey)) {
1092 if (!str->isString())
1094 SPREF"dbgputs: expected string as first argument");
1105 if (!str->isString())
1107 SPREF"warnputs: expected string as first argument");
1124 if (!
phrase->isString()) {
1126 SPREF"normKey: expected string as argument");
1135 if (
globalKTI->currentModulePath.isEmpty()) {
1137 SPREF"loadProps: no current module path, aiiie...");
1140 for (
int i = 0; i <
fnames.size(); ++i) {
1143 SPREF"loadProps: expected string as file name");
1147 for (
int i = 0; i <
fnames.size(); ++i)
1163 QString::fromLatin1(
SPREF"loadProps: cannot read map '%1'")
1170 if (!loadedPmapPaths.contains(
qfpath)) {
1173 errorString = loadProps_bin(
qfpath);
1176 errorString = loadProps_text(
qfpath);
1178 if (!errorString.isEmpty()) {
1182 loadedPmapPaths.insert(
qfpath);
1191 if (!
phrase->isString()) {
1193 SPREF"getProp: expected string as first argument");
1195 if (!
prop->isString()) {
1197 SPREF"getProp: expected string as second argument");
1202 if (
props.isEmpty()) {
1205 if (!
props.isEmpty()) {
1208 if (!
qval.isEmpty()) {
1217 if (!
phrase->isString()) {
1219 SPREF"setProp: expected string as first argument");
1221 if (!
prop->isString()) {
1223 SPREF"setProp: expected string as second argument");
1225 if (!value->isString()) {
1227 SPREF"setProp: expected string as third argument");
1232 QByteArray
qvalue = value->toString(exec).qstring().toUtf8();
1241 static const int hlen = 2;
1246 int len =
qstr.length();
1258 if (i >= len)
break;
1299 if (!str->isString()) {
1301 SPREF"toUpperFirst: expected string as first argument");
1303 if (!(
nalt->isNumber() ||
nalt->isNull())) {
1305 SPREF"toUpperFirst: expected number as second argument");
1319 if (!str->isString()) {
1321 SPREF"toLowerFirst: expected string as first argument");
1323 if (!(
nalt->isNumber() ||
nalt->isNull())) {
1325 SPREF"toLowerFirst: expected number as second argument");
1339 if (!key->isString()) {
1341 SPREF"getConfString: expected string "
1342 "as first argument");
1344 if (!(
dval->isString() ||
dval->isNull())) {
1346 SPREF"getConfString: expected string "
1347 "as second argument (when given)");
1350 if (
dval->isNull()) {
1355 if (config.contains(
qkey)) {
1365 if (!key->isString()) {
1367 SPREF"getConfBool: expected string as "
1370 if (!(
dval->isBoolean() ||
dval->isNull())) {
1372 SPREF"getConfBool: expected boolean "
1373 "as second argument (when given)");
1379 falsities.append(QString::fromLatin1(
"no"));
1380 falsities.append(QString::fromLatin1(
"false"));
1383 if (
dval->isNull()) {
1388 if (config.contains(
qkey)) {
1399 if (!key->isString()) {
1401 SPREF"getConfNumber: expected string "
1402 "as first argument");
1404 if (!(
dval->isNumber() ||
dval->isNull())) {
1406 SPREF"getConfNumber: expected number "
1407 "as second argument (when given)");
1410 if (
dval->isNull()) {
1415 if (config.contains(
qkey)) {
1433 if (!file.open(QIODevice::ReadOnly)) {
1434 return QString::fromLatin1(
SPREF"loadProps_text: cannot read file '%1'")
1438 stream.setCodec(
"UTF-8");
1448 int slen =
s.length();
1461 if (i + 1 >=
slen) {
1462 return QString::fromLatin1(
SPREF"loadProps_text: unexpected end "
1463 "of file in %1").arg(
fpath);
1470 return QString::fromLatin1(
SPREF"loadProps_text: separator "
1471 "characters must not be letters at %1:%2")
1509 if (!
ekey.isEmpty()) {
1518 if (
ekeys.size() < 1) {
1519 return QString::fromLatin1(
SPREF"loadProps_text: no entry key "
1520 "for entry ending at %1:%2")
1526 foreach (
const QByteArray &
ekey,
ekeys) {
1542 return QString::fromLatin1(
SPREF"loadProps_text: property separator "
1543 "inside property value at %1:%2")
1555 return QString::fromLatin1(
SPREF"loadProps: internal error 10 at %1:%2")
1561 return QString::fromLatin1(
SPREF"loadProps: internal error 20 at %1:%2")
1569 return QString::fromLatin1(
SPREF"loadProps: unexpected end of file in %1")
1580template <
typename T>
1583 if (pos +
nbytes > len) {
1614 return QByteArray();
1618 return QByteArray();
1628 if (!file.open(QIODevice::ReadOnly)) {
1629 return QString::fromLatin1(
SPREF"loadProps: cannot read file '%1'")
1633 QByteArray
head(8,
'0');
1634 file.read(
head.data(),
head.size());
1638 if (
head ==
"TSPMAP00") {
1639 return loadProps_bin_00(
fpath);
1640 }
else if (
head ==
"TSPMAP01") {
1641 return loadProps_bin_01(
fpath);
1644 return QString::fromLatin1(
SPREF"loadProps: unknown version of compiled map '%1'")
1652 if (!file.open(QIODevice::ReadOnly)) {
1653 return QString::fromLatin1(
SPREF"loadProps: cannot read file '%1'")
1656 QByteArray
fctmp = file.readAll();
1658 const char *
fc =
fctmp.data();
1675 for (
int i = 0; i <
nentries; ++i) {
1702 foreach (
const QByteArray &
ekey,
ekeys) {
1710 return QString::fromLatin1(
SPREF"loadProps: corrupt compiled map '%1'")
1719 QFile *file =
new QFile(
fpath);
1720 if (!file->open(QIODevice::ReadOnly)) {
1721 return QString::fromLatin1(
SPREF"loadProps: cannot read file '%1'")
1729 fstr = file->read(8 + 4 + 8);
1733 if (
head !=
"TSPMAP01") {
1734 return QString::fromLatin1(
SPREF"loadProps: corrupt compiled map '%1'")
1752 loadedPmapHandles.insert(file);
1759 QFile *file =
ref.first;
1762 if (file !=
NULL && file->seek(offset)) {
1763 QByteArray
fstr = file->read(4 + 4);
1775 phraseUnparsedProps.remove(
phrase);
class for supporting programmable translations
QString removeAcceleratorMarker(const QString &label_)
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics.
TsConfig readConfig(const QString &fname)
int countLines(const QString &s, int p)
QByteArray normKeystr(const QString &raw, bool mayHaveAcc=true)
QHash< QString, TsConfigGroup > TsConfig
QHash< QString, QString > TsConfigGroup
QString expt2str(ExecState *exec)
static QString toCaseFirst(const QString &qstr, int qnalt, bool toupper)
JSValue * variantToJsValue(const QVariant &val)
static quint64 bin_read_int64(const char *fc, qlonglong len, qlonglong &pos)
void dbgout(const char *str)
static QByteArray bin_read_string(const char *fc, qlonglong len, qlonglong &pos)
static int bin_read_int_nbytes(const char *fc, qlonglong len, qlonglong &pos, int nbytes)
KTranscript * load_transcript()
static quint32 bin_read_int(const char *fc, qlonglong len, qlonglong &pos)
QString trimSmart(const QString &raw)
void warnout(const char *str)
void ref()
Tells KGlobal about one more operations that should be finished before the application exits.
KSharedConfigPtr config()
Returns the general config object.