LuaUtils.pas 49 KB

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