QSPVar *qspVarReference(const QSP_CHAR *name, QSP_BOOL isCreate) { int i; QSPVar *var; QSP_CHAR *uName; unsigned char bCode; if (*name == QSP_STRCHAR[0]) ++name; if (!(*name) || qspIsDigit(*name) || qspStrPBrk(name, QSP_DELIMS)) { qspSetError(QSP_ERR_NOTCORRECTNAME); return nullptr; } qspUpperStr(uName = qspGetNewText(name, -1)); bCode = 0; for (i = 0; uName[i]; ++i) bCode = qspRand8[bCode ^ (unsigned char)uName[i]]; var = qspVars + QSP_VARSSEEK * bCode; for (i = 0; i < QSP_VARSSEEK; ++i) { if (!var->Name) { if (isCreate) var->Name = uName; else free(uName); return var; } if (!qspStrsComp(var->Name, uName)) { free(uName); return var; } ++var; } free(uName); qspSetError(QSP_ERR_TOOMANYVARS); return nullptr; }
QSP_BOOL qspStatementShowMenu(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg) { int ind, maxItems, len; QSPVar *var; QSP_CHAR *imgPath, *str, *pos, *pos2; if (!(var = qspVarReferenceWithType(QSP_STR(args[0]), QSP_FALSE, 0))) return QSP_FALSE; qspClearMenu(QSP_FALSE); qspCallDeleteMenu(); if (count == 1) { ind = 0; maxItems = QSP_MAXMENUITEMS; } else { ind = QSP_NUM(args[1]); if (ind < 0) ind = 0; if (count == 2) maxItems = QSP_MAXMENUITEMS; else { maxItems = QSP_NUM(args[2]); if (maxItems < 0) maxItems = 0; } } while (ind < var->ValsCount) { if (qspCurMenuItems == maxItems) break; if (!((str = var->Values[ind].Str) && qspIsAnyString(str))) break; if (!(pos2 = qspInStrRChars(str, QSP_MENUDELIM, 0))) { qspSetError(QSP_ERR_COLONNOTFOUND); return QSP_FALSE; } if (qspCurMenuItems == QSP_MAXMENUITEMS) { qspSetError(QSP_ERR_CANTADDMENUITEM); return QSP_FALSE; } if (pos = qspInStrRChars(str, QSP_MENUDELIM, pos2)) { len = (int)(pos2 - pos) - 1; imgPath = (qspIsAnyString(++pos2) ? qspGetAbsFromRelPath(pos2) : 0); } else { pos = pos2; len = -1; imgPath = 0; } qspCurMenuLocs[qspCurMenuItems++] = qspGetNewText(pos + 1, len); *pos = 0; qspCallAddMenuItem(str, imgPath); *pos = QSP_MENUDELIM[0]; if (imgPath) free(imgPath); ++ind; } if (qspCurMenuItems) qspCallShowMenu(); return QSP_FALSE; }
static void qspSetVar(QSP_CHAR *name, QSPVariant *val, QSP_CHAR op) { QSPVariant oldVal; QSPVar *var; int index; if (!(var = qspGetVarData(name, QSP_TRUE, &index))) return; if (op == QSP_EQUAL[0]) { if (qspConvertVariantTo(val, *name == QSP_STRCHAR[0])) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } qspSetVarValueByReference(var, index, val); } else if (op == QSP_ADD[0]) { oldVal = qspGetVarValueByReference(var, index, *name == QSP_STRCHAR[0]); if (oldVal.IsStr && val->IsStr) QSP_STR(oldVal) = qspGetAddText(QSP_STR(oldVal), QSP_PSTR(val), -1, -1); else if (qspIsCanConvertToNum(&oldVal) && qspIsCanConvertToNum(val)) { qspConvertVariantTo(&oldVal, QSP_FALSE); qspConvertVariantTo(val, QSP_FALSE); QSP_NUM(oldVal) += QSP_PNUM(val); qspConvertVariantTo(&oldVal, *name == QSP_STRCHAR[0]); } else { if (!oldVal.IsStr) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } qspConvertVariantTo(val, QSP_TRUE); QSP_STR(oldVal) = qspGetAddText(QSP_STR(oldVal), QSP_PSTR(val), -1, -1); } qspSetVarValueByReference(var, index, &oldVal); if (oldVal.IsStr) free(QSP_STR(oldVal)); } else if (qspIsInList(QSP_SUB QSP_DIV QSP_MUL, op)) { if (qspConvertVariantTo(val, QSP_FALSE)) { qspSetError(QSP_ERR_TYPEMISMATCH); return; } oldVal = qspGetVarValueByReference(var, index, *name == QSP_STRCHAR[0]); if (qspConvertVariantTo(&oldVal, QSP_FALSE)) { qspSetError(QSP_ERR_TYPEMISMATCH); free(QSP_STR(oldVal)); return; } if (op == QSP_SUB[0]) QSP_NUM(oldVal) -= QSP_PNUM(val); else if (op == QSP_DIV[0]) { if (!QSP_PNUM(val)) { qspSetError(QSP_ERR_DIVBYZERO); return; } QSP_NUM(oldVal) /= QSP_PNUM(val); } else QSP_NUM(oldVal) *= QSP_PNUM(val); qspConvertVariantTo(&oldVal, *name == QSP_STRCHAR[0]); qspSetVarValueByReference(var, index, &oldVal); if (oldVal.IsStr) free(QSP_STR(oldVal)); } }
QSP_CHAR *qspFormatText(QSP_CHAR *txt, QSP_BOOL canReturnSelf) { QSPVariant val; QSP_CHAR *newTxt, *lPos, *rPos; int oldRefreshCount, len, txtLen, oldTxtLen, bufSize; if (qspGetVarNumValue(QSP_FMT("DISABLESUBEX"))) { if (canReturnSelf) return txt; return qspGetNewText(txt, -1); } lPos = qspStrStr(txt, QSP_LSUBEX); if (!lPos) { if (canReturnSelf) return txt; return qspGetNewText(txt, -1); } bufSize = 256; newTxt = (QSP_CHAR *)malloc(bufSize * sizeof(QSP_CHAR)); txtLen = oldTxtLen = 0; oldRefreshCount = qspRefreshCount; do { len = (int)(lPos - txt); if ((txtLen += len) >= bufSize) { bufSize = txtLen + 128; newTxt = (QSP_CHAR *)realloc(newTxt, bufSize * sizeof(QSP_CHAR)); } qspStrNCopy(newTxt + oldTxtLen, txt, len); oldTxtLen = txtLen; txt = lPos + QSP_LEN(QSP_LSUBEX); rPos = qspStrPos(txt, QSP_RSUBEX, QSP_FALSE); if (!rPos) { qspSetError(QSP_ERR_BRACKNOTFOUND); free(newTxt); return 0; } *rPos = 0; val = qspExprValue(txt); *rPos = QSP_RSUBEX[0]; if (qspRefreshCount != oldRefreshCount || qspErrorNum) { free(newTxt); return 0; } qspConvertVariantTo(&val, QSP_TRUE); if ((txtLen += qspStrLen(QSP_STR(val))) >= bufSize) { bufSize = txtLen + 128; newTxt = (QSP_CHAR *)realloc(newTxt, bufSize * sizeof(QSP_CHAR)); } qspStrCopy(newTxt + oldTxtLen, QSP_STR(val)); free(QSP_STR(val)); oldTxtLen = txtLen; txt = rPos + QSP_LEN(QSP_RSUBEX); lPos = qspStrStr(txt, QSP_LSUBEX); } while (lPos); return qspGetAddText(newTxt, txt, txtLen, -1); }
QSP_BOOL qspStatementAddObject(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg) { QSPObj *obj; int i, objInd; QSP_CHAR *imgPath; if (count == 3) { objInd = QSP_NUM(args[2]) - 1; if (objInd < 0 || objInd > qspCurObjectsCount) return QSP_FALSE; } else objInd = qspCurObjectsCount; if (qspCurObjectsCount == QSP_MAXOBJECTS) { qspSetError(QSP_ERR_CANTADDOBJECT); return QSP_FALSE; } if (qspCurSelObject >= objInd) qspCurSelObject = -1; if (count >= 2 && qspIsAnyString(QSP_STR(args[1]))) imgPath = qspGetAbsFromRelPath(QSP_STR(args[1])); else imgPath = 0; for (i = qspCurObjectsCount; i > objInd; --i) qspCurObjects[i] = qspCurObjects[i - 1]; ++qspCurObjectsCount; obj = qspCurObjects + objInd; obj->Image = imgPath; obj->Desc = qspGetNewText(QSP_STR(args[0]), -1); qspIsObjectsChanged = QSP_TRUE; qspExecLocByVarNameWithArgs(QSP_FMT("ONOBJADD"), args, (count < 3 ? count : 2)); return QSP_FALSE; }
void qspAddAction(QSPVariant *args, int count, QSPLineOfCode *code, int start, int end, QSP_BOOL isManageLines) { QSPCurAct *act; QSP_CHAR *imgPath; if (qspActIndex(QSP_STR(args[0])) >= 0) return; if (qspCurActionsCount == QSP_MAXACTIONS) { qspSetError(QSP_ERR_CANTADDACTION); return; } if (count == 2 && qspIsAnyString(QSP_STR(args[1]))) imgPath = qspGetAbsFromRelPath(QSP_STR(args[1])); else imgPath = 0; act = qspCurActions + qspCurActionsCount++; act->Image = imgPath; act->Desc = qspGetNewText(QSP_STR(args[0]), -1); qspCopyPrepLines(&act->OnPressLines, code, start, end); act->OnPressLinesCount = end - start; act->Location = qspRealCurLoc; act->ActIndex = qspRealActIndex; act->StartLine = qspRealLine; act->IsManageLines = isManageLines; qspIsActionsChanged = QSP_TRUE; }
void qspStatementSinglelineAddAct(QSPLineOfCode *s, int statPos, int endPos) { QSPVariant args[2]; QSPLineOfCode code; int i, oldRefreshCount, count, offset; QSP_CHAR ch, *pos = s->Str + s->Stats[statPos].EndPos; if (*pos != QSP_COLONDELIM[0]) { qspSetError(QSP_ERR_COLONNOTFOUND); return; } if (statPos == endPos - 1) { qspSetError(QSP_ERR_CODENOTFOUND); return; } oldRefreshCount = qspRefreshCount; *pos = 0; count = qspGetStatArgs(s->Str + s->Stats[statPos].ParamPos, qspStatAct, args); *pos = QSP_COLONDELIM[0]; if (qspRefreshCount != oldRefreshCount || qspErrorNum) return; ++statPos; code.Str = pos + 1; code.Label = qspGetLineLabel(code.Str); code.LineNum = 0; code.IsMultiline = QSP_FALSE; pos = s->Str + s->Stats[endPos - 1].EndPos; if (*pos == QSP_COLONDELIM[0]) ++pos; ch = *pos; *pos = 0; code.StatsCount = endPos - statPos; code.Stats = (QSPCachedStat *)malloc(code.StatsCount * sizeof(QSPCachedStat)); offset = (int)(code.Str - s->Str); for (i = 0; i < code.StatsCount; ++i) { code.Stats[i].Stat = s->Stats[statPos].Stat; code.Stats[i].EndPos = s->Stats[statPos].EndPos - offset; code.Stats[i].ParamPos = s->Stats[statPos].ParamPos - offset; ++statPos; } qspAddAction(args, count, &code, 0, 1, QSP_FALSE); *pos = ch; qspFreeVariants(args, count); free(code.Stats); if (code.Label) free(code.Label); }
void qspStatementSinglelineAddAct(QSPLineOfCode *s, int statPos, int endPos) { QSPVariant args[2]; QSPLineOfCode code; int i, oldRefreshCount, count, offset; QSP_CHAR *lastPos, *firstPos = s->Str.Str + s->Stats[statPos].EndPos; if (*firstPos != QSP_COLONDELIM[0]) { qspSetError(QSP_ERR_COLONNOTFOUND); return; } if (statPos == endPos - 1) { qspSetError(QSP_ERR_CODENOTFOUND); return; } oldRefreshCount = qspRefreshCount; count = qspGetStatArgs(qspStringFromPair(s->Str.Str + s->Stats[statPos].ParamPos, firstPos), qspStatAct, args); if (qspRefreshCount != oldRefreshCount || qspErrorNum) return; ++statPos; firstPos += QSP_STATIC_LEN(QSP_COLONDELIM); lastPos = s->Str.Str + s->Stats[endPos - 1].EndPos; if (lastPos != s->Str.End && *lastPos == QSP_COLONDELIM[0]) lastPos += QSP_STATIC_LEN(QSP_COLONDELIM); code.Str = qspStringFromPair(firstPos, lastPos); code.Label = qspGetLineLabel(code.Str); code.LineNum = 0; code.IsMultiline = QSP_FALSE; code.StatsCount = endPos - statPos; code.Stats = (QSPCachedStat *)malloc(code.StatsCount * sizeof(QSPCachedStat)); offset = (int)(firstPos - s->Str.Str); for (i = 0; i < code.StatsCount; ++i) { code.Stats[i].Stat = s->Stats[statPos].Stat; code.Stats[i].EndPos = s->Stats[statPos].EndPos - offset; code.Stats[i].ParamPos = s->Stats[statPos].ParamPos - offset; ++statPos; } qspAddAction(args, count, &code, 0, 1, QSP_FALSE); qspFreeVariants(args, count); free(code.Stats); qspFreeString(code.Label); }
static QSPVar *qspGetVarData(QSP_CHAR *s, QSP_BOOL isSet, int *index) { QSPVar *var; QSPVariant ind; int oldRefreshCount; QSP_CHAR *temp, *rPos, *lPos = qspStrChar(s, QSP_LSBRACK[0]); if (lPos) { rPos = qspStrPos(lPos, QSP_RSBRACK, QSP_FALSE); if (!rPos) { qspSetError(QSP_ERR_BRACKNOTFOUND); return 0; } *lPos = 0; var = qspVarReference(s, isSet); *lPos = QSP_LSBRACK[0]; if (!var) return 0; temp = qspSkipSpaces(lPos + 1); if (temp == rPos) { if (isSet) *index = var->ValsCount; else *index = (var->ValsCount ? var->ValsCount - 1 : 0); } else { oldRefreshCount = qspRefreshCount; *rPos = 0; ind = qspExprValue(temp); *rPos = QSP_RSBRACK[0]; if (qspRefreshCount != oldRefreshCount || qspErrorNum) return 0; if (ind.IsStr) { *index = qspGetVarTextIndex(var, QSP_STR(ind), isSet); free(QSP_STR(ind)); } else *index = QSP_NUM(ind); } return var; } *index = 0; return qspVarReference(s, isSet); }
int qspArrayPos(QSP_CHAR *varName, QSPVariant *val, int ind, QSP_BOOL isRegExp) { int num, count; QSPVar *var; QSP_CHAR *str; regex_t *regExp; QSP_BOOL isString; if (!(var = qspVarReferenceWithType(varName, QSP_FALSE, &isString))) return -1; if (qspConvertVariantTo(val, isRegExp || isString)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (isRegExp) { regExp = qspRegExpGetCompiled(QSP_PSTR(val)); if (!regExp) return -1; } count = var->ValsCount; if (ind < 0) ind = 0; else if (ind > count) ind = count; while (ind <= count) { if (val->IsStr) { if (!(ind < count && (str = var->Values[ind].Str))) str = QSP_FMT(""); if (isRegExp) { if (qspRegExpStrMatch(regExp, str)) return ind; } else if (!qspStrsComp(str, QSP_PSTR(val))) return ind; } else { num = (ind < count ? var->Values[ind].Num : 0); if (num == QSP_PNUM(val)) return ind; } ++ind; } return -1; }
void qspStatementSetVarValue(QSP_CHAR *s) { QSPVariant v; int oldRefreshCount; QSP_CHAR ch, *name, *pos = qspStrPos(s, QSP_EQUAL, QSP_FALSE); if (!pos) { qspSetError(QSP_ERR_EQNOTFOUND); return; } oldRefreshCount = qspRefreshCount; v = qspExprValue(pos + QSP_LEN(QSP_EQUAL)); if (qspRefreshCount != oldRefreshCount || qspErrorNum) return; if (pos != s && qspIsInList(QSP_ADD QSP_SUB QSP_DIV QSP_MUL, *(pos - 1))) --pos; ch = *pos; *pos = 0; name = qspDelSpcCanRetSelf(s); qspSetVarValue(name, &v, ch); *pos = ch; if (name != s) free(name); if (v.IsStr) free(QSP_STR(v)); }
void qspStatementLocal(QSP_CHAR *s) { QSPVariant v; QSPVar *var; QSP_BOOL isVarFound; QSP_CHAR *curPos, *varName, *commaPos, *eqPos; int i, groupInd, count, bufSize, oldRefreshCount; s = qspSkipSpaces(s); if (!(*s)) { qspSetError(QSP_ERR_SYNTAX); return; } groupInd = qspSavedVarsGroupsCount - 1; count = bufSize = qspSavedVarsGroups[groupInd].VarsCount; isVarFound = QSP_FALSE; curPos = s; eqPos = qspStrPos(curPos, QSP_EQUAL, QSP_FALSE); if (eqPos) *eqPos = 0; while (1) { /* Skip type char */ if (*curPos == QSP_STRCHAR[0]) ++curPos; /* Get variable's name */ commaPos = qspStrPos(curPos, QSP_COMMA, QSP_FALSE); if (commaPos) { *commaPos = 0; varName = (eqPos ? qspGetVarNameOnly(curPos) : qspDelSpc(curPos)); *commaPos = QSP_COMMA[0]; } else varName = (eqPos ? qspGetVarNameOnly(curPos) : qspDelSpc(curPos)); qspUpperStr(varName); /* Check for the existence */ for (i = 0; i < count; ++i) { if (!qspStrsComp(varName, qspSavedVarsGroups[groupInd].Vars[i].Name)) { isVarFound = QSP_TRUE; break; } } /* Get variable's data */ if (isVarFound) { /* Already exists */ isVarFound = QSP_FALSE; free(varName); } else { /* Add variable to the local group */ if (!(var = qspVarReference(varName, QSP_FALSE))) { free(varName); if (eqPos) *eqPos = QSP_EQUAL[0]; return; } if (count >= bufSize) { bufSize = count + 4; qspSavedVarsGroups[groupInd].Vars = (QSPVar *)realloc(qspSavedVarsGroups[groupInd].Vars, bufSize * sizeof(QSPVar)); } qspMoveVar(qspSavedVarsGroups[groupInd].Vars + count, var); qspSavedVarsGroups[groupInd].Vars[count].Name = varName; qspSavedVarsGroups[groupInd].VarsCount = ++count; } if (!commaPos) break; curPos = qspSkipSpaces(commaPos + QSP_LEN(QSP_COMMA)); if (!(*curPos)) { qspSetError(QSP_ERR_SYNTAX); if (eqPos) *eqPos = QSP_EQUAL[0]; return; } } if (eqPos) { oldRefreshCount = qspRefreshCount; v = qspExprValue(eqPos + QSP_LEN(QSP_EQUAL)); if (qspRefreshCount != oldRefreshCount || qspErrorNum) { *eqPos = QSP_EQUAL[0]; return; } varName = qspDelSpcCanRetSelf(s); qspSetVarValue(varName, &v, QSP_EQUAL[0]); if (varName != s) free(varName); if (v.IsStr) free(QSP_STR(v)); *eqPos = QSP_EQUAL[0]; } }
int qspArrayPos(QSPVariant *args, int argsCount, QSP_BOOL isRegExp) { int num, count, ind; QSPVar *var; QSPVariant *val; QSP_CHAR *str; OnigUChar *tempBeg, *tempEnd; regex_t *onigExp; OnigErrorInfo onigInfo; QSP_BOOL isString; if (qspConvertVariantTo(args, argsCount == 2)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (argsCount == 2) { str = QSP_STR(args[0]); ind = 0; val = args + 1; } else { qspConvertVariantTo(args + 1, QSP_TRUE); str = QSP_STR(args[1]); ind = QSP_NUM(args[0]); val = args + 2; if (ind < 0) ind = 0; } if (!(var = qspVarReferenceWithType(str, QSP_FALSE, &isString))) return -1; if (qspConvertVariantTo(val, isRegExp || isString)) { qspSetError(QSP_ERR_TYPEMISMATCH); return -1; } if (isRegExp) { tempBeg = (OnigUChar *)QSP_PSTR(val); tempEnd = (OnigUChar *)qspStrEnd(QSP_PSTR(val)); if (onig_new(&onigExp, tempBeg, tempEnd, ONIG_OPTION_DEFAULT, QSP_ONIG_ENC, ONIG_SYNTAX_PERL_NG, &onigInfo)) { qspSetError(QSP_ERR_INCORRECTREGEXP); return -1; } } count = var->ValsCount; if (ind > count) ind = count; while (ind <= count) { if (val->IsStr) { if (!(ind < count && (str = var->Values[ind].Str))) str = QSP_FMT(""); if (isRegExp) { tempBeg = (OnigUChar *)str; tempEnd = (OnigUChar *)qspStrEnd(str); if (onig_match(onigExp, tempBeg, tempEnd, tempBeg, 0, ONIG_OPTION_NONE) == tempEnd - tempBeg) { onig_free(onigExp); return ind; } } else if (!qspStrsComp(str, QSP_PSTR(val))) return ind; } else { num = (ind < count ? var->Values[ind].Num : 0); if (num == QSP_PNUM(val)) return ind; } ++ind; } if (isRegExp) onig_free(onigExp); return -1; }