LuaUtils.pas 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. //******************************************************************************
  2. //*** LUA SCRIPT DELPHI UTILITIES ***
  3. //*** ***
  4. //*** (c) 2005 Jean-Fran輟is Goulet, Massimo Magnano, Kuma ***
  5. //*** ***
  6. //*** ***
  7. //******************************************************************************
  8. // File : LuaUtils.pas
  9. //
  10. // Description : Useful functions for work with Lua in Delphi.
  11. //
  12. //******************************************************************************
  13. //** See Copyright Notice in lua.h
  14. //Revision 1.6
  15. // JF Adds :
  16. // LuaTableToVirtualTreeView
  17. //
  18. //Revision 1.1
  19. // MaxM Adds :
  20. // LuaPCallFunction
  21. //
  22. //Revision 1.0
  23. // MaxM Adds :
  24. // LuaPushVariant
  25. // LuaToVariant
  26. // LuaGetTableInteger, LuaGet\SetTableTMethod
  27. // LuaLoadBufferFromFile
  28. // Solved Bugs : Stack problem in LuaProcessTableName
  29. // LuaToInteger why Round?, Trunc is better
  30. unit LuaUtils;
  31. interface
  32. uses
  33. SysUtils, Classes, ComCtrls, lua, lualib, lauxlib, Variants, VirtualTrees;
  34. const
  35. ERR_Script ='Script Error : ';
  36. type
  37. TOnLuaStdout = procedure (S: PChar; N: Integer);
  38. ELuaException = class(Exception)
  39. Title: string;
  40. Line: Integer;
  41. Msg: string;
  42. constructor Create(Title: string; Line: Integer; Msg: string);
  43. end;
  44. PBasicTreeData = ^TBasicTreeData;
  45. TBasicTreeData = record
  46. sName: String;
  47. sValue: String;
  48. end;
  49. TVariantArray =array of Variant;
  50. PVariantArray =^TVariantArray;
  51. function Quote(const Str: string): string;
  52. function Dequote(const QuotedStr: string): string;
  53. function lua_print(L: Plua_State): Integer; cdecl;
  54. function lua_io_write(L: Plua_State): Integer; cdecl;
  55. function LuaToBoolean(L: PLua_State; Index: Integer): Boolean;
  56. procedure LuaPushBoolean(L: PLua_State; B: Boolean);
  57. function LuaToInteger(L: PLua_State; Index: Integer): Integer;
  58. procedure LuaPushInteger(L: PLua_State; N: Integer);
  59. function LuaToVariant(L: Plua_State; Index: Integer): Variant;
  60. procedure LuaPushVariant(L: Plua_State; N: Variant);
  61. function LuaToString(L: PLua_State; Index: Integer): string;
  62. procedure LuaPushString(L: PLua_State; const S: string);
  63. function LuaIncIndex(L: Plua_State; Index: Integer): Integer;
  64. function LuaAbsIndex(L: Plua_State; Index: Integer): Integer;
  65. procedure LuaGetTable(L: Plua_State; TableIndex: Integer; const Key: string);
  66. function LuaGetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string): Boolean;
  67. function LuaGetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string): Double;
  68. function LuaGetTableInteger(L: Plua_State; TableIndex: Integer; const Key: string): Integer;
  69. function LuaGetTableString(L: Plua_State; TableIndex: Integer; const Key: string): string;
  70. function LuaGetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string): lua_CFunction;
  71. function LuaGetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string): Pointer;
  72. function LuaGetTableTMethod(L: Plua_State; TableIndex: Integer; const Key: string): TMethod;
  73. procedure LuaRawGetTable(L: Plua_State; TableIndex: Integer; const Key: string);
  74. function LuaRawGetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string): Boolean;
  75. function LuaRawGetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string): Double;
  76. function LuaRawGetTableString(L: Plua_State; TableIndex: Integer; const Key: string): string;
  77. function LuaRawGetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string): lua_CFunction;
  78. function LuaRawGetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string): Pointer;
  79. procedure LuaSetTableValue(L: PLua_State; TableIndex: Integer; const Key: string; ValueIndex: Integer);
  80. procedure LuaSetTableNil(L: Plua_State; TableIndex: Integer; const Key: string);
  81. procedure LuaSetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string; B: Boolean);
  82. procedure LuaSetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string; N: Double);
  83. procedure LuaSetTableString(L: Plua_State; TableIndex: Integer; const Key: string; S: string);
  84. procedure LuaSetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string; F: lua_CFunction);
  85. procedure LuaSetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string; P: Pointer);
  86. procedure LuaSetTableTMethod(L: Plua_State; TableIndex: Integer; const Key: string; M: TMethod);
  87. procedure LuaSetTableClear(L: Plua_State; TableIndex: Integer);
  88. procedure LuaRawSetTableValue(L: PLua_State; TableIndex: Integer; const Key: string; ValueIndex: Integer);
  89. procedure LuaRawSetTableNil(L: Plua_State; TableIndex: Integer; const Key: string);
  90. procedure LuaRawSetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string; B: Boolean);
  91. procedure LuaRawSetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string; N: Double);
  92. procedure LuaRawSetTableString(L: Plua_State; TableIndex: Integer; const Key: string; S: string);
  93. procedure LuaRawSetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string; F: lua_CFunction);
  94. procedure LuaRawSetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string; P: Pointer);
  95. procedure LuaRawSetTableClear(L: Plua_State; TableIndex: Integer);
  96. function LuaGetMetaFunction(L: Plua_State; Index: Integer; Key: string): lua_CFunction;
  97. procedure LuaSetMetaFunction(L: Plua_State; Index: Integer; Key: string; F: lua_CFunction);
  98. procedure LuaShowStack(L: Plua_State; Caption: string = '');
  99. function LuaStackToStr(L: Plua_State; Index: Integer; MaxTable: Integer = -1): string;
  100. procedure LuaRegisterCustom(L: PLua_State; TableIndex: Integer; const Name: PChar; F: lua_CFunction);
  101. procedure LuaRegister(L: Plua_State; const Name: PChar; F: lua_CFunction);
  102. procedure LuaRegisterMetatable(L: Plua_State; const Name: PChar; F: lua_CFunction);
  103. procedure LuaRegisterProperty(L: PLua_State; const Name: PChar; ReadFunc, WriteFunc: lua_CFunction);
  104. procedure LuaStackToStrings(L: Plua_State; Lines: TStrings; MaxTable: Integer = -1);
  105. procedure LuaLocalToStrings(L: Plua_State; Lines: TStrings; MaxTable: Integer = -1; Level: Integer = 0);
  106. procedure LuaTableToStrings(L: Plua_State; Index: Integer; Lines: TStrings; MaxTable: Integer = -1);
  107. procedure LuaTableToVirtualTreeView(L: Plua_State; Index: Integer; VTV: TVirtualStringTree; MaxTable: Integer);
  108. procedure LuaTableToTreeView(L: Plua_State; Index: Integer; TV: TTreeView; MaxTable: Integer = -1);
  109. function LuaGetIdentValue(L: Plua_State; Ident: string; MaxTable: Integer = -1): string;
  110. procedure LuaSetIdentValue(L: Plua_State; Ident, Value: string; MaxTable: Integer = -1);
  111. procedure LuaLoadBuffer(L: Plua_State; const Code: string; const Name: string);
  112. procedure LuaLoadBufferFromFile(L: Plua_State; const Filename: string; const Name: string);
  113. procedure LuaPCall(L: Plua_State; NArgs, NResults, ErrFunc: Integer);
  114. function LuaPCallFunction(L: Plua_State; FunctionName :String;
  115. const Args: array of Variant;
  116. Results : PVariantArray;
  117. ErrFunc: Integer=0;
  118. NResults :Integer=LUA_MULTRET):Integer;
  119. procedure LuaError(L: Plua_State; const Msg: string);
  120. procedure LuaErrorFmt(L: Plua_State; const Fmt: string; const Args: array of Const);
  121. function LuaDataStrToStrings(const TableStr: string; Strings: TStrings): string;
  122. function LuaDoFile(L: Plua_State): Integer; cdecl;
  123. const
  124. LuaGlobalVariableStr = '[LUA_GLOBALSINDEX]';
  125. var
  126. OnLuaStdout: TOnLuaStdout;
  127. DefaultMaxTable: Integer;
  128. implementation
  129. uses
  130. Dialogs;
  131. const
  132. QuoteStr = '"';
  133. CR = #$0D;
  134. LF = #$0A;
  135. CRLF = CR + LF;
  136. function Quote(const Str: string): string;
  137. begin
  138. Result := AnsiQuotedStr(Str, QuoteStr);
  139. end;
  140. function Dequote(const QuotedStr: string): string;
  141. begin
  142. Result := AnsiDequotedStr(QuotedStr, QuoteStr);
  143. end;
  144. function fwrite(S: PChar; Un, Len: Integer; Dummy: Integer): Integer;
  145. // 標準出力
  146. var
  147. Size: Integer;
  148. begin
  149. Size := Un * Len;
  150. if (Assigned(OnLuaStdout)) then
  151. OnLuaStdout(S, Size);
  152. Result := Size;
  153. end;
  154. function fputs(const S: string; Dummy: Integer): Integer;
  155. // 標準出力
  156. begin
  157. Result := fwrite(PChar(S), SizeOf(Char), Length(S), Dummy);
  158. end;
  159. function lua_print(L: Plua_State): Integer; cdecl;
  160. // 標準出力関数
  161. const
  162. TAB = #$08;
  163. NL = #$0A;
  164. stdout = 0;
  165. var
  166. N, I: Integer;
  167. S: PChar;
  168. begin
  169. N := lua_gettop(L); (* number of arguments *)
  170. lua_getglobal(L, 'tostring');
  171. for I := 1 to N do
  172. begin
  173. lua_pushvalue(L, -1); (* function to be called *)
  174. lua_pushvalue(L, i); (* value to print *)
  175. lua_call(L, 1, 1);
  176. S := lua_tostring(L, -1); (* get result *)
  177. if (S = nil) then
  178. begin
  179. Result := luaL_error(L, '`tostring'' must return a string to `print''');
  180. Exit;
  181. end;
  182. if (I > 1) then fputs(TAB, stdout);
  183. fputs(S, stdout);
  184. lua_pop(L, 1); (* pop result *)
  185. end;
  186. fputs(NL, stdout);
  187. Result := 0;
  188. end;
  189. function lua_io_write(L: Plua_State): Integer; cdecl;
  190. // 標準出力関数
  191. function pushresult(L: Plua_State; I: Boolean; FileName: PChar): Integer;
  192. begin
  193. lua_pushboolean(L, 1);
  194. Result := 1;
  195. end;
  196. const
  197. F = 0;
  198. var
  199. NArgs: Integer;
  200. Status: Boolean;
  201. Arg: Integer;
  202. Len: Integer;
  203. S: PChar;
  204. begin
  205. Arg := 1;
  206. NArgs := lua_gettop(L);
  207. Status := True;
  208. while (NArgs > 0) do
  209. begin
  210. Dec(NArgs);
  211. if (lua_type(L, Arg) = LUA_TNUMBER) then
  212. begin
  213. (* optimization: could be done exactly as for strings *)
  214. Status := Status and
  215. (fputs(Format(LUA_NUMBER_FMT, [lua_tonumber(L, Arg)]), 0) > 0);
  216. end else
  217. begin
  218. S := luaL_checklstring(L, Arg, @Len);
  219. Status := Status and (fwrite(S, SizeOf(Char), Len, F) = Len);
  220. end;
  221. Inc(Arg);
  222. end;
  223. Result := pushresult(L, Status, nil);
  224. end;
  225. function LuaToBoolean(L: PLua_State; Index: Integer): Boolean;
  226. begin
  227. Result := (lua_toboolean(L, Index) <> 0);
  228. end;
  229. procedure LuaPushBoolean(L: PLua_State; B: Boolean);
  230. begin
  231. lua_pushboolean(L, Integer(B));
  232. end;
  233. function LuaToInteger(L: PLua_State; Index: Integer): Integer;
  234. begin
  235. Result := Trunc(lua_tonumber(L, Index)); //Round(lua_tonumber(L, Index));
  236. end;
  237. procedure LuaPushInteger(L: PLua_State; N: Integer);
  238. begin
  239. lua_pushnumber(L, N);
  240. end;
  241. function LuaToVariant(L: Plua_State; Index: Integer): Variant;
  242. Var
  243. dataType :Integer;
  244. dataNum :Double;
  245. begin
  246. dataType :=lua_type(L, Index);
  247. Case dataType of
  248. LUA_TSTRING : Result := VarAsType(LuaToString(L, Index), varString);
  249. LUA_TUSERDATA,
  250. LUA_TLIGHTUSERDATA : Result := VarAsType(Integer(lua_touserdata(L, Index)), varInteger);
  251. LUA_TNONE,
  252. LUA_TNIL : Result := varNull;
  253. LUA_TBOOLEAN : Result := VarAsType(LuaToBoolean(L, Index), varBoolean);
  254. LUA_TNUMBER : begin
  255. dataNum :=lua_tonumber(L, Index);
  256. if (Abs(dataNum)>MAXINT)
  257. then Result :=VarAsType(dataNum, varDouble)
  258. else begin
  259. if (Frac(dataNum)<>0)
  260. then Result :=VarAsType(dataNum, varDouble)
  261. else Result :=VarAsType(dataNum, varInteger)
  262. end;
  263. end;
  264. end;
  265. end;
  266. procedure LuaPushVariant(L: Plua_State; N: Variant);
  267. begin
  268. case VarType(N) of
  269. varEmpty,
  270. varNull :lua_pushnil(L);
  271. varBoolean :LuaPushBoolean(L, N);
  272. varStrArg,
  273. varOleStr,
  274. varString :LuaPushString(L, N);
  275. varDate :LuaPushString(L, DateTimeToStr(VarToDateTime(N)));
  276. else lua_pushnumber(L, N);
  277. end;
  278. end;
  279. function LuaToString(L: PLua_State; Index: Integer): string;
  280. var
  281. Size: Integer;
  282. begin
  283. Size := lua_strlen(L, Index);
  284. SetLength(Result, Size);
  285. if (Size > 0) then
  286. Move(lua_tostring(L, Index)^, Result[1], Size);
  287. end;
  288. procedure LuaPushString(L: PLua_State; const S: string);
  289. begin
  290. lua_pushstring(L, PChar(S));
  291. end;
  292. function LuaIncIndex(L: Plua_State; Index: Integer): Integer;
  293. // 相対インデックス -1 ~ -N へ変換
  294. begin
  295. if ((Index = LUA_GLOBALSINDEX) or (Index = LUA_REGISTRYINDEX)) then
  296. begin
  297. Result := Index;
  298. Exit;
  299. end;
  300. Result := LuaAbsIndex(L, Index) - lua_gettop(L) - 1;
  301. end;
  302. function LuaAbsIndex(L: Plua_State; Index: Integer): Integer;
  303. // 絶対インデックス 1 ~ N へ変換
  304. begin
  305. if ((Index = LUA_GLOBALSINDEX) or (Index = LUA_REGISTRYINDEX)) then
  306. begin
  307. Result := Index;
  308. Exit;
  309. end;
  310. if (Index < 0) then
  311. Result := Index + lua_gettop(L) + 1
  312. else
  313. Result := Index;
  314. end;
  315. procedure LuaPushKeyString(L: PLua_State; var Index: Integer; const Key: string);
  316. begin
  317. Index := LuaAbsIndex(L, Index);
  318. lua_pushstring(L, PChar(Key));
  319. end;
  320. procedure LuaGetTable(L: Plua_State; TableIndex: Integer; const Key: string);
  321. begin
  322. LuaPushKeyString(L, TableIndex, Key);
  323. lua_gettable(L, TableIndex);
  324. end;
  325. function LuaGetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string): Boolean;
  326. begin
  327. LuaGetTable(L, TableIndex, Key);
  328. Result := (lua_toboolean(L, -1) <> 0);
  329. lua_pop(L, 1);
  330. end;
  331. function LuaGetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string): Double;
  332. begin
  333. LuaGetTable(L, TableIndex, Key);
  334. Result := lua_tonumber(L, -1);
  335. lua_pop(L, 1);
  336. end;
  337. function LuaGetTableInteger(L: Plua_State; TableIndex: Integer; const Key: string): Integer;
  338. begin
  339. LuaGetTable(L, TableIndex, Key);
  340. Result := LuaToInteger(L, -1);
  341. lua_pop(L, 1);
  342. end;
  343. function LuaGetTableString(L: Plua_State; TableIndex: Integer; const Key: string): string;
  344. begin
  345. LuaGetTable(L, TableIndex, Key);
  346. Result := lua_tostring(L, -1);
  347. lua_pop(L, 1);
  348. end;
  349. function LuaGetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string): lua_CFunction;
  350. begin
  351. LuaGetTable(L, TableIndex, Key);
  352. Result := lua_tocfunction(L, -1);
  353. lua_pop(L, 1);
  354. end;
  355. function LuaGetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string): Pointer;
  356. begin
  357. LuaGetTable(L, TableIndex, Key);
  358. Result := lua_touserdata(L, -1);
  359. lua_pop(L, 1);
  360. end;
  361. function LuaGetTableTMethod(L: Plua_State; TableIndex: Integer; const Key: string): TMethod;
  362. begin
  363. Result.Code :=LuaGetTableLightUserData(L, TableIndex, Key+'_Code'); //Code is the Method Pointer
  364. Result.Data :=LuaGetTableLightUserData(L, TableIndex, Key+'_Data'); //Data is the object Pointer
  365. end;
  366. procedure LuaRawGetTable(L: Plua_State; TableIndex: Integer; const Key: string);
  367. begin
  368. LuaPushKeyString(L, TableIndex, Key);
  369. lua_rawget(L, TableIndex);
  370. end;
  371. function LuaRawGetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string): Boolean;
  372. begin
  373. LuaRawGetTable(L, TableIndex, Key);
  374. Result := (lua_toboolean(L, -1) <> 0);
  375. lua_pop(L, 1);
  376. end;
  377. function LuaRawGetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string): Double;
  378. begin
  379. LuaRawGetTable(L, TableIndex, Key);
  380. Result := lua_tonumber(L, -1);
  381. lua_pop(L, 1);
  382. end;
  383. function LuaRawGetTableString(L: Plua_State; TableIndex: Integer; const Key: string): string;
  384. begin
  385. LuaRawGetTable(L, TableIndex, Key);
  386. Result := lua_tostring(L, -1);
  387. lua_pop(L, 1);
  388. end;
  389. function LuaRawGetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string): lua_CFunction;
  390. begin
  391. LuaRawGetTable(L, TableIndex, Key);
  392. Result := lua_tocfunction(L, -1);
  393. lua_pop(L, 1);
  394. end;
  395. function LuaRawGetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string): Pointer;
  396. begin
  397. LuaRawGetTable(L, TableIndex, Key);
  398. Result := lua_touserdata(L, -1);
  399. lua_pop(L, 1);
  400. end;
  401. procedure LuaSetTableValue(L: PLua_State; TableIndex: Integer; const Key: string; ValueIndex: Integer);
  402. begin
  403. TableIndex := LuaAbsIndex(L, TableIndex);
  404. ValueIndex := LuaAbsIndex(L, ValueIndex);
  405. lua_pushstring(L, PChar(Key));
  406. lua_pushvalue(L, ValueIndex);
  407. lua_settable(L, TableIndex);
  408. end;
  409. procedure LuaSetTableNil(L: Plua_State; TableIndex: Integer; const Key: string);
  410. begin
  411. LuaPushKeyString(L, TableIndex, Key);
  412. lua_pushnil(L);
  413. lua_settable(L, TableIndex);
  414. end;
  415. procedure LuaSetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string; B: Boolean);
  416. begin
  417. LuaPushKeyString(L, TableIndex, Key);
  418. lua_pushboolean(L, Integer(B));
  419. lua_settable(L, TableIndex);
  420. end;
  421. procedure LuaSetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string; N: Double);
  422. begin
  423. LuaPushKeyString(L, TableIndex, Key);
  424. lua_pushnumber(L, N);
  425. lua_settable(L, TableIndex);
  426. end;
  427. procedure LuaSetTableString(L: Plua_State; TableIndex: Integer; const Key: string; S: string);
  428. begin
  429. LuaPushKeyString(L, TableIndex, Key);
  430. lua_pushstring(L, PChar(S));
  431. lua_settable(L, TableIndex);
  432. end;
  433. procedure LuaSetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string; F: lua_CFunction);
  434. begin
  435. LuaPushKeyString(L, TableIndex, Key);
  436. lua_pushcfunction(L, F);
  437. lua_settable(L, TableIndex);
  438. end;
  439. procedure LuaSetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string; P: Pointer);
  440. begin
  441. LuaPushKeyString(L, TableIndex, Key);
  442. lua_pushlightuserdata(L, P);
  443. lua_settable(L, TableIndex);
  444. end;
  445. procedure LuaSetTableTMethod(L: Plua_State; TableIndex: Integer; const Key: string; M: TMethod);
  446. begin
  447. LuaSetTableLightUserData(L, TableIndex, Key+'_Code', M.Code);
  448. LuaSetTableLightUserData(L, TableIndex, Key+'_Data', M.Data);
  449. end;
  450. procedure LuaSetTableClear(L: Plua_State; TableIndex: Integer);
  451. begin
  452. TableIndex := LuaAbsIndex(L, TableIndex);
  453. lua_pushnil(L);
  454. while (lua_next(L, TableIndex) <> 0) do
  455. begin
  456. lua_pushnil(L);
  457. lua_replace(L, -1 - 1);
  458. lua_settable(L, TableIndex);
  459. lua_pushnil(L);
  460. end;
  461. end;
  462. procedure LuaRawSetTableValue(L: PLua_State; TableIndex: Integer; const Key: string; ValueIndex: Integer);
  463. begin
  464. TableIndex := LuaAbsIndex(L, TableIndex);
  465. ValueIndex := LuaAbsIndex(L, ValueIndex);
  466. lua_pushstring(L, PChar(Key));
  467. lua_pushvalue(L, ValueIndex);
  468. lua_rawset(L, TableIndex);
  469. end;
  470. procedure LuaRawSetTableNil(L: Plua_State; TableIndex: Integer; const Key: string);
  471. begin
  472. LuaPushKeyString(L, TableIndex, Key);
  473. lua_pushnil(L);
  474. lua_rawset(L, TableIndex);
  475. end;
  476. procedure LuaRawSetTableBoolean(L: Plua_State; TableIndex: Integer; const Key: string; B: Boolean);
  477. begin
  478. LuaPushKeyString(L, TableIndex, Key);
  479. lua_pushboolean(L, Integer(B));
  480. lua_rawset(L, TableIndex);
  481. end;
  482. procedure LuaRawSetTableNumber(L: Plua_State; TableIndex: Integer; const Key: string; N: Double);
  483. begin
  484. LuaPushKeyString(L, TableIndex, Key);
  485. lua_pushnumber(L, N);
  486. lua_rawset(L, TableIndex);
  487. end;
  488. procedure LuaRawSetTableString(L: Plua_State; TableIndex: Integer; const Key: string; S: string);
  489. begin
  490. LuaPushKeyString(L, TableIndex, Key);
  491. lua_pushstring(L, PChar(S));
  492. lua_rawset(L, TableIndex);
  493. end;
  494. procedure LuaRawSetTableFunction(L: Plua_State; TableIndex: Integer; const Key: string; F: lua_CFunction);
  495. begin
  496. LuaPushKeyString(L, TableIndex, Key);
  497. lua_pushcfunction(L, F);
  498. lua_rawset(L, TableIndex);
  499. end;
  500. procedure LuaRawSetTableLightUserData(L: Plua_State; TableIndex: Integer; const Key: string; P: Pointer);
  501. begin
  502. LuaPushKeyString(L, TableIndex, Key);
  503. lua_pushlightuserdata(L, P);
  504. lua_rawset(L, TableIndex);
  505. end;
  506. procedure LuaRawSetTableClear(L: Plua_State; TableIndex: Integer);
  507. begin
  508. TableIndex := LuaAbsIndex(L, TableIndex);
  509. lua_pushnil(L);
  510. while (lua_next(L, TableIndex) <> 0) do
  511. begin
  512. lua_pushnil(L);
  513. lua_replace(L, -1 - 1);
  514. lua_rawset(L, TableIndex);
  515. lua_pushnil(L);
  516. end;
  517. end;
  518. function LuaGetMetaFunction(L: Plua_State; Index: Integer; Key: string): lua_CFunction;
  519. // メタ関数の取得
  520. begin
  521. Result := nil;
  522. Index := LuaAbsIndex(L, Index);
  523. if (lua_getmetatable(L, Index) = 0) then
  524. Exit;
  525. LuaGetTable(L, -1, Key);
  526. if (lua_iscfunction(L, -1) <> 0) then
  527. Result := lua_tocfunction(L, -1);
  528. lua_pop(L, 2);
  529. end;
  530. procedure LuaSetMetaFunction(L: Plua_State; Index: Integer; Key: string; F: lua_CFunction);
  531. // メタ関数の設定
  532. // Key = __add, __sub, __mul, __div, __pow, __unm, __concat,
  533. // __eq, __lt, __le, __index, __newindex, __call
  534. // [メモ]
  535. // __newindex は 新規代入時しか呼ばれないので注意
  536. // table をグローバル変数とするとこうなる。
  537. //
  538. // a=1 -- (a=nilなので)メタ関数呼び出される
  539. // a=2 -- メタ関数は呼び出されない
  540. // a=3 -- メタ関数は呼び出されない
  541. // a=nil
  542. // a=4 -- (a=nilなので)メタ関数呼び出される
  543. //
  544. // lua 付属の trace-globals では__newindex と __index をセットで上書きして
  545. // グローバル変数へのアクセスをローカル変数へのアクセスに切り替えてグロー
  546. // バル変数の実体は常に table[key] = nil を保たせて __newindex イベントを
  547. // 発生させている。
  548. begin
  549. Index := LuaAbsIndex(L, Index);
  550. if (lua_getmetatable(L, Index) = 0) then
  551. lua_newtable(L);
  552. LuaRawSetTableFunction(L, -1, Key, F);
  553. lua_setmetatable(L, Index);
  554. end;
  555. function LuaStackToStr(L: Plua_State; Index: Integer; MaxTable: Integer): string;
  556. //スタックの内容を文字列に変換
  557. // nil : nil
  558. // Number : FloatToStr
  559. // Boolean: True/False
  560. // stirng : "..."
  561. // Table : { Key1=Value Key2=Value }
  562. function TableToStr(Index: Integer): string;
  563. var
  564. Key, Value: string;
  565. Count: Integer;
  566. begin
  567. Result := '{ ';
  568. Count := 0;
  569. lua_pushnil(L);
  570. while (lua_next(L, Index) <> 0) do
  571. begin
  572. Inc(Count);
  573. if (Count > MaxTable) then
  574. begin
  575. Result := Result + '... ';
  576. lua_pop(L, 2);
  577. Break;
  578. end;
  579. if lua_type(L, -2) = LUA_TNUMBER then
  580. Key := '[' + Dequote(LuaStackToStr(L, -2, MaxTable)) + ']'
  581. else
  582. Key := Dequote(LuaStackToStr(L, -2, MaxTable));
  583. if (Key = '_G') then
  584. Value := LuaGlobalVariableStr
  585. else
  586. Value := LuaStackToStr(L, -1, MaxTable);
  587. if (lua_type(L, -1) = LUA_TFUNCTION) then
  588. Result := Result + Format('%s()=%p ', [Key, lua_topointer(L, -1)])
  589. else
  590. Result := Result + Format('%s=%s ', [Key, Value]);
  591. // Key は次のために残す
  592. lua_pop(L, 1);
  593. end;
  594. Result := Result + '}';
  595. end;
  596. var
  597. Size: Integer;
  598. begin
  599. if (MaxTable < 0) then
  600. MaxTable := DefaultMaxTable;
  601. Index := LuaAbsIndex(L, Index);
  602. case (lua_type(L, Index)) of
  603. LUA_TNIL:
  604. Result := 'nil';
  605. LUA_TNUMBER:
  606. Result := Format('%g', [lua_tonumber(L, Index)]);
  607. LUA_TBOOLEAN:
  608. Result := BoolToStr(lua_toboolean(L, Index) <> 0, True);
  609. LUA_TSTRING:
  610. begin
  611. Size := lua_strlen(L, Index);
  612. SetLength(Result, Size);
  613. if (Size > 0) then
  614. Move(lua_tostring(L, Index)^, Result[1], Size);
  615. Result := Quote(Result);
  616. end;
  617. LUA_TTABLE:
  618. Result := TableToStr(Index);
  619. LUA_TFUNCTION:
  620. if (lua_iscfunction(L, Index) <> 0) then
  621. Result := Format('CFUNC:%p', [Pointer(lua_tocfunction(L, Index))])
  622. else
  623. Result := Format('FUNC:%p', [lua_topointer(L, Index)]);
  624. LUA_TUSERDATA:
  625. Result := Format('USERDATA:%p', [lua_touserdata(L, Index)]);
  626. LUA_TTHREAD:
  627. Result := Format('THREAD:%p', [lua_tothread(L, Index)]);
  628. LUA_TLIGHTUSERDATA:
  629. Result := Format('LIGHTUSERDATA:%p', [lua_touserdata(L, Index)]);
  630. else
  631. Assert(False);
  632. end;
  633. end;
  634. procedure LuaShowStack(L: Plua_State; Caption: string);
  635. var
  636. I, N: Integer;
  637. S: string;
  638. begin
  639. N := lua_gettop(L);
  640. S := '[' + Caption + ']';
  641. for I := N downto 1 do
  642. begin
  643. S := S + CRLF + Format('%3d,%3d:%s', [LuaAbsIndex(L, I), LuaIncIndex(L, I),
  644. LuaStackToStr(L, I, -1)]);
  645. end;
  646. ShowMessage(S);
  647. end;
  648. procedure LuaProcessTableName(L: Plua_State; const Name: PChar;
  649. var LastName: string; var TableIndex, Count: Integer);
  650. // Name のテーブル要素をスタックに積んで、
  651. // スタックに積んだ数と Name の最終要素の名前とその親テーブルのインデックスを返す
  652. // テーブルが無い場合は作成する
  653. // LuaProcessTableName(L, 'print', S, TI, Count) → S = print, TI = LUA_GLOBALSINDEX, Count = 0
  654. // LuaProcessTableName(L, 'io.write', S, TI, Count) → S = write, TI -> io, Count = 1
  655. // LuaProcessTableName(L, 'a.b.c.func', S, TI, Count) → S = func, TI -> a.b.c, Count = 3
  656. var
  657. S: string;
  658. function GetToken: string;
  659. var
  660. Index: Integer;
  661. begin
  662. Index := Pos('.', S);
  663. if (Index = 0) then
  664. begin
  665. Result := S;
  666. S := '';
  667. Exit;
  668. end;
  669. Result := Copy(S, 1, Index - 1);
  670. S := Copy(S, Index + 1, Length(S));
  671. end;
  672. begin
  673. S := Name;
  674. Count := 0;
  675. LastName := GetToken;
  676. while (S <> '') do
  677. begin
  678. Inc(Count);
  679. TableIndex := LuaAbsIndex(L, TableIndex);
  680. LuaGetTable(L, TableIndex, LastName);
  681. if (lua_type(L, -1) <> LUA_TTABLE) then
  682. begin
  683. lua_pop(L, 1);
  684. lua_pushstring(L, PChar(LastName));
  685. lua_newtable(L);
  686. lua_rawset(L, TableIndex);
  687. LuaGetTable(L, TableIndex, LastName);
  688. end;
  689. TableIndex := -1;
  690. LastName := GetToken;
  691. end;
  692. end;
  693. procedure LuaRegisterCustom(L: PLua_State; TableIndex: Integer; const Name: PChar; F: lua_CFunction);
  694. var
  695. Count: Integer;
  696. S: string;
  697. begin
  698. LuaProcessTableName(L, Name, S, TableIndex, Count);
  699. LuaRawSetTableFunction(L, TableIndex, S, F);
  700. lua_pop(L, Count);
  701. end;
  702. procedure LuaRegister(L: Plua_State; const Name: PChar; F: lua_CFunction);
  703. // 関数の登録
  704. // LuaRegister(L, 'print', lua_print);
  705. // LuaRegister(L, 'io.write', lua_io_write); // テーブル io が無い場合は作成
  706. // LuaRegister(L, 'a.b.c.func', a_b_c_func); // テーブル a.b.c が無い場合は作成
  707. begin
  708. LuaRegisterCustom(L, LUA_GLOBALSINDEX, Name, F);
  709. end;
  710. procedure LuaRegisterMetatable(L: Plua_State; const Name: PChar; F: lua_CFunction);
  711. begin
  712. LuaRegisterCustom(L, LUA_REGISTRYINDEX, Name, F);
  713. end;
  714. procedure LuaRegisterProperty(L: PLua_State; const Name: PChar; ReadFunc, WriteFunc: lua_CFunction);
  715. var
  716. Count: Integer;
  717. TI: Integer;
  718. S: string;
  719. begin
  720. TI := LUA_GLOBALSINDEX;
  721. LuaProcessTableName(L, Name, S, TI, Count);
  722. TI := LuaAbsIndex(L, TI);
  723. LuaGetTable(L, TI, S);
  724. if (lua_type(L, -1) <> LUA_TTABLE) then
  725. begin
  726. lua_pop(L, 1);
  727. lua_pushstring(L, PChar(S));
  728. lua_newtable(L);
  729. lua_settable(L, TI);
  730. LuaGetTable(L, TI, S);
  731. end;
  732. if (Assigned(ReadFunc)) then
  733. LuaSetMetaFunction(L, -1, '__index', ReadFunc);
  734. if (Assigned(WriteFunc)) then
  735. LuaSetMetaFunction(L, -1, '__newindex', WriteFunc);
  736. lua_pop(L, Count + 1);
  737. end;
  738. procedure LuaStackToStrings(L: Plua_State; Lines: TStrings; MaxTable: Integer);
  739. var
  740. I: Integer;
  741. begin
  742. Lines.Clear;
  743. for I := lua_gettop(L) downto 1 do
  744. Lines.Add(LuaStackToStr(L, I, MaxTable));
  745. end;
  746. procedure LuaLocalToStrings(L: Plua_State; Lines: TStrings; MaxTable: Integer; Level: Integer);
  747. var
  748. Name: PChar;
  749. Index: Integer;
  750. Debug: lua_Debug;
  751. AR: Plua_Debug;
  752. begin
  753. AR := @Debug;
  754. Lines.Clear;
  755. Index := 1;
  756. if (lua_getstack(L, Level, AR) = 0) then
  757. Exit;
  758. Name := lua_getlocal(L, AR, Index);
  759. while (Name <> nil) do
  760. begin
  761. Lines.Values[Name] := LuaStackToStr(L, -1, MaxTable);
  762. lua_pop(L, 1);
  763. Inc(Index);
  764. Name := lua_getlocal(L, AR, Index);
  765. end;
  766. end;
  767. procedure LuaTableToStrings(L: Plua_State; Index: Integer; Lines: TStrings; MaxTable: Integer);
  768. var
  769. Key, Value: string;
  770. begin
  771. Index := LuaAbsIndex(L, Index);
  772. Lines.Clear;
  773. lua_pushnil(L);
  774. while (lua_next(L, Index) <> 0) do
  775. begin
  776. Key := Dequote(LuaStackToStr(L, -2, MaxTable));
  777. Value := LuaStackToStr(L, -1, MaxTable);
  778. Lines.Values[Key] := Value;
  779. lua_pop(L, 1);
  780. end;
  781. end;
  782. procedure LuaTableToVirtualTreeView(L: Plua_State; Index: Integer; VTV: TVirtualStringTree; MaxTable: Integer);
  783. // Go through all child of current table and create nodes
  784. procedure ParseTreeNode(TreeNode: PVirtualNode; Index: Integer);
  785. var
  786. Key: string;
  787. pData: PBasicTreeData;
  788. pNode: PVirtualNode;
  789. begin
  790. // Retreive absolute index
  791. Index := LuaAbsIndex(L, Index);
  792. // Get the root node if current node is not assigned
  793. //if not Assigned(TreeNode) then
  794. //TreeNode := VTV.RootNode;
  795. lua_pushnil(L);
  796. while (lua_next(L, Index) <> 0) do
  797. begin
  798. Key := Dequote(LuaStackToStr(L, -2, MaxTable));
  799. if (lua_type(L, -1) <> LUA_TTABLE) then
  800. begin
  801. pData := VTV.GetNodeData(VTV.AddChild(TreeNode));
  802. pData.sName := Key;
  803. pData.sValue := LuaStackToStr(L, -1, MaxTable);
  804. end
  805. else
  806. begin
  807. if (Key = '_G') then
  808. begin
  809. pData := VTV.GetNodeData(VTV.AddChild(TreeNode));
  810. pData.sName := Key;
  811. pData.sValue := '[LUA_GLOBALSINDEX]';
  812. end
  813. else
  814. begin
  815. pNode := VTV.AddChild(TreeNode);
  816. pData := VTV.GetNodeData(pNode);
  817. pData.sName := Key;
  818. pData.sValue := '';
  819. ParseTreeNode(pNode, -1);
  820. end;
  821. end;
  822. lua_pop(L, 1);
  823. end;
  824. end;
  825. begin
  826. Assert(lua_type(L, Index) = LUA_TTABLE);
  827. VTV.BeginUpdate;
  828. VTV.Clear;
  829. try
  830. ParseTreeNode(nil, Index);
  831. finally
  832. VTV.EndUpdate;
  833. end;
  834. end;
  835. procedure LuaTableToTreeView(L: Plua_State; Index: Integer; TV: TTreeView; MaxTable: Integer);
  836. // Go through all child of current table and create nodes
  837. procedure ParseTreeNode(TreeNode: TTreeNode; Index: Integer);
  838. var
  839. Key: string;
  840. begin
  841. Index := LuaAbsIndex(L, Index);
  842. lua_pushnil(L);
  843. while (lua_next(L, Index) <> 0) do
  844. begin
  845. Key := Dequote(LuaStackToStr(L, -2, MaxTable));
  846. if (lua_type(L, -1) <> LUA_TTABLE) then
  847. TV.Items.AddChild(TreeNode, Key + '=' + LuaStackToStr(L, -1, MaxTable))
  848. else
  849. begin
  850. if (Key = '_G') then
  851. TV.Items.AddChild(TreeNode, Key + '=[LUA_GLOBALSINDEX]')
  852. else
  853. ParseTreeNode(TV.Items.AddChild(TreeNode, Key), -1);
  854. end;
  855. lua_pop(L, 1);
  856. end;
  857. end;
  858. begin
  859. Assert(lua_type(L, Index) = LUA_TTABLE);
  860. TV.Items.BeginUpdate;
  861. TV.Items.Clear;
  862. try
  863. ParseTreeNode(nil, Index);
  864. finally
  865. TV.Items.EndUpdate;
  866. end;
  867. end;
  868. function LuaGetIdentValue(L: Plua_State; Ident: string; MaxTable: Integer): string;
  869. const
  870. DebugValue = '___DEBUG_VALUE___';
  871. var
  872. Local: TStrings;
  873. Code: string;
  874. Hook: lua_Hook;
  875. Mask: Integer;
  876. Count: Integer;
  877. begin
  878. if (Ident = '') then
  879. begin
  880. Result := '';
  881. Exit;
  882. end;
  883. Local := TStringList.Create;
  884. try
  885. LuaLocalToStrings(L, Local, MaxTable);
  886. Result := Local.Values[Ident];
  887. if (Result <> '') then
  888. Exit;
  889. finally
  890. Local.Free;
  891. end;
  892. Code := DebugValue + '=' + Ident;
  893. luaL_loadbuffer(L, PChar(Code), Length(Code), 'debug');
  894. Hook := lua_gethook(L);
  895. Mask := lua_gethookmask(L);
  896. Count := lua_gethookcount(L);
  897. lua_sethook(L, Hook, 0, Count);
  898. if (lua_pcall(L, 0, 0, 0) = 0) then
  899. LuaRawGetTable(L, LUA_GLOBALSINDEX, DebugValue);
  900. Result := LuaStackToStr(L, -1, MaxTable);
  901. lua_remove(L, -1);
  902. lua_dostring(L, DebugValue + '=nil');
  903. lua_sethook(L, Hook, Mask, Count);
  904. end;
  905. procedure LuaSetIdentValue(L: Plua_State; Ident, Value: string; MaxTable: Integer);
  906. var
  907. Local: TStrings;
  908. Code: string;
  909. Index: Integer;
  910. Debug: lua_Debug;
  911. AR: Plua_Debug;
  912. begin
  913. Local := TStringList.Create;
  914. try
  915. AR := @Debug;
  916. LuaLocalToStrings(L, Local, MaxTable);
  917. Index := Local.IndexOf(Ident);
  918. if (Index >= 0) then
  919. begin
  920. try
  921. lua_pushnumber(L, StrToFloat(Value));
  922. except
  923. lua_pushstring(L, PChar(Dequote(Value)));
  924. end;
  925. lua_getstack(L, 0, AR);
  926. lua_getinfo(L, 'Snlu', AR);
  927. lua_setlocal(L, AR, Index + 1);
  928. end else
  929. begin
  930. Code := Ident + '=' + Value;
  931. luaL_loadbuffer(L, PChar(Code), Length(Code), 'debug');
  932. if (lua_pcall(L, 0, 0, 0) <> 0) then
  933. lua_remove(L, -1);
  934. end;
  935. finally
  936. Local.Free;
  937. end;
  938. end;
  939. procedure LuaProcessErrorMessage(const ErrMsg: string; var Title: string; var Line: Integer; var Msg: string);
  940. const
  941. Term = #$00;
  942. function S(Index: Integer): Char;
  943. begin
  944. if (Index <= Length(ErrMsg)) then
  945. Result := ErrMsg[Index]
  946. else
  947. Result := Term;
  948. end;
  949. function IsDigit(C: Char): Boolean;
  950. begin
  951. Result := ('0' <= C) and (C <= '9');
  952. end;
  953. function PP(var Index: Integer): Integer;
  954. begin
  955. Inc(Index);
  956. Result := Index;
  957. end;
  958. var
  959. I, Start, Stop: Integer;
  960. LS: string;
  961. Find: Boolean;
  962. begin
  963. // ErrMsg = Title:Line:Message
  964. Title := '';
  965. Line := 0;
  966. Msg := ErrMsg;
  967. Find := False;
  968. I := 1 - 1;
  969. Stop := 0;
  970. // :数値: を探す
  971. repeat
  972. while (S(PP(I)) <> ':') do
  973. if (S(I) = Term) then
  974. Exit;
  975. Start := I;
  976. if (not IsDigit(S(PP(I)))) then
  977. Continue;
  978. while (IsDigit(S(PP(I)))) do
  979. if (S(I - 1) = Term) then
  980. Exit;
  981. Stop := I;
  982. if (S(I) = ':') then
  983. Find := True;
  984. until (Find);
  985. Title := Copy(ErrMsg, 1, Start - 1);
  986. LS := Copy(ErrMsg, Start + 1, Stop - Start - 1);
  987. Line := StrToIntDef(LS, 0);
  988. Msg := Copy(ErrMsg, Stop + 1, Length(ErrMsg));
  989. end;
  990. procedure LuaLoadBuffer(L: Plua_State; const Code: string; const Name: string);
  991. var
  992. Title, Msg: string;
  993. Line: Integer;
  994. begin
  995. if (luaL_loadbuffer(L, PChar(Code), Length(Code), PChar(Name)) = 0) then
  996. Exit;
  997. LuaProcessErrorMessage(Dequote(LuaStackToStr(L, -1, -1)),
  998. Title, Line, Msg);
  999. raise ELuaException.Create(Title, Line, Msg);
  1000. end;
  1001. procedure LuaLoadBufferFromFile(L: Plua_State; const Filename: string; const Name: string);
  1002. Var
  1003. xCode :String;
  1004. xFile :TStringList;
  1005. begin
  1006. xFile := TStringList.Create;
  1007. xFile.LoadFromFile(FileName);
  1008. xCode := xFile.Text;
  1009. xFile.Free;
  1010. LuaLoadBuffer(L, xCode, Name);
  1011. end;
  1012. procedure LuaPCall(L: Plua_State; NArgs, NResults, ErrFunc: Integer);
  1013. var
  1014. Title, Msg: string;
  1015. Line: Integer;
  1016. begin
  1017. if (lua_pcall(L, NArgs, NResults, ErrFunc) = 0) then
  1018. Exit;
  1019. LuaProcessErrorMessage(Dequote(LuaStackToStr(L, -1, -1)),
  1020. Title, Line, Msg);
  1021. raise ELuaException.Create(Title, Line, Msg);
  1022. end;
  1023. function LuaPCallFunction(L: Plua_State; FunctionName :String;
  1024. const Args: array of Variant;
  1025. Results : PVariantArray;
  1026. ErrFunc: Integer=0;
  1027. NResults :Integer=LUA_MULTRET):Integer;
  1028. var
  1029. NArgs,
  1030. i :Integer;
  1031. begin
  1032. //Put Function To Call on the Stack
  1033. luaPushString(L, FunctionName);
  1034. lua_gettable(L, LUA_GLOBALSINDEX);
  1035. //Put Parameters on the Stack
  1036. NArgs := High(Args)+1;
  1037. for i:=0 to (NArgs-1) do
  1038. LuaPushVariant(L, Args[i]);
  1039. //Call the Function
  1040. LuaPcall(L, NArgs, NResults, ErrFunc);
  1041. Result :=lua_gettop(L); //Get Number of Results
  1042. if (Results<>Nil)
  1043. then begin
  1044. //Get Results in the right order
  1045. SetLength(Results^, Result);
  1046. for i:=0 to Result-1 do
  1047. begin
  1048. Results^[Result-(i+1)] :=LuaToVariant(L, -(i+1));
  1049. end;
  1050. end;
  1051. end;
  1052. procedure LuaError(L: Plua_State; const Msg: string);
  1053. begin
  1054. luaL_error(L, PChar(Msg));
  1055. end;
  1056. procedure LuaErrorFmt(L: Plua_State; const Fmt: string; const Args: array of Const);
  1057. begin
  1058. LuaError(L, Format(Fmt, Args));
  1059. end;
  1060. { ELuaException }
  1061. constructor ELuaException.Create(Title: string; Line: Integer;
  1062. Msg: string);
  1063. var
  1064. LS: string;
  1065. begin
  1066. if (Line > 0) then
  1067. LS := Format('(%d)', [Line])
  1068. else
  1069. LS := '';
  1070. inherited Create(Title + LS + Msg);
  1071. Self.Title := Title;
  1072. Self.Line := Line;
  1073. Self.Msg := Msg;
  1074. end;
  1075. function LuaDataStrToStrings(const TableStr: string; Strings: TStrings): string;
  1076. (*
  1077. LuaStackToStr 形式から Strings.Values[Name] 構造へ変換
  1078. TableStr
  1079. { Name = "Lua" Version = 5.0 }
  1080. Strings
  1081. Name="Lua"
  1082. Version=5.0
  1083. DataList : Data DataList
  1084. |
  1085. Data : Table
  1086. | {グローバル変数}
  1087. | Ident ( )
  1088. | Ident = Value
  1089. | Ident
  1090. |
  1091. Table : { DataList }
  1092. |
  1093. Value : "..."
  1094. | Data
  1095. *)
  1096. const
  1097. EOF = #$00;
  1098. var
  1099. Index: Integer;
  1100. Text: string;
  1101. Token: Char;
  1102. function S(Index: Integer): Char;
  1103. begin
  1104. if (Index <= Length(TableStr)) then
  1105. Result := TableStr[Index]
  1106. else
  1107. Result := EOF;
  1108. end;
  1109. function GetString: string;
  1110. var
  1111. SI: Integer;
  1112. begin
  1113. Dec(Index);
  1114. Result := '';
  1115. repeat
  1116. Assert(S(Index) = '"');
  1117. SI := Index;
  1118. Inc(Index);
  1119. while (S(Index) <> '"') do
  1120. Inc(Index);
  1121. Result := Result + Copy(TableStr, SI, Index - SI + 1);
  1122. Inc(Index);
  1123. until (S(Index) <> '"');
  1124. end;
  1125. function GetValue: string;
  1126. function IsIdent(C: Char): Boolean;
  1127. const
  1128. S = ' =(){}' + CR + LF;
  1129. begin
  1130. Result := (Pos(C, S) = 0);
  1131. end;
  1132. var
  1133. SI: Integer;
  1134. begin
  1135. Dec(Index);
  1136. SI := Index;
  1137. while (IsIdent(S(Index))) do
  1138. Inc(Index);
  1139. Result := Copy(TableStr, SI, Index - SI);
  1140. end;
  1141. function GetToken: Char;
  1142. function SkipSpace(var Index: Integer): Integer;
  1143. const
  1144. TAB = #$09;
  1145. CR = #$0D;
  1146. LF = #$0A;
  1147. begin
  1148. while (S(Index) in [' ', TAB, CR, LF]) do
  1149. Inc(Index);
  1150. Result := Index;
  1151. end;
  1152. begin
  1153. SkipSpace(Index);
  1154. Token := S(Index);
  1155. Inc(Index);
  1156. Text := Token;
  1157. case (Token) of
  1158. EOF: ;
  1159. '"': Text := GetString;
  1160. '{':
  1161. if (Copy(TableStr, Index - 1, Length(LuaGlobalVariableStr)) = LuaGlobalVariableStr) then
  1162. begin
  1163. Token := 'G';
  1164. Text := LuaGlobalVariableStr;
  1165. Inc(Index, Length(LuaGlobalVariableStr) - 1);
  1166. end;
  1167. '}': ;
  1168. '(': ;
  1169. ')': ;
  1170. '=': ;
  1171. else Text := GetValue
  1172. end;
  1173. Result := Token;
  1174. end;
  1175. procedure Check(S: string);
  1176. begin
  1177. if (Pos(Token, S) = -1) then
  1178. raise Exception.CreateFmt('Error %s is required :%s', [Copy(TableStr, Index - 1, Length(TableStr))]);
  1179. end;
  1180. function CheckGetToken(S: string): Char;
  1181. begin
  1182. Result := GetToken;
  1183. Check(S);
  1184. end;
  1185. function ParseData: string; forward;
  1186. function ParseTable: string; forward;
  1187. function ParseValue: string; forward;
  1188. function ParseDataList: string;
  1189. begin
  1190. with (TStringList.Create) do
  1191. try
  1192. while not (Token in [EOF, '}']) do
  1193. Add(ParseData);
  1194. Result := Text;
  1195. finally
  1196. Free;
  1197. end;
  1198. end;
  1199. function ParseData: string;
  1200. begin
  1201. if (Token = EOF) then
  1202. begin
  1203. Result := '';
  1204. Exit;
  1205. end;
  1206. case (Token) of
  1207. '{': Result := ParseTable;
  1208. 'G':
  1209. begin
  1210. Result := Text;
  1211. GetToken;
  1212. end;
  1213. else
  1214. begin
  1215. Result := Text;
  1216. case (GetToken) of
  1217. '(':
  1218. begin
  1219. CheckGetToken(')');
  1220. Result := Format('%s=()', [Result]);
  1221. GetToken;
  1222. end;
  1223. '=':
  1224. begin
  1225. GetToken;
  1226. Result := Format('%s=%s', [Result, ParseValue]);
  1227. end;
  1228. end;
  1229. end;
  1230. end;
  1231. end;
  1232. function ParseTable: string;
  1233. begin
  1234. if (Token in [EOF]) then
  1235. begin
  1236. Result := '';
  1237. Exit;
  1238. end;
  1239. Check('{');
  1240. GetToken;
  1241. with (TStringList.Create) do
  1242. try
  1243. Text := ParseDataList;
  1244. Result := CommaText;
  1245. finally
  1246. Free;
  1247. end;
  1248. Check('}');
  1249. GetToken;
  1250. end;
  1251. function ParseValue: string;
  1252. begin
  1253. if (Token = EOF) then
  1254. begin
  1255. Result := '';
  1256. Exit;
  1257. end;
  1258. case (Token) of
  1259. '"':
  1260. begin
  1261. Result := Text;
  1262. GetToken;
  1263. end;
  1264. else
  1265. Result := ParseData;
  1266. end;
  1267. end;
  1268. begin
  1269. Index := 1;
  1270. GetToken;
  1271. Strings.Text := ParseDataList;
  1272. end;
  1273. function LuaDoFile(L: Plua_State): Integer; cdecl;
  1274. // dofile 引数(arg)戻り値付き
  1275. // Lua: DoFile(FileName, Args...)
  1276. const
  1277. ArgIdent = 'arg';
  1278. var
  1279. FileName: PChar;
  1280. I, N, R: Integer;
  1281. ArgTable, ArgBackup: Integer;
  1282. begin
  1283. N := lua_gettop(L);
  1284. // arg, result の保存
  1285. lua_getglobal(L, ArgIdent);
  1286. ArgBackup := lua_gettop(L);
  1287. FileName := luaL_checkstring(L, 1);
  1288. lua_newtable(L);
  1289. ArgTable := lua_gettop(L);
  1290. for I := 2 to N do
  1291. begin
  1292. lua_pushvalue(L, I);
  1293. lua_rawseti(L, ArgTable, I - 1);
  1294. end;
  1295. lua_setglobal(L, ArgIdent);
  1296. Result := lua_gettop(L);
  1297. luaL_loadfile(L, PChar(FileName));
  1298. R := lua_pcall(L, 0, LUA_MULTRET, 0);
  1299. Result := lua_gettop(L) - Result;
  1300. LuaRawSetTableValue(L, LUA_GLOBALSINDEX, ArgIdent, ArgBackup);
  1301. lua_remove(L, ArgBackup);
  1302. if (R <> 0) then
  1303. lua_error(L);
  1304. end;
  1305. initialization
  1306. DefaultMaxTable := 256;
  1307. end.