29 #include <kjs/value.h>
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>
38 #include <QStringList>
46 #include <QTextStream>
87 void setupInterpreter (
const QString &lang);
95 class Scriptface :
public JSObject
102 JSValue *loadf (ExecState *exec,
const List &fnames);
103 JSValue *setcallf (ExecState *exec, JSValue *name,
104 JSValue *func, JSValue *fval);
105 JSValue *hascallf (ExecState *exec, JSValue *name);
106 JSValue *acallf (ExecState *exec,
const List &argv);
107 JSValue *setcallForallf (ExecState *exec, JSValue *name,
108 JSValue *func, JSValue *fval);
109 JSValue *fallbackf (ExecState *exec);
110 JSValue *nsubsf (ExecState *exec);
111 JSValue *subsf (ExecState *exec, JSValue *index);
112 JSValue *valsf (ExecState *exec, JSValue *index);
113 JSValue *msgctxtf (ExecState *exec);
114 JSValue *dynctxtf (ExecState *exec, JSValue *key);
115 JSValue *msgidf (ExecState *exec);
116 JSValue *msgkeyf (ExecState *exec);
117 JSValue *msgstrff (ExecState *exec);
118 JSValue *dbgputsf (ExecState *exec, JSValue *str);
119 JSValue *warnputsf (ExecState *exec, JSValue *str);
120 JSValue *localeCountryf (ExecState *exec);
121 JSValue *normKeyf (ExecState *exec, JSValue *phrase);
122 JSValue *loadPropsf (ExecState *exec,
const List &fnames);
123 JSValue *getPropf (ExecState *exec, JSValue *phrase, JSValue *prop);
124 JSValue *setPropf (ExecState *exec, JSValue *phrase, JSValue *prop, JSValue *value);
125 JSValue *toUpperFirstf (ExecState *exec, JSValue *str, JSValue *nalt);
126 JSValue *toLowerFirstf (ExecState *exec, JSValue *str, JSValue *nalt);
127 JSValue *getConfStringf (ExecState *exec, JSValue *key, JSValue *dval);
128 JSValue *getConfBoolf (ExecState *exec, JSValue *key, JSValue *dval);
129 JSValue *getConfNumberf (ExecState *exec, JSValue *key, JSValue *dval);
167 bool getOwnPropertySlot (ExecState *exec,
const Identifier& propertyName, PropertySlot& slot);
168 JSValue *getValueProperty (ExecState *exec,
int token)
const;
169 void put (ExecState *exec,
const Identifier &propertyName, JSValue *value,
int attr);
170 void putValueProperty (ExecState *exec,
int token, JSValue *value,
int attr);
171 const ClassInfo* classInfo()
const {
return &info; }
173 static const ClassInfo info;
217 #define DBGP "KTranscript: "
220 fprintf(stderr,
DBGP"%s\n", str);
225 template <
typename T1>
226 void dbgout (
const char* str,
const T1 &a1) {
228 fprintf(stderr,
DBGP"%s\n", QString::fromUtf8(str).arg(a1).toLocal8Bit().data());
230 Q_UNUSED(str); Q_UNUSED(a1);
233 template <
typename T1,
typename T2>
234 void dbgout (
const char* str,
const T1 &a1,
const T2 &a2) {
236 fprintf(stderr,
DBGP"%s\n", QString::fromUtf8(str).arg(a1).arg(a2).toLocal8Bit().data());
238 Q_UNUSED(str); Q_UNUSED(a1); Q_UNUSED(a2);
241 template <
typename T1,
typename T2,
typename T3>
242 void dbgout (
const char* str,
const T1 &a1,
const T2 &a2,
const T3 &a3) {
244 fprintf(stderr,
DBGP"%s\n", QString::fromUtf8(str).arg(a1).arg(a2).arg(a3).toLocal8Bit().data());
246 Q_UNUSED(str); Q_UNUSED(a1); Q_UNUSED(a2); Q_UNUSED(a3);
250 #define WARNP "KTranscript: "
252 fprintf(stderr,
WARNP"%s\n", str);
254 template <
typename T1>
255 void warnout (
const char* str,
const T1 &a1) {
256 fprintf(stderr,
WARNP"%s\n", QString::fromUtf8(str).arg(a1).toLocal8Bit().data());
262 UString::UString(
const QString &d)
264 unsigned int len = d.length();
265 UChar *dat =
static_cast<UChar*
>(fastMalloc(
sizeof(UChar) * len));
266 memcpy(dat, d.unicode(), len *
sizeof(UChar));
267 m_rep = UString::Rep::create(dat, len);
269 QString UString::qstring()
const
271 return QString((QChar*) data(), size());
278 JSValue *expt = exec->exception();
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());
287 QString strexpt = exec->exception()->toString(exec).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) {
300 if (s[i] == QLatin1Char(
'\n')) {
318 int len = key.length();
320 for (
int i = 0; i < len; ++i) {
350 int len = raw.length();
353 while (is < len && raw[is].isSpace() && raw[is] != QLatin1Char(
'\n')) {
356 if (is >= len || raw[is] != QLatin1Char(
'\n')) {
361 while (ie >= 0 && raw[ie].isSpace() && raw[ie] != QLatin1Char(
'\n')) {
364 if (ie < 0 || raw[ie] != QLatin1Char(
'\n')) {
368 return raw.mid(is + 1, ie - is - 1);
376 if (vtype == QVariant::String)
377 return jsString(val.toString());
378 else if ( vtype == QVariant::Double \
379 || vtype == QVariant::Int || vtype == QVariant::UInt \
380 || vtype == QVariant::LongLong || vtype == QVariant::ULongLong)
381 return jsNumber(val.toDouble());
383 return jsUndefined();
394 TsConfig::iterator configGroup;
398 if (!file.open(QIODevice::ReadOnly)) {
401 QTextStream stream(&file);
402 stream.setCodec(
"UTF-8");
403 while (!stream.atEnd()) {
404 QString line = stream.readLine();
408 p1 = line.indexOf(QLatin1Char(
'#'));
410 line = line.left(p1);
412 line = line.trimmed();
413 if (line.isEmpty()) {
417 if (line[0] == QLatin1Char(
'[')) {
420 p2 = line.indexOf(QLatin1Char(
']'), p1 + 1);
424 QString group = line.mid(p1 + 1, p2 - p1 - 1).trimmed();
425 configGroup = config.find(group);
426 if (configGroup == config.end()) {
432 p1 = line.indexOf(QLatin1Char(
'='));
436 QString field = line.left(p1).trimmed();
437 QString value = line.mid(p1 + 1).trimmed();
438 if (!field.isEmpty()) {
439 (*configGroup)[field] = value;
462 KTranscriptImp::KTranscriptImp ()
465 const QString tsConfigPath = QDir::homePath() + QLatin1Char(
'/') + QLatin1String(
".transcriptrc");
469 KTranscriptImp::~KTranscriptImp ()
500 if (geteuid() == 0 && getuid() != 0)
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);
527 Scriptface *sface = m_sface[lang];
528 ExecState *exec = sface->jsi->globalExec();
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;
542 int argc = argv.size();
550 QString funcName = argv[0].toString();
551 if (!sface->funcs.contains(funcName))
553 error = QString::fromLatin1(
"Unregistered call to '%1'.").arg(funcName);
556 JSObject *func = sface->funcs[funcName];
557 JSValue *fval = sface->fvals[funcName];
561 currentModulePath = sface->fpaths[funcName];
565 for (
int i = 1; i < argc; ++i)
568 if (fval->isObject())
569 val = func->callAsFunction(exec, fval->getObject(), arglist);
571 val = func->callAsFunction(exec, gobj, arglist);
577 if (exec->hadException())
578 exec->clearException();
582 else if (!exec->hadException())
588 return val->getString().qstring();
593 QString strval = val->toString(exec).qstring();
594 error = QString::fromLatin1(
"Non-string return value: %1").arg(strval);
603 exec->clearException();
613 if (!m_sface.contains(lang))
617 Scriptface *sface = m_sface[lang];
619 return sface->nameForalls;
633 if (!m_sface.contains(mlang))
634 setupInterpreter(mlang);
638 int posls = mpath.lastIndexOf(QLatin1Char(
'/'));
641 modErrors.append(QString::fromLatin1(
"Funny module path '%1', skipping.")
645 currentModulePath = mpath.left(posls);
646 QString fname = mpath.mid(posls + 1);
648 fname = fname.left(fname.lastIndexOf(QLatin1Char(
'.')));
651 ExecState *exec = m_sface[mlang]->jsi->globalExec();
653 alist.append(jsString(fname));
655 m_sface[mlang]->loadf(exec, alist);
658 if (exec->hadException())
661 exec->clearException();
666 currentModulePath.clear();
668 foreach (
const QString &merr, modErrors)
669 error.append(merr + QLatin1Char(
'\n'));
675 void 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,
688 DontDelete|ReadOnly);
692 m_sface[lang] = sface;
699 #include "ktranscript.lut.h"
736 KJS_DEFINE_PROTOTYPE(ScriptfaceProto)
737 KJS_IMPLEMENT_PROTOFUNC(ScriptfaceProtoFunc)
738 KJS_IMPLEMENT_PROTOTYPE("Scriptface", ScriptfaceProto, ScriptfaceProtoFunc, ObjectPrototype)
740 const ClassInfo Scriptface::info = {
"Scriptface", 0, &ScriptfaceTable, 0};
742 Scriptface::Scriptface (ExecState *exec,
const TsConfigGroup &config_)
743 : JSObject(ScriptfaceProto::self(exec)), fallback(NULL),
config(config_)
746 Scriptface::~Scriptface ()
748 qDeleteAll(loadedPmapHandles);
751 bool Scriptface::getOwnPropertySlot (ExecState *exec,
const Identifier& propertyName, PropertySlot& slot)
753 return getStaticValueSlot<Scriptface, JSObject>(exec, &ScriptfaceTable,
this, propertyName, slot);
756 JSValue *Scriptface::getValueProperty (ExecState * ,
int token)
const
760 dbgout(
"Scriptface::getValueProperty: Unknown property id %1", token);
762 return jsUndefined();
765 void Scriptface::put (ExecState *exec,
const Identifier &propertyName, JSValue *value,
int attr)
767 lookupPut<Scriptface, JSObject>(exec, propertyName, value, attr, &ScriptfaceTable,
this);
770 void Scriptface::putValueProperty (ExecState * ,
int token, JSValue * ,
int )
774 dbgout(
"Scriptface::putValueProperty: Unknown property id %1", token);
778 #define CALLARG(i) (args.size() > i ? args[i] : jsNull())
779 JSValue *ScriptfaceProtoFunc::callAsFunction (ExecState *exec, JSObject *thisObj,
const List &args)
781 if (!thisObj->inherits(&Scriptface::info)) {
782 return throwError(exec, TypeError);
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:
839 return jsUndefined();
845 #define SPREF SFNAME"."
847 JSValue *Scriptface::loadf (ExecState *exec,
const List &fnames)
849 if (globalKTI->currentModulePath.isEmpty())
850 return throwError(exec, GeneralError,
851 SPREF"load: no current module path, aiiie...");
853 for (
int i = 0; i < fnames.size(); ++i)
854 if (!fnames[i]->isString())
855 return throwError(exec, TypeError,
856 SPREF"load: expected string as file name");
858 for (
int i = 0; i < fnames.size(); ++i)
860 QString qfname = fnames[i]->getString().qstring();
861 QString qfpath = globalKTI->currentModulePath + QLatin1Char(
'/') + qfname + QLatin1String(
".js");
864 if (!file.open(QIODevice::ReadOnly))
865 return throwError(exec, GeneralError,
866 QString::fromLatin1(
SPREF"load: cannot read file '%1'") \
869 QTextStream stream(&file);
870 stream.setCodec(
"UTF-8");
871 QString source = stream.readAll();
874 Completion comp = jsi->evaluate(qfpath, 0, source);
876 if (comp.complType() == Throw)
878 JSValue *exval = comp.value();
879 ExecState *exec = jsi->globalExec();
880 QString msg = exval->toString(exec).qstring();
883 if (exval->type() == ObjectType)
885 JSValue *lval = exval->getObject()->get(exec,
"line");
886 if (lval->type() == NumberType)
887 line = QString::number(lval->toInt32(exec));
890 return throwError(exec, TypeError,
891 QString::fromLatin1(
"at %1:%2: %3")
892 .arg(qfpath, line, msg));
894 dbgout(
"Loaded module: %1", qfpath);
897 return jsUndefined();
900 JSValue *Scriptface::setcallf (ExecState *exec, JSValue *name,
901 JSValue *func, JSValue *fval)
903 if (!name->isString())
904 return throwError(exec, TypeError,
905 SPREF"setcall: expected string as first argument");
906 if ( !func->isObject()
907 || !func->getObject()->implementsCall())
908 return throwError(exec, TypeError,
909 SPREF"setcall: expected function as second argument");
910 if (!(fval->isObject() || fval->isNull()))
911 return throwError(exec, TypeError,
912 SPREF"setcall: expected object or null as third argument");
914 QString qname = name->toString(exec).qstring();
915 funcs[qname] = func->getObject();
919 put(exec, Identifier(QString::fromLatin1(
"#:f<%1>").arg(qname)), func, Internal);
920 put(exec, Identifier(QString::fromLatin1(
"#:o<%1>").arg(qname)), fval, Internal);
924 fpaths[qname] = globalKTI->currentModulePath;
926 return jsUndefined();
929 JSValue *Scriptface::hascallf (ExecState *exec, JSValue *name)
931 if (!name->isString())
932 return throwError(exec, TypeError,
933 SPREF"hascall: expected string as first argument");
935 QString qname = name->toString(exec).qstring();
936 return jsBoolean(funcs.contains(qname));
939 JSValue *Scriptface::acallf (ExecState *exec,
const List &argv)
941 if (argv.size() < 1) {
942 return throwError(exec, SyntaxError,
943 SPREF"acall: expected at least one argument (call name)");
945 if (!argv[0]->isString()) {
946 return throwError(exec, SyntaxError,
947 SPREF"acall: expected string as first argument (call name)");
951 QString callname = argv[0]->getString().qstring();
952 if (!funcs.contains(callname)) {
953 return throwError(exec, EvalError,
954 QString::fromLatin1(
SPREF"acall: unregistered call to '%1'").arg(callname));
956 JSObject *func = funcs[callname];
957 JSValue *fval = fvals[callname];
961 globalKTI->currentModulePath = fpaths[callname];
965 for (
int i = 1; i < argv.size(); ++i)
966 arglist.append(argv[i]);
968 if (fval->isObject()) {
970 val = func->callAsFunction(exec, fval->getObject(), arglist);
974 val = func->callAsFunction(exec, jsi->globalObject(), arglist);
979 JSValue *Scriptface::setcallForallf (ExecState *exec, JSValue *name,
980 JSValue *func, JSValue *fval)
982 if (!name->isString())
983 return throwError(exec, TypeError,
984 SPREF"setcallForall: expected string as first argument");
985 if ( !func->isObject()
986 || !func->getObject()->implementsCall())
987 return throwError(exec, TypeError,
988 SPREF"setcallForall: expected function as second argument");
989 if (!(fval->isObject() || fval->isNull()))
990 return throwError(exec, TypeError,
991 SPREF"setcallForall: expected object or null as third argument");
993 QString qname = name->toString(exec).qstring();
994 funcs[qname] = func->getObject();
998 put(exec, Identifier(QString::fromLatin1(
"#:fall<%1>").arg(qname)), func, Internal);
999 put(exec, Identifier(QString::fromLatin1(
"#:oall<%1>").arg(qname)), fval, Internal);
1003 fpaths[qname] = globalKTI->currentModulePath;
1006 nameForalls.append(qname);
1008 return jsUndefined();
1011 JSValue *Scriptface::fallbackf (ExecState *exec)
1014 if (fallback != NULL)
1016 return jsUndefined();
1019 JSValue *Scriptface::nsubsf (ExecState *exec)
1022 return jsNumber(subs->size());
1025 JSValue *Scriptface::subsf (ExecState *exec, JSValue *index)
1027 if (!index->isNumber())
1028 return throwError(exec, TypeError,
1029 SPREF"subs: expected number as first argument");
1031 int i = qRound(index->getNumber());
1032 if (i < 0 || i >= subs->size())
1033 return throwError(exec, RangeError,
1034 SPREF"subs: index out of range");
1036 return jsString(subs->at(i));
1039 JSValue *Scriptface::valsf (ExecState *exec, JSValue *index)
1041 if (!index->isNumber())
1042 return throwError(exec, TypeError,
1043 SPREF"vals: expected number as first argument");
1045 int i = qRound(index->getNumber());
1046 if (i < 0 || i >= vals->size())
1047 return throwError(exec, RangeError,
1048 SPREF"vals: index out of range");
1053 JSValue *Scriptface::msgctxtf (ExecState *exec)
1056 return jsString(*msgctxt);
1059 JSValue *Scriptface::dynctxtf (ExecState *exec, JSValue *key)
1061 if (!key->isString())
1062 return throwError(exec, TypeError,
1063 SPREF"dynctxt: expected string as first argument");
1065 QString qkey = key->getString().qstring();
1066 if (dynctxt->contains(qkey)) {
1067 return jsString(dynctxt->value(qkey));
1069 return jsUndefined();
1072 JSValue *Scriptface::msgidf (ExecState *exec)
1075 return jsString(*msgid);
1078 JSValue *Scriptface::msgkeyf (ExecState *exec)
1081 return jsString(
QString(*msgctxt + QLatin1Char(
'|') + *msgid));
1084 JSValue *Scriptface::msgstrff (ExecState *exec)
1087 return jsString(*
final);
1090 JSValue *Scriptface::dbgputsf (ExecState *exec, JSValue *str)
1092 if (!str->isString())
1093 return throwError(exec, TypeError,
1094 SPREF"dbgputs: expected string as first argument");
1096 QString qstr = str->getString().qstring();
1098 dbgout(
"[JS-debug] %1", qstr);
1100 return jsUndefined();
1103 JSValue *Scriptface::warnputsf (ExecState *exec, JSValue *str)
1105 if (!str->isString())
1106 return throwError(exec, TypeError,
1107 SPREF"warnputs: expected string as first argument");
1109 QString qstr = str->getString().qstring();
1111 warnout(
"[JS-warning] %1", qstr);
1113 return jsUndefined();
1116 JSValue *Scriptface::localeCountryf (ExecState *exec)
1119 return jsString(*ctry);
1122 JSValue *Scriptface::normKeyf (ExecState *exec, JSValue *phrase)
1124 if (!phrase->isString()) {
1125 return throwError(exec, TypeError,
1126 SPREF"normKey: expected string as argument");
1129 QByteArray nqphrase =
normKeystr(phrase->toString(exec).qstring());
1130 return jsString(QString::fromUtf8(nqphrase));
1133 JSValue *Scriptface::loadPropsf (ExecState *exec,
const List &fnames)
1135 if (globalKTI->currentModulePath.isEmpty()) {
1136 return throwError(exec, GeneralError,
1137 SPREF"loadProps: no current module path, aiiie...");
1140 for (
int i = 0; i < fnames.size(); ++i) {
1141 if (!fnames[i]->isString()) {
1142 return throwError(exec, TypeError,
1143 SPREF"loadProps: expected string as file name");
1147 for (
int i = 0; i < fnames.size(); ++i)
1149 QString qfname = fnames[i]->getString().qstring();
1150 QString qfpath_base = globalKTI->currentModulePath + QLatin1Char(
'/') + qfname;
1154 QString qfpath = qfpath_base + QLatin1String(
".pmapc");
1155 bool haveCompiled =
true;
1156 QFile file_check(qfpath);
1157 if (!file_check.open(QIODevice::ReadOnly)) {
1158 haveCompiled =
false;
1159 qfpath = qfpath_base + QLatin1String(
".pmap");
1160 QFile file_check(qfpath);
1161 if (!file_check.open(QIODevice::ReadOnly)) {
1162 return throwError(exec, GeneralError,
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()) {
1179 return throwError(exec, SyntaxError, errorString);
1181 dbgout(
"Loaded property map: %1", qfpath);
1182 loadedPmapPaths.insert(qfpath);
1186 return jsUndefined();
1189 JSValue *Scriptface::getPropf (ExecState *exec, JSValue *phrase, JSValue *prop)
1191 if (!phrase->isString()) {
1192 return throwError(exec, TypeError,
1193 SPREF"getProp: expected string as first argument");
1195 if (!prop->isString()) {
1196 return throwError(exec, TypeError,
1197 SPREF"getProp: expected string as second argument");
1200 QByteArray qphrase =
normKeystr(phrase->toString(exec).qstring());
1202 if (props.isEmpty()) {
1203 props = resolveUnparsedProps(qphrase);
1205 if (!props.isEmpty()) {
1206 QByteArray qprop =
normKeystr(prop->toString(exec).qstring());
1207 QByteArray qval = props.value(qprop);
1208 if (!qval.isEmpty()) {
1209 return jsString(QString::fromUtf8(qval));
1212 return jsUndefined();
1215 JSValue *Scriptface::setPropf (ExecState *exec, JSValue *phrase, JSValue *prop, JSValue *value)
1217 if (!phrase->isString()) {
1218 return throwError(exec, TypeError,
1219 SPREF"setProp: expected string as first argument");
1221 if (!prop->isString()) {
1222 return throwError(exec, TypeError,
1223 SPREF"setProp: expected string as second argument");
1225 if (!value->isString()) {
1226 return throwError(exec, TypeError,
1227 SPREF"setProp: expected string as third argument");
1230 QByteArray qphrase =
normKeystr(phrase->toString(exec).qstring());
1231 QByteArray qprop =
normKeystr(prop->toString(exec).qstring());
1232 QByteArray qvalue = value->toString(exec).qstring().toUtf8();
1234 phraseProps[qphrase][qprop] = qvalue;
1235 return jsUndefined();
1240 static const QLatin1String head(
"~@");
1241 static const int hlen = 2;
1246 int len = qstr.length();
1248 int remainingAlts = 0;
1249 bool checkCase =
true;
1255 if (qnalt && !remainingAlts && qstr.mid(i, hlen) == head) {
1258 if (i >= len)
break;
1262 remainingAlts = qnalt;
1265 else if (remainingAlts && c == altSep) {
1271 else if (checkCase && c.isLetter()) {
1274 qstrcc[i] = c.toUpper();
1276 qstrcc[i] = c.toLower();
1285 if (numChcased > 0 && remainingAlts == 0) {
1296 JSValue *Scriptface::toUpperFirstf (ExecState *exec,
1297 JSValue *str, JSValue *nalt)
1299 if (!str->isString()) {
1300 return throwError(exec, TypeError,
1301 SPREF"toUpperFirst: expected string as first argument");
1303 if (!(nalt->isNumber() || nalt->isNull())) {
1304 return throwError(exec, TypeError,
1305 SPREF"toUpperFirst: expected number as second argument");
1308 QString qstr = str->toString(exec).qstring();
1309 int qnalt = nalt->isNull() ? 0 : nalt->toInteger(exec);
1313 return jsString(qstruc);
1316 JSValue *Scriptface::toLowerFirstf (ExecState *exec,
1317 JSValue *str, JSValue *nalt)
1319 if (!str->isString()) {
1320 return throwError(exec, TypeError,
1321 SPREF"toLowerFirst: expected string as first argument");
1323 if (!(nalt->isNumber() || nalt->isNull())) {
1324 return throwError(exec, TypeError,
1325 SPREF"toLowerFirst: expected number as second argument");
1328 QString qstr = str->toString(exec).qstring();
1329 int qnalt = nalt->isNull() ? 0 : nalt->toInteger(exec);
1333 return jsString(qstrlc);
1336 JSValue *Scriptface::getConfStringf (ExecState *exec,
1337 JSValue *key, JSValue *dval)
1339 if (!key->isString()) {
1340 return throwError(exec, TypeError,
1341 SPREF"getConfString: expected string "
1342 "as first argument");
1344 if (!(dval->isString() || dval->isNull())) {
1345 return throwError(exec, TypeError,
1346 SPREF"getConfString: expected string "
1347 "as second argument (when given)");
1350 if (dval->isNull()) {
1351 dval = jsUndefined();
1354 QString qkey = key->getString().qstring();
1355 if (
config.contains(qkey)) {
1356 return jsString(
config.value(qkey));
1362 JSValue *Scriptface::getConfBoolf (ExecState *exec,
1363 JSValue *key, JSValue *dval)
1365 if (!key->isString()) {
1366 return throwError(exec, TypeError,
1367 SPREF"getConfBool: expected string as "
1370 if (!(dval->isBoolean() || dval->isNull())) {
1371 return throwError(exec, TypeError,
1372 SPREF"getConfBool: expected boolean "
1373 "as second argument (when given)");
1377 if (falsities.isEmpty()) {
1378 falsities.append(
QString(QLatin1Char(
'0')));
1379 falsities.append(QString::fromLatin1(
"no"));
1380 falsities.append(QString::fromLatin1(
"false"));
1383 if (dval->isNull()) {
1384 dval = jsUndefined();
1387 QString qkey = key->getString().qstring();
1388 if (
config.contains(qkey)) {
1390 return jsBoolean(!falsities.contains(qval));
1396 JSValue *Scriptface::getConfNumberf (ExecState *exec,
1397 JSValue *key, JSValue *dval)
1399 if (!key->isString()) {
1400 return throwError(exec, TypeError,
1401 SPREF"getConfNumber: expected string "
1402 "as first argument");
1404 if (!(dval->isNumber() || dval->isNull())) {
1405 return throwError(exec, TypeError,
1406 SPREF"getConfNumber: expected number "
1407 "as second argument (when given)");
1410 if (dval->isNull()) {
1411 dval = jsUndefined();
1414 QString qkey = key->getString().qstring();
1415 if (
config.contains(qkey)) {
1418 double qnum = qval.toDouble(&convOk);
1420 return jsNumber(qnum);
1433 if (!file.open(QIODevice::ReadOnly)) {
1434 return QString::fromLatin1(
SPREF"loadProps_text: cannot read file '%1'")
1437 QTextStream stream(&file);
1438 stream.setCodec(
"UTF-8");
1445 enum {s_nextEntry, s_nextKey, s_nextValue};
1448 int slen = s.length();
1449 int state = s_nextEntry;
1451 QChar prop_sep, key_sep;
1454 int i_checkpoint = i;
1456 if (state == s_nextEntry) {
1457 while (s[i].isSpace()) {
1459 if (i >= slen)
goto END_PROP_PARSE;
1461 if (i + 1 >= slen) {
1462 return QString::fromLatin1(
SPREF"loadProps_text: unexpected end "
1463 "of file in %1").arg(fpath);
1465 if (s[i] != QLatin1Char(
'#')) {
1468 prop_sep = s[i + 1];
1469 if (key_sep.isLetter() || prop_sep.isLetter()) {
1470 return QString::fromLatin1(
SPREF"loadProps_text: separator "
1471 "characters must not be letters at %1:%2")
1485 while (s[i] != QLatin1Char(
'\n')) {
1487 if (i >= slen)
goto END_PROP_PARSE;
1491 else if (state == s_nextKey) {
1494 while (s[i] != key_sep && s[i] != prop_sep) {
1496 if (i >= slen)
goto END_PROP_PARSE;
1498 if (s[i] == key_sep) {
1504 state = s_nextValue;
1508 QByteArray ekey =
normKeystr(s.mid(ip, i - ip),
false);
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) {
1527 phraseProps[ekey] = props;
1531 state = s_nextEntry;
1535 else if (state == s_nextValue) {
1538 while (s[i] != prop_sep) {
1540 if (i >= slen)
goto END_PROP_PARSE;
1541 if (s[i] == key_sep) {
1542 return QString::fromLatin1(
SPREF"loadProps_text: property separator "
1543 "inside property value at %1:%2")
1548 QByteArray pval =
trimSmart(s.mid(ip, i - ip)).toUtf8();
1555 return QString::fromLatin1(
SPREF"loadProps: internal error 10 at %1:%2")
1560 if (i == i_checkpoint || i >= slen) {
1561 return QString::fromLatin1(
SPREF"loadProps: internal error 20 at %1:%2")
1568 if (state != s_nextEntry) {
1569 return QString::fromLatin1(
SPREF"loadProps: unexpected end of file in %1")
1580 template <
typename T>
1583 if (pos + nbytes > len) {
1587 T num = qFromBigEndian<T>((uchar*) fc + pos);
1595 return bin_read_int_nbytes<quint64>(fc, len, pos, 8);
1601 return bin_read_int_nbytes<quint32>(fc, len, pos, 4);
1614 return QByteArray();
1616 if (nbytes < 0 || pos + nbytes > len) {
1618 return QByteArray();
1620 QByteArray s(fc + pos, nbytes);
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();
1659 const int fclen = fctmp.size();
1665 QByteArray head(fc, 8);
1667 if (head !=
"TSPMAP00")
goto END_PROP_PARSE;
1672 if (pos < 0)
goto END_PROP_PARSE;
1675 for (
int i = 0; i < nentries; ++i) {
1680 if (pos < 0)
goto END_PROP_PARSE;
1681 for (
int j = 0; j < nekeys; ++j) {
1683 if (pos < 0)
goto END_PROP_PARSE;
1691 if (pos < 0)
goto END_PROP_PARSE;
1692 for (
int j = 0; j < nprops; ++j) {
1694 if (pos < 0)
goto END_PROP_PARSE;
1696 if (pos < 0)
goto END_PROP_PARSE;
1702 foreach (
const QByteArray &ekey, ekeys) {
1703 phraseProps[ekey] = props;
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);
1731 QByteArray head = fstr.left(8);
1733 if (head !=
"TSPMAP01") {
1734 return QString::fromLatin1(
SPREF"loadProps: corrupt compiled map '%1'")
1741 fstr = file->read(lenekeys);
1743 for (
quint32 i = 0; i < numekeys; ++i) {
1752 loadedPmapHandles.insert(file);
1759 QFile *file = ref.first;
1762 if (file != NULL && file->seek(offset)) {
1763 QByteArray fstr = file->read(4 + 4);
1767 fstr = file->read(lenpkeys);
1769 for (
quint32 i = 0; i < numpkeys; ++i) {
1774 phraseProps[phrase] = props;
1775 phraseUnparsedProps.remove(phrase);
JSValue * variantToJsValue(const QVariant &val)
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics.
QString expt2str(ExecState *exec)
void warnout(const char *str)
QString removeAcceleratorMarker(const QString &label_)
static QByteArray bin_read_string(const char *fc, qlonglong len, qlonglong &pos)
void ref()
Tells KGlobal about one more operations that should be finished before the application exits...
KSharedConfigPtr config()
Returns the general config object.
KTranscript * load_transcript()
static quint32 bin_read_int(const char *fc, qlonglong len, qlonglong &pos)
QHash< QString, TsConfigGroup > TsConfig
TsConfig readConfig(const QString &fname)
static QString toCaseFirst(const QString &qstr, int qnalt, bool toupper)
static int bin_read_int_nbytes(const char *fc, qlonglong len, qlonglong &pos, int nbytes)
QByteArray normKeystr(const QString &raw, bool mayHaveAcc=true)
QString trimSmart(const QString &raw)
QHash< QString, QString > TsConfigGroup
int countLines(const QString &s, int p)
class for supporting programmable translations
void dbgout(const char *str)
static quint64 bin_read_int64(const char *fc, qlonglong len, qlonglong &pos)
#define KDE_EXPORT
The KDE_EXPORT macro marks the symbol of the given variable to be visible, so it can be used from out...