statements.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  1. /* Copyright (C) 2005-2010 Valeriy Argunov (nporep AT mail DOT ru) */
  2. /*
  3. * This library is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation; either version 2.1 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #include "statements.h"
  18. #include "actions.h"
  19. #include "callbacks.h"
  20. #include "common.h"
  21. #include "errors.h"
  22. #include "game.h"
  23. #include "locations.h"
  24. #include "mathops.h"
  25. #include "menu.h"
  26. #include "objects.h"
  27. #include "playlist.h"
  28. #include "text.h"
  29. #include "variables.h"
  30. QSPStatement qspStats[qspStatLast_Statement];
  31. QSPStatName qspStatsNames[QSP_STATSLEVELS][QSP_MAXSTATSNAMES];
  32. int qspStatsNamesCounts[QSP_STATSLEVELS];
  33. int qspStatMaxLen = 0;
  34. static void qspAddStatement(int, int, QSP_STATEMENT, int, int, ...);
  35. static void qspAddStatName(int, QSP_CHAR *, int);
  36. static int qspStatsCompare(const void *, const void *);
  37. static int qspStatStringCompare(const void *, const void *);
  38. static int qspGetStatCode(QSP_CHAR *, QSP_CHAR **);
  39. static int qspSearchElse(QSPLineOfCode *, int, int);
  40. static int qspSearchEnd(QSPLineOfCode *, int, int);
  41. static int qspSearchLabel(QSPLineOfCode *, int, int, QSP_CHAR *);
  42. static QSP_BOOL qspExecString(QSPLineOfCode *, int, int, QSP_CHAR **);
  43. static QSP_BOOL qspExecMultilineCode(QSPLineOfCode *, int, int, QSP_CHAR **, int *, int *);
  44. static QSP_BOOL qspExecSinglelineCode(QSPLineOfCode *, int, int, QSP_CHAR **, int *, int *);
  45. static QSP_BOOL qspExecCode(QSPLineOfCode *, int, int, int, QSP_CHAR **);
  46. static QSP_BOOL qspExecCodeBlockWithLocals(QSPLineOfCode *, int, int, int, QSP_CHAR **);
  47. static QSP_BOOL qspExecStringWithLocals(QSPLineOfCode *, int, int, QSP_CHAR **);
  48. static QSP_BOOL qspStatementIf(QSPLineOfCode *, int, int, QSP_CHAR **);
  49. static QSP_CHAR *qspPrepareForLoop(QSP_CHAR *, QSPVar *, QSP_CHAR **, QSP_CHAR **);
  50. static QSP_BOOL qspCheckForLoop(QSP_CHAR *, QSP_CHAR *, QSP_CHAR *, QSP_CHAR *, int *);
  51. static void qspEndForLoop(QSP_CHAR *, int);
  52. static QSP_BOOL qspStatementSinglelineFor(QSPLineOfCode *, int, int, QSP_CHAR **);
  53. static QSP_BOOL qspStatementMultilineFor(QSPLineOfCode *, int, int, int, QSP_CHAR **);
  54. static void qspStatementLocal(QSP_CHAR *);
  55. static QSP_BOOL qspStatementAddText(QSPVariant *, int, QSP_CHAR **, int);
  56. static QSP_BOOL qspStatementClear(QSPVariant *, int, QSP_CHAR **, int);
  57. static QSP_BOOL qspStatementExit(QSPVariant *, int, QSP_CHAR **, int);
  58. static QSP_BOOL qspStatementGoSub(QSPVariant *, int, QSP_CHAR **, int);
  59. static QSP_BOOL qspStatementGoTo(QSPVariant *, int, QSP_CHAR **, int);
  60. static QSP_BOOL qspStatementJump(QSPVariant *, int, QSP_CHAR **, int);
  61. static QSP_BOOL qspStatementWait(QSPVariant *, int, QSP_CHAR **, int);
  62. static QSP_BOOL qspStatementSetTimer(QSPVariant *, int, QSP_CHAR **, int);
  63. static QSP_BOOL qspStatementShowWin(QSPVariant *, int, QSP_CHAR **, int);
  64. static QSP_BOOL qspStatementRefInt(QSPVariant *, int, QSP_CHAR **, int);
  65. static QSP_BOOL qspStatementView(QSPVariant *, int, QSP_CHAR **, int);
  66. static QSP_BOOL qspStatementMsg(QSPVariant *, int, QSP_CHAR **, int);
  67. static QSP_BOOL qspStatementExec(QSPVariant *, int, QSP_CHAR **, int);
  68. static QSP_BOOL qspStatementDynamic(QSPVariant *, int, QSP_CHAR **, int);
  69. static void qspAddStatement(int statCode, int extArg, QSP_STATEMENT func, int minArgs, int maxArgs, ...)
  70. {
  71. int i;
  72. va_list marker;
  73. qspStats[statCode].ExtArg = extArg;
  74. qspStats[statCode].Func = func;
  75. qspStats[statCode].MinArgsCount = minArgs;
  76. qspStats[statCode].MaxArgsCount = maxArgs;
  77. if (maxArgs > 0)
  78. {
  79. va_start(marker, maxArgs);
  80. for (i = 0; i < maxArgs; ++i)
  81. qspStats[statCode].ArgsTypes[i] = va_arg(marker, int);
  82. va_end(marker);
  83. }
  84. }
  85. static void qspAddStatName(int statCode, QSP_CHAR *statName, int level)
  86. {
  87. int count, len = qspStrLen(statName);
  88. count = qspStatsNamesCounts[level];
  89. qspStatsNames[level][count].Name = statName;
  90. qspStatsNames[level][count].NameLen = len;
  91. qspStatsNames[level][count].Code = statCode;
  92. qspStatsNamesCounts[level] = count + 1;
  93. /* Max length */
  94. if (len > qspStatMaxLen) qspStatMaxLen = len;
  95. }
  96. static int qspStatsCompare(const void *statName1, const void *statName2)
  97. {
  98. return qspStrsComp(((QSPStatName *)statName1)->Name, ((QSPStatName *)statName2)->Name);
  99. }
  100. static int qspStatStringCompare(const void *name, const void *compareTo)
  101. {
  102. return qspStrsNComp((QSP_CHAR *)name, ((QSPStatName *)compareTo)->Name, ((QSPStatName *)compareTo)->NameLen);
  103. }
  104. void qspInitStats()
  105. {
  106. /*
  107. Format:
  108. qspAddStatement(
  109. Statement,
  110. Extended Argument,
  111. Statement's Function,
  112. Minimum Arguments' Count,
  113. Maximum Arguments' Count,
  114. Arguments' Types [optional]
  115. );
  116. "Arguments' Types":
  117. 0 - Unknown / Any
  118. 1 - String
  119. 2 - Number
  120. */
  121. int i;
  122. for (i = 0; i < QSP_STATSLEVELS; ++i) qspStatsNamesCounts[i] = 0;
  123. qspStatMaxLen = 0;
  124. qspAddStatement(qspStatElse, 0, 0, 0, 0);
  125. qspAddStatement(qspStatElseIf, 0, 0, 1, 1, 2);
  126. qspAddStatement(qspStatEnd, 0, 0, 0, 0);
  127. qspAddStatement(qspStatLocal, 0, 0, 0, 0);
  128. qspAddStatement(qspStatSet, 0, 0, 0, 0);
  129. qspAddStatement(qspStatIf, 0, 0, 1, 1, 2);
  130. qspAddStatement(qspStatAct, 0, 0, 1, 2, 1, 1);
  131. qspAddStatement(qspStatFor, 0, 0, 0, 0);
  132. qspAddStatement(qspStatAddObj, 0, qspStatementAddObject, 1, 3, 1, 1, 2);
  133. qspAddStatement(qspStatClA, 3, qspStatementClear, 0, 0);
  134. qspAddStatement(qspStatCloseAll, 1, qspStatementCloseFile, 0, 0);
  135. qspAddStatement(qspStatClose, 0, qspStatementCloseFile, 0, 1, 1);
  136. qspAddStatement(qspStatClS, 4, qspStatementClear, 0, 0);
  137. qspAddStatement(qspStatCmdClear, 2, qspStatementClear, 0, 0);
  138. qspAddStatement(qspStatCopyArr, 0, qspStatementCopyArr, 2, 4, 1, 1, 2, 2);
  139. qspAddStatement(qspStatDelAct, 0, qspStatementDelAct, 1, 1, 1);
  140. qspAddStatement(qspStatDelObj, 0, qspStatementDelObj, 1, 1, 1);
  141. qspAddStatement(qspStatDynamic, 0, qspStatementDynamic, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  142. qspAddStatement(qspStatExec, 0, qspStatementExec, 1, 1, 1);
  143. qspAddStatement(qspStatExit, 0, qspStatementExit, 0, 0);
  144. qspAddStatement(qspStatFreeLib, 6, qspStatementClear, 0, 0);
  145. qspAddStatement(qspStatGoSub, 0, qspStatementGoSub, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  146. qspAddStatement(qspStatGoTo, 1, qspStatementGoTo, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  147. qspAddStatement(qspStatIncLib, 1, qspStatementOpenQst, 1, 1, 1);
  148. qspAddStatement(qspStatJump, 0, qspStatementJump, 1, 1, 1);
  149. qspAddStatement(qspStatKillAll, 5, qspStatementClear, 0, 0);
  150. qspAddStatement(qspStatKillObj, 1, qspStatementDelObj, 0, 1, 2);
  151. qspAddStatement(qspStatKillVar, 0, qspStatementKillVar, 0, 2, 1, 2);
  152. qspAddStatement(qspStatMenu, 0, qspStatementShowMenu, 1, 3, 1, 2, 2);
  153. qspAddStatement(qspStatMClear, 1, qspStatementClear, 0, 0);
  154. qspAddStatement(qspStatMNL, 5, qspStatementAddText, 0, 1, 1);
  155. qspAddStatement(qspStatMPL, 3, qspStatementAddText, 0, 1, 1);
  156. qspAddStatement(qspStatMP, 1, qspStatementAddText, 1, 1, 1);
  157. qspAddStatement(qspStatClear, 0, qspStatementClear, 0, 0);
  158. qspAddStatement(qspStatNL, 4, qspStatementAddText, 0, 1, 1);
  159. qspAddStatement(qspStatPL, 2, qspStatementAddText, 0, 1, 1);
  160. qspAddStatement(qspStatP, 0, qspStatementAddText, 1, 1, 1);
  161. qspAddStatement(qspStatMsg, 0, qspStatementMsg, 1, 1, 1);
  162. qspAddStatement(qspStatOpenGame, 0, qspStatementOpenGame, 0, 1, 1);
  163. qspAddStatement(qspStatOpenQst, 0, qspStatementOpenQst, 1, 1, 1);
  164. qspAddStatement(qspStatPlay, 0, qspStatementPlayFile, 1, 2, 1, 2);
  165. qspAddStatement(qspStatRefInt, 0, qspStatementRefInt, 0, 0);
  166. qspAddStatement(qspStatSaveGame, 0, qspStatementSaveGame, 0, 1, 1);
  167. qspAddStatement(qspStatSetTimer, 0, qspStatementSetTimer, 1, 1, 2);
  168. qspAddStatement(qspStatShowActs, 0, qspStatementShowWin, 1, 1, 2);
  169. qspAddStatement(qspStatShowInput, 3, qspStatementShowWin, 1, 1, 2);
  170. qspAddStatement(qspStatShowObjs, 1, qspStatementShowWin, 1, 1, 2);
  171. qspAddStatement(qspStatShowVars, 2, qspStatementShowWin, 1, 1, 2);
  172. qspAddStatement(qspStatUnSelect, 0, qspStatementUnSelect, 0, 0);
  173. qspAddStatement(qspStatView, 0, qspStatementView, 0, 1, 1);
  174. qspAddStatement(qspStatWait, 0, qspStatementWait, 1, 1, 2);
  175. qspAddStatement(qspStatXGoTo, 0, qspStatementGoTo, 1, 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  176. /* Names */
  177. qspAddStatName(qspStatElse, QSP_STATELSE, 2);
  178. qspAddStatName(qspStatElseIf, QSP_FMT("ELSEIF"), 1);
  179. qspAddStatName(qspStatEnd, QSP_FMT("END"), 2);
  180. qspAddStatName(qspStatLocal, QSP_FMT("LOCAL"), 2);
  181. qspAddStatName(qspStatSet, QSP_FMT("SET"), 2);
  182. qspAddStatName(qspStatSet, QSP_FMT("LET"), 2);
  183. qspAddStatName(qspStatIf, QSP_FMT("IF"), 2);
  184. qspAddStatName(qspStatAct, QSP_FMT("ACT"), 2);
  185. qspAddStatName(qspStatFor, QSP_FMT("FOR"), 2);
  186. qspAddStatName(qspStatAddObj, QSP_FMT("ADDOBJ"), 2);
  187. qspAddStatName(qspStatAddObj, QSP_FMT("ADD OBJ"), 2);
  188. qspAddStatName(qspStatClA, QSP_FMT("CLA"), 2);
  189. qspAddStatName(qspStatCloseAll, QSP_FMT("CLOSE ALL"), 1);
  190. qspAddStatName(qspStatClose, QSP_FMT("CLOSE"), 2);
  191. qspAddStatName(qspStatClS, QSP_FMT("CLS"), 2);
  192. qspAddStatName(qspStatCmdClear, QSP_FMT("CMDCLEAR"), 2);
  193. qspAddStatName(qspStatCmdClear, QSP_FMT("CMDCLR"), 2);
  194. qspAddStatName(qspStatCopyArr, QSP_FMT("COPYARR"), 2);
  195. qspAddStatName(qspStatDelAct, QSP_FMT("DELACT"), 2);
  196. qspAddStatName(qspStatDelAct, QSP_FMT("DEL ACT"), 2);
  197. qspAddStatName(qspStatDelObj, QSP_FMT("DELOBJ"), 2);
  198. qspAddStatName(qspStatDelObj, QSP_FMT("DEL OBJ"), 2);
  199. qspAddStatName(qspStatDynamic, QSP_FMT("DYNAMIC"), 2);
  200. qspAddStatName(qspStatExec, QSP_FMT("EXEC"), 2);
  201. qspAddStatName(qspStatExit, QSP_FMT("EXIT"), 2);
  202. qspAddStatName(qspStatFreeLib, QSP_FMT("FREELIB"), 2);
  203. qspAddStatName(qspStatFreeLib, QSP_FMT("DELLIB"), 2);
  204. qspAddStatName(qspStatFreeLib, QSP_FMT("KILLQST"), 2);
  205. qspAddStatName(qspStatGoSub, QSP_FMT("GOSUB"), 2);
  206. qspAddStatName(qspStatGoSub, QSP_FMT("GS"), 2);
  207. qspAddStatName(qspStatGoTo, QSP_FMT("GOTO"), 2);
  208. qspAddStatName(qspStatGoTo, QSP_FMT("GT"), 2);
  209. qspAddStatName(qspStatIncLib, QSP_FMT("INCLIB"), 2);
  210. qspAddStatName(qspStatIncLib, QSP_FMT("ADDLIB"), 2);
  211. qspAddStatName(qspStatIncLib, QSP_FMT("ADDQST"), 2);
  212. qspAddStatName(qspStatJump, QSP_FMT("JUMP"), 2);
  213. qspAddStatName(qspStatKillAll, QSP_FMT("KILLALL"), 2);
  214. qspAddStatName(qspStatKillObj, QSP_FMT("KILLOBJ"), 2);
  215. qspAddStatName(qspStatKillVar, QSP_FMT("KILLVAR"), 2);
  216. qspAddStatName(qspStatMenu, QSP_FMT("MENU"), 2);
  217. qspAddStatName(qspStatMClear, QSP_FMT("*CLEAR"), 2);
  218. qspAddStatName(qspStatMClear, QSP_FMT("*CLR"), 2);
  219. qspAddStatName(qspStatMNL, QSP_FMT("*NL"), 2);
  220. qspAddStatName(qspStatMPL, QSP_FMT("*PL"), 1);
  221. qspAddStatName(qspStatMP, QSP_FMT("*P"), 2);
  222. qspAddStatName(qspStatClear, QSP_FMT("CLEAR"), 2);
  223. qspAddStatName(qspStatClear, QSP_FMT("CLR"), 2);
  224. qspAddStatName(qspStatNL, QSP_FMT("NL"), 2);
  225. qspAddStatName(qspStatPL, QSP_FMT("PL"), 1);
  226. qspAddStatName(qspStatP, QSP_FMT("P"), 2);
  227. qspAddStatName(qspStatMsg, QSP_FMT("MSG"), 2);
  228. qspAddStatName(qspStatOpenGame, QSP_FMT("OPENGAME"), 2);
  229. qspAddStatName(qspStatOpenQst, QSP_FMT("OPENQST"), 2);
  230. qspAddStatName(qspStatPlay, QSP_FMT("PLAY"), 0);
  231. qspAddStatName(qspStatRefInt, QSP_FMT("REFINT"), 2);
  232. qspAddStatName(qspStatSaveGame, QSP_FMT("SAVEGAME"), 2);
  233. qspAddStatName(qspStatSetTimer, QSP_FMT("SETTIMER"), 1);
  234. qspAddStatName(qspStatShowActs, QSP_FMT("SHOWACTS"), 2);
  235. qspAddStatName(qspStatShowInput, QSP_FMT("SHOWINPUT"), 2);
  236. qspAddStatName(qspStatShowObjs, QSP_FMT("SHOWOBJS"), 2);
  237. qspAddStatName(qspStatShowVars, QSP_FMT("SHOWSTAT"), 2);
  238. qspAddStatName(qspStatUnSelect, QSP_FMT("UNSELECT"), 1);
  239. qspAddStatName(qspStatUnSelect, QSP_FMT("UNSEL"), 2);
  240. qspAddStatName(qspStatView, QSP_FMT("VIEW"), 2);
  241. qspAddStatName(qspStatWait, QSP_FMT("WAIT"), 2);
  242. qspAddStatName(qspStatXGoTo, QSP_FMT("XGOTO"), 2);
  243. qspAddStatName(qspStatXGoTo, QSP_FMT("XGT"), 2);
  244. for (i = 0; i < QSP_STATSLEVELS; ++i)
  245. qsort(qspStatsNames[i], qspStatsNamesCounts[i], sizeof(QSPStatName), qspStatsCompare);
  246. }
  247. static int qspGetStatCode(QSP_CHAR *s, QSP_CHAR **pos)
  248. {
  249. int i;
  250. QSP_CHAR *uStr;
  251. QSPStatName *name;
  252. if (!(*s)) return qspStatUnknown;
  253. if (*s == QSP_LABEL[0]) return qspStatLabel;
  254. if (*s == QSP_COMMENT[0]) return qspStatComment;
  255. /* ------------------------------------------------------------------ */
  256. qspUpperStr(uStr = qspGetNewText(s, qspStatMaxLen));
  257. for (i = 0; i < QSP_STATSLEVELS; ++i)
  258. {
  259. name = (QSPStatName *)bsearch(uStr, qspStatsNames[i], qspStatsNamesCounts[i], sizeof(QSPStatName), qspStatStringCompare);
  260. if (name && qspIsInListEOL(QSP_DELIMS, s[name->NameLen]))
  261. {
  262. *pos = s + name->NameLen;
  263. free(uStr);
  264. return name->Code;
  265. }
  266. }
  267. free(uStr);
  268. return qspStatUnknown;
  269. }
  270. static int qspSearchElse(QSPLineOfCode *s, int start, int end)
  271. {
  272. int c = 1;
  273. s += start;
  274. while (start < end)
  275. {
  276. switch (s->Stats->Stat)
  277. {
  278. case qspStatAct:
  279. case qspStatFor:
  280. case qspStatIf:
  281. if (s->IsMultiline) ++c;
  282. break;
  283. case qspStatElse:
  284. case qspStatElseIf:
  285. if (c == 1) return start;
  286. break;
  287. case qspStatEnd:
  288. if (!(--c)) return -1;
  289. break;
  290. }
  291. ++start;
  292. ++s;
  293. }
  294. return -1;
  295. }
  296. static int qspSearchEnd(QSPLineOfCode *s, int start, int end)
  297. {
  298. int c = 1;
  299. s += start;
  300. while (start < end)
  301. {
  302. switch (s->Stats->Stat)
  303. {
  304. case qspStatAct:
  305. case qspStatFor:
  306. case qspStatIf:
  307. if (s->IsMultiline) ++c;
  308. break;
  309. case qspStatEnd:
  310. if (!(--c)) return start;
  311. break;
  312. }
  313. ++start;
  314. ++s;
  315. }
  316. return -1;
  317. }
  318. static int qspSearchLabel(QSPLineOfCode *s, int start, int end, QSP_CHAR *str)
  319. {
  320. s += start;
  321. while (start < end)
  322. {
  323. if (s->Label && !qspStrsComp(s->Label, str)) return start;
  324. ++start;
  325. ++s;
  326. }
  327. return -1;
  328. }
  329. int qspGetStatArgs(QSP_CHAR *s, int statCode, QSPVariant *args)
  330. {
  331. int type;
  332. int oldRefreshCount, count = 0;
  333. QSP_CHAR *pos, *brack = 0;
  334. s = qspSkipSpaces(s);
  335. if (*s == QSP_LRBRACK[0])
  336. {
  337. if (!(brack = qspStrPos(s, QSP_RRBRACK, QSP_FALSE)))
  338. {
  339. qspSetError(QSP_ERR_BRACKNOTFOUND);
  340. return 0;
  341. }
  342. if (qspIsAnyString(brack + 1))
  343. brack = 0;
  344. else
  345. {
  346. *brack = 0;
  347. s = qspSkipSpaces(s + 1);
  348. }
  349. }
  350. if (*s)
  351. {
  352. oldRefreshCount = qspRefreshCount;
  353. while (1)
  354. {
  355. if (count == qspStats[statCode].MaxArgsCount)
  356. {
  357. qspSetError(QSP_ERR_ARGSCOUNT);
  358. break;
  359. }
  360. pos = qspStrPos(s, QSP_COMMA, QSP_FALSE);
  361. if (pos)
  362. {
  363. *pos = 0;
  364. args[count] = qspExprValue(s);
  365. *pos = QSP_COMMA[0];
  366. }
  367. else
  368. args[count] = qspExprValue(s);
  369. if (qspRefreshCount != oldRefreshCount || qspErrorNum) break;
  370. type = qspStats[statCode].ArgsTypes[count];
  371. if (type && qspConvertVariantTo(args + count, type == 1))
  372. {
  373. qspSetError(QSP_ERR_TYPEMISMATCH);
  374. ++count;
  375. break;
  376. }
  377. ++count;
  378. if (!pos) break;
  379. s = qspSkipSpaces(pos + QSP_LEN(QSP_COMMA));
  380. if (!(*s))
  381. {
  382. qspSetError(QSP_ERR_SYNTAX);
  383. break;
  384. }
  385. }
  386. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  387. {
  388. qspFreeVariants(args, count);
  389. if (brack) *brack = QSP_RRBRACK[0];
  390. return 0;
  391. }
  392. }
  393. if (brack) *brack = QSP_RRBRACK[0];
  394. if (count < qspStats[statCode].MinArgsCount)
  395. {
  396. qspSetError(QSP_ERR_ARGSCOUNT);
  397. qspFreeVariants(args, count);
  398. return 0;
  399. }
  400. return count;
  401. }
  402. static QSP_BOOL qspExecString(QSPLineOfCode *s, int startStat, int endStat, QSP_CHAR **jumpTo)
  403. {
  404. QSPVariant args[QSP_STATMAXARGS];
  405. QSP_BOOL isExit;
  406. QSP_CHAR *pos;
  407. int i, statCode, count, oldRefreshCount = qspRefreshCount;
  408. for (i = startStat; i < endStat; ++i)
  409. {
  410. statCode = s->Stats[i].Stat;
  411. switch (statCode)
  412. {
  413. case qspStatUnknown:
  414. case qspStatLabel:
  415. case qspStatElse:
  416. case qspStatEnd:
  417. break;
  418. case qspStatComment:
  419. case qspStatElseIf:
  420. return QSP_FALSE;
  421. case qspStatAct:
  422. qspStatementSinglelineAddAct(s, i, endStat);
  423. return QSP_FALSE;
  424. case qspStatIf:
  425. return qspStatementIf(s, i, endStat, jumpTo);
  426. case qspStatFor:
  427. return qspStatementSinglelineFor(s, i, endStat, jumpTo);
  428. case qspStatLocal:
  429. if (i < s->StatsCount - 1)
  430. {
  431. pos = s->Str + s->Stats[i].EndPos;
  432. *pos = 0;
  433. qspStatementLocal(s->Str + s->Stats[i].ParamPos);
  434. *pos = QSP_STATDELIM[0];
  435. }
  436. else
  437. qspStatementLocal(s->Str + s->Stats[i].ParamPos);
  438. break;
  439. case qspStatSet:
  440. if (i < s->StatsCount - 1)
  441. {
  442. pos = s->Str + s->Stats[i].EndPos;
  443. *pos = 0;
  444. qspStatementSetVarValue(s->Str + s->Stats[i].ParamPos);
  445. *pos = QSP_STATDELIM[0];
  446. }
  447. else
  448. qspStatementSetVarValue(s->Str + s->Stats[i].ParamPos);
  449. break;
  450. default:
  451. if (i < s->StatsCount - 1)
  452. {
  453. pos = s->Str + s->Stats[i].EndPos;
  454. *pos = 0;
  455. count = qspGetStatArgs(s->Str + s->Stats[i].ParamPos, statCode, args);
  456. *pos = QSP_STATDELIM[0];
  457. }
  458. else
  459. count = qspGetStatArgs(s->Str + s->Stats[i].ParamPos, statCode, args);
  460. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return QSP_FALSE;
  461. isExit = qspStats[statCode].Func(args, count, jumpTo, qspStats[statCode].ExtArg);
  462. qspFreeVariants(args, count);
  463. if (isExit || qspRefreshCount != oldRefreshCount || qspErrorNum || **jumpTo) return isExit;
  464. break;
  465. }
  466. }
  467. return QSP_FALSE;
  468. }
  469. static QSP_BOOL qspExecMultilineCode(QSPLineOfCode *s, int endLine, int codeOffset,
  470. QSP_CHAR **jumpTo, int *lineInd, int *action)
  471. {
  472. QSPVariant arg;
  473. QSPLineOfCode *line;
  474. QSP_CHAR *pos;
  475. int ind, statCode, elsePos, oldRefreshCount;
  476. ind = *lineInd;
  477. endLine = qspSearchEnd(s, ind + 1, endLine);
  478. if (endLine < 0)
  479. {
  480. qspSetError(QSP_ERR_ENDNOTFOUND);
  481. return QSP_FALSE;
  482. }
  483. line = s + ind;
  484. statCode = line->Stats->Stat;
  485. switch (statCode)
  486. {
  487. case qspStatIf:
  488. case qspStatElseIf:
  489. pos = line->Str + line->Stats->EndPos;
  490. oldRefreshCount = qspRefreshCount;
  491. *pos = 0;
  492. qspGetStatArgs(line->Str + line->Stats->ParamPos, statCode, &arg);
  493. *pos = QSP_COLONDELIM[0];
  494. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return QSP_FALSE;
  495. elsePos = qspSearchElse(s, ind + 1, endLine);
  496. if (QSP_NUM(arg))
  497. {
  498. *lineInd = endLine;
  499. *action = qspFlowSkip;
  500. if (elsePos >= 0)
  501. return qspExecCodeBlockWithLocals(s, ind + 1, elsePos, codeOffset, jumpTo);
  502. return qspExecCodeBlockWithLocals(s, ind + 1, endLine, codeOffset, jumpTo);
  503. }
  504. else
  505. {
  506. *lineInd = (elsePos >= 0 ? elsePos : endLine);
  507. *action = qspFlowContinue;
  508. }
  509. break;
  510. case qspStatAct:
  511. *lineInd = endLine;
  512. *action = qspFlowContinue;
  513. qspStatementMultilineAddAct(s, endLine, ind, codeOffset > 0);
  514. break;
  515. case qspStatFor:
  516. *lineInd = endLine;
  517. *action = qspFlowSkip;
  518. return qspStatementMultilineFor(s, endLine, ind, codeOffset, jumpTo);
  519. }
  520. return QSP_FALSE;
  521. }
  522. static QSP_BOOL qspExecSinglelineCode(QSPLineOfCode *s, int endLine, int codeOffset,
  523. QSP_CHAR **jumpTo, int *lineInd, int *action)
  524. {
  525. QSPVariant arg;
  526. QSPLineOfCode *line;
  527. QSP_CHAR *pos;
  528. int ind, elsePos, oldRefreshCount;
  529. ind = *lineInd;
  530. line = s + ind;
  531. switch (line->Stats->Stat)
  532. {
  533. case qspStatElseIf:
  534. pos = line->Str + line->Stats->EndPos;
  535. if (*pos != QSP_COLONDELIM[0])
  536. {
  537. qspSetError(QSP_ERR_COLONNOTFOUND);
  538. break;
  539. }
  540. endLine = qspSearchEnd(s, ind + 1, endLine);
  541. if (endLine < 0)
  542. {
  543. qspSetError(QSP_ERR_ENDNOTFOUND);
  544. break;
  545. }
  546. oldRefreshCount = qspRefreshCount;
  547. *pos = 0;
  548. qspGetStatArgs(line->Str + line->Stats->ParamPos, qspStatElseIf, &arg);
  549. *pos = QSP_COLONDELIM[0];
  550. if (qspRefreshCount != oldRefreshCount || qspErrorNum) break;
  551. if (QSP_NUM(arg))
  552. {
  553. *lineInd = endLine;
  554. *action = qspFlowSkip;
  555. return qspExecStringWithLocals(line, 1, line->StatsCount, jumpTo);
  556. }
  557. else
  558. {
  559. elsePos = qspSearchElse(s, ind + 1, endLine);
  560. *lineInd = (elsePos >= 0 ? elsePos : endLine);
  561. *action = qspFlowContinue;
  562. }
  563. break;
  564. case qspStatElse:
  565. endLine = qspSearchEnd(s, ind + 1, endLine);
  566. if (endLine < 0)
  567. {
  568. qspSetError(QSP_ERR_ENDNOTFOUND);
  569. break;
  570. }
  571. *lineInd = endLine;
  572. *action = qspFlowSkip;
  573. if (line->StatsCount > 1)
  574. return qspExecStringWithLocals(line, 1, line->StatsCount, jumpTo);
  575. else
  576. {
  577. elsePos = qspSearchElse(s, ind + 1, endLine);
  578. if (elsePos >= 0)
  579. return qspExecCodeBlockWithLocals(s, ind + 1, elsePos, codeOffset, jumpTo);
  580. return qspExecCodeBlockWithLocals(s, ind + 1, endLine, codeOffset, jumpTo);
  581. }
  582. break;
  583. }
  584. return QSP_FALSE;
  585. }
  586. static QSP_BOOL qspExecCode(QSPLineOfCode *s, int startLine, int endLine, int codeOffset, QSP_CHAR **jumpTo)
  587. {
  588. QSPLineOfCode *line;
  589. QSP_CHAR *jumpToFake;
  590. QSP_BOOL uLevel, isExit = QSP_FALSE;
  591. int i, oldRefreshCount, action = qspFlowExecute;
  592. oldRefreshCount = qspRefreshCount;
  593. /* Prepare temporary data */
  594. if (uLevel = !jumpTo)
  595. {
  596. jumpToFake = qspGetNewText(QSP_FMT(""), 0);
  597. jumpTo = &jumpToFake;
  598. }
  599. /* Code execution */
  600. i = startLine;
  601. while (i < endLine)
  602. {
  603. line = s + i;
  604. if (codeOffset > 0)
  605. {
  606. qspRealLine = line->LineNum + codeOffset;
  607. if (qspIsDebug && *line->Str)
  608. {
  609. qspCallDebug(line->Str);
  610. if (qspRefreshCount != oldRefreshCount) break;
  611. }
  612. }
  613. if (line->IsMultiline)
  614. isExit = qspExecMultilineCode(s, endLine, codeOffset, jumpTo, &i, &action);
  615. else
  616. isExit = qspExecSinglelineCode(s, endLine, codeOffset, jumpTo, &i, &action);
  617. if (isExit || qspRefreshCount != oldRefreshCount || qspErrorNum) break;
  618. if (action == qspFlowContinue)
  619. {
  620. action = qspFlowExecute;
  621. continue;
  622. }
  623. if (action == qspFlowSkip)
  624. action = qspFlowExecute;
  625. else
  626. {
  627. isExit = qspExecString(line, 0, line->StatsCount, jumpTo);
  628. if (isExit || qspRefreshCount != oldRefreshCount || qspErrorNum) break;
  629. ++i;
  630. }
  631. if (**jumpTo)
  632. {
  633. i = qspSearchLabel(s, startLine, endLine, *jumpTo);
  634. if (i < 0)
  635. {
  636. if (uLevel) qspSetError(QSP_ERR_LABELNOTFOUND);
  637. break;
  638. }
  639. **jumpTo = 0;
  640. }
  641. }
  642. if (uLevel) free(jumpToFake);
  643. return isExit;
  644. }
  645. static QSP_BOOL qspExecCodeBlockWithLocals(QSPLineOfCode *s, int startLine, int endLine, int codeOffset, QSP_CHAR **jumpTo)
  646. {
  647. QSP_BOOL isExit;
  648. int oldRefreshCount, ind = qspSavedVarsGroupsCount;
  649. qspSavedVarsGroups = (QSPVarsGroup *)realloc(qspSavedVarsGroups, (ind + 1) * sizeof(QSPVarsGroup));
  650. qspSavedVarsGroups[ind].Vars = 0;
  651. qspSavedVarsGroups[ind].VarsCount = 0;
  652. ++qspSavedVarsGroupsCount;
  653. oldRefreshCount = qspRefreshCount;
  654. isExit = qspExecCode(s, startLine, endLine, codeOffset, jumpTo);
  655. if (oldRefreshCount != qspRefreshCount || qspErrorNum)
  656. {
  657. if (qspSavedVarsGroupsCount)
  658. {
  659. --qspSavedVarsGroupsCount;
  660. qspClearVarsList(qspSavedVarsGroups[ind].Vars, qspSavedVarsGroups[ind].VarsCount);
  661. }
  662. return QSP_FALSE;
  663. }
  664. --qspSavedVarsGroupsCount;
  665. qspRestoreVarsList(qspSavedVarsGroups[ind].Vars, qspSavedVarsGroups[ind].VarsCount);
  666. return isExit;
  667. }
  668. static QSP_BOOL qspExecStringWithLocals(QSPLineOfCode *s, int startStat, int endStat, QSP_CHAR **jumpTo)
  669. {
  670. QSP_BOOL isExit;
  671. int oldRefreshCount, ind = qspSavedVarsGroupsCount;
  672. qspSavedVarsGroups = (QSPVarsGroup *)realloc(qspSavedVarsGroups, (ind + 1) * sizeof(QSPVarsGroup));
  673. qspSavedVarsGroups[ind].Vars = 0;
  674. qspSavedVarsGroups[ind].VarsCount = 0;
  675. ++qspSavedVarsGroupsCount;
  676. oldRefreshCount = qspRefreshCount;
  677. isExit = qspExecString(s, startStat, endStat, jumpTo);
  678. if (oldRefreshCount != qspRefreshCount || qspErrorNum)
  679. {
  680. if (qspSavedVarsGroupsCount)
  681. {
  682. --qspSavedVarsGroupsCount;
  683. qspClearVarsList(qspSavedVarsGroups[ind].Vars, qspSavedVarsGroups[ind].VarsCount);
  684. }
  685. return QSP_FALSE;
  686. }
  687. --qspSavedVarsGroupsCount;
  688. qspRestoreVarsList(qspSavedVarsGroups[ind].Vars, qspSavedVarsGroups[ind].VarsCount);
  689. return isExit;
  690. }
  691. QSP_BOOL qspExecTopCodeWithLocals(QSPLineOfCode *s, int endLine, int codeOffset, QSP_BOOL isNewLoc)
  692. {
  693. QSP_BOOL isExit;
  694. QSPVar *savedVars;
  695. QSPVarsGroup *savedGroups;
  696. int oldRefreshCount, varsCount, groupsCount;
  697. if (isNewLoc)
  698. qspPrepareGlobalVars();
  699. else
  700. varsCount = qspPrepareLocalVars(&savedVars);
  701. if (qspErrorNum) return QSP_FALSE;
  702. groupsCount = qspSavedVarsGroupsCount;
  703. savedGroups = qspSavedVarsGroups;
  704. qspSavedVarsGroupsCount = 1;
  705. qspSavedVarsGroups = (QSPVarsGroup *)malloc(sizeof(QSPVarsGroup));
  706. qspSavedVarsGroups[0].Vars = 0;
  707. qspSavedVarsGroups[0].VarsCount = 0;
  708. oldRefreshCount = qspRefreshCount;
  709. isExit = qspExecCode(s, 0, endLine, codeOffset, 0);
  710. if (oldRefreshCount != qspRefreshCount || qspErrorNum)
  711. {
  712. if (qspSavedVarsGroupsCount)
  713. qspClearVarsList(qspSavedVarsGroups[0].Vars, qspSavedVarsGroups[0].VarsCount);
  714. if (!isNewLoc)
  715. qspClearLocalVars(savedVars, varsCount);
  716. }
  717. else
  718. {
  719. qspRestoreVarsList(qspSavedVarsGroups[0].Vars, qspSavedVarsGroups[0].VarsCount);
  720. if (!isNewLoc)
  721. {
  722. if (qspErrorNum)
  723. qspClearLocalVars(savedVars, varsCount);
  724. else
  725. qspRestoreLocalVars(savedVars, varsCount, savedGroups, groupsCount);
  726. }
  727. }
  728. if (qspSavedVarsGroups) free(qspSavedVarsGroups);
  729. qspSavedVarsGroups = savedGroups;
  730. qspSavedVarsGroupsCount = groupsCount;
  731. return isExit;
  732. }
  733. void qspExecStringAsCodeWithArgs(QSP_CHAR *s, QSPVariant *args, int count)
  734. {
  735. QSPLineOfCode *strs;
  736. QSPVar local, *var;
  737. int oldRefreshCount;
  738. if (!(var = qspVarReference(QSP_VARARGS, QSP_TRUE))) return;
  739. qspMoveVar(&local, var);
  740. qspSetArgs(var, args, count);
  741. count = qspPreprocessData(s, &strs);
  742. oldRefreshCount = qspRefreshCount;
  743. qspExecCodeBlockWithLocals(strs, 0, count, 0, 0);
  744. qspFreePrepLines(strs, count);
  745. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  746. {
  747. qspEmptyVar(&local);
  748. return;
  749. }
  750. if (!(var = qspVarReference(QSP_VARARGS, QSP_TRUE)))
  751. {
  752. qspEmptyVar(&local);
  753. return;
  754. }
  755. qspEmptyVar(var);
  756. qspMoveVar(var, &local);
  757. }
  758. QSP_CHAR *qspGetLineLabel(QSP_CHAR *str)
  759. {
  760. QSP_CHAR *delimPos;
  761. str = qspSkipSpaces(str);
  762. if (*str == QSP_LABEL[0])
  763. {
  764. delimPos = qspStrChar(str, QSP_STATDELIM[0]);
  765. if (delimPos)
  766. {
  767. *delimPos = 0;
  768. str = qspDelSpc(str + 1);
  769. *delimPos = QSP_STATDELIM[0];
  770. }
  771. else
  772. str = qspDelSpc(str + 1);
  773. qspUpperStr(str);
  774. return str;
  775. }
  776. return 0;
  777. }
  778. void qspInitLineOfCode(QSPLineOfCode *line, QSP_CHAR *str, int lineNum)
  779. {
  780. QSP_BOOL isInLoop, isSearchElse;
  781. int statCode, count = 0;
  782. QSP_CHAR ch, *uStr, *nextPos, *temp, *buf, *elsePos, *delimPos = 0, *paramPos = 0;
  783. line->Str = str;
  784. line->LineNum = lineNum;
  785. line->StatsCount = 0;
  786. line->Stats = 0;
  787. buf = qspSkipSpaces(str);
  788. statCode = qspGetStatCode(buf, &paramPos);
  789. if (*buf && statCode != qspStatComment)
  790. {
  791. isInLoop = isSearchElse = QSP_TRUE;
  792. elsePos = 0;
  793. qspUpperStr(uStr = qspGetNewText(str, -1));
  794. switch (statCode)
  795. {
  796. case qspStatAct:
  797. case qspStatFor:
  798. case qspStatIf:
  799. case qspStatElseIf:
  800. delimPos = qspStrPos(buf, QSP_COLONDELIM, QSP_FALSE);
  801. if (delimPos)
  802. {
  803. nextPos = delimPos + 1;
  804. if (!(*nextPos)) isInLoop = QSP_FALSE;
  805. }
  806. break;
  807. case qspStatElse:
  808. nextPos = qspSkipSpaces(paramPos);
  809. if (*nextPos == QSP_COLONDELIM[0]) ++nextPos;
  810. delimPos = (*nextPos ? nextPos : 0);
  811. break;
  812. default:
  813. delimPos = qspStrPos(buf, QSP_STATDELIM, QSP_FALSE);
  814. if (delimPos) nextPos = delimPos + 1;
  815. elsePos = qspStrPos(uStr + (buf - str), QSP_STATELSE, QSP_TRUE);
  816. if (elsePos)
  817. elsePos = str + (elsePos - uStr);
  818. else
  819. isSearchElse = QSP_FALSE;
  820. if (elsePos && (!delimPos || elsePos < delimPos))
  821. {
  822. nextPos = delimPos = elsePos;
  823. elsePos = 0;
  824. }
  825. if (statCode == qspStatUnknown && buf != delimPos)
  826. {
  827. if (delimPos)
  828. {
  829. *delimPos = 0;
  830. temp = qspStrPos(buf, QSP_EQUAL, QSP_FALSE);
  831. *delimPos = QSP_STATDELIM[0];
  832. }
  833. else
  834. temp = qspStrPos(buf, QSP_EQUAL, QSP_FALSE);
  835. statCode = (temp ? qspStatSet : qspStatMPL);
  836. }
  837. break;
  838. }
  839. while (delimPos && isInLoop)
  840. {
  841. line->StatsCount++;
  842. line->Stats = (QSPCachedStat *)realloc(line->Stats, line->StatsCount * sizeof(QSPCachedStat));
  843. line->Stats[count].Stat = statCode;
  844. line->Stats[count].EndPos = (int)(delimPos - str);
  845. if (paramPos)
  846. line->Stats[count].ParamPos = (int)(qspSkipSpaces(paramPos) - str);
  847. else
  848. line->Stats[count].ParamPos = (int)(buf - str);
  849. ++count;
  850. buf = qspSkipSpaces(nextPos);
  851. paramPos = 0;
  852. statCode = qspGetStatCode(buf, &paramPos);
  853. if (*buf && statCode != qspStatComment)
  854. {
  855. switch (statCode)
  856. {
  857. case qspStatAct:
  858. case qspStatFor:
  859. case qspStatIf:
  860. case qspStatElseIf:
  861. delimPos = qspStrPos(buf, QSP_COLONDELIM, QSP_FALSE);
  862. if (delimPos)
  863. {
  864. nextPos = delimPos + 1;
  865. if (!(*nextPos)) isInLoop = QSP_FALSE;
  866. }
  867. break;
  868. case qspStatElse:
  869. nextPos = qspSkipSpaces(paramPos);
  870. if (*nextPos == QSP_COLONDELIM[0]) ++nextPos;
  871. delimPos = (*nextPos ? nextPos : 0);
  872. break;
  873. default:
  874. delimPos = qspStrPos(buf, QSP_STATDELIM, QSP_FALSE);
  875. if (delimPos) nextPos = delimPos + 1;
  876. if (elsePos && buf >= elsePos) elsePos = 0;
  877. if (!elsePos && isSearchElse)
  878. {
  879. elsePos = qspStrPos(uStr + (buf - str), QSP_STATELSE, QSP_TRUE);
  880. if (elsePos)
  881. elsePos = str + (elsePos - uStr);
  882. else
  883. isSearchElse = QSP_FALSE;
  884. }
  885. if (elsePos && (!delimPos || elsePos < delimPos))
  886. {
  887. nextPos = delimPos = elsePos;
  888. elsePos = 0;
  889. }
  890. if (statCode == qspStatUnknown && buf != delimPos)
  891. {
  892. if (delimPos)
  893. {
  894. ch = *delimPos;
  895. *delimPos = 0;
  896. temp = qspStrPos(buf, QSP_EQUAL, QSP_FALSE);
  897. *delimPos = ch;
  898. }
  899. else
  900. temp = qspStrPos(buf, QSP_EQUAL, QSP_FALSE);
  901. statCode = (temp ? qspStatSet : qspStatMPL);
  902. }
  903. break;
  904. }
  905. }
  906. else
  907. delimPos = 0;
  908. }
  909. free(uStr);
  910. }
  911. // Check for ELSE IF
  912. if (count == 1 && delimPos && line->Stats->Stat == qspStatElse && statCode == qspStatIf &&
  913. *(str + line->Stats->ParamPos) != QSP_COLONDELIM[0])
  914. {
  915. count = 0;
  916. statCode = qspStatElseIf;
  917. }
  918. else
  919. {
  920. line->StatsCount++;
  921. line->Stats = (QSPCachedStat *)realloc(line->Stats, line->StatsCount * sizeof(QSPCachedStat));
  922. }
  923. line->Stats[count].Stat = statCode;
  924. if (delimPos)
  925. line->Stats[count].EndPos = (int)(delimPos - str);
  926. else
  927. line->Stats[count].EndPos = (int)(qspStrEnd(buf) - str);
  928. if (paramPos)
  929. line->Stats[count].ParamPos = (int)(qspSkipSpaces(paramPos) - str);
  930. else
  931. line->Stats[count].ParamPos = (int)(buf - str);
  932. switch (line->Stats->Stat)
  933. {
  934. case qspStatAct:
  935. case qspStatFor:
  936. case qspStatIf:
  937. case qspStatElseIf:
  938. line->IsMultiline = (line->StatsCount == 1 && *(str + line->Stats->EndPos) == QSP_COLONDELIM[0]);
  939. break;
  940. default:
  941. line->IsMultiline = QSP_FALSE;
  942. break;
  943. }
  944. line->Label = qspGetLineLabel(str);
  945. }
  946. static QSP_BOOL qspStatementIf(QSPLineOfCode *s, int startStat, int endStat, QSP_CHAR **jumpTo)
  947. {
  948. QSPVariant arg;
  949. int i, c, elseStat, oldRefreshCount;
  950. QSP_CHAR *pos = s->Str + s->Stats[startStat].EndPos;
  951. if (*pos != QSP_COLONDELIM[0])
  952. {
  953. qspSetError(QSP_ERR_COLONNOTFOUND);
  954. return QSP_FALSE;
  955. }
  956. elseStat = 0;
  957. c = 1;
  958. for (i = startStat + 1; i < endStat; ++i)
  959. {
  960. switch (s->Stats[i].Stat)
  961. {
  962. case qspStatIf:
  963. ++c;
  964. break;
  965. case qspStatElse:
  966. --c;
  967. break;
  968. }
  969. if (!c)
  970. {
  971. elseStat = i;
  972. break;
  973. }
  974. }
  975. if (elseStat)
  976. {
  977. if (elseStat == startStat + 1)
  978. {
  979. qspSetError(QSP_ERR_CODENOTFOUND);
  980. return QSP_FALSE;
  981. }
  982. if (elseStat == endStat - 1)
  983. {
  984. qspSetError(QSP_ERR_CODENOTFOUND);
  985. return QSP_FALSE;
  986. }
  987. }
  988. else if (startStat == endStat - 1)
  989. {
  990. qspSetError(QSP_ERR_CODENOTFOUND);
  991. return QSP_FALSE;
  992. }
  993. oldRefreshCount = qspRefreshCount;
  994. *pos = 0;
  995. qspGetStatArgs(s->Str + s->Stats[startStat].ParamPos, qspStatIf, &arg);
  996. *pos = QSP_COLONDELIM[0];
  997. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return QSP_FALSE;
  998. if (QSP_NUM(arg))
  999. {
  1000. if (elseStat)
  1001. return qspExecStringWithLocals(s, startStat + 1, elseStat, jumpTo);
  1002. else
  1003. return qspExecStringWithLocals(s, startStat + 1, endStat, jumpTo);
  1004. }
  1005. else if (elseStat)
  1006. return qspExecStringWithLocals(s, elseStat + 1, endStat, jumpTo);
  1007. return QSP_FALSE;
  1008. }
  1009. static QSP_CHAR *qspPrepareForLoop(QSP_CHAR *paramPos, QSPVar *local, QSP_CHAR **toPosRes, QSP_CHAR **stepPosRes)
  1010. {
  1011. QSPVar *var;
  1012. int oldRefreshCount;
  1013. QSPVariant initValue;
  1014. QSP_CHAR *uStr, *eqPos, *toPos, *stepPos, *varName;
  1015. eqPos = qspStrPos(paramPos, QSP_EQUAL, QSP_FALSE);
  1016. if (!eqPos)
  1017. {
  1018. qspSetError(QSP_ERR_EQNOTFOUND);
  1019. return 0;
  1020. }
  1021. *eqPos = 0;
  1022. varName = qspDelSpc(paramPos);
  1023. *eqPos = QSP_EQUAL[0];
  1024. if (qspStrChar(varName, QSP_LSBRACK[0]))
  1025. {
  1026. qspSetError(QSP_ERR_NOTCORRECTNAME);
  1027. free(varName);
  1028. return 0;
  1029. }
  1030. qspUpperStr(uStr = qspGetNewText(eqPos, -1));
  1031. toPos = qspStrPos(uStr + QSP_LEN(QSP_EQUAL), QSP_STATFORTO, QSP_TRUE);
  1032. if (!toPos)
  1033. {
  1034. qspSetError(QSP_ERR_TONOTFOUND);
  1035. free(varName);
  1036. free(uStr);
  1037. return 0;
  1038. }
  1039. toPos = eqPos + (toPos - uStr);
  1040. stepPos = qspStrPos(uStr + (toPos - eqPos) + QSP_LEN(QSP_STATFORTO), QSP_STATFORSTEP, QSP_TRUE);
  1041. if (stepPos) stepPos = eqPos + (stepPos - uStr);
  1042. free(uStr);
  1043. oldRefreshCount = qspRefreshCount;
  1044. *toPos = 0;
  1045. initValue = qspExprValue(eqPos + QSP_LEN(QSP_EQUAL));
  1046. *toPos = QSP_STATFORTO[0];
  1047. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  1048. {
  1049. free(varName);
  1050. return 0;
  1051. }
  1052. if (qspConvertVariantTo(&initValue, QSP_FALSE))
  1053. {
  1054. qspSetError(QSP_ERR_TYPEMISMATCH);
  1055. free(varName);
  1056. free(QSP_STR(initValue));
  1057. return 0;
  1058. }
  1059. if (!(var = qspVarReference(varName, QSP_TRUE)))
  1060. {
  1061. free(varName);
  1062. return 0;
  1063. }
  1064. qspMoveVar(local, var);
  1065. qspConvertVariantTo(&initValue, (*varName == QSP_STRCHAR[0]));
  1066. qspSetVarValueByReference(var, 0, &initValue);
  1067. if (initValue.IsStr) free(QSP_STR(initValue));
  1068. *toPosRes = toPos;
  1069. *stepPosRes = stepPos;
  1070. return varName;
  1071. }
  1072. static QSP_BOOL qspCheckForLoop(QSP_CHAR *varName, QSP_CHAR *toPos, QSP_CHAR *stepPos, QSP_CHAR *endPos, int *curStep)
  1073. {
  1074. QSPVar *var;
  1075. QSPVariant toValue, stepValue, curValue;
  1076. int oldRefreshCount = qspRefreshCount;
  1077. if (stepPos)
  1078. {
  1079. *endPos = 0;
  1080. stepValue = qspExprValue(stepPos + QSP_LEN(QSP_STATFORSTEP));
  1081. *endPos = QSP_COLONDELIM[0];
  1082. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return QSP_FALSE;
  1083. if (qspConvertVariantTo(&stepValue, QSP_FALSE))
  1084. {
  1085. qspSetError(QSP_ERR_TYPEMISMATCH);
  1086. free(QSP_STR(stepValue));
  1087. return QSP_FALSE;
  1088. }
  1089. *curStep = QSP_NUM(stepValue);
  1090. *stepPos = 0;
  1091. toValue = qspExprValue(toPos + QSP_LEN(QSP_STATFORTO));
  1092. *stepPos = QSP_STATFORSTEP[0];
  1093. }
  1094. else
  1095. {
  1096. *endPos = 0;
  1097. toValue = qspExprValue(toPos + QSP_LEN(QSP_STATFORTO));
  1098. *endPos = QSP_COLONDELIM[0];
  1099. }
  1100. if (qspRefreshCount != oldRefreshCount || qspErrorNum) return QSP_FALSE;
  1101. if (qspConvertVariantTo(&toValue, QSP_FALSE))
  1102. {
  1103. qspSetError(QSP_ERR_TYPEMISMATCH);
  1104. free(QSP_STR(toValue));
  1105. return QSP_FALSE;
  1106. }
  1107. if (!(var = qspVarReference(varName, QSP_TRUE))) return QSP_FALSE;
  1108. curValue = qspGetVarValueByReference(var, 0, (*varName == QSP_STRCHAR[0]));
  1109. if (qspConvertVariantTo(&curValue, QSP_FALSE))
  1110. {
  1111. qspSetError(QSP_ERR_TYPEMISMATCH);
  1112. free(QSP_STR(curValue));
  1113. return QSP_FALSE;
  1114. }
  1115. if (*curStep >= 0)
  1116. {
  1117. if (QSP_NUM(curValue) > QSP_NUM(toValue)) return QSP_TRUE;
  1118. }
  1119. else
  1120. {
  1121. if (QSP_NUM(curValue) < QSP_NUM(toValue)) return QSP_TRUE;
  1122. }
  1123. return QSP_FALSE;
  1124. }
  1125. static void qspEndForLoop(QSP_CHAR *varName, int curStep)
  1126. {
  1127. QSPVar *var;
  1128. QSPVariant curValue;
  1129. if (!(var = qspVarReference(varName, QSP_TRUE))) return;
  1130. curValue = qspGetVarValueByReference(var, 0, (*varName == QSP_STRCHAR[0]));
  1131. if (qspConvertVariantTo(&curValue, QSP_FALSE))
  1132. {
  1133. qspSetError(QSP_ERR_TYPEMISMATCH);
  1134. free(QSP_STR(curValue));
  1135. return;
  1136. }
  1137. QSP_NUM(curValue) += curStep;
  1138. qspConvertVariantTo(&curValue, (*varName == QSP_STRCHAR[0]));
  1139. qspSetVarValueByReference(var, 0, &curValue);
  1140. if (curValue.IsStr) free(QSP_STR(curValue));
  1141. }
  1142. static QSP_BOOL qspStatementSinglelineFor(QSPLineOfCode *s, int startStat, int endStat, QSP_CHAR **jumpTo)
  1143. {
  1144. QSP_BOOL isExit;
  1145. QSPVar local, *var;
  1146. int curStep, oldRefreshCount;
  1147. QSP_CHAR *endPos, *toPos, *stepPos, *varName;
  1148. endPos = s->Str + s->Stats[startStat].EndPos;
  1149. if (*endPos != QSP_COLONDELIM[0])
  1150. {
  1151. qspSetError(QSP_ERR_COLONNOTFOUND);
  1152. return QSP_FALSE;
  1153. }
  1154. if (!(varName = qspPrepareForLoop(s->Str + s->Stats[startStat].ParamPos, &local, &toPos, &stepPos)))
  1155. return QSP_FALSE;
  1156. curStep = 1;
  1157. oldRefreshCount = qspRefreshCount;
  1158. while (1)
  1159. {
  1160. if (qspCheckForLoop(varName, toPos, stepPos, endPos, &curStep)) break;
  1161. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  1162. {
  1163. free(varName);
  1164. qspEmptyVar(&local);
  1165. return QSP_FALSE;
  1166. }
  1167. isExit = qspExecStringWithLocals(s, startStat + 1, endStat, jumpTo);
  1168. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  1169. {
  1170. free(varName);
  1171. qspEmptyVar(&local);
  1172. return QSP_FALSE;
  1173. }
  1174. if (isExit || **jumpTo) break;
  1175. qspEndForLoop(varName, curStep);
  1176. if (qspErrorNum)
  1177. {
  1178. free(varName);
  1179. qspEmptyVar(&local);
  1180. return QSP_FALSE;
  1181. }
  1182. }
  1183. if (!(var = qspVarReference(varName, QSP_TRUE)))
  1184. {
  1185. free(varName);
  1186. qspEmptyVar(&local);
  1187. return QSP_FALSE;
  1188. }
  1189. free(varName);
  1190. qspEmptyVar(var);
  1191. qspMoveVar(var, &local);
  1192. return QSP_FALSE;
  1193. }
  1194. static QSP_BOOL qspStatementMultilineFor(QSPLineOfCode *s, int endLine, int lineInd,
  1195. int codeOffset, QSP_CHAR **jumpTo)
  1196. {
  1197. QSP_BOOL isExit;
  1198. QSPVar local, *var;
  1199. int curStep, oldRefreshCount;
  1200. QSP_CHAR *endPos, *toPos, *stepPos, *varName;
  1201. QSPLineOfCode *line = s + lineInd;
  1202. if (!(varName = qspPrepareForLoop(line->Str + line->Stats->ParamPos, &local, &toPos, &stepPos)))
  1203. return QSP_FALSE;
  1204. endPos = line->Str + line->Stats->EndPos;
  1205. curStep = 1;
  1206. ++lineInd;
  1207. oldRefreshCount = qspRefreshCount;
  1208. while (1)
  1209. {
  1210. if (qspCheckForLoop(varName, toPos, stepPos, endPos, &curStep)) break;
  1211. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  1212. {
  1213. free(varName);
  1214. qspEmptyVar(&local);
  1215. return QSP_FALSE;
  1216. }
  1217. isExit = qspExecCodeBlockWithLocals(s, lineInd, endLine, codeOffset, jumpTo);
  1218. if (qspRefreshCount != oldRefreshCount || qspErrorNum)
  1219. {
  1220. free(varName);
  1221. qspEmptyVar(&local);
  1222. return QSP_FALSE;
  1223. }
  1224. if (isExit || **jumpTo) break;
  1225. if (codeOffset > 0)
  1226. {
  1227. qspRealLine = line->LineNum + codeOffset;
  1228. if (qspIsDebug)
  1229. {
  1230. qspCallDebug(line->Str);
  1231. if (qspRefreshCount != oldRefreshCount)
  1232. {
  1233. free(varName);
  1234. qspEmptyVar(&local);
  1235. return QSP_FALSE;
  1236. }
  1237. }
  1238. }
  1239. qspEndForLoop(varName, curStep);
  1240. if (qspErrorNum)
  1241. {
  1242. free(varName);
  1243. qspEmptyVar(&local);
  1244. return QSP_FALSE;
  1245. }
  1246. }
  1247. if (!(var = qspVarReference(varName, QSP_TRUE)))
  1248. {
  1249. free(varName);
  1250. qspEmptyVar(&local);
  1251. return QSP_FALSE;
  1252. }
  1253. free(varName);
  1254. qspEmptyVar(var);
  1255. qspMoveVar(var, &local);
  1256. return QSP_FALSE;
  1257. }
  1258. static void qspStatementLocal(QSP_CHAR *s)
  1259. {
  1260. int i, ind, count, varsCount;
  1261. QSPVar *savedVars;
  1262. varsCount = qspGetVarsList(s, &savedVars);
  1263. if (qspErrorNum) return;
  1264. if (varsCount)
  1265. {
  1266. ind = qspSavedVarsGroupsCount - 1;
  1267. count = qspSavedVarsGroups[ind].VarsCount;
  1268. qspSavedVarsGroups[ind].Vars = (QSPVar *)realloc(qspSavedVarsGroups[ind].Vars, (count + varsCount) * sizeof(QSPVar));
  1269. for (i = 0; i < varsCount; ++i)
  1270. {
  1271. qspSavedVarsGroups[ind].Vars[count].Name = savedVars[i].Name;
  1272. qspMoveVar(qspSavedVarsGroups[ind].Vars + count, savedVars + i);
  1273. ++count;
  1274. }
  1275. qspSavedVarsGroups[ind].VarsCount = count;
  1276. }
  1277. free(savedVars);
  1278. }
  1279. static QSP_BOOL qspStatementAddText(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1280. {
  1281. switch (extArg)
  1282. {
  1283. case 0:
  1284. if (*QSP_STR(args[0]))
  1285. {
  1286. qspCurVarsLen = qspAddText(&qspCurVars, QSP_STR(args[0]), qspCurVarsLen, -1, QSP_FALSE);
  1287. qspIsVarsDescChanged = QSP_TRUE;
  1288. }
  1289. break;
  1290. case 1:
  1291. if (*QSP_STR(args[0]))
  1292. {
  1293. qspCurDescLen = qspAddText(&qspCurDesc, QSP_STR(args[0]), qspCurDescLen, -1, QSP_FALSE);
  1294. qspIsMainDescChanged = QSP_TRUE;
  1295. }
  1296. break;
  1297. case 2:
  1298. if (count) qspCurVarsLen = qspAddText(&qspCurVars, QSP_STR(args[0]), qspCurVarsLen, -1, QSP_FALSE);
  1299. qspCurVarsLen = qspAddText(&qspCurVars, QSP_STRSDELIM, qspCurVarsLen, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  1300. qspIsVarsDescChanged = QSP_TRUE;
  1301. break;
  1302. case 3:
  1303. if (count) qspCurDescLen = qspAddText(&qspCurDesc, QSP_STR(args[0]), qspCurDescLen, -1, QSP_FALSE);
  1304. qspCurDescLen = qspAddText(&qspCurDesc, QSP_STRSDELIM, qspCurDescLen, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  1305. qspIsMainDescChanged = QSP_TRUE;
  1306. break;
  1307. case 4:
  1308. qspCurVarsLen = qspAddText(&qspCurVars, QSP_STRSDELIM, qspCurVarsLen, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  1309. if (count) qspCurVarsLen = qspAddText(&qspCurVars, QSP_STR(args[0]), qspCurVarsLen, -1, QSP_FALSE);
  1310. qspIsVarsDescChanged = QSP_TRUE;
  1311. break;
  1312. case 5:
  1313. qspCurDescLen = qspAddText(&qspCurDesc, QSP_STRSDELIM, qspCurDescLen, QSP_LEN(QSP_STRSDELIM), QSP_FALSE);
  1314. if (count) qspCurDescLen = qspAddText(&qspCurDesc, QSP_STR(args[0]), qspCurDescLen, -1, QSP_FALSE);
  1315. qspIsMainDescChanged = QSP_TRUE;
  1316. break;
  1317. }
  1318. return QSP_FALSE;
  1319. }
  1320. static QSP_BOOL qspStatementClear(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1321. {
  1322. switch (extArg)
  1323. {
  1324. case 0:
  1325. if (qspClearText(&qspCurVars, &qspCurVarsLen))
  1326. qspIsVarsDescChanged = QSP_TRUE;
  1327. break;
  1328. case 1:
  1329. if (qspClearText(&qspCurDesc, &qspCurDescLen))
  1330. qspIsMainDescChanged = QSP_TRUE;
  1331. break;
  1332. case 2:
  1333. qspClearText(&qspCurInput, &qspCurInputLen);
  1334. qspCallSetInputStrText(0);
  1335. break;
  1336. case 3:
  1337. qspClearActions(QSP_FALSE);
  1338. break;
  1339. case 4:
  1340. if (qspClearText(&qspCurVars, &qspCurVarsLen))
  1341. qspIsVarsDescChanged = QSP_TRUE;
  1342. if (qspClearText(&qspCurDesc, &qspCurDescLen))
  1343. qspIsMainDescChanged = QSP_TRUE;
  1344. qspClearText(&qspCurInput, &qspCurInputLen);
  1345. qspClearActions(QSP_FALSE);
  1346. qspCallSetInputStrText(0);
  1347. break;
  1348. case 5:
  1349. qspClearVars(QSP_FALSE);
  1350. qspClearObjectsWithNotify();
  1351. break;
  1352. case 6:
  1353. qspClearIncludes(QSP_FALSE);
  1354. if (qspCurLoc >= qspLocsCount) qspCurLoc = -1;
  1355. break;
  1356. }
  1357. return QSP_FALSE;
  1358. }
  1359. static QSP_BOOL qspStatementExit(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1360. {
  1361. return QSP_TRUE;
  1362. }
  1363. static QSP_BOOL qspStatementGoSub(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1364. {
  1365. qspExecLocByNameWithArgs(QSP_STR(args[0]), args + 1, count - 1);
  1366. return QSP_FALSE;
  1367. }
  1368. static QSP_BOOL qspStatementGoTo(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1369. {
  1370. int locInd = qspLocIndex(QSP_STR(args[0]));
  1371. if (locInd < 0)
  1372. {
  1373. qspSetError(QSP_ERR_LOCNOTFOUND);
  1374. return QSP_FALSE;
  1375. }
  1376. qspCurLoc = locInd;
  1377. qspRefreshCurLoc(extArg, args + 1, count - 1);
  1378. return QSP_FALSE;
  1379. }
  1380. static QSP_BOOL qspStatementJump(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1381. {
  1382. free(*jumpTo);
  1383. qspUpperStr(*jumpTo = qspDelSpc(QSP_STR(args[0])));
  1384. return QSP_FALSE;
  1385. }
  1386. static QSP_BOOL qspStatementWait(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1387. {
  1388. int num = QSP_NUM(args[0]);
  1389. qspCallRefreshInt(QSP_TRUE);
  1390. if (num < 0) num = 0;
  1391. qspCallSleep(num);
  1392. return QSP_FALSE;
  1393. }
  1394. static QSP_BOOL qspStatementSetTimer(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1395. {
  1396. int num = QSP_NUM(args[0]);
  1397. if (num < 0) num = 0;
  1398. qspTimerInterval = num;
  1399. qspCallSetTimer(num);
  1400. return QSP_FALSE;
  1401. }
  1402. static QSP_BOOL qspStatementShowWin(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1403. {
  1404. QSP_BOOL val = QSP_NUM(args[0]) != 0;
  1405. switch (extArg)
  1406. {
  1407. case 0:
  1408. qspCallShowWindow(QSP_WIN_ACTS, qspCurIsShowActs = val);
  1409. break;
  1410. case 1:
  1411. qspCallShowWindow(QSP_WIN_OBJS, qspCurIsShowObjs = val);
  1412. break;
  1413. case 2:
  1414. qspCallShowWindow(QSP_WIN_VARS, qspCurIsShowVars = val);
  1415. break;
  1416. case 3:
  1417. qspCallShowWindow(QSP_WIN_INPUT, qspCurIsShowInput = val);
  1418. break;
  1419. }
  1420. return QSP_FALSE;
  1421. }
  1422. static QSP_BOOL qspStatementRefInt(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1423. {
  1424. qspCallRefreshInt(QSP_TRUE);
  1425. return QSP_FALSE;
  1426. }
  1427. static QSP_BOOL qspStatementView(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1428. {
  1429. QSP_CHAR *file;
  1430. if (count && qspIsAnyString(QSP_STR(args[0])))
  1431. {
  1432. qspViewPath = qspGetAddText(qspViewPath, QSP_STR(args[0]), 0, -1);
  1433. file = qspGetPathAsIs(qspViewPath);
  1434. qspCallShowPicture(file);
  1435. free(file);
  1436. }
  1437. else
  1438. {
  1439. if (qspViewPath)
  1440. {
  1441. free(qspViewPath);
  1442. qspViewPath = 0;
  1443. }
  1444. qspCallShowPicture(0);
  1445. }
  1446. return QSP_FALSE;
  1447. }
  1448. static QSP_BOOL qspStatementMsg(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1449. {
  1450. qspCallShowMessage(QSP_STR(args[0]));
  1451. return QSP_FALSE;
  1452. }
  1453. static QSP_BOOL qspStatementExec(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1454. {
  1455. qspCallSystem(QSP_STR(args[0]));
  1456. return QSP_FALSE;
  1457. }
  1458. static QSP_BOOL qspStatementDynamic(QSPVariant *args, int count, QSP_CHAR **jumpTo, int extArg)
  1459. {
  1460. qspExecStringAsCodeWithArgs(QSP_STR(args[0]), args + 1, count - 1);
  1461. return QSP_FALSE;
  1462. }