QSP_CHAR *qspStrPos(QSP_CHAR *txt, QSP_CHAR *str, QSP_BOOL isIsolated) { QSP_BOOL isLastDelim; int strLen, c1, c2, c3; QSP_CHAR quot, *pos = qspStrStr(txt, str); if (!pos) return 0; if (!(isIsolated || qspStrPBrk(txt, QSP_QUOTS QSP_LQUOT QSP_LRBRACK QSP_LSBRACK))) return pos; strLen = qspStrLen(str); pos = qspStrEnd(txt) - strLen + 1; c1 = c2 = c3 = 0; isLastDelim = QSP_TRUE; while (txt < pos) { if (qspIsInList(QSP_QUOTS, *txt)) { quot = *txt; while (++txt < pos) if (*txt == quot && *(++txt) != quot) break; if (txt >= pos) return 0; isLastDelim = QSP_TRUE; } if (*txt == QSP_LRBRACK[0]) ++c1; else if (*txt == QSP_RRBRACK[0]) { if (c1) --c1; } else if (*txt == QSP_LSBRACK[0]) ++c2; else if (*txt == QSP_RSBRACK[0]) { if (c2) --c2; } else if (*txt == QSP_LQUOT[0]) ++c3; else if (*txt == QSP_RQUOT[0]) { if (c3) --c3; } if (!(c1 || c2 || c3)) { if (isIsolated) { if (qspIsInList(QSP_DELIMS, *txt)) isLastDelim = QSP_TRUE; else if (isLastDelim) { if (qspIsInListEOL(QSP_DELIMS, txt[strLen]) && !qspStrsNComp(txt, str, strLen)) return txt; isLastDelim = QSP_FALSE; } } else if (!qspStrsNComp(txt, str, strLen)) return txt; } ++txt; } return 0; }
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 *qspInStrRChars(QSP_CHAR *str, QSP_CHAR *chars, QSP_CHAR *end) { QSP_CHAR *pos = 0; while (*str) { if (end && str == end) break; if (qspIsInList(chars, *str)) pos = str; ++str; } return pos; }
QSP_CHAR *qspDelSpc(QSP_CHAR *s) { int len; QSP_CHAR *str, *begin = qspSkipSpaces(s), *end = qspStrEnd(begin); while (begin < end && qspIsInList(QSP_SPACES, *(end - 1))) --end; len = (int)(end - begin); str = (QSP_CHAR *)malloc((len + 1) * sizeof(QSP_CHAR)); qspStrNCopy(str, begin, len); str[len] = 0; return str; }
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)); }
QSP_CHAR *qspSkipSpaces(QSP_CHAR *s) { while (qspIsInList(QSP_SPACES, *s)) ++s; return s; }
static int qspProcessPreformattedStrings(QSPString data, QSPLineOfCode **strs) { QSPLineOfCode *ret, *line; QSP_BOOL isNewLine; QSP_CHAR *str, *pos, quot = 0; QSPString strsDelim; int lineNum = 0, lastLineNum = 0, count = 0, quotsCount = 0, strLen = 0, bufSize = 8, strBufSize = 256; str = (QSP_CHAR *)malloc(strBufSize * sizeof(QSP_CHAR)); ret = (QSPLineOfCode *)malloc(bufSize * sizeof(QSPLineOfCode)); strsDelim = QSP_STATIC_STR(QSP_STRSDELIM); pos = data.Str; while (pos < data.End) { isNewLine = (qspStrsNComp(data, strsDelim, QSP_STATIC_LEN(QSP_STRSDELIM)) == 0); if (isNewLine) ++lineNum; if (quotsCount || quot || !isNewLine) { if (strLen >= strBufSize) { strBufSize = strLen + 256; str = (QSP_CHAR *)realloc(str, strBufSize * sizeof(QSP_CHAR)); } str[strLen++] = *pos; if (quot) { if (*pos == quot) { if (++pos < data.End && *pos == quot) { if (strLen >= strBufSize) { strBufSize = strLen + 256; str = (QSP_CHAR *)realloc(str, strBufSize * sizeof(QSP_CHAR)); } str[strLen++] = *pos++; } else quot = 0; } else ++pos; } else { if (*pos == QSP_LQUOT[0]) ++quotsCount; else if (*pos == QSP_RQUOT[0]) { if (quotsCount) --quotsCount; } else if (qspIsInList(QSP_QUOTS, *pos)) quot = *pos; ++pos; } } else { if (count >= bufSize) { bufSize = count + 16; ret = (QSPLineOfCode *)realloc(ret, bufSize * sizeof(QSPLineOfCode)); } line = ret + count++; line->Str = qspGetNewText(qspDelSpc(qspStringFromLen(str, strLen))); line->LineNum = lastLineNum; line->Label = qspNullString; line->Stats = 0; lastLineNum = lineNum; strLen = 0; pos += QSP_STATIC_LEN(QSP_STRSDELIM); } data.Str = pos; } if (count >= bufSize) ret = (QSPLineOfCode *)realloc(ret, (count + 1) * sizeof(QSPLineOfCode)); line = ret + count++; line->Str = qspGetNewText(qspDelSpc(qspStringFromLen(str, strLen))); line->LineNum = lastLineNum; line->Label = qspNullString; line->Stats = 0; free(str); *strs = ret; return count; }