├── 1_makeall.cmd ├── 1_makeall.sh ├── LICENSE.txt ├── bin ├── jual.exe ├── jualc.exe ├── libinet.dll ├── libsqlite3.dll ├── linux │ ├── jual │ ├── jualc │ ├── libinet.so │ ├── libsqlite3.so │ ├── modsample.so │ └── uint8array.so ├── modsample.dll └── uint8array.dll ├── changelog.txt ├── jscript.cmd ├── jscript2jual.js ├── jual_reference.txt ├── lib ├── activex_fso.js ├── common.js └── jual2node.js ├── node2jual.js ├── readme.md ├── runtests.sh ├── runtests_node.cmd ├── runtests_wsh.cmd ├── samples ├── echo-client.js ├── echo-server.js ├── example_array_cons.js ├── example_method_calls.js ├── example_ternary_op.js ├── test_activex_fso.js ├── test_concat.js ├── test_console.js ├── test_coroutines.js ├── test_fileio.js ├── test_gotostat.js ├── test_pairs.js ├── test_sort.js ├── test_sqlite.js └── test_uint8array.js ├── src ├── 1_make.cmd ├── 1_make.sh ├── 2_jualc.c ├── 3_jual.c ├── Makefile ├── inet │ ├── 1_make.cmd │ ├── 1_make.sh │ ├── inet.c │ ├── inet_unix.c │ ├── inet_win32.c │ └── jxapi.h ├── jual_ffi.c ├── jual_init.h ├── lapi.c ├── lapi.h ├── lauxlib.c ├── lauxlib.h ├── lbaselib.c ├── lbitlib.c ├── lcode.c ├── lcode.h ├── lcorolib.c ├── lctype.c ├── lctype.h ├── ldblib.c ├── ldebug.c ├── ldebug.h ├── ldo.c ├── ldo.h ├── ldump.c ├── lfunc.c ├── lfunc.h ├── lgc.c ├── lgc.h ├── linit.c ├── liolib.c ├── llex.c ├── llex.h ├── llimits.h ├── lmathlib.c ├── lmem.c ├── lmem.h ├── loadlib.c ├── lobject.c ├── lobject.h ├── lopcodes.c ├── lopcodes.h ├── loslib.c ├── lparser.c ├── lparser.h ├── lprefix.h ├── lstate.c ├── lstate.h ├── lstring.c ├── lstring.h ├── lstrlib.c ├── ltable.c ├── ltable.h ├── ltablib.c ├── ltm.c ├── ltm.h ├── lua.c ├── lua.h ├── lua.hpp ├── luac.c ├── luaconf.h ├── lualib.h ├── lundump.c ├── lundump.h ├── lutf8lib.c ├── lvm.c ├── lvm.h ├── lzio.c ├── lzio.h ├── modsample │ ├── 1_make.cmd │ ├── 1_make.sh │ ├── jxapi.h │ └── modsample.c ├── sqlite │ ├── 1_make.cmd │ ├── 1_make.sh │ ├── jxapi.h │ ├── libsqlite3.c │ ├── sqlite3.c │ └── sqlite3.h └── uint8array │ ├── 1_make.cmd │ ├── 1_make.sh │ ├── jxapi.h │ └── uint8array.c └── testsuite ├── 10_functions.js ├── 11_arrays.js ├── 12_assocarrays.js ├── 13_string_funcs.js ├── 14_objects.js ├── 15_classes.js ├── 16_simple_functions.js ├── 18_dateobj.js ├── 19_include_library.js ├── 1_comments.js ├── 20_mathobj.js ├── 2_vars_numbers.js ├── 3_strings.js ├── 4_operators.js ├── 5_compound_ops.js ├── 6_ifstat.js ├── 7_whilestat.js ├── 8_dostat.js ├── 99_cmdargs.js └── 9_forstat.js /1_makeall.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Making jual and jualc 3 | cd src 4 | call 1_make.cmd 5 | 6 | echo Making sample module 7 | cd modsample 8 | call 1_make.cmd 9 | 10 | echo Making inet module 11 | cd ../inet 12 | call 1_make.cmd 13 | 14 | 15 | echo Making uint8array module 16 | cd ../uint8array 17 | call 1_make.cmd 18 | 19 | echo Making sqlite module 20 | cd ../sqlite 21 | call 1_make.cmd 22 | 23 | cd ../../ -------------------------------------------------------------------------------- /1_makeall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Making jual and jualc" 3 | cd src 4 | ./1_make.sh 5 | 6 | echo "Making sample module" 7 | cd modsample 8 | ./1_make.sh 9 | 10 | echo "Making inet module" 11 | cd ../inet 12 | ./1_make.sh 13 | 14 | echo "Making uint8array module" 15 | cd ../uint8array 16 | ./1_make.sh 17 | 18 | echo "Making sqlite module" 19 | cd ../sqlite 20 | ./1_make.sh 21 | 22 | cd ../../ -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/LICENSE.txt -------------------------------------------------------------------------------- /bin/jual.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/jual.exe -------------------------------------------------------------------------------- /bin/jualc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/jualc.exe -------------------------------------------------------------------------------- /bin/libinet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/libinet.dll -------------------------------------------------------------------------------- /bin/libsqlite3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/libsqlite3.dll -------------------------------------------------------------------------------- /bin/linux/jual: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/jual -------------------------------------------------------------------------------- /bin/linux/jualc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/jualc -------------------------------------------------------------------------------- /bin/linux/libinet.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/libinet.so -------------------------------------------------------------------------------- /bin/linux/libsqlite3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/libsqlite3.so -------------------------------------------------------------------------------- /bin/linux/modsample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/modsample.so -------------------------------------------------------------------------------- /bin/linux/uint8array.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/linux/uint8array.so -------------------------------------------------------------------------------- /bin/modsample.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/modsample.dll -------------------------------------------------------------------------------- /bin/uint8array.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sajonoso/jual/e124139ad4581fb7e02fa38051135ce2f4578f14/bin/uint8array.dll -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | Version 1.0 2 | Initial release based on Lua 5.3.0 3 | 4 | Version 1.1 5 | * Updated code base to Lua 5.3.1 6 | * implemented compound arithmetic assignment 7 | * Implemented new module library system (simply include jxapi.h) 8 | * Implemented new library for TCP/IP access with sample echo server and client 9 | * Implemented Date object 10 | * Compiled linux binaries (using 32-bit RHEL 6.6) -------------------------------------------------------------------------------- /jscript.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | /* 2>nul: 3 | rem Copyright 2015 Sajon Oso 4 | rem This batch file runs the Windows Scripting Host (WSH) and executes the source file passed as the first argument 5 | rem The embedded script loads a library file (jual_compat.js) which will make the WSH engine compatible with JualScript 6 | rem This compatibility script can be modified for other javascript engines as well like NodeJS. 7 | 8 | set JSCRIPTOUT=tmp.jsz 9 | echo /* > %JSCRIPTOUT% 10 | type %~f0 >> %JSCRIPTOUT% 11 | set TARGETSCRIPT=NUL 12 | if EXIST %1 set TARGETSCRIPT=%1 13 | if NOT %TARGETSCRIPT%==NUL ( 14 | type %TARGETSCRIPT% >> %JSCRIPTOUT% 15 | cscript /nologo /E:jscript %JSCRIPTOUT% %* 16 | rem del %JSCRIPTOUT% 17 | ) 18 | goto :eof 19 | */ 20 | 21 | 22 | 23 | // ## define function to load a library 24 | function includeJS (filename) { 25 | var fso = new ActiveXObject ("Scripting.FileSystemObject"); 26 | if (!fso.FileExists(filename)) filename = "../" + filename; 27 | if (!fso.FileExists(filename)) filename = "../bin/" + filename; 28 | var fileStream = fso.openTextFile (filename); 29 | var fileData = fileStream.readAll(); 30 | fileStream.Close(); 31 | return fileData; 32 | } 33 | 34 | eval(includeJS("jscript2jual.js")); 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | // To help debug code when running jscript with this wrapper file, simply subtract the reported error line number by 100 99 | // For the calculation to work this line should be line 99 with a terminating new line character. 100 | -------------------------------------------------------------------------------- /jscript2jual.js: -------------------------------------------------------------------------------- 1 | // This library makes JScript compatible with JualScript 2 | // You can copy and modify this file for other JavaScript engines 3 | 4 | isJUALSCRIPT = false; 5 | 6 | // ## STRING functions 7 | // Supported methods 8 | // charAt charCodeAt concat indexOf replace split slice toLowerCase toUpperCase 9 | String.prototype.size = function() { return this.length; }; 10 | // Object.defineProperty (String.prototype, 'size', {enumerable: false}); 11 | Array.prototype.size = String.prototype.size; 12 | // Object.defineProperty (Array.prototype, 'size', {enumerable: false}); 13 | 14 | 15 | // DATE functions 16 | function Date_pad(num, pad) { 17 | if (num==null) { num = 0; }; 18 | var ns = "0000" + num; 19 | return ns.slice(-pad); 20 | } 21 | Date.prototype.toLocalISOString = function() { 22 | var out= this.getFullYear() + "-" + Date_pad(this.getMonth()+1, 2) + "-" + Date_pad(this.getDate(), 2) + 23 | "T" + Date_pad(this.getHours(), 2) + ":" + Date_pad(this.getMinutes(), 2) + ":" + Date_pad(this.getSeconds(), 2) + "." + Date_pad(this.getMilliseconds(), 3); 24 | return out; 25 | }; 26 | 27 | 28 | 29 | function print(szOut) { 30 | var szTmp=szOut; 31 | if (typeof szOut == 'string') szTmp=szOut.replace(/\n/g,"\r\n"); 32 | if (typeof szOut == 'boolean') szTmp=szOut?"true":"false"; 33 | WScript.echo(szTmp); 34 | }; 35 | 36 | 37 | // ## FILE Functions 38 | var io = {}; 39 | io.fso = new ActiveXObject("Scripting.FileSystemObject"); 40 | io.close = function(hFile) { hFile.ts.Close(); }; 41 | // io.flush - Not supported by FSO 42 | io.exists = function(szFilename) { return io.fso.FileExists(szFilename); }; 43 | io.open = function(szFilename, szMode) { 44 | var hFile = {}; 45 | hFile.name = szFilename; 46 | if (szMode == "r") { 47 | hFile.ts = io.fso.OpenTextFile(szFilename, 1); 48 | return hFile; 49 | }; 50 | if (szMode == "w") { 51 | hFile.ts = io.fso.OpenTextFile(szFilename, 2, true); 52 | return hFile; 53 | }; 54 | return null; 55 | }; 56 | io.readbyte = function(hFile, iNumBytes) { return hFile.ts.read(iNumBytes); }; 57 | io.readline = function(hFile) { return hFile.ts.AtEndOfStream?null:hFile.ts.ReadLine(); }; 58 | // io.seek - Not supported by FSO 59 | io.size = function(hFile) { return (io.fso.FileExists(hFile.name) ? io.fso.GetFile(hFile.name).Size : 0) }; 60 | io.writebyte = function(hFile, szData) { return hFile.ts.write(szData); }; 61 | 62 | var os = {}; 63 | os.exit = function(iCode) { WScript.Quit(iCode); }; 64 | 65 | 66 | // ## Transfer command line arguments 67 | var arg=[]; for (i=0; i >= 23 | Bitwise & | ^ ~ << >> 24 | 25 | 26 | STANDARD LIBRARY 27 | ## GENERAL Functions 28 | isNaN(var) // for compatibility with Javascript 29 | parseInt(szText, iRadix) 30 | parseFloat(szText); 31 | isNum(cChar) 32 | isAlpha(cChar) 33 | noexpr(szString) // use with replace for no regular expression (i.e exact match) 34 | 35 | ## NUMBER Functions 36 | number.toString(radix) 37 | 38 | ## STRING Functions 39 | // Assume that functions requiring an index does not support negative indexes. 40 | // Assume result is undefined when a negative index is passed. 41 | // the only exception is the slice method which only support 1 positive or negative index or 2 positive indexes 42 | string.charAt( iPos_0based ) 43 | string.charCodeAt( iPos_0based ) 44 | string.fromCharCode(iCharactercode0, iCharacterCode1) 45 | string.indexOf( szSearch, [iStart] ) 46 | string.len() 47 | string.replace( szSearch, szReplacement ) 48 | string.split( szSeparator) 49 | string.slice( iStart_0based, [iEnd_0based] ) 50 | string.toLowerCase() 51 | string.toUpperCase() 52 | 53 | 54 | ## Array function 55 | array.join(szSeparator) 56 | 57 | 58 | ## TO BE IMPLEMENTED 59 | ## Binary string operations ( also works on normal strings ) 60 | getByte (szBinaryString, iPos); 61 | setByte (szBinaryString, iPos, iValue); 62 | compress ( szBinaryString , szAlgorithm); 63 | uncompress ( szBinaryString , szAlgorithm); 64 | base64enc ( szBinaryString ); 65 | base64dec ( szBase64String ); 66 | 67 | 68 | ## MATH Functions 69 | Math.abs( iNum ); 70 | Math.acos( iNum ); 71 | Math.asin( iNum ); 72 | Math.atan( iNum ); 73 | Math.atan2( iNumY, iNumX ); 74 | Math.ceil( iNum ); 75 | Math.cos( iNum ); 76 | Math.exp( iNum ); 77 | Math.floor( iNum ); 78 | Math.log( iNum ); 79 | Math.max( iNum1, iNum2, ..., iNumN ); 80 | Math.min( iNum1, iNum2, ..., iNumN ); 81 | Math.pow( iNum ); 82 | Math.random(); 83 | Math.round( iNum ); 84 | Math.sin( iNum ); 85 | Math.sqrt( iNum ); 86 | Math.tan( iNum ); 87 | 88 | ## DATE object 89 | date.getFullYear(); 90 | date.getMonth(); 91 | date.getDate(); 92 | date.getHours(); 93 | date.getMinutes(); 94 | date.getSeconds(); 95 | date.toLocalISOString(); 96 | 97 | ## FILE Functions 98 | io.close(hFile); 99 | io.flush(hFile); 100 | io.exists(szFilename); 101 | io.open(szFilename, szMode); 102 | io.readbyte(hFile, iNumBytes); 103 | io.readline(hFile); 104 | io.seek(hFile, iPosition); 105 | io.size(hFile); 106 | io.writebyte(hFile, szData); 107 | 108 | 109 | ## OS Functions 110 | os.getenv( szVarName ); 111 | os.exit( [iExitCode] ); 112 | os.execute( szCommand ); 113 | os.gettime( blUTC ); 114 | -------------------------------------------------------------------------------- /lib/activex_fso.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 Sajon Oso 3 | This library is a partial implementation of the ActiveX Scripting.FileSystemObject for JualScript 4 | */ 5 | 6 | textstream_MT = {}; 7 | textstream_MT.Skip = function(numChars) { 8 | if (numChars <=0 ) { return; }; 9 | this.handle:seek("cur", numChars); 10 | }; 11 | textstream_MT.SkipLine = function() { 12 | var data = this.handle:read("l"); 13 | if (data == null || this.handle:seek("cur", 0) == (this.size)) { 14 | this.AtEndOfStream = true; 15 | }; 16 | }; 17 | textstream_MT.Read = function(numChars) { 18 | if (numChars <=0 ) { return ""; }; 19 | var data = this.handle:read(numChars); 20 | if (data == null || this.handle:seek("cur", 0) == (this.size)) { 21 | this.AtEndOfStream = true; 22 | }; 23 | if (data==null) { return ""; }; 24 | return data; 25 | }; 26 | textstream_MT.ReadAll = function() { 27 | var data = this.handle:read("a"); 28 | this.AtEndOfStream = true; 29 | if (data == null) { 30 | return ""; 31 | }; 32 | return data; 33 | }; 34 | textstream_MT.ReadLine = function() { 35 | var data = this.handle:read("l"); 36 | if (data == null || this.handle:seek("cur", 0) == (this.size)) { 37 | this.AtEndOfStream = true; 38 | }; 39 | if (data==null) { return ""; }; 40 | return data; 41 | }; 42 | textstream_MT.Write = function(text) { 43 | this.handle:write(text); 44 | }; 45 | textstream_MT.Close = function() { 46 | io.close(this.handle); 47 | }; 48 | 49 | 50 | fso_MT = {}; 51 | fso_MT.OpenTextFile = function(fileName, mode, create) { 52 | var tso = {}; 53 | tso.handle = 0; 54 | tso.size = 0; 55 | tso.AtEndOfStream = false; 56 | 57 | var openMode = "rb"; // default to reading 58 | if (mode == 1) { openMode = "rb"; }; // read in binary mode only 59 | if (mode == 2) { openMode = "wb"; }; // write in binary mode to prevent \n translation 60 | if (mode == 8) { openMode = "ab"; }; 61 | 62 | tso.handle = io.open(fileName, openMode); 63 | if (tso.handle == null) { return null; }; 64 | 65 | this.AtEndOfStream = false; 66 | tso.size = tso.handle:seek("end"); 67 | if (tso.size == 0) { 68 | // if file is zero bytes 69 | tso.AtEndOfStream = true; 70 | }; 71 | tso.handle:seek("set"); 72 | setmetatable(tso, { __index : textstream_MT} ); 73 | return tso; 74 | }; 75 | 76 | function ActiveXObject(application) { 77 | var obj = {}; 78 | 79 | if (application == "Scripting.FileSystemObject") { 80 | setmetatable(obj, {__index : fso_MT } ); 81 | }; 82 | 83 | return obj; 84 | }; 85 | -------------------------------------------------------------------------------- /lib/common.js: -------------------------------------------------------------------------------- 1 | // common functions 2 | 3 | GLOBALVAL=1.23456; 4 | 5 | function isNum(cChar) { 6 | var cc = cChar.charCodeAt(0); 7 | return (cc>47 && cc<58); // (0-9) 8 | }; 9 | 10 | function isAlpha(cChar) { 11 | var cc = cChar.charCodeAt(0); 12 | return ( (cc>64 && cc<91) || // (A-Z) 13 | (cc>96 && cc<123) ); // (a-z) 14 | } 15 | 16 | function noexpr(szString) { 17 | var expr=""; 18 | var i, iLen, cChar; 19 | var escapeChar; 20 | if (isJUALSCRIPT) { escapeChar="%"; } else { escapeChar="\\"; }; 21 | iLen = len(szString); 22 | for (i=0; i ./result/$f"_expect" 18 | ../bin/jual $f "parm 1" parm2 parm3 > ./result/$f"_result" 19 | done 20 | 21 | # Compare results 22 | for f in $FILES 23 | do 24 | RRESULT="FAIL" 25 | diff ./result/$f"_expect" ./result/$f"_result" >/dev/null 2>&1 26 | if [ $? -eq 0 ]; then 27 | RRESULT="PASS" 28 | fi 29 | echo Result: $RRESULT - $f 30 | done 31 | 32 | cd ../ 33 | -------------------------------------------------------------------------------- /runtests_node.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | set NODE_PROGRAM=..\..\node 3 | set TMPRESULT=.\result 4 | cd .\testsuite\ 5 | 6 | echo Clearing Results 7 | rmdir /s /q %TMPRESULT% 8 | ping -n 1 -w 1000 1.2.3.4 >nul: 9 | mkdir %TMPRESULT% 10 | ping -n 1 -w 1000 1.2.3.4 >nul: 11 | echo Running Tests 12 | 13 | for %%f in (*.js) do call ..\jscript %%f "parm 1" parm2 parm3 > %TMPRESULT%\%%f_expect 14 | for %%f in (*.js) do call %NODE_PROGRAM% -r ..\node2jual.js %%f "parm 1" parm2 parm3 > %TMPRESULT%\%%f_result 15 | for %%f in (*.js) do call :CompareResults %%f 16 | 17 | cd ..\ 18 | goto :eof 19 | 20 | :CompareResults 21 | set RRESULT=FAIL 22 | fc %TMPRESULT%\%1_expect %TMPRESULT%\%1_result | find "FC: no differences encountered" > nul: 23 | if %ERRORLEVEL%==0 set RRESULT=PASS 24 | echo Result: %RRESULT% - %1 25 | goto:eof 26 | -------------------------------------------------------------------------------- /runtests_wsh.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | set TMPRESULT=.\result 3 | cd .\testsuite\ 4 | 5 | echo Clearing Results 6 | rmdir /s /q %TMPRESULT% 7 | ping -n 1 -w 1000 1.2.3.4 >nul: 8 | mkdir %TMPRESULT% 9 | ping -n 1 -w 1000 1.2.3.4 >nul: 10 | echo Running Tests 11 | 12 | for %%f in (*.js) do call ..\jscript %%f "parm 1" parm2 parm3 > %TMPRESULT%\%%f_expect 13 | for %%f in (*.js) do call ..\bin\jual %%f "parm 1" parm2 parm3 > %TMPRESULT%\%%f_result 14 | for %%f in (*.js) do call :CompareResults %%f 15 | 16 | cd ..\ 17 | goto :eof 18 | 19 | :CompareResults 20 | set RRESULT=FAIL 21 | fc %TMPRESULT%\%1_expect %TMPRESULT%\%1_result | find "FC: no differences encountered" > nul: 22 | if %ERRORLEVEL%==0 set RRESULT=PASS 23 | echo Result: %RRESULT% - %1 24 | goto:eof 25 | -------------------------------------------------------------------------------- /samples/echo-client.js: -------------------------------------------------------------------------------- 1 | require_n("libinet"); 2 | 3 | var tc = TCPClient("localhost", 1122, 5000); 4 | 5 | if (tc != null) { 6 | 7 | var szLine = TCPReadLine(tc); 8 | if (szLine != null) { print(szLine); } 9 | 10 | TCPWrite(tc, "GET /test.txt\r\n"); 11 | szLine = TCPReadLine(tc); 12 | if (szLine != null) { print(szLine); } 13 | 14 | TCPWrite(tc, "POST /serverhandler\r\n"); 15 | szLine = TCPReadLine(tc); 16 | if (szLine != null) { print(szLine); } 17 | 18 | TCPWrite(tc, "quit\r\n"); 19 | 20 | TCPClose(tc); 21 | }; 22 | -------------------------------------------------------------------------------- /samples/echo-server.js: -------------------------------------------------------------------------------- 1 | require_n("libinet"); 2 | 3 | var ts = TCPServer("localhost", 1122, 5000); 4 | if (ts == null) { os.exit() }; 5 | 6 | var szOutput; 7 | var blServerRunning = true; 8 | while (blServerRunning) { 9 | print( "Listening on localhost port 81 for connections" ); 10 | var tc = TCPAccept(ts); 11 | 12 | print( "Connection established" ); 13 | if (tc != null) { 14 | TCPWrite(tc, "Welcome to the echo server! \r\n"); 15 | while (true) { 16 | var szLine = TCPReadLine(tc); 17 | if (szLine != null) { 18 | if (szLine == "close") { 19 | break; 20 | } else if (szLine == "quit") { 21 | blServerRunning = false; 22 | break; 23 | } else { 24 | szOutput = "" + szLine + "\r\n"; 25 | TCPWrite(tc, szOutput); 26 | print("Client wrote " + szLine.size() + "bytes(s) " + szOutput); 27 | }; 28 | }; 29 | }; 30 | 31 | print( "Connection closed." ); 32 | 33 | TCPClose(tc); 34 | }; 35 | }; 36 | 37 | TCPClose(ts); 38 | -------------------------------------------------------------------------------- /samples/example_array_cons.js: -------------------------------------------------------------------------------- 1 | var t=["one", "two", "three"]; 2 | var x=["four", "five", "six", "seven", "eight", [1,2,3], "nine" ]; 3 | print( x[5][1] ); 4 | 5 | var obj = { 2:"fire", one:"1", two:"2", three:65, "good":true, 7.5:"yes" }; 6 | var obj2 = { "good":true, "times":{3:"e", 5:"r"} }; 7 | 8 | print( obj[2] ); 9 | print( obj.one ); 10 | print( obj.two ); 11 | print( obj.three ); 12 | print( obj.good ); 13 | print( obj[7.5] ); 14 | 15 | // var y = {"one", fire:1, water:2 }; 16 | /* 17 | for (keys in y) { 18 | print(keys + " " + y[keys]); 19 | } 20 | 21 | print( y.join(" ")); 22 | */ -------------------------------------------------------------------------------- /samples/example_method_calls.js: -------------------------------------------------------------------------------- 1 | 2 | // This file demonstrates the use of object oriented methods in both JualScript 3 | // and JavaScript. It shows how an object can be defined that will produce the same 4 | // results in both languages 5 | 6 | // functions declared via a statment like this are unchanged 7 | function walk(distance) { 8 | print( "Someone will walk " + distance + " miles" ); 9 | } 10 | walk(200); 11 | 12 | 13 | var person = {}; 14 | person.name = "John"; 15 | 16 | // functions declared via assignment have a hidden 'this' 17 | // parameter passed as the first parameter 18 | person.drive = function(/* this, */ colour, car) { 19 | print( this.name + " is now driving his " + colour + " " + car ); 20 | } 21 | // functions called with the dot notation will automatically have the 22 | // function converted to a method call with the preceeding object passed as the first parameter 23 | // The method call below will result in the same ouput in JualScript and JavaScript 24 | person.drive( /* person, */ "purple", "porsche"); 25 | 26 | 27 | // If you would like to declare the method separately, this is the correct way 28 | // to separately declare a method for an object 29 | person_run = function(distance) { 30 | print( this.name + " will run " + distance + " miles" ); 31 | } 32 | person.run = person_run; 33 | // The method call below will result in the same ouput in JualScript and JavaScript 34 | person.run(500); 35 | 36 | 37 | // Do not declare a method for an object via a the function statement 38 | // You will manually need to include the object as the first parameter 39 | // However, this will break compatibility with JavaScript, because the first parameter 40 | // can not be named 'this', therefore it will be undefined in JavaScript. 41 | function person_walk(who, distance) { 42 | print( who.name + " will walk " + distance + " miles" ); 43 | } 44 | person.walk = person_walk; 45 | 46 | // The method call below will result in different ouput in JualScript and JavaScript 47 | person.walk(500); 48 | -------------------------------------------------------------------------------- /samples/example_ternary_op.js: -------------------------------------------------------------------------------- 1 | // Testing simulation of ternary operator with logical AND + OR operators 2 | 3 | var condition, j, t 4 | 5 | condition=true; 6 | t=(condition && [false] || [true])[0]; 7 | print(t); 8 | 9 | condition=false; 10 | var j=(condition && [false] || [true])[0]; 11 | print(j); 12 | 13 | 14 | condition=true; 15 | t=(condition && "fire" || "water"); 16 | print(t); 17 | 18 | condition=false; 19 | j=(condition && "fire" || "water"); 20 | print(j); 21 | 22 | j = (["peter","paul"])[1]; 23 | print(j); -------------------------------------------------------------------------------- /samples/test_activex_fso.js: -------------------------------------------------------------------------------- 1 | // The JualScript engine can now simulate JScript Scripting.FileSystemObject object! 2 | 3 | var file ="test17a.txt"; 4 | 5 | if (isJUALSCRIPT) { 6 | eval( includeJS("../lib/activex_fso.js") ); 7 | file ="test17b.txt"; 8 | }; 9 | 10 | var fso = new ActiveXObject("Scripting.FileSystemObject"); 11 | 12 | 13 | // test creation of file 14 | var wf = fso.OpenTextFile(file, 2, true); 15 | wf.Write("This is the contents of the test file\n"); 16 | wf.Write("It should be in plain ASCII format\n"); 17 | wf.Close(); 18 | wf = null; 19 | 20 | // test reading file 21 | var rf = fso.OpenTextFile(file, 1); 22 | var contents=""; 23 | while (!rf.AtEndOfStream) { 24 | contents = contents + rf.ReadLine() + "\n"; 25 | }; 26 | rf.Close(); 27 | rf = null; 28 | print(contents); 29 | -------------------------------------------------------------------------------- /samples/test_concat.js: -------------------------------------------------------------------------------- 1 | var iList = "0"; 2 | for (i=1; i<10; i=i+1) { 3 | iList = iList + " " + i; 4 | }; 5 | print(iList); 6 | 7 | iList = "*"; 8 | for (i=1; i<10; i=i+1) { 9 | iList = iList + " " + i; 10 | }; 11 | print(iList); -------------------------------------------------------------------------------- /samples/test_console.js: -------------------------------------------------------------------------------- 1 | print("What is your name?"); 2 | var szInput = io.read(); 3 | print("Pleased to meet you " + szInput); 4 | -------------------------------------------------------------------------------- /samples/test_coroutines.js: -------------------------------------------------------------------------------- 1 | // Testing co-routines in JualScript 2 | // translated from http://lua-users.org/wiki/CoroutinesTutorial 3 | 4 | function odd(x) { 5 | print('A: odd', x); 6 | coroutine.yield(x); 7 | print('B: odd', x); 8 | } 9 | 10 | function even(x) { 11 | print('C: even', x); 12 | if (x==2) { return x }; 13 | print('D: even ', x); 14 | } 15 | 16 | function cro(x) { 17 | for (i=1; i<=x; i=i+1) { 18 | if (i==3) { coroutine.yield(-1); }; 19 | if (i % 2 == 0) { even(i); } else { odd(i); }; 20 | }; 21 | } 22 | co = coroutine.create(cro) 23 | 24 | var count = 1 25 | while (coroutine.status(co) != 'dead') { 26 | print('----', count) ; count = count+1; 27 | errorfree, value = coroutine.resume(co, 5); 28 | print('E: errorfree, value, status', errorfree, value, coroutine.status(co)); 29 | }; 30 | -------------------------------------------------------------------------------- /samples/test_fileio.js: -------------------------------------------------------------------------------- 1 | 2 | var szMyFileName = "testfile.txt"; 3 | 4 | // Create a text file 5 | var hFile = io.open(szMyFileName, "w"); 6 | if (hFile == null) { return; }; 7 | 8 | var j=0; 9 | var szLine; 10 | while (j<15) { 11 | szLine = "This is line number" + j + "\n"; 12 | io.writebyte(hFile, szLine); 13 | j+=1; 14 | } 15 | io.close(hFile); 16 | 17 | 18 | // Read a text file 19 | var hFileIn = io.open(szMyFileName, "r"); 20 | 21 | szLine = io.readline(hFileIn); 22 | while (szLine != null) { 23 | print(szLine); 24 | szLine = io.readline(hFileIn); 25 | } 26 | io.close(hFileIn); 27 | 28 | 29 | // Create a binary file 30 | var hBinWrite = io.open("myfile.bin", "w"); 31 | if (hBinWrite == null) { return; }; 32 | 33 | var j=0; 34 | var aChars=[]; 35 | while (j<256) { 36 | aChars[j] = String.fromCharCode(j); 37 | j+=1; 38 | }; 39 | szLine = aChars.join(); 40 | io.writebyte(hBinWrite, szLine); 41 | io.seek(hBinWrite,0x31); 42 | io.writebyte(hBinWrite, String.fromCharCode(0xFF) ); 43 | io.close(hBinWrite); 44 | 45 | 46 | // Read a binary file 47 | var hBinRead = io.open("myfile.bin", "rb"); 48 | if (hBinRead == null) { return; }; 49 | io.seek(hBinRead, 0x31); 50 | szLine = io.readbyte(hBinRead, 10); 51 | io.close(hBinRead); 52 | print(szLine); 53 | -------------------------------------------------------------------------------- /samples/test_gotostat.js: -------------------------------------------------------------------------------- 1 | var iDoTimes=5; 2 | goto HERE; 3 | 4 | ::THERE:: 5 | print("I got there"); 6 | goto EVERYWHERE; 7 | 8 | ::HERE:: 9 | print("I got here"); 10 | iDoTimes = iDoTimes - 1; 11 | if (iDoTimes > 0) { goto HERE; }; 12 | goto THERE; 13 | 14 | ::EVERYWHERE:: 15 | print("I got everywhere!"); 16 | -------------------------------------------------------------------------------- /samples/test_pairs.js: -------------------------------------------------------------------------------- 1 | var mya={}; 2 | mya.a = "alpha"; 3 | mya.s = "beta"; 4 | mya.c = "cappa"; 5 | mya.d = "delta"; 6 | mya.e = "epsilon"; 7 | mya.f = "feta"; 8 | mya.g = "gamma"; 9 | 10 | var iary = [ "apple", "orange", "pears", "bananas"]; 11 | 12 | for (key in mya) { 13 | print(key + " " + mya[key]); 14 | }; 15 | 16 | print(mya["a"]); 17 | 18 | // the next two loops does not work under JavaScript 19 | 20 | for (key,ival in pairs(mya)) { 21 | print(key + " " + ival); 22 | }; 23 | 24 | print(""); 25 | 26 | for (key,ival in ipairs(iary)) { 27 | print(key + " " + ival); 28 | }; 29 | -------------------------------------------------------------------------------- /samples/test_sort.js: -------------------------------------------------------------------------------- 1 | // From http://rosettacode.org/wiki/Sorting_algorithms/Heapsort#Javascript 2 | 3 | function swap(data, i, j) { 4 | var tmp = data[i]; 5 | data[i] = data[j]; 6 | data[j] = tmp; 7 | } 8 | 9 | function heap_sort(arr) { 10 | put_array_in_heap_order(arr); 11 | end = arr.size() - 1; 12 | while(end > 0) { 13 | swap(arr, 0, end); 14 | sift_element_down_heap(arr, 0, end); 15 | end = end-1; 16 | } 17 | } 18 | 19 | function put_array_in_heap_order(arr) { 20 | var i; 21 | i = arr.size() / 2 - 1; 22 | i = Math.floor(i); 23 | while (i >= 0) { 24 | sift_element_down_heap(arr, i, arr.size()); 25 | i = i-1; 26 | } 27 | } 28 | 29 | function sift_element_down_heap(heap, i, max) { 30 | var i_big, c1, c2; 31 | while(i < max) { 32 | i_big = i; 33 | c1 = 2*i + 1; 34 | c2 = c1 + 1; 35 | if (c1 < max && heap[c1] > heap[i_big]) { 36 | i_big = c1; 37 | }; 38 | if (c2 < max && heap[c2] > heap[i_big]) { 39 | i_big = c2; 40 | } 41 | if (i_big == i) { return; }; 42 | swap(heap,i, i_big); 43 | i = i_big; 44 | } 45 | } 46 | 47 | function GenerateArray() { 48 | var iLen=1000; 49 | var out= new Array(); 50 | for (i=0; i 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define IP4STR_SIZE 16 17 | #define SOCKET_LINECACHE_MAX 256 18 | #define MAX_CONNECTIONS 128 19 | 20 | #ifndef TRUE 21 | #define TRUE 1 22 | #endif 23 | 24 | #ifndef FALSE 25 | #define FALSE 0 26 | #endif 27 | 28 | 29 | typedef struct tcp_socket_ { 30 | int ip[4]; 31 | int port; 32 | int cacheUsed; 33 | int cacheStart; 34 | char cacheLine[SOCKET_LINECACHE_MAX]; 35 | // OS_specific struct goes here 36 | int sock; 37 | } tcp_socket; 38 | 39 | 40 | IP4INT ResolveHostIP(const char *hostAddress) { 41 | struct addrinfo hints; 42 | struct addrinfo *result = NULL; 43 | struct addrinfo *ptr = NULL; 44 | 45 | memset( &hints, 0, sizeof(hints) ); 46 | hints.ai_family = AF_UNSPEC; 47 | hints.ai_socktype = SOCK_STREAM; 48 | hints.ai_protocol = IPPROTO_TCP; 49 | 50 | // Resolve the server address and port 51 | int iResult = getaddrinfo(hostAddress, "80", &hints, &result); 52 | if ( iResult != 0 ) { 53 | return 0; 54 | }; 55 | 56 | struct sockaddr_in *sin; 57 | IP4INT IP4Result; 58 | for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { 59 | if (ptr->ai_family == AF_INET) { 60 | sin = (struct sockaddr_in *)ptr->ai_addr; 61 | IP4Result = sin->sin_addr.s_addr; 62 | freeaddrinfo(result); 63 | return IP4Result; 64 | }; 65 | }; 66 | 67 | freeaddrinfo(result); 68 | return 0; 69 | } 70 | 71 | 72 | tcp_socket *TCPClient(tcp_socket *ts, const char *address, int port, int timeout) { 73 | 74 | IP4INT testIP; 75 | testIP = isIPString(address); 76 | if (testIP == 0) { 77 | testIP = ResolveHostIP(address); 78 | if (testIP == 0) return NULL; 79 | }; 80 | 81 | ts->sock = socket( AF_INET, SOCK_STREAM, 0 ); 82 | 83 | if (ts->sock < 0) return NULL; 84 | 85 | ip4toarray(ts->ip, testIP); 86 | ts->cacheUsed = 0; 87 | ts->cacheStart = 0; 88 | 89 | struct sockaddr_in sin; 90 | memset( &sin, 0, sizeof(sin)); 91 | 92 | sin.sin_family = AF_INET; 93 | sin.sin_addr.s_addr = testIP; 94 | sin.sin_port = htons( port ); 95 | 96 | if (connect(ts->sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 97 | close (ts->sock); 98 | return NULL; 99 | }; 100 | 101 | return ts; 102 | } 103 | 104 | 105 | tcp_socket *TCPServer(tcp_socket *ts, const char *address, int port, int timeout, void *onConnection) { 106 | IP4INT testIP; 107 | 108 | // Assuming address is at least one terminated character 109 | // check for special case of listening to any address 110 | if (address[0] == '*' && address[1] == '\0') { 111 | testIP = INADDR_ANY; 112 | } else { 113 | 114 | testIP = isIPString(address); 115 | if (testIP == 0) { 116 | testIP = ResolveHostIP(address); 117 | if (testIP == 0) return NULL; 118 | }; 119 | }; 120 | 121 | ts->sock = socket( AF_INET, SOCK_STREAM, 0 ); 122 | 123 | if (ts->sock < 0) return NULL; 124 | 125 | ip4toarray(ts->ip, testIP); 126 | ts->cacheUsed = 0; 127 | ts->cacheStart = 0; 128 | 129 | struct sockaddr_in sin; 130 | memset( &sin, 0, sizeof(sin)); 131 | 132 | sin.sin_family = AF_INET; 133 | sin.sin_addr.s_addr = testIP; 134 | sin.sin_port = htons( port ); 135 | 136 | if (bind(ts->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { 137 | // could not bind - port may be in use 138 | return NULL; 139 | }; 140 | 141 | // parm2 default SOMAXCONN 142 | if (listen(ts->sock, MAX_CONNECTIONS) < 0) { 143 | // could not listen - port may be in use 144 | return NULL; 145 | }; 146 | 147 | return ts; 148 | } 149 | 150 | 151 | tcp_socket *TCPAccept(tcp_socket *ts, tcp_socket *tc) { 152 | // this call is blocking ... 153 | struct sockaddr_in client_info; 154 | int size = sizeof(client_info); 155 | 156 | int ClientSocket = accept(ts->sock, (struct sockaddr *)&client_info, &size); 157 | 158 | if (ClientSocket < 0) { 159 | close(ts->sock); 160 | return NULL; 161 | } 162 | 163 | tc->sock = ClientSocket; 164 | ip4toarray(tc->ip, client_info.sin_addr.s_addr); 165 | tc->cacheUsed = 0; 166 | tc->cacheStart = 0; 167 | 168 | return tc; 169 | } 170 | 171 | 172 | int TCPWrite(tcp_socket *ts, const char *buffer, int bufferSize) { 173 | int iResult = send( ts->sock, buffer, bufferSize, 0 ); 174 | if (iResult != bufferSize) { 175 | // printf("send failed: %d\n", WSAGetLastError()); 176 | close( ts->sock ); 177 | return FALSE; 178 | } 179 | 180 | return TRUE; 181 | } 182 | 183 | 184 | // result < 0 = error 185 | // result = 0 = socket closed 186 | // result > 0 = number of bytes read 187 | int TCPRead(tcp_socket *ts, char *buffer, int bufferSize) { 188 | int iResult = recv( ts->sock, buffer, bufferSize, 0); 189 | return iResult; 190 | } 191 | 192 | // return number of characters in line. zero is a valid response i.e empty line 193 | // errors return negative results 194 | int TCPReadLine(tcp_socket *ts, char *buffer, int bufferSize) { 195 | char *cache = ts->cacheLine; 196 | int iRead = 0; 197 | 198 | if (bufferSize > 0) buffer[0] = '\0'; 199 | 200 | // if cache is free read more data 201 | if (ts->cacheUsed == 0) { 202 | ts->cacheStart = 0; 203 | iRead = TCPRead(ts, cache, SOCKET_LINECACHE_MAX-1); 204 | if (iRead < 0) return iRead; 205 | if (iRead == 0) return -1; 206 | 207 | ts->cacheUsed = iRead; 208 | }; 209 | 210 | // Copy cache to output buffer filling cache again if required. 211 | int i, k; 212 | k = ts->cacheStart; 213 | for (i=0; icacheUsed--; 216 | if (ts->cacheUsed == 0) { 217 | ts->cacheStart = 0; 218 | } else { 219 | ts->cacheStart = k+1; 220 | }; 221 | buffer[i] = '\0'; 222 | return i; 223 | } else { 224 | buffer[i] = cache[k]; 225 | if (cache[k] == '\r') i--; 226 | ts->cacheUsed--; 227 | k++; 228 | if (ts->cacheUsed == 0) { 229 | ts->cacheStart = 0; 230 | k=0; 231 | iRead = TCPRead(ts, cache, SOCKET_LINECACHE_MAX-1); 232 | if (iRead <= 0) { 233 | buffer[i+1] = '\0'; 234 | if (iRead < 0) return iRead; 235 | if (iRead == 0) return i; 236 | }; 237 | ts->cacheUsed = iRead; 238 | }; 239 | }; 240 | }; 241 | ts->cacheStart = k; 242 | 243 | // reached buffer size - terminate string and return content so far 244 | buffer[bufferSize-1] = '\0'; 245 | return bufferSize-1; 246 | } 247 | 248 | void TCPClose(tcp_socket *ts) { 249 | close( ts->sock ); 250 | } 251 | -------------------------------------------------------------------------------- /src/inet/inet_win32.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Sajon Oso 3 | Jual Native C module - Internet Protocol Suite 4 | Currently only implements IPv4 socket functions 5 | Windows Specific functions 6 | */ 7 | 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define IP4STR_SIZE 16 16 | #define SOCKET_LINECACHE_MAX 256 17 | #define MAX_CONNECTIONS 128 18 | 19 | 20 | typedef struct tcp_socket_ { 21 | int ip[4]; 22 | int port; 23 | int cacheUsed; 24 | int cacheStart; 25 | char cacheLine[SOCKET_LINECACHE_MAX]; 26 | // OS_specific struct goes here 27 | SOCKET sock; 28 | } tcp_socket; 29 | 30 | 31 | static int WSAInitilized = 0x00; 32 | 33 | int WSAInit() { 34 | WSADATA wsaData; 35 | return (0 == WSAStartup(MAKEWORD(2,2), &wsaData)); 36 | } 37 | 38 | 39 | IP4INT ResolveHostIP(const char *hostAddress) { 40 | struct addrinfo hints; 41 | struct addrinfo *result = NULL; 42 | struct addrinfo *ptr = NULL; 43 | 44 | ZeroMemory( &hints, sizeof(hints) ); 45 | hints.ai_family = AF_UNSPEC; 46 | hints.ai_socktype = SOCK_STREAM; 47 | hints.ai_protocol = IPPROTO_TCP; 48 | 49 | // Resolve the server address and port 50 | int iResult = getaddrinfo(hostAddress, "80", &hints, &result); 51 | if ( iResult != 0 ) { 52 | // printf("getaddrinfo failed with error: %d\n", iResult); 53 | WSACleanup(); 54 | return 0; 55 | }; 56 | 57 | struct sockaddr_in *sin; 58 | for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { 59 | if (ptr->ai_family == AF_INET) { 60 | sin = (struct sockaddr_in *)ptr->ai_addr; 61 | return sin->sin_addr.s_addr; 62 | }; 63 | }; 64 | 65 | return 0; 66 | } 67 | 68 | 69 | tcp_socket *TCPClient(tcp_socket *ts, const char *address, int port, int timeout) { 70 | int initState; 71 | if (!WSAInitilized) initState = WSAInit(); 72 | if (!initState) return NULL; 73 | 74 | IP4INT testIP; 75 | testIP = isIPString(address); 76 | if (testIP == 0) { 77 | testIP = ResolveHostIP(address); 78 | if (testIP == 0) return NULL; 79 | }; 80 | 81 | ts->sock = socket( AF_INET, SOCK_STREAM, 0 ); 82 | ip4toarray(ts->ip, testIP); 83 | ts->cacheUsed = 0; 84 | ts->cacheStart = 0; 85 | 86 | struct sockaddr_in sin; 87 | memset( &sin, 0, sizeof(sin)); 88 | 89 | sin.sin_family = AF_INET; 90 | sin.sin_addr.s_addr = testIP; 91 | sin.sin_port = htons( port ); 92 | 93 | if (connect(ts->sock, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) { 94 | return NULL; 95 | WSACleanup(); 96 | }; 97 | 98 | return ts; 99 | } 100 | 101 | 102 | tcp_socket *TCPServer(tcp_socket *ts, const char *address, int port, int timeout, void *onConnection) { 103 | int initState; 104 | if (!WSAInitilized) initState = WSAInit(); 105 | if (!initState) return NULL; 106 | 107 | IP4INT testIP; 108 | 109 | // Assuming address is at least one terminated character 110 | // check for special case of listening to any address 111 | if (address[0] == '*' && address[1] == '\0') { 112 | testIP = INADDR_ANY; 113 | } else { 114 | 115 | testIP = isIPString(address); 116 | if (testIP == 0) { 117 | testIP = ResolveHostIP(address); 118 | if (testIP == 0) return NULL; 119 | }; 120 | }; 121 | 122 | ts->sock = socket( AF_INET, SOCK_STREAM, 0 ); 123 | ip4toarray(ts->ip, testIP); 124 | ts->cacheUsed = 0; 125 | ts->cacheStart = 0; 126 | 127 | struct sockaddr_in sin; 128 | memset( &sin, 0, sizeof(sin)); 129 | 130 | sin.sin_family = AF_INET; 131 | sin.sin_addr.s_addr = testIP; 132 | sin.sin_port = htons( port ); 133 | 134 | if (bind(ts->sock, (SOCKADDR *) &sin, sizeof(sin)) == SOCKET_ERROR) { 135 | // could not bind - port may be in use 136 | WSACleanup(); 137 | return NULL; 138 | }; 139 | 140 | // parm2 default SOMAXCONN 141 | if (listen(ts->sock, MAX_CONNECTIONS) == SOCKET_ERROR) { 142 | // could not listen - port may be in use 143 | WSACleanup(); 144 | return NULL; 145 | }; 146 | 147 | return ts; 148 | } 149 | 150 | 151 | tcp_socket *TCPAccept(tcp_socket *ts, tcp_socket *tc) { 152 | // this call is blocking ... 153 | struct sockaddr_in client_info; 154 | int size = sizeof(client_info); 155 | 156 | SOCKET ClientSocket = accept(ts->sock, (struct sockaddr *)&client_info, &size); 157 | 158 | if (ClientSocket == INVALID_SOCKET) { 159 | // printf("accept failed with error: %d\n", WSAGetLastError()); 160 | closesocket(ts->sock); 161 | WSACleanup(); 162 | return NULL; 163 | } 164 | 165 | tc->sock = ClientSocket; 166 | ip4toarray(tc->ip, client_info.sin_addr.s_addr); 167 | tc->cacheUsed = 0; 168 | tc->cacheStart = 0; 169 | 170 | return tc; 171 | } 172 | 173 | 174 | int TCPWrite(tcp_socket *ts, const char *buffer, int bufferSize) { 175 | int iResult = send( ts->sock, buffer, bufferSize, 0 ); 176 | if (iResult == SOCKET_ERROR) { 177 | // printf("send failed: %d\n", WSAGetLastError()); 178 | closesocket( ts->sock ); 179 | WSACleanup(); 180 | return FALSE; 181 | } 182 | 183 | return TRUE; 184 | } 185 | 186 | 187 | // result < 0 = error 188 | // result = 0 = socket closed 189 | // result > 0 = number of bytes read 190 | int TCPRead(tcp_socket *ts, char *buffer, int bufferSize) { 191 | int iResult = recv( ts->sock, buffer, bufferSize, 0); 192 | return iResult; 193 | } 194 | 195 | // return number of characters in line. zero is a valid response i.e empty line 196 | // errors return negative results 197 | int TCPReadLine(tcp_socket *ts, char *buffer, int bufferSize) { 198 | char *cache = ts->cacheLine; 199 | int iRead = 0; 200 | 201 | if (bufferSize > 0) buffer[0] = '\0'; 202 | 203 | // if cache is free read more data 204 | if (ts->cacheUsed == 0) { 205 | ts->cacheStart = 0; 206 | iRead = TCPRead(ts, cache, SOCKET_LINECACHE_MAX-1); 207 | if (iRead < 0) return iRead; 208 | if (iRead == 0) return -1; 209 | 210 | ts->cacheUsed = iRead; 211 | }; 212 | 213 | // Copy cache to output buffer filling cache again if required. 214 | int i, k; 215 | k = ts->cacheStart; 216 | for (i=0; icacheUsed--; 219 | if (ts->cacheUsed == 0) { 220 | ts->cacheStart = 0; 221 | } else { 222 | ts->cacheStart = k+1; 223 | }; 224 | buffer[i] = '\0'; 225 | return i; 226 | } else { 227 | buffer[i] = cache[k]; 228 | if (cache[k] == '\r') i--; 229 | ts->cacheUsed--; 230 | k++; 231 | if (ts->cacheUsed == 0) { 232 | ts->cacheStart = 0; 233 | k=0; 234 | iRead = TCPRead(ts, cache, SOCKET_LINECACHE_MAX-1); 235 | if (iRead <= 0) { 236 | buffer[i+1] = '\0'; 237 | if (iRead < 0) return iRead; 238 | if (iRead == 0) return i; 239 | }; 240 | ts->cacheUsed = iRead; 241 | }; 242 | }; 243 | }; 244 | ts->cacheStart = k; 245 | 246 | // reached buffer size - terminate string and return content so far 247 | buffer[bufferSize-1] = '\0'; 248 | return bufferSize-1; 249 | } 250 | 251 | void TCPClose(tcp_socket *ts) { 252 | closesocket( ts->sock ); 253 | } 254 | -------------------------------------------------------------------------------- /src/inet/jxapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jual Native C module API interface 3 | 4 | This is the only file you need to include in your module file to interface with the jual module system 5 | */ 6 | 7 | typedef struct usrObject { 8 | size_t size; // Variable data size 9 | void *ptr; // Generic pointer 10 | unsigned char values[1]; // Variable data 11 | } usrObject; 12 | 13 | typedef struct jual_xapi_ { 14 | int STRBUFFER_SIZE; 15 | void *LS; 16 | void *fnGetNumber; 17 | void *fnGetString; 18 | void *fnGetObject; 19 | void *fnNumberPush; 20 | void *fnStrInit; 21 | void *fnStrAppend; 22 | void *fnStrPush; 23 | } jual_xapi; 24 | 25 | typedef int defGetNumber(void *LS, int argnum); 26 | typedef const char *defGetString(void *LS, int argnum, size_t *tSize); 27 | typedef void *defGetObject(void *LS, int argnum); 28 | typedef void defNumberPush(void *LS, int iValue); 29 | typedef char *defStrInit(void *LS, void *strBuf, size_t tSize); 30 | typedef void defStrAppend(void *strBuf, const char *szValue, size_t tSize); 31 | typedef void defStrPush(void *strBuf); 32 | 33 | 34 | /* 35 | 36 | Your exported C functions should look something like this: 37 | 38 | int myfunc(jual_xapi *JXAPI) 39 | { 40 | void *L = JXAPI->LS; 41 | // Map functions as required 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 44 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 45 | 46 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 47 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 48 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 49 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 50 | 51 | int iArgument1 = GetNumber(L, 1); 52 | 53 | NumberPush(L, 123456789); 54 | return 1; // always 1 to indicate number of variables returned or 0 if returning nothing. 55 | }; 56 | */ 57 | -------------------------------------------------------------------------------- /src/lapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $ 3 | ** Auxiliary functions from Lua API 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lapi_h 8 | #define lapi_h 9 | 10 | 11 | #include "llimits.h" 12 | #include "lstate.h" 13 | 14 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ 15 | "stack overflow");} 16 | 17 | #define adjustresults(L,nres) \ 18 | { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } 19 | 20 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ 21 | "not enough elements in the stack") 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lbitlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 roberto Exp $ 3 | ** Standard library for bitwise operations 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lbitlib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lua.h" 14 | 15 | #include "lauxlib.h" 16 | #include "lualib.h" 17 | 18 | 19 | #if defined(LUA_COMPAT_BITLIB) /* { */ 20 | 21 | 22 | /* number of bits to consider in a number */ 23 | #if !defined(LUA_NBITS) 24 | #define LUA_NBITS 32 25 | #endif 26 | 27 | 28 | /* 29 | ** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must 30 | ** be made in two parts to avoid problems when LUA_NBITS is equal to the 31 | ** number of bits in a lua_Unsigned.) 32 | */ 33 | #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) 34 | 35 | 36 | /* macro to trim extra bits */ 37 | #define trim(x) ((x) & ALLONES) 38 | 39 | 40 | /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ 41 | #define mask(n) (~((ALLONES << 1) << ((n) - 1))) 42 | 43 | 44 | 45 | static lua_Unsigned andaux (lua_State *L) { 46 | int i, n = lua_gettop(L); 47 | lua_Unsigned r = ~(lua_Unsigned)0; 48 | for (i = 1; i <= n; i++) 49 | r &= luaL_checkunsigned(L, i); 50 | return trim(r); 51 | } 52 | 53 | 54 | static int b_and (lua_State *L) { 55 | lua_Unsigned r = andaux(L); 56 | lua_pushunsigned(L, r); 57 | return 1; 58 | } 59 | 60 | 61 | static int b_test (lua_State *L) { 62 | lua_Unsigned r = andaux(L); 63 | lua_pushboolean(L, r != 0); 64 | return 1; 65 | } 66 | 67 | 68 | static int b_or (lua_State *L) { 69 | int i, n = lua_gettop(L); 70 | lua_Unsigned r = 0; 71 | for (i = 1; i <= n; i++) 72 | r |= luaL_checkunsigned(L, i); 73 | lua_pushunsigned(L, trim(r)); 74 | return 1; 75 | } 76 | 77 | 78 | static int b_xor (lua_State *L) { 79 | int i, n = lua_gettop(L); 80 | lua_Unsigned r = 0; 81 | for (i = 1; i <= n; i++) 82 | r ^= luaL_checkunsigned(L, i); 83 | lua_pushunsigned(L, trim(r)); 84 | return 1; 85 | } 86 | 87 | 88 | static int b_not (lua_State *L) { 89 | lua_Unsigned r = ~luaL_checkunsigned(L, 1); 90 | lua_pushunsigned(L, trim(r)); 91 | return 1; 92 | } 93 | 94 | 95 | static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { 96 | if (i < 0) { /* shift right? */ 97 | i = -i; 98 | r = trim(r); 99 | if (i >= LUA_NBITS) r = 0; 100 | else r >>= i; 101 | } 102 | else { /* shift left */ 103 | if (i >= LUA_NBITS) r = 0; 104 | else r <<= i; 105 | r = trim(r); 106 | } 107 | lua_pushunsigned(L, r); 108 | return 1; 109 | } 110 | 111 | 112 | static int b_lshift (lua_State *L) { 113 | return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2)); 114 | } 115 | 116 | 117 | static int b_rshift (lua_State *L) { 118 | return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2)); 119 | } 120 | 121 | 122 | static int b_arshift (lua_State *L) { 123 | lua_Unsigned r = luaL_checkunsigned(L, 1); 124 | lua_Integer i = luaL_checkinteger(L, 2); 125 | if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) 126 | return b_shift(L, r, -i); 127 | else { /* arithmetic shift for 'negative' number */ 128 | if (i >= LUA_NBITS) r = ALLONES; 129 | else 130 | r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ 131 | lua_pushunsigned(L, r); 132 | return 1; 133 | } 134 | } 135 | 136 | 137 | static int b_rot (lua_State *L, lua_Integer d) { 138 | lua_Unsigned r = luaL_checkunsigned(L, 1); 139 | int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ 140 | r = trim(r); 141 | if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ 142 | r = (r << i) | (r >> (LUA_NBITS - i)); 143 | lua_pushunsigned(L, trim(r)); 144 | return 1; 145 | } 146 | 147 | 148 | static int b_lrot (lua_State *L) { 149 | return b_rot(L, luaL_checkinteger(L, 2)); 150 | } 151 | 152 | 153 | static int b_rrot (lua_State *L) { 154 | return b_rot(L, -luaL_checkinteger(L, 2)); 155 | } 156 | 157 | 158 | /* 159 | ** get field and width arguments for field-manipulation functions, 160 | ** checking whether they are valid. 161 | ** ('luaL_error' called without 'return' to avoid later warnings about 162 | ** 'width' being used uninitialized.) 163 | */ 164 | static int fieldargs (lua_State *L, int farg, int *width) { 165 | lua_Integer f = luaL_checkinteger(L, farg); 166 | lua_Integer w = luaL_optinteger(L, farg + 1, 1); 167 | luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); 168 | luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); 169 | if (f + w > LUA_NBITS) 170 | luaL_error(L, "trying to access non-existent bits"); 171 | *width = (int)w; 172 | return (int)f; 173 | } 174 | 175 | 176 | static int b_extract (lua_State *L) { 177 | int w; 178 | lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); 179 | int f = fieldargs(L, 2, &w); 180 | r = (r >> f) & mask(w); 181 | lua_pushunsigned(L, r); 182 | return 1; 183 | } 184 | 185 | 186 | static int b_replace (lua_State *L) { 187 | int w; 188 | lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); 189 | lua_Unsigned v = luaL_checkunsigned(L, 2); 190 | int f = fieldargs(L, 3, &w); 191 | int m = mask(w); 192 | v &= m; /* erase bits outside given width */ 193 | r = (r & ~(m << f)) | (v << f); 194 | lua_pushunsigned(L, r); 195 | return 1; 196 | } 197 | 198 | 199 | static const luaL_Reg bitlib[] = { 200 | {"arshift", b_arshift}, 201 | {"band", b_and}, 202 | {"bnot", b_not}, 203 | {"bor", b_or}, 204 | {"bxor", b_xor}, 205 | {"btest", b_test}, 206 | {"extract", b_extract}, 207 | {"lrotate", b_lrot}, 208 | {"lshift", b_lshift}, 209 | {"replace", b_replace}, 210 | {"rrotate", b_rrot}, 211 | {"rshift", b_rshift}, 212 | {NULL, NULL} 213 | }; 214 | 215 | 216 | 217 | LUAMOD_API int luaopen_bit32 (lua_State *L) { 218 | luaL_newlib(L, bitlib); 219 | return 1; 220 | } 221 | 222 | 223 | #else /* }{ */ 224 | 225 | 226 | LUAMOD_API int luaopen_bit32 (lua_State *L) { 227 | return luaL_error(L, "library 'bit32' has been deprecated"); 228 | } 229 | 230 | #endif /* } */ 231 | -------------------------------------------------------------------------------- /src/lcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $ 3 | ** Code generator for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lcode_h 8 | #define lcode_h 9 | 10 | #include "llex.h" 11 | #include "lobject.h" 12 | #include "lopcodes.h" 13 | #include "lparser.h" 14 | 15 | 16 | /* 17 | ** Marks the end of a patch list. It is an invalid value both as an absolute 18 | ** address, and as a list link (would link an element to itself). 19 | */ 20 | #define NO_JUMP (-1) 21 | 22 | 23 | /* 24 | ** grep "ORDER OPR" if you change these enums (ORDER OP) 25 | */ 26 | typedef enum BinOpr { 27 | OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, 28 | OPR_DIV, 29 | OPR_IDIV, 30 | OPR_BAND, OPR_BOR, OPR_BXOR, 31 | OPR_SHL, OPR_SHR, 32 | OPR_CONCAT, 33 | OPR_EQ, OPR_LT, OPR_LE, 34 | OPR_NE, OPR_GT, OPR_GE, 35 | OPR_AND, OPR_OR, 36 | OPR_NOBINOPR 37 | } BinOpr; 38 | 39 | 40 | typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; 41 | 42 | 43 | #define getcode(fs,e) ((fs)->f->code[(e)->u.info]) 44 | 45 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) 46 | 47 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) 48 | 49 | #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) 50 | 51 | LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); 52 | LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); 53 | LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); 54 | LUAI_FUNC void luaK_fixline (FuncState *fs, int line); 55 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); 56 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); 57 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); 58 | LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); 59 | LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); 60 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); 61 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); 62 | LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); 63 | LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); 64 | LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); 65 | LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); 66 | LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); 67 | LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); 68 | LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); 69 | LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); 70 | LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); 71 | LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); 72 | LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); 73 | LUAI_FUNC int luaK_jump (FuncState *fs); 74 | LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); 75 | LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); 76 | LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); 77 | LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); 78 | LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); 79 | LUAI_FUNC int luaK_getlabel (FuncState *fs); 80 | LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); 81 | LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); 82 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, 83 | expdesc *v2, int line); 84 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); 85 | 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /src/lcorolib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp $ 3 | ** Coroutine Library 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lcorolib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lauxlib.h" 18 | #include "lualib.h" 19 | 20 | 21 | static lua_State *getco (lua_State *L) { 22 | lua_State *co = lua_tothread(L, 1); 23 | luaL_argcheck(L, co, 1, "thread expected"); 24 | return co; 25 | } 26 | 27 | 28 | static int auxresume (lua_State *L, lua_State *co, int narg) { 29 | int status; 30 | if (!lua_checkstack(co, narg)) { 31 | lua_pushliteral(L, "too many arguments to resume"); 32 | return -1; /* error flag */ 33 | } 34 | if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { 35 | lua_pushliteral(L, "cannot resume dead coroutine"); 36 | return -1; /* error flag */ 37 | } 38 | lua_xmove(L, co, narg); 39 | status = lua_resume(co, L, narg); 40 | if (status == LUA_OK || status == LUA_YIELD) { 41 | int nres = lua_gettop(co); 42 | if (!lua_checkstack(L, nres + 1)) { 43 | lua_pop(co, nres); /* remove results anyway */ 44 | lua_pushliteral(L, "too many results to resume"); 45 | return -1; /* error flag */ 46 | } 47 | lua_xmove(co, L, nres); /* move yielded values */ 48 | return nres; 49 | } 50 | else { 51 | lua_xmove(co, L, 1); /* move error message */ 52 | return -1; /* error flag */ 53 | } 54 | } 55 | 56 | 57 | static int luaB_coresume (lua_State *L) { 58 | lua_State *co = getco(L); 59 | int r; 60 | r = auxresume(L, co, lua_gettop(L) - 1); 61 | if (r < 0) { 62 | lua_pushboolean(L, 0); 63 | lua_insert(L, -2); 64 | return 2; /* return false + error message */ 65 | } 66 | else { 67 | lua_pushboolean(L, 1); 68 | lua_insert(L, -(r + 1)); 69 | return r + 1; /* return true + 'resume' returns */ 70 | } 71 | } 72 | 73 | 74 | static int luaB_auxwrap (lua_State *L) { 75 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 76 | int r = auxresume(L, co, lua_gettop(L)); 77 | if (r < 0) { 78 | if (lua_isstring(L, -1)) { /* error object is a string? */ 79 | luaL_where(L, 1); /* add extra info */ 80 | lua_insert(L, -2); 81 | lua_concat(L, 2); 82 | } 83 | return lua_error(L); /* propagate error */ 84 | } 85 | return r; 86 | } 87 | 88 | 89 | static int luaB_cocreate (lua_State *L) { 90 | lua_State *NL; 91 | luaL_checktype(L, 1, LUA_TFUNCTION); 92 | NL = lua_newthread(L); 93 | lua_pushvalue(L, 1); /* move function to top */ 94 | lua_xmove(L, NL, 1); /* move function from L to NL */ 95 | return 1; 96 | } 97 | 98 | 99 | static int luaB_cowrap (lua_State *L) { 100 | luaB_cocreate(L); 101 | lua_pushcclosure(L, luaB_auxwrap, 1); 102 | return 1; 103 | } 104 | 105 | 106 | static int luaB_yield (lua_State *L) { 107 | return lua_yield(L, lua_gettop(L)); 108 | } 109 | 110 | 111 | static int luaB_costatus (lua_State *L) { 112 | lua_State *co = getco(L); 113 | if (L == co) lua_pushliteral(L, "running"); 114 | else { 115 | switch (lua_status(co)) { 116 | case LUA_YIELD: 117 | lua_pushliteral(L, "suspended"); 118 | break; 119 | case LUA_OK: { 120 | lua_Debug ar; 121 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ 122 | lua_pushliteral(L, "normal"); /* it is running */ 123 | else if (lua_gettop(co) == 0) 124 | lua_pushliteral(L, "dead"); 125 | else 126 | lua_pushliteral(L, "suspended"); /* initial state */ 127 | break; 128 | } 129 | default: /* some error occurred */ 130 | lua_pushliteral(L, "dead"); 131 | break; 132 | } 133 | } 134 | return 1; 135 | } 136 | 137 | 138 | static int luaB_yieldable (lua_State *L) { 139 | lua_pushboolean(L, lua_isyieldable(L)); 140 | return 1; 141 | } 142 | 143 | 144 | static int luaB_corunning (lua_State *L) { 145 | int ismain = lua_pushthread(L); 146 | lua_pushboolean(L, ismain); 147 | return 2; 148 | } 149 | 150 | 151 | static const luaL_Reg co_funcs[] = { 152 | {"create", luaB_cocreate}, 153 | {"resume", luaB_coresume}, 154 | {"running", luaB_corunning}, 155 | {"status", luaB_costatus}, 156 | {"wrap", luaB_cowrap}, 157 | {"yield", luaB_yield}, 158 | {"isyieldable", luaB_yieldable}, 159 | {NULL, NULL} 160 | }; 161 | 162 | 163 | 164 | LUAMOD_API int luaopen_coroutine (lua_State *L) { 165 | luaL_newlib(L, co_funcs); 166 | return 1; 167 | } 168 | 169 | -------------------------------------------------------------------------------- /src/lctype.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lctype_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include "lctype.h" 14 | 15 | #if !LUA_USE_CTYPE /* { */ 16 | 17 | #include 18 | 19 | LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { 20 | 0x00, /* EOZ */ 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ 22 | 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 | 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ 26 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 27 | 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ 28 | 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 29 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ 30 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 31 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ 32 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, 33 | 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ 34 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 35 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ 36 | 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | }; 54 | 55 | #endif /* } */ 56 | -------------------------------------------------------------------------------- /src/lctype.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ 3 | ** 'ctype' functions for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lctype_h 8 | #define lctype_h 9 | 10 | #include "lua.h" 11 | 12 | 13 | /* 14 | ** WARNING: the functions defined here do not necessarily correspond 15 | ** to the similar functions in the standard C ctype.h. They are 16 | ** optimized for the specific needs of Lua 17 | */ 18 | 19 | #if !defined(LUA_USE_CTYPE) 20 | 21 | #if 'A' == 65 && '0' == 48 22 | /* ASCII case: can use its own tables; faster and fixed */ 23 | #define LUA_USE_CTYPE 0 24 | #else 25 | /* must use standard C ctype */ 26 | #define LUA_USE_CTYPE 1 27 | #endif 28 | 29 | #endif 30 | 31 | 32 | #if !LUA_USE_CTYPE /* { */ 33 | 34 | #include 35 | 36 | #include "llimits.h" 37 | 38 | 39 | #define ALPHABIT 0 40 | #define DIGITBIT 1 41 | #define PRINTBIT 2 42 | #define SPACEBIT 3 43 | #define XDIGITBIT 4 44 | 45 | 46 | #define MASK(B) (1 << (B)) 47 | 48 | 49 | /* 50 | ** add 1 to char to allow index -1 (EOZ) 51 | */ 52 | #define testprop(c,p) (luai_ctype_[(c)+1] & (p)) 53 | 54 | /* 55 | ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' 56 | */ 57 | #define lislalpha(c) testprop(c, MASK(ALPHABIT)) 58 | #define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) 59 | #define lisdigit(c) testprop(c, MASK(DIGITBIT)) 60 | #define lisspace(c) testprop(c, MASK(SPACEBIT)) 61 | #define lisprint(c) testprop(c, MASK(PRINTBIT)) 62 | #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) 63 | 64 | /* 65 | ** this 'ltolower' only works for alphabetic characters 66 | */ 67 | #define ltolower(c) ((c) | ('A' ^ 'a')) 68 | 69 | 70 | /* two more entries for 0 and -1 (EOZ) */ 71 | LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; 72 | 73 | 74 | #else /* }{ */ 75 | 76 | /* 77 | ** use standard C ctypes 78 | */ 79 | 80 | #include 81 | 82 | 83 | #define lislalpha(c) (isalpha(c) || (c) == '_') 84 | #define lislalnum(c) (isalnum(c) || (c) == '_') 85 | #define lisdigit(c) (isdigit(c)) 86 | #define lisspace(c) (isspace(c)) 87 | #define lisprint(c) (isprint(c)) 88 | #define lisxdigit(c) (isxdigit(c)) 89 | 90 | #define ltolower(c) (tolower(c)) 91 | 92 | #endif /* } */ 93 | 94 | #endif 95 | 96 | -------------------------------------------------------------------------------- /src/ldebug.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $ 3 | ** Auxiliary functions from Debug Interface module 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldebug_h 8 | #define ldebug_h 9 | 10 | 11 | #include "lstate.h" 12 | 13 | 14 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) 15 | 16 | #define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) 17 | 18 | #define resethookcount(L) (L->hookcount = L->basehookcount) 19 | 20 | 21 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 22 | const char *opname); 23 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, 24 | const TValue *p2); 25 | LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, 26 | const TValue *p2, 27 | const char *msg); 28 | LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, 29 | const TValue *p2); 30 | LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, 31 | const TValue *p2); 32 | LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); 33 | LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, 34 | TString *src, int line); 35 | LUAI_FUNC l_noret luaG_errormsg (lua_State *L); 36 | LUAI_FUNC void luaG_traceexec (lua_State *L); 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/ldo.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp $ 3 | ** Stack and Call structure of Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ldo_h 8 | #define ldo_h 9 | 10 | 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | #include "lzio.h" 14 | 15 | 16 | #define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ 17 | luaD_growstack(L, n); else condmovestack(L); 18 | 19 | 20 | #define incr_top(L) {L->top++; luaD_checkstack(L,0);} 21 | 22 | #define savestack(L,p) ((char *)(p) - (char *)L->stack) 23 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) 24 | 25 | 26 | /* type of protected functions, to be ran by 'runprotected' */ 27 | typedef void (*Pfunc) (lua_State *L, void *ud); 28 | 29 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 30 | const char *mode); 31 | LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); 32 | LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); 33 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, 34 | int allowyield); 35 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, 36 | ptrdiff_t oldtop, ptrdiff_t ef); 37 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres); 38 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); 39 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); 40 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); 41 | 42 | LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); 43 | LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /src/ldump.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp $ 3 | ** save precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ldump_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lobject.h" 18 | #include "lstate.h" 19 | #include "lundump.h" 20 | 21 | 22 | typedef struct { 23 | lua_State *L; 24 | lua_Writer writer; 25 | void *data; 26 | int strip; 27 | int status; 28 | } DumpState; 29 | 30 | 31 | /* 32 | ** All high-level dumps go through DumpVector; you can change it to 33 | ** change the endianness of the result 34 | */ 35 | #define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) 36 | 37 | #define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) 38 | 39 | 40 | static void DumpBlock (const void *b, size_t size, DumpState *D) { 41 | if (D->status == 0) { 42 | lua_unlock(D->L); 43 | D->status = (*D->writer)(D->L, b, size, D->data); 44 | lua_lock(D->L); 45 | } 46 | } 47 | 48 | 49 | #define DumpVar(x,D) DumpVector(&x,1,D) 50 | 51 | 52 | static void DumpByte (int y, DumpState *D) { 53 | lu_byte x = (lu_byte)y; 54 | DumpVar(x, D); 55 | } 56 | 57 | 58 | static void DumpInt (int x, DumpState *D) { 59 | DumpVar(x, D); 60 | } 61 | 62 | 63 | static void DumpNumber (lua_Number x, DumpState *D) { 64 | DumpVar(x, D); 65 | } 66 | 67 | 68 | static void DumpInteger (lua_Integer x, DumpState *D) { 69 | DumpVar(x, D); 70 | } 71 | 72 | 73 | static void DumpString (const TString *s, DumpState *D) { 74 | if (s == NULL) 75 | DumpByte(0, D); 76 | else { 77 | size_t size = tsslen(s) + 1; /* include trailing '\0' */ 78 | const char *str = getstr(s); 79 | if (size < 0xFF) 80 | DumpByte(cast_int(size), D); 81 | else { 82 | DumpByte(0xFF, D); 83 | DumpVar(size, D); 84 | } 85 | DumpVector(str, size - 1, D); /* no need to save '\0' */ 86 | } 87 | } 88 | 89 | 90 | static void DumpCode (const Proto *f, DumpState *D) { 91 | DumpInt(f->sizecode, D); 92 | DumpVector(f->code, f->sizecode, D); 93 | } 94 | 95 | 96 | static void DumpFunction(const Proto *f, TString *psource, DumpState *D); 97 | 98 | static void DumpConstants (const Proto *f, DumpState *D) { 99 | int i; 100 | int n = f->sizek; 101 | DumpInt(n, D); 102 | for (i = 0; i < n; i++) { 103 | const TValue *o = &f->k[i]; 104 | DumpByte(ttype(o), D); 105 | switch (ttype(o)) { 106 | case LUA_TNIL: 107 | break; 108 | case LUA_TBOOLEAN: 109 | DumpByte(bvalue(o), D); 110 | break; 111 | case LUA_TNUMFLT: 112 | DumpNumber(fltvalue(o), D); 113 | break; 114 | case LUA_TNUMINT: 115 | DumpInteger(ivalue(o), D); 116 | break; 117 | case LUA_TSHRSTR: 118 | case LUA_TLNGSTR: 119 | DumpString(tsvalue(o), D); 120 | break; 121 | default: 122 | lua_assert(0); 123 | } 124 | } 125 | } 126 | 127 | 128 | static void DumpProtos (const Proto *f, DumpState *D) { 129 | int i; 130 | int n = f->sizep; 131 | DumpInt(n, D); 132 | for (i = 0; i < n; i++) 133 | DumpFunction(f->p[i], f->source, D); 134 | } 135 | 136 | 137 | static void DumpUpvalues (const Proto *f, DumpState *D) { 138 | int i, n = f->sizeupvalues; 139 | DumpInt(n, D); 140 | for (i = 0; i < n; i++) { 141 | DumpByte(f->upvalues[i].instack, D); 142 | DumpByte(f->upvalues[i].idx, D); 143 | } 144 | } 145 | 146 | 147 | static void DumpDebug (const Proto *f, DumpState *D) { 148 | int i, n; 149 | n = (D->strip) ? 0 : f->sizelineinfo; 150 | DumpInt(n, D); 151 | DumpVector(f->lineinfo, n, D); 152 | n = (D->strip) ? 0 : f->sizelocvars; 153 | DumpInt(n, D); 154 | for (i = 0; i < n; i++) { 155 | DumpString(f->locvars[i].varname, D); 156 | DumpInt(f->locvars[i].startpc, D); 157 | DumpInt(f->locvars[i].endpc, D); 158 | } 159 | n = (D->strip) ? 0 : f->sizeupvalues; 160 | DumpInt(n, D); 161 | for (i = 0; i < n; i++) 162 | DumpString(f->upvalues[i].name, D); 163 | } 164 | 165 | 166 | static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { 167 | if (D->strip || f->source == psource) 168 | DumpString(NULL, D); /* no debug info or same source as its parent */ 169 | else 170 | DumpString(f->source, D); 171 | DumpInt(f->linedefined, D); 172 | DumpInt(f->lastlinedefined, D); 173 | DumpByte(f->numparams, D); 174 | DumpByte(f->is_vararg, D); 175 | DumpByte(f->maxstacksize, D); 176 | DumpCode(f, D); 177 | DumpConstants(f, D); 178 | DumpUpvalues(f, D); 179 | DumpProtos(f, D); 180 | DumpDebug(f, D); 181 | } 182 | 183 | 184 | static void DumpHeader (DumpState *D) { 185 | DumpLiteral(LUA_SIGNATURE, D); 186 | DumpByte(LUAC_VERSION, D); 187 | DumpByte(LUAC_FORMAT, D); 188 | DumpLiteral(LUAC_DATA, D); 189 | DumpByte(sizeof(int), D); 190 | DumpByte(sizeof(size_t), D); 191 | DumpByte(sizeof(Instruction), D); 192 | DumpByte(sizeof(lua_Integer), D); 193 | DumpByte(sizeof(lua_Number), D); 194 | DumpInteger(LUAC_INT, D); 195 | DumpNumber(LUAC_NUM, D); 196 | } 197 | 198 | 199 | /* 200 | ** dump Lua function as precompiled chunk 201 | */ 202 | int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 203 | int strip) { 204 | DumpState D; 205 | D.L = L; 206 | D.writer = w; 207 | D.data = data; 208 | D.strip = strip; 209 | D.status = 0; 210 | DumpHeader(&D); 211 | DumpByte(f->sizeupvalues, &D); 212 | DumpFunction(f, NULL, &D); 213 | return D.status; 214 | } 215 | 216 | -------------------------------------------------------------------------------- /src/lfunc.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lfunc_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "lfunc.h" 18 | #include "lgc.h" 19 | #include "lmem.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | 23 | 24 | 25 | CClosure *luaF_newCclosure (lua_State *L, int n) { 26 | GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); 27 | CClosure *c = gco2ccl(o); 28 | c->nupvalues = cast_byte(n); 29 | return c; 30 | } 31 | 32 | 33 | LClosure *luaF_newLclosure (lua_State *L, int n) { 34 | GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); 35 | LClosure *c = gco2lcl(o); 36 | c->p = NULL; 37 | c->nupvalues = cast_byte(n); 38 | while (n--) c->upvals[n] = NULL; 39 | return c; 40 | } 41 | 42 | /* 43 | ** fill a closure with new closed upvalues 44 | */ 45 | void luaF_initupvals (lua_State *L, LClosure *cl) { 46 | int i; 47 | for (i = 0; i < cl->nupvalues; i++) { 48 | UpVal *uv = luaM_new(L, UpVal); 49 | uv->refcount = 1; 50 | uv->v = &uv->u.value; /* make it closed */ 51 | setnilvalue(uv->v); 52 | cl->upvals[i] = uv; 53 | } 54 | } 55 | 56 | 57 | UpVal *luaF_findupval (lua_State *L, StkId level) { 58 | UpVal **pp = &L->openupval; 59 | UpVal *p; 60 | UpVal *uv; 61 | lua_assert(isintwups(L) || L->openupval == NULL); 62 | while (*pp != NULL && (p = *pp)->v >= level) { 63 | lua_assert(upisopen(p)); 64 | if (p->v == level) /* found a corresponding upvalue? */ 65 | return p; /* return it */ 66 | pp = &p->u.open.next; 67 | } 68 | /* not found: create a new upvalue */ 69 | uv = luaM_new(L, UpVal); 70 | uv->refcount = 0; 71 | uv->u.open.next = *pp; /* link it to list of open upvalues */ 72 | uv->u.open.touched = 1; 73 | *pp = uv; 74 | uv->v = level; /* current value lives in the stack */ 75 | if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ 76 | L->twups = G(L)->twups; /* link it to the list */ 77 | G(L)->twups = L; 78 | } 79 | return uv; 80 | } 81 | 82 | 83 | void luaF_close (lua_State *L, StkId level) { 84 | UpVal *uv; 85 | while (L->openupval != NULL && (uv = L->openupval)->v >= level) { 86 | lua_assert(upisopen(uv)); 87 | L->openupval = uv->u.open.next; /* remove from 'open' list */ 88 | if (uv->refcount == 0) /* no references? */ 89 | luaM_free(L, uv); /* free upvalue */ 90 | else { 91 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ 92 | uv->v = &uv->u.value; /* now current value lives here */ 93 | luaC_upvalbarrier(L, uv); 94 | } 95 | } 96 | } 97 | 98 | 99 | Proto *luaF_newproto (lua_State *L) { 100 | GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); 101 | Proto *f = gco2p(o); 102 | f->k = NULL; 103 | f->sizek = 0; 104 | f->p = NULL; 105 | f->sizep = 0; 106 | f->code = NULL; 107 | f->cache = NULL; 108 | f->sizecode = 0; 109 | f->lineinfo = NULL; 110 | f->sizelineinfo = 0; 111 | f->upvalues = NULL; 112 | f->sizeupvalues = 0; 113 | f->numparams = 0; 114 | f->is_vararg = 0; 115 | f->maxstacksize = 0; 116 | f->locvars = NULL; 117 | f->sizelocvars = 0; 118 | f->linedefined = 0; 119 | f->lastlinedefined = 0; 120 | f->source = NULL; 121 | return f; 122 | } 123 | 124 | 125 | void luaF_freeproto (lua_State *L, Proto *f) { 126 | luaM_freearray(L, f->code, f->sizecode); 127 | luaM_freearray(L, f->p, f->sizep); 128 | luaM_freearray(L, f->k, f->sizek); 129 | luaM_freearray(L, f->lineinfo, f->sizelineinfo); 130 | luaM_freearray(L, f->locvars, f->sizelocvars); 131 | luaM_freearray(L, f->upvalues, f->sizeupvalues); 132 | luaM_free(L, f); 133 | } 134 | 135 | 136 | /* 137 | ** Look for n-th local variable at line 'line' in function 'func'. 138 | ** Returns NULL if not found. 139 | */ 140 | const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { 141 | int i; 142 | for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { 143 | if (pc < f->locvars[i].endpc) { /* is variable active? */ 144 | local_number--; 145 | if (local_number == 0) 146 | return getstr(f->locvars[i].varname); 147 | } 148 | } 149 | return NULL; /* not found */ 150 | } 151 | 152 | -------------------------------------------------------------------------------- /src/lfunc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $ 3 | ** Auxiliary functions to manipulate prototypes and closures 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lfunc_h 8 | #define lfunc_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ 15 | cast(int, sizeof(TValue)*((n)-1))) 16 | 17 | #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ 18 | cast(int, sizeof(TValue *)*((n)-1))) 19 | 20 | 21 | /* test whether thread is in 'twups' list */ 22 | #define isintwups(L) (L->twups != L) 23 | 24 | 25 | /* 26 | ** maximum number of upvalues in a closure (both C and Lua). (Value 27 | ** must fit in a VM register.) 28 | */ 29 | #define MAXUPVAL 255 30 | 31 | 32 | /* 33 | ** Upvalues for Lua closures 34 | */ 35 | struct UpVal { 36 | TValue *v; /* points to stack or to its own value */ 37 | lu_mem refcount; /* reference counter */ 38 | union { 39 | struct { /* (when open) */ 40 | UpVal *next; /* linked list */ 41 | int touched; /* mark to avoid cycles with dead threads */ 42 | } open; 43 | TValue value; /* the value (when closed) */ 44 | } u; 45 | }; 46 | 47 | #define upisopen(up) ((up)->v != &(up)->u.value) 48 | 49 | 50 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); 51 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); 52 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); 53 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 54 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 55 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); 56 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 57 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, 58 | int pc); 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/lgc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lgc.h,v 2.86 2014/10/25 11:50:46 roberto Exp $ 3 | ** Garbage Collector 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lgc_h 8 | #define lgc_h 9 | 10 | 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | /* 15 | ** Collectable objects may have one of three colors: white, which 16 | ** means the object is not marked; gray, which means the 17 | ** object is marked, but its references may be not marked; and 18 | ** black, which means that the object and all its references are marked. 19 | ** The main invariant of the garbage collector, while marking objects, 20 | ** is that a black object can never point to a white one. Moreover, 21 | ** any gray object must be in a "gray list" (gray, grayagain, weak, 22 | ** allweak, ephemeron) so that it can be visited again before finishing 23 | ** the collection cycle. These lists have no meaning when the invariant 24 | ** is not being enforced (e.g., sweep phase). 25 | */ 26 | 27 | 28 | 29 | /* how much to allocate before next GC step */ 30 | #if !defined(GCSTEPSIZE) 31 | /* ~100 small strings */ 32 | #define GCSTEPSIZE (cast_int(100 * sizeof(TString))) 33 | #endif 34 | 35 | 36 | /* 37 | ** Possible states of the Garbage Collector 38 | */ 39 | #define GCSpropagate 0 40 | #define GCSatomic 1 41 | #define GCSswpallgc 2 42 | #define GCSswpfinobj 3 43 | #define GCSswptobefnz 4 44 | #define GCSswpend 5 45 | #define GCScallfin 6 46 | #define GCSpause 7 47 | 48 | 49 | #define issweepphase(g) \ 50 | (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) 51 | 52 | 53 | /* 54 | ** macro to tell when main invariant (white objects cannot point to black 55 | ** ones) must be kept. During a collection, the sweep 56 | ** phase may break the invariant, as objects turned white may point to 57 | ** still-black objects. The invariant is restored when sweep ends and 58 | ** all objects are white again. 59 | */ 60 | 61 | #define keepinvariant(g) ((g)->gcstate <= GCSatomic) 62 | 63 | 64 | /* 65 | ** some useful bit tricks 66 | */ 67 | #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) 68 | #define setbits(x,m) ((x) |= (m)) 69 | #define testbits(x,m) ((x) & (m)) 70 | #define bitmask(b) (1<<(b)) 71 | #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) 72 | #define l_setbit(x,b) setbits(x, bitmask(b)) 73 | #define resetbit(x,b) resetbits(x, bitmask(b)) 74 | #define testbit(x,b) testbits(x, bitmask(b)) 75 | 76 | 77 | /* Layout for bit use in 'marked' field: */ 78 | #define WHITE0BIT 0 /* object is white (type 0) */ 79 | #define WHITE1BIT 1 /* object is white (type 1) */ 80 | #define BLACKBIT 2 /* object is black */ 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ 83 | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 85 | 86 | 87 | #define iswhite(x) testbits((x)->marked, WHITEBITS) 88 | #define isblack(x) testbit((x)->marked, BLACKBIT) 89 | #define isgray(x) /* neither white nor black */ \ 90 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) 91 | 92 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) 93 | 94 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) 95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) 96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) 97 | 98 | #define changewhite(x) ((x)->marked ^= WHITEBITS) 99 | #define gray2black(x) l_setbit((x)->marked, BLACKBIT) 100 | 101 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) 102 | 103 | 104 | #define luaC_condGC(L,c) \ 105 | {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} 106 | #define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) 107 | 108 | 109 | #define luaC_barrier(L,p,v) { \ 110 | if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ 111 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } 112 | 113 | #define luaC_barrierback(L,p,v) { \ 114 | if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ 115 | luaC_barrierback_(L,p); } 116 | 117 | #define luaC_objbarrier(L,p,o) { \ 118 | if (isblack(p) && iswhite(o)) \ 119 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } 120 | 121 | #define luaC_upvalbarrier(L,uv) \ 122 | { if (iscollectable((uv)->v) && !upisopen(uv)) \ 123 | luaC_upvalbarrier_(L,uv); } 124 | 125 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); 126 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); 127 | LUAI_FUNC void luaC_step (lua_State *L); 128 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); 129 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); 130 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); 131 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); 132 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); 133 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); 134 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); 135 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); 136 | 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /src/linit.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $ 3 | ** Initialization of libraries for lua.c and other clients 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #define linit_c 9 | #define LUA_LIB 10 | 11 | /* 12 | ** If you embed Lua in your program and need to open the standard 13 | ** libraries, call luaL_openlibs in your program. If you need a 14 | ** different set of libraries, copy this file to your project and edit 15 | ** it to suit your needs. 16 | ** 17 | ** You can also *preload* libraries, so that a later 'require' can 18 | ** open the library, which is already linked to the application. 19 | ** For that, do the following code: 20 | ** 21 | ** luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); 22 | ** lua_pushcfunction(L, luaopen_modname); 23 | ** lua_setfield(L, -2, modname); 24 | ** lua_pop(L, 1); // remove _PRELOAD table 25 | */ 26 | 27 | #include "lprefix.h" 28 | 29 | 30 | #include 31 | 32 | #include "lua.h" 33 | 34 | #include "lualib.h" 35 | #include "lauxlib.h" 36 | 37 | 38 | /* 39 | ** these libs are loaded by lua.c and are readily available to any Lua 40 | ** program 41 | */ 42 | static const luaL_Reg loadedlibs[] = { 43 | {"_G", luaopen_base}, 44 | {LUA_LOADLIBNAME, luaopen_package}, 45 | {LUA_COLIBNAME, luaopen_coroutine}, 46 | {LUA_TABLIBNAME, luaopen_table}, 47 | {LUA_IOLIBNAME, luaopen_io}, 48 | {LUA_OSLIBNAME, luaopen_os}, 49 | {LUA_STRLIBNAME, luaopen_string}, 50 | {LUA_MATHLIBNAME, luaopen_math}, 51 | {LUA_UTF8LIBNAME, luaopen_utf8}, 52 | {LUA_DBLIBNAME, luaopen_debug}, 53 | #if defined(LUA_COMPAT_BITLIB) 54 | {LUA_BITLIBNAME, luaopen_bit32}, 55 | #endif 56 | {NULL, NULL} 57 | }; 58 | 59 | 60 | LUALIB_API void luaL_openlibs (lua_State *L) { 61 | const luaL_Reg *lib; 62 | /* "require" functions from 'loadedlibs' and set results to global table */ 63 | for (lib = loadedlibs; lib->func; lib++) { 64 | luaL_requiref(L, lib->name, lib->func, 1); 65 | lua_pop(L, 1); /* remove lib */ 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/llex.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp $ 3 | ** Copyright 2015 Sajon Oso 4 | ** Lexical Analyzer 5 | ** See Copyright Notice in lua.h 6 | */ 7 | 8 | #ifndef llex_h 9 | #define llex_h 10 | 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | #define FIRST_RESERVED 257 16 | 17 | 18 | #if !defined(LUA_ENV) 19 | #define LUA_ENV "_ENV" 20 | #endif 21 | 22 | 23 | /* 24 | * WARNING: if you change the order of this enumeration, 25 | * grep "ORDER RESERVED" 26 | */ 27 | enum RESERVED { 28 | /* terminal symbols denoted by reserved words */ 29 | TK_AND = FIRST_RESERVED, TK_NOT, TK_OR, TK_BREAK, TK_DO, TK_ELSE, 30 | TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, TK_GOTO, TK_IF, TK_IN, 31 | TK_LOCAL, TK_NIL, 32 | TK_RETURN, TK_TRUE, TK_UNTIL, TK_WHILE, 33 | /* FUTURE RESERVED */ 34 | TK_CASE, TK_CATCH, TK_CLASS, TK_CONST, TK_CONTINUE, 35 | TK_DEFAULT, TK_EACH, TK_EXTENDS, TK_FINALLY, TK_IMPLEMENTS, TK_IMPORT, 36 | TK_INTERFACE, TK_NEW, TK_OVERRIDE, TK_PRIVATE, TK_PUBLIC, TK_PROTECTED, TK_STATIC, 37 | TK_SUPER, TK_SWITCH, TK_THROW, TK_TO, TK_TRY, TK_UNDEFINED, /* change NUM_RESERVED if TK_UNDEFINED is not last */ 38 | /* other terminal symbols */ 39 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, 40 | TK_CADD, TK_CSUB, TK_CMUL, TK_CDIV, TK_CMOD, 41 | TK_SHL, TK_SHR, TK_DBCOLON, TK_EOS, 42 | TK_FLT, TK_INT, TK_NAME, TK_STRING 43 | }; 44 | 45 | /* number of reserved words */ 46 | #define NUM_RESERVED (cast(int, TK_UNDEFINED-FIRST_RESERVED+1)) 47 | 48 | 49 | typedef union { 50 | lua_Number r; 51 | lua_Integer i; 52 | TString *ts; 53 | } SemInfo; /* semantics information */ 54 | 55 | 56 | typedef struct Token { 57 | int token; 58 | SemInfo seminfo; 59 | } Token; 60 | 61 | 62 | /* state of the lexer plus state of the parser when shared by all 63 | functions */ 64 | typedef struct LexState { 65 | int current; /* current character (charint) */ 66 | int linenumber; /* input line counter */ 67 | int lastline; /* line of last token 'consumed' */ 68 | Token t; /* current token */ 69 | Token lookahead; /* look ahead token */ 70 | struct FuncState *fs; /* current function (parser) */ 71 | struct lua_State *L; 72 | ZIO *z; /* input stream */ 73 | Mbuffer *buff; /* buffer for tokens */ 74 | Table *h; /* to avoid collection/reuse strings */ 75 | struct Dyndata *dyd; /* dynamic structures used by the parser */ 76 | TString *source; /* current source name */ 77 | TString *envn; /* environment variable name */ 78 | char decpoint; /* locale decimal point */ 79 | } LexState; 80 | 81 | 82 | LUAI_FUNC void luaX_init (lua_State *L); 83 | LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, 84 | TString *source, int firstchar); 85 | LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); 86 | LUAI_FUNC void luaX_next (LexState *ls); 87 | LUAI_FUNC int luaX_lookahead (LexState *ls); 88 | LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); 89 | LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); 90 | 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /src/llimits.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: llimits.h,v 1.135 2015/06/09 14:21:00 roberto Exp $ 3 | ** Limits, basic types, and some other 'installation-dependent' definitions 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef llimits_h 8 | #define llimits_h 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | #include "lua.h" 16 | 17 | /* 18 | ** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count 19 | ** the total memory used by Lua (in bytes). Usually, 'size_t' and 20 | ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. 21 | */ 22 | #if defined(LUAI_MEM) /* { external definitions? */ 23 | typedef LUAI_UMEM lu_mem; 24 | typedef LUAI_MEM l_mem; 25 | #elif LUAI_BITSINT >= 32 /* }{ */ 26 | typedef size_t lu_mem; 27 | typedef ptrdiff_t l_mem; 28 | #else /* 16-bit ints */ /* }{ */ 29 | typedef unsigned long lu_mem; 30 | typedef long l_mem; 31 | #endif /* } */ 32 | 33 | 34 | /* chars used as small naturals (so that 'char' is reserved for characters) */ 35 | typedef unsigned char lu_byte; 36 | 37 | 38 | /* maximum value for size_t */ 39 | #define MAX_SIZET ((size_t)(~(size_t)0)) 40 | 41 | /* maximum size visible for Lua (must be representable in a lua_Integer */ 42 | #define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ 43 | : (size_t)(LUA_MAXINTEGER)) 44 | 45 | 46 | #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) 47 | 48 | #define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) 49 | 50 | 51 | #define MAX_INT INT_MAX /* maximum value of an int */ 52 | 53 | 54 | /* 55 | ** conversion of pointer to unsigned integer: 56 | ** this is for hashing only; there is no problem if the integer 57 | ** cannot hold the whole pointer value 58 | */ 59 | #define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) 60 | 61 | 62 | 63 | /* type to ensure maximum alignment */ 64 | #if defined(LUAI_USER_ALIGNMENT_T) 65 | typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; 66 | #else 67 | typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign; 68 | #endif 69 | 70 | 71 | 72 | /* types of 'usual argument conversions' for lua_Number and lua_Integer */ 73 | typedef LUAI_UACNUMBER l_uacNumber; 74 | typedef LUAI_UACINT l_uacInt; 75 | 76 | 77 | /* internal assertions for in-house debugging */ 78 | #if defined(lua_assert) 79 | #define check_exp(c,e) (lua_assert(c), (e)) 80 | /* to avoid problems with conditions too long */ 81 | #define lua_longassert(c) { if (!(c)) lua_assert(0); } 82 | #else 83 | #define lua_assert(c) ((void)0) 84 | #define check_exp(c,e) (e) 85 | #define lua_longassert(c) ((void)0) 86 | #endif 87 | 88 | /* 89 | ** assertion for checking API calls 90 | */ 91 | #if !defined(luai_apicheck) 92 | #define luai_apicheck(l,e) lua_assert(e) 93 | #endif 94 | 95 | #define api_check(l,e,msg) luai_apicheck(l,(e) && msg) 96 | 97 | 98 | /* macro to avoid warnings about unused variables */ 99 | #if !defined(UNUSED) 100 | #define UNUSED(x) ((void)(x)) 101 | #endif 102 | 103 | 104 | /* type casts (a macro highlights casts in the code) */ 105 | #define cast(t, exp) ((t)(exp)) 106 | 107 | #define cast_void(i) cast(void, (i)) 108 | #define cast_byte(i) cast(lu_byte, (i)) 109 | #define cast_num(i) cast(lua_Number, (i)) 110 | #define cast_int(i) cast(int, (i)) 111 | #define cast_uchar(i) cast(unsigned char, (i)) 112 | 113 | 114 | /* cast a signed lua_Integer to lua_Unsigned */ 115 | #if !defined(l_castS2U) 116 | #define l_castS2U(i) ((lua_Unsigned)(i)) 117 | #endif 118 | 119 | /* 120 | ** cast a lua_Unsigned to a signed lua_Integer; this cast is 121 | ** not strict ISO C, but two-complement architectures should 122 | ** work fine. 123 | */ 124 | #if !defined(l_castU2S) 125 | #define l_castU2S(i) ((lua_Integer)(i)) 126 | #endif 127 | 128 | 129 | /* 130 | ** non-return type 131 | */ 132 | #if defined(__GNUC__) 133 | #define l_noret void __attribute__((noreturn)) 134 | #elif defined(_MSC_VER) && _MSC_VER >= 1200 135 | #define l_noret void __declspec(noreturn) 136 | #else 137 | #define l_noret void 138 | #endif 139 | 140 | 141 | 142 | /* 143 | ** maximum depth for nested C calls and syntactical nested non-terminals 144 | ** in a program. (Value must fit in an unsigned short int.) 145 | */ 146 | #if !defined(LUAI_MAXCCALLS) 147 | #define LUAI_MAXCCALLS 200 148 | #endif 149 | 150 | 151 | 152 | /* 153 | ** type for virtual-machine instructions; 154 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) 155 | */ 156 | #if LUAI_BITSINT >= 32 157 | typedef unsigned int Instruction; 158 | #else 159 | typedef unsigned long Instruction; 160 | #endif 161 | 162 | 163 | 164 | /* 165 | ** Maximum length for short strings, that is, strings that are 166 | ** internalized. (Cannot be smaller than reserved words or tags for 167 | ** metamethods, as these strings must be internalized; 168 | ** #("function") = 8, #("__newindex") = 10.) 169 | */ 170 | #if !defined(LUAI_MAXSHORTLEN) 171 | #define LUAI_MAXSHORTLEN 40 172 | #endif 173 | 174 | 175 | /* 176 | ** Initial size for the string table (must be power of 2). 177 | ** The Lua core alone registers ~50 strings (reserved words + 178 | ** metaevent keys + a few others). Libraries would typically add 179 | ** a few dozens more. 180 | */ 181 | #if !defined(MINSTRTABSIZE) 182 | #define MINSTRTABSIZE 128 183 | #endif 184 | 185 | 186 | /* 187 | ** Size of cache for strings in the API (better be a prime) 188 | */ 189 | #if !defined(STRCACHE_SIZE) 190 | #define STRCACHE_SIZE 127 191 | #endif 192 | 193 | 194 | /* minimum size for string buffer */ 195 | #if !defined(LUA_MINBUFFER) 196 | #define LUA_MINBUFFER 32 197 | #endif 198 | 199 | 200 | /* 201 | ** macros that are executed whenether program enters the Lua core 202 | ** ('lua_lock') and leaves the core ('lua_unlock') 203 | */ 204 | #if !defined(lua_lock) 205 | #define lua_lock(L) ((void) 0) 206 | #define lua_unlock(L) ((void) 0) 207 | #endif 208 | 209 | /* 210 | ** macro executed during Lua functions at points where the 211 | ** function can yield. 212 | */ 213 | #if !defined(luai_threadyield) 214 | #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} 215 | #endif 216 | 217 | 218 | /* 219 | ** these macros allow user-specific actions on threads when you defined 220 | ** LUAI_EXTRASPACE and need to do something extra when a thread is 221 | ** created/deleted/resumed/yielded. 222 | */ 223 | #if !defined(luai_userstateopen) 224 | #define luai_userstateopen(L) ((void)L) 225 | #endif 226 | 227 | #if !defined(luai_userstateclose) 228 | #define luai_userstateclose(L) ((void)L) 229 | #endif 230 | 231 | #if !defined(luai_userstatethread) 232 | #define luai_userstatethread(L,L1) ((void)L) 233 | #endif 234 | 235 | #if !defined(luai_userstatefree) 236 | #define luai_userstatefree(L,L1) ((void)L) 237 | #endif 238 | 239 | #if !defined(luai_userstateresume) 240 | #define luai_userstateresume(L,n) ((void)L) 241 | #endif 242 | 243 | #if !defined(luai_userstateyield) 244 | #define luai_userstateyield(L,n) ((void)L) 245 | #endif 246 | 247 | 248 | 249 | /* 250 | ** The luai_num* macros define the primitive operations over numbers. 251 | */ 252 | 253 | /* floor division (defined as 'floor(a/b)') */ 254 | #if !defined(luai_numidiv) 255 | #define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) 256 | #endif 257 | 258 | /* float division */ 259 | #if !defined(luai_numdiv) 260 | #define luai_numdiv(L,a,b) ((a)/(b)) 261 | #endif 262 | 263 | /* 264 | ** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when 265 | ** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of 266 | ** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) 267 | ** ~= floor(a/b)'. That happens when the division has a non-integer 268 | ** negative result, which is equivalent to the test below. 269 | */ 270 | #if !defined(luai_nummod) 271 | #define luai_nummod(L,a,b,m) \ 272 | { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } 273 | #endif 274 | 275 | /* exponentiation */ 276 | #if !defined(luai_numpow) 277 | #define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) 278 | #endif 279 | 280 | /* the others are quite standard operations */ 281 | #if !defined(luai_numadd) 282 | #define luai_numadd(L,a,b) ((a)+(b)) 283 | #define luai_numsub(L,a,b) ((a)-(b)) 284 | #define luai_nummul(L,a,b) ((a)*(b)) 285 | #define luai_numunm(L,a) (-(a)) 286 | #define luai_numeq(a,b) ((a)==(b)) 287 | #define luai_numlt(a,b) ((a)<(b)) 288 | #define luai_numle(a,b) ((a)<=(b)) 289 | #define luai_numisnan(a) (!luai_numeq((a), (a))) 290 | #endif 291 | 292 | 293 | 294 | 295 | 296 | /* 297 | ** macro to control inclusion of some hard tests on stack reallocation 298 | */ 299 | #if !defined(HARDSTACKTESTS) 300 | #define condmovestack(L) ((void)0) 301 | #else 302 | /* realloc stack keeping its size */ 303 | #define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) 304 | #endif 305 | 306 | #if !defined(HARDMEMTESTS) 307 | #define condchangemem(L) condmovestack(L) 308 | #else 309 | #define condchangemem(L) \ 310 | ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) 311 | #endif 312 | 313 | #endif 314 | -------------------------------------------------------------------------------- /src/lmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lmem_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lgc.h" 20 | #include "lmem.h" 21 | #include "lobject.h" 22 | #include "lstate.h" 23 | 24 | 25 | 26 | /* 27 | ** About the realloc function: 28 | ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); 29 | ** ('osize' is the old size, 'nsize' is the new size) 30 | ** 31 | ** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no 32 | ** matter 'x'). 33 | ** 34 | ** * frealloc(ud, p, x, 0) frees the block 'p' 35 | ** (in this specific case, frealloc must return NULL); 36 | ** particularly, frealloc(ud, NULL, 0, 0) does nothing 37 | ** (which is equivalent to free(NULL) in ISO C) 38 | ** 39 | ** frealloc returns NULL if it cannot create or reallocate the area 40 | ** (any reallocation to an equal or smaller size cannot fail!) 41 | */ 42 | 43 | 44 | 45 | #define MINSIZEARRAY 4 46 | 47 | 48 | void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, 49 | int limit, const char *what) { 50 | void *newblock; 51 | int newsize; 52 | if (*size >= limit/2) { /* cannot double it? */ 53 | if (*size >= limit) /* cannot grow even a little? */ 54 | luaG_runerror(L, "too many %s (limit is %d)", what, limit); 55 | newsize = limit; /* still have at least one free place */ 56 | } 57 | else { 58 | newsize = (*size)*2; 59 | if (newsize < MINSIZEARRAY) 60 | newsize = MINSIZEARRAY; /* minimum size */ 61 | } 62 | newblock = luaM_reallocv(L, block, *size, newsize, size_elems); 63 | *size = newsize; /* update only when everything else is OK */ 64 | return newblock; 65 | } 66 | 67 | 68 | l_noret luaM_toobig (lua_State *L) { 69 | luaG_runerror(L, "memory allocation error: block too big"); 70 | } 71 | 72 | 73 | 74 | /* 75 | ** generic allocation routine. 76 | */ 77 | void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 78 | void *newblock; 79 | global_State *g = G(L); 80 | size_t realosize = (block) ? osize : 0; 81 | lua_assert((realosize == 0) == (block == NULL)); 82 | #if defined(HARDMEMTESTS) 83 | if (nsize > realosize && g->gcrunning) 84 | luaC_fullgc(L, 1); /* force a GC whenever possible */ 85 | #endif 86 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); 87 | if (newblock == NULL && nsize > 0) { 88 | lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ 89 | if (g->version) { /* is state fully built? */ 90 | luaC_fullgc(L, 1); /* try to free some memory... */ 91 | newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ 92 | } 93 | if (newblock == NULL) 94 | luaD_throw(L, LUA_ERRMEM); 95 | } 96 | lua_assert((nsize == 0) == (newblock == NULL)); 97 | g->GCdebt = (g->GCdebt + nsize) - realosize; 98 | return newblock; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/lmem.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $ 3 | ** Interface to Memory Manager 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lmem_h 8 | #define lmem_h 9 | 10 | 11 | #include 12 | 13 | #include "llimits.h" 14 | #include "lua.h" 15 | 16 | 17 | /* 18 | ** This macro reallocs a vector 'b' from 'on' to 'n' elements, where 19 | ** each element has size 'e'. In case of arithmetic overflow of the 20 | ** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because 21 | ** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). 22 | ** 23 | ** (The macro is somewhat complex to avoid warnings: The 'sizeof' 24 | ** comparison avoids a runtime comparison when overflow cannot occur. 25 | ** The compiler should be able to optimize the real test by itself, but 26 | ** when it does it, it may give a warning about "comparison is always 27 | ** false due to limited range of data type"; the +1 tricks the compiler, 28 | ** avoiding this warning but also this optimization.) 29 | */ 30 | #define luaM_reallocv(L,b,on,n,e) \ 31 | (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ 32 | ? luaM_toobig(L) : cast_void(0)) , \ 33 | luaM_realloc_(L, (b), (on)*(e), (n)*(e))) 34 | 35 | /* 36 | ** Arrays of chars do not need any test 37 | */ 38 | #define luaM_reallocvchar(L,b,on,n) \ 39 | cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) 40 | 41 | #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) 42 | #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) 43 | #define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) 44 | 45 | #define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) 46 | #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) 47 | #define luaM_newvector(L,n,t) \ 48 | cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) 49 | 50 | #define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) 51 | 52 | #define luaM_growvector(L,v,nelems,size,t,limit,e) \ 53 | if ((nelems)+1 > (size)) \ 54 | ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) 55 | 56 | #define luaM_reallocvector(L, v,oldn,n,t) \ 57 | ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) 58 | 59 | LUAI_FUNC l_noret luaM_toobig (lua_State *L); 60 | 61 | /* not to be called directly */ 62 | LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, 63 | size_t size); 64 | LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, 65 | size_t size_elem, int limit, 66 | const char *what); 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /src/lopcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $ 3 | ** Opcodes for Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lopcodes_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lopcodes.h" 16 | 17 | 18 | /* ORDER OP */ 19 | 20 | LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { 21 | "MOVE", 22 | "LOADK", 23 | "LOADKX", 24 | "LOADBOOL", 25 | "LOADNIL", 26 | "GETUPVAL", 27 | "GETTABUP", 28 | "GETTABLE", 29 | "SETTABUP", 30 | "SETUPVAL", 31 | "SETTABLE", 32 | "NEWTABLE", 33 | "SELF", 34 | "ADD", 35 | "SUB", 36 | "MUL", 37 | "MOD", 38 | "POW", 39 | "DIV", 40 | "IDIV", 41 | "BAND", 42 | "BOR", 43 | "BXOR", 44 | "SHL", 45 | "SHR", 46 | "UNM", 47 | "BNOT", 48 | "NOT", 49 | "LEN", 50 | "CONCAT", 51 | "JMP", 52 | "EQ", 53 | "LT", 54 | "LE", 55 | "TEST", 56 | "TESTSET", 57 | "CALL", 58 | "TAILCALL", 59 | "RETURN", 60 | "FORLOOP", 61 | "FORPREP", 62 | "TFORCALL", 63 | "TFORLOOP", 64 | "SETLIST", 65 | "CLOSURE", 66 | "VARARG", 67 | "EXTRAARG", 68 | NULL 69 | }; 70 | 71 | 72 | #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) 73 | 74 | LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { 75 | /* T A B C mode opcode */ 76 | opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ 77 | ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ 78 | ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ 79 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ 80 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ 81 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ 82 | ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ 83 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ 84 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ 85 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ 86 | ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ 87 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ 88 | ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ 89 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ 90 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ 91 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ 92 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ 93 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ 94 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ 95 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ 96 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ 97 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ 98 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ 99 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ 100 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ 101 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ 102 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ 103 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ 104 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ 105 | ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ 106 | ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ 107 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ 108 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ 109 | ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ 110 | ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ 111 | ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ 112 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ 113 | ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ 114 | ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ 115 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ 116 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ 117 | ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ 118 | ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ 119 | ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ 120 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ 121 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ 122 | ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ 123 | }; 124 | 125 | -------------------------------------------------------------------------------- /src/lparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lparser.h,v 1.74 2014/10/25 11:50:46 roberto Exp $ 3 | ** Lua Parser 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lparser_h 8 | #define lparser_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* 16 | ** Expression descriptor 17 | */ 18 | 19 | typedef enum { 20 | VVOID, /* no value */ 21 | VNIL, 22 | VTRUE, 23 | VFALSE, 24 | VK, /* info = index of constant in 'k' */ 25 | VKFLT, /* nval = numerical float value */ 26 | VKINT, /* nval = numerical integer value */ 27 | VNONRELOC, /* info = result register */ 28 | VLOCAL, /* info = local register */ 29 | VUPVAL, /* info = index of upvalue in 'upvalues' */ 30 | VINDEXED, /* t = table register/upvalue; idx = index R/K */ 31 | VJMP, /* info = instruction pc */ 32 | VRELOCABLE, /* info = instruction pc */ 33 | VCALL, /* info = instruction pc */ 34 | VVARARG /* info = instruction pc */ 35 | } expkind; 36 | 37 | 38 | #define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) 39 | #define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) 40 | 41 | typedef struct expdesc { 42 | expkind k; 43 | union { 44 | struct { /* for indexed variables (VINDEXED) */ 45 | short idx; /* index (R/K) */ 46 | lu_byte t; /* table (register or upvalue) */ 47 | lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ 48 | } ind; 49 | int info; /* for generic use */ 50 | lua_Number nval; /* for VKFLT */ 51 | lua_Integer ival; /* for VKINT */ 52 | } u; 53 | int t; /* patch list of 'exit when true' */ 54 | int f; /* patch list of 'exit when false' */ 55 | } expdesc; 56 | 57 | 58 | /* description of active local variable */ 59 | typedef struct Vardesc { 60 | short idx; /* variable index in stack */ 61 | } Vardesc; 62 | 63 | 64 | /* description of pending goto statements and label statements */ 65 | typedef struct Labeldesc { 66 | TString *name; /* label identifier */ 67 | int pc; /* position in code */ 68 | int line; /* line where it appeared */ 69 | lu_byte nactvar; /* local level where it appears in current block */ 70 | } Labeldesc; 71 | 72 | 73 | /* list of labels or gotos */ 74 | typedef struct Labellist { 75 | Labeldesc *arr; /* array */ 76 | int n; /* number of entries in use */ 77 | int size; /* array size */ 78 | } Labellist; 79 | 80 | 81 | /* dynamic structures used by the parser */ 82 | typedef struct Dyndata { 83 | struct { /* list of active local variables */ 84 | Vardesc *arr; 85 | int n; 86 | int size; 87 | } actvar; 88 | Labellist gt; /* list of pending gotos */ 89 | Labellist label; /* list of active labels */ 90 | } Dyndata; 91 | 92 | 93 | /* control of blocks */ 94 | struct BlockCnt; /* defined in lparser.c */ 95 | 96 | 97 | /* state needed to generate code for a given function */ 98 | typedef struct FuncState { 99 | Proto *f; /* current function header */ 100 | struct FuncState *prev; /* enclosing function */ 101 | struct LexState *ls; /* lexical state */ 102 | struct BlockCnt *bl; /* chain of current blocks */ 103 | int pc; /* next position to code (equivalent to 'ncode') */ 104 | int lasttarget; /* 'label' of last 'jump label' */ 105 | int jpc; /* list of pending jumps to 'pc' */ 106 | int nk; /* number of elements in 'k' */ 107 | int np; /* number of elements in 'p' */ 108 | int firstlocal; /* index of first local var (in Dyndata array) */ 109 | short nlocvars; /* number of elements in 'f->locvars' */ 110 | lu_byte nactvar; /* number of active local variables */ 111 | lu_byte nups; /* number of upvalues */ 112 | lu_byte freereg; /* first free register */ 113 | } FuncState; 114 | 115 | 116 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 117 | Dyndata *dyd, const char *name, int firstchar); 118 | 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/lprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ 3 | ** Definitions for Lua code that must come before any other header file 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lprefix_h 8 | #define lprefix_h 9 | 10 | 11 | /* 12 | ** Allows POSIX/XSI stuff 13 | */ 14 | #if !defined(LUA_USE_C89) /* { */ 15 | 16 | #if !defined(_XOPEN_SOURCE) 17 | #define _XOPEN_SOURCE 600 18 | #elif _XOPEN_SOURCE == 0 19 | #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ 20 | #endif 21 | 22 | /* 23 | ** Allows manipulation of large files in gcc and some other compilers 24 | */ 25 | #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) 26 | #define _LARGEFILE_SOURCE 1 27 | #define _FILE_OFFSET_BITS 64 28 | #endif 29 | 30 | #endif /* } */ 31 | 32 | 33 | /* 34 | ** Windows stuff 35 | */ 36 | #if defined(_WIN32) /* { */ 37 | 38 | #if !defined(_CRT_SECURE_NO_WARNINGS) 39 | #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ 40 | #endif 41 | 42 | #endif /* } */ 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/lstate.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp $ 3 | ** Global State 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstate_h 8 | #define lstate_h 9 | 10 | #include "lua.h" 11 | 12 | #include "lobject.h" 13 | #include "ltm.h" 14 | #include "lzio.h" 15 | 16 | 17 | /* 18 | 19 | ** Some notes about garbage-collected objects: All objects in Lua must 20 | ** be kept somehow accessible until being freed, so all objects always 21 | ** belong to one (and only one) of these lists, using field 'next' of 22 | ** the 'CommonHeader' for the link: 23 | ** 24 | ** 'allgc': all objects not marked for finalization; 25 | ** 'finobj': all objects marked for finalization; 26 | ** 'tobefnz': all objects ready to be finalized; 27 | ** 'fixedgc': all objects that are not to be collected (currently 28 | ** only small strings, such as reserved words). 29 | 30 | */ 31 | 32 | 33 | struct lua_longjmp; /* defined in ldo.c */ 34 | 35 | 36 | 37 | /* extra stack space to handle TM calls and some other extras */ 38 | #define EXTRA_STACK 5 39 | 40 | 41 | #define BASIC_STACK_SIZE (2*LUA_MINSTACK) 42 | 43 | 44 | /* kinds of Garbage Collection */ 45 | #define KGC_NORMAL 0 46 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ 47 | 48 | 49 | typedef struct stringtable { 50 | TString **hash; 51 | int nuse; /* number of elements */ 52 | int size; 53 | } stringtable; 54 | 55 | 56 | /* 57 | ** Information about a call. 58 | ** When a thread yields, 'func' is adjusted to pretend that the 59 | ** top function has only the yielded values in its stack; in that 60 | ** case, the actual 'func' value is saved in field 'extra'. 61 | ** When a function calls another with a continuation, 'extra' keeps 62 | ** the function index so that, in case of errors, the continuation 63 | ** function can be called with the correct top. 64 | */ 65 | typedef struct CallInfo { 66 | StkId func; /* function index in the stack */ 67 | StkId top; /* top for this function */ 68 | struct CallInfo *previous, *next; /* dynamic call link */ 69 | union { 70 | struct { /* only for Lua functions */ 71 | StkId base; /* base for this function */ 72 | const Instruction *savedpc; 73 | } l; 74 | struct { /* only for C functions */ 75 | lua_KFunction k; /* continuation in case of yields */ 76 | ptrdiff_t old_errfunc; 77 | lua_KContext ctx; /* context info. in case of yields */ 78 | } c; 79 | } u; 80 | ptrdiff_t extra; 81 | short nresults; /* expected number of results from this function */ 82 | lu_byte callstatus; 83 | } CallInfo; 84 | 85 | 86 | /* 87 | ** Bits in CallInfo status 88 | */ 89 | #define CIST_OAH (1<<0) /* original value of 'allowhook' */ 90 | #define CIST_LUA (1<<1) /* call is running a Lua function */ 91 | #define CIST_HOOKED (1<<2) /* call is running a debug hook */ 92 | #define CIST_REENTRY (1<<3) /* call is running on same invocation of 93 | luaV_execute of previous call */ 94 | #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ 95 | #define CIST_TAIL (1<<5) /* call was tail called */ 96 | #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ 97 | #define CIST_LEQ (1<<7) /* using __lt for __le */ 98 | 99 | #define isLua(ci) ((ci)->callstatus & CIST_LUA) 100 | 101 | /* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ 102 | #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) 103 | #define getoah(st) ((st) & CIST_OAH) 104 | 105 | 106 | /* 107 | ** 'global state', shared by all threads of this state 108 | */ 109 | typedef struct global_State { 110 | lua_Alloc frealloc; /* function to reallocate memory */ 111 | void *ud; /* auxiliary data to 'frealloc' */ 112 | lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ 113 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ 114 | lu_mem GCmemtrav; /* memory traversed by the GC */ 115 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ 116 | stringtable strt; /* hash table for strings */ 117 | TValue l_registry; 118 | unsigned int seed; /* randomized seed for hashes */ 119 | lu_byte currentwhite; 120 | lu_byte gcstate; /* state of garbage collector */ 121 | lu_byte gckind; /* kind of GC running */ 122 | lu_byte gcrunning; /* true if GC is running */ 123 | GCObject *allgc; /* list of all collectable objects */ 124 | GCObject **sweepgc; /* current position of sweep in list */ 125 | GCObject *finobj; /* list of collectable objects with finalizers */ 126 | GCObject *gray; /* list of gray objects */ 127 | GCObject *grayagain; /* list of objects to be traversed atomically */ 128 | GCObject *weak; /* list of tables with weak values */ 129 | GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ 130 | GCObject *allweak; /* list of all-weak tables */ 131 | GCObject *tobefnz; /* list of userdata to be GC */ 132 | GCObject *fixedgc; /* list of objects not to be collected */ 133 | struct lua_State *twups; /* list of threads with open upvalues */ 134 | Mbuffer buff; /* temporary buffer for string concatenation */ 135 | unsigned int gcfinnum; /* number of finalizers to call in each GC step */ 136 | int gcpause; /* size of pause between successive GCs */ 137 | int gcstepmul; /* GC 'granularity' */ 138 | lua_CFunction panic; /* to be called in unprotected errors */ 139 | struct lua_State *mainthread; 140 | const lua_Number *version; /* pointer to version number */ 141 | TString *memerrmsg; /* memory-error message */ 142 | TString *tmname[TM_N]; /* array with tag-method names */ 143 | struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ 144 | TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */ 145 | } global_State; 146 | 147 | 148 | /* 149 | ** 'per thread' state 150 | */ 151 | struct lua_State { 152 | CommonHeader; 153 | lu_byte status; 154 | StkId top; /* first free slot in the stack */ 155 | global_State *l_G; 156 | CallInfo *ci; /* call info for current function */ 157 | const Instruction *oldpc; /* last pc traced */ 158 | StkId stack_last; /* last free slot in the stack */ 159 | StkId stack; /* stack base */ 160 | UpVal *openupval; /* list of open upvalues in this stack */ 161 | GCObject *gclist; 162 | struct lua_State *twups; /* list of threads with open upvalues */ 163 | struct lua_longjmp *errorJmp; /* current error recover point */ 164 | CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ 165 | lua_Hook hook; 166 | ptrdiff_t errfunc; /* current error handling function (stack index) */ 167 | int stacksize; 168 | int basehookcount; 169 | int hookcount; 170 | unsigned short nny; /* number of non-yieldable calls in stack */ 171 | unsigned short nCcalls; /* number of nested C calls */ 172 | lu_byte hookmask; 173 | lu_byte allowhook; 174 | }; 175 | 176 | 177 | #define G(L) (L->l_G) 178 | 179 | 180 | /* 181 | ** Union of all collectable objects (only for conversions) 182 | */ 183 | union GCUnion { 184 | GCObject gc; /* common header */ 185 | struct TString ts; 186 | struct Udata u; 187 | union Closure cl; 188 | struct Table h; 189 | struct Proto p; 190 | struct lua_State th; /* thread */ 191 | }; 192 | 193 | 194 | #define cast_u(o) cast(union GCUnion *, (o)) 195 | 196 | /* macros to convert a GCObject into a specific value */ 197 | #define gco2ts(o) \ 198 | check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) 199 | #define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u)) 200 | #define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) 201 | #define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c)) 202 | #define gco2cl(o) \ 203 | check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) 204 | #define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) 205 | #define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) 206 | #define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) 207 | 208 | 209 | /* macro to convert a Lua object into a GCObject */ 210 | #define obj2gco(v) \ 211 | check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc))) 212 | 213 | 214 | /* actual number of total bytes allocated */ 215 | #define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) 216 | 217 | LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); 218 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); 219 | LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); 220 | LUAI_FUNC void luaE_freeCI (lua_State *L); 221 | LUAI_FUNC void luaE_shrinkCI (lua_State *L); 222 | 223 | 224 | #endif 225 | 226 | -------------------------------------------------------------------------------- /src/lstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $ 3 | ** String table (keeps all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lstring_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lmem.h" 20 | #include "lobject.h" 21 | #include "lstate.h" 22 | #include "lstring.h" 23 | 24 | 25 | #define MEMERRMSG "not enough memory" 26 | 27 | 28 | /* 29 | ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to 30 | ** compute its hash 31 | */ 32 | #if !defined(LUAI_HASHLIMIT) 33 | #define LUAI_HASHLIMIT 5 34 | #endif 35 | 36 | 37 | /* 38 | ** equality for long strings 39 | */ 40 | int luaS_eqlngstr (TString *a, TString *b) { 41 | size_t len = a->u.lnglen; 42 | lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); 43 | return (a == b) || /* same instance or... */ 44 | ((len == b->u.lnglen) && /* equal length and ... */ 45 | (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ 46 | } 47 | 48 | 49 | unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { 50 | unsigned int h = seed ^ cast(unsigned int, l); 51 | size_t l1; 52 | size_t step = (l >> LUAI_HASHLIMIT) + 1; 53 | for (l1 = l; l1 >= step; l1 -= step) 54 | h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); 55 | return h; 56 | } 57 | 58 | 59 | /* 60 | ** resizes the string table 61 | */ 62 | void luaS_resize (lua_State *L, int newsize) { 63 | int i; 64 | stringtable *tb = &G(L)->strt; 65 | if (newsize > tb->size) { /* grow table if needed */ 66 | luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); 67 | for (i = tb->size; i < newsize; i++) 68 | tb->hash[i] = NULL; 69 | } 70 | for (i = 0; i < tb->size; i++) { /* rehash */ 71 | TString *p = tb->hash[i]; 72 | tb->hash[i] = NULL; 73 | while (p) { /* for each node in the list */ 74 | TString *hnext = p->u.hnext; /* save next */ 75 | unsigned int h = lmod(p->hash, newsize); /* new position */ 76 | p->u.hnext = tb->hash[h]; /* chain it */ 77 | tb->hash[h] = p; 78 | p = hnext; 79 | } 80 | } 81 | if (newsize < tb->size) { /* shrink table if needed */ 82 | /* vanishing slice should be empty */ 83 | lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); 84 | luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); 85 | } 86 | tb->size = newsize; 87 | } 88 | 89 | 90 | /* 91 | ** Clear API string cache. (Entries cannot be empty, so fill them with 92 | ** a non-collectable string.) 93 | */ 94 | void luaS_clearcache (global_State *g) { 95 | int i; 96 | for (i = 0; i < STRCACHE_SIZE; i++) { 97 | if (iswhite(g->strcache[i][0])) /* will entry be collected? */ 98 | g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */ 99 | } 100 | } 101 | 102 | 103 | /* 104 | ** Initialize the string table and the string cache 105 | */ 106 | void luaS_init (lua_State *L) { 107 | global_State *g = G(L); 108 | int i; 109 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ 110 | /* pre-create memory-error message */ 111 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); 112 | luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ 113 | for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */ 114 | g->strcache[i][0] = g->memerrmsg; 115 | } 116 | 117 | 118 | 119 | /* 120 | ** creates a new string object 121 | */ 122 | static TString *createstrobj (lua_State *L, const char *str, size_t l, 123 | int tag, unsigned int h) { 124 | TString *ts; 125 | GCObject *o; 126 | size_t totalsize; /* total size of TString object */ 127 | totalsize = sizelstring(l); 128 | o = luaC_newobj(L, tag, totalsize); 129 | ts = gco2ts(o); 130 | ts->hash = h; 131 | ts->extra = 0; 132 | memcpy(getaddrstr(ts), str, l * sizeof(char)); 133 | getaddrstr(ts)[l] = '\0'; /* ending 0 */ 134 | return ts; 135 | } 136 | 137 | 138 | void luaS_remove (lua_State *L, TString *ts) { 139 | stringtable *tb = &G(L)->strt; 140 | TString **p = &tb->hash[lmod(ts->hash, tb->size)]; 141 | while (*p != ts) /* find previous element */ 142 | p = &(*p)->u.hnext; 143 | *p = (*p)->u.hnext; /* remove element from its list */ 144 | tb->nuse--; 145 | } 146 | 147 | 148 | /* 149 | ** checks whether short string exists and reuses it or creates a new one 150 | */ 151 | static TString *internshrstr (lua_State *L, const char *str, size_t l) { 152 | TString *ts; 153 | global_State *g = G(L); 154 | unsigned int h = luaS_hash(str, l, g->seed); 155 | TString **list = &g->strt.hash[lmod(h, g->strt.size)]; 156 | for (ts = *list; ts != NULL; ts = ts->u.hnext) { 157 | if (l == ts->shrlen && 158 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { 159 | /* found! */ 160 | if (isdead(g, ts)) /* dead (but not collected yet)? */ 161 | changewhite(ts); /* resurrect it */ 162 | return ts; 163 | } 164 | } 165 | if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { 166 | luaS_resize(L, g->strt.size * 2); 167 | list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ 168 | } 169 | ts = createstrobj(L, str, l, LUA_TSHRSTR, h); 170 | ts->shrlen = cast_byte(l); 171 | ts->u.hnext = *list; 172 | *list = ts; 173 | g->strt.nuse++; 174 | return ts; 175 | } 176 | 177 | 178 | /* 179 | ** new string (with explicit length) 180 | */ 181 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { 182 | if (l <= LUAI_MAXSHORTLEN) /* short string? */ 183 | return internshrstr(L, str, l); 184 | else { 185 | TString *ts; 186 | if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) 187 | luaM_toobig(L); 188 | ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); 189 | ts->u.lnglen = l; 190 | return ts; 191 | } 192 | } 193 | 194 | 195 | /* 196 | ** Create or reuse a zero-terminated string, first checking in the 197 | ** cache (using the string address as a key). The cache can contain 198 | ** only zero-terminated strings, so it is safe to use 'strcmp' to 199 | ** check hits. 200 | */ 201 | TString *luaS_new (lua_State *L, const char *str) { 202 | unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */ 203 | TString **p = G(L)->strcache[i]; 204 | if (strcmp(str, getstr(p[0])) == 0) /* hit? */ 205 | return p[0]; /* that it is */ 206 | else { /* normal route */ 207 | TString *s = luaS_newlstr(L, str, strlen(str)); 208 | p[0] = s; 209 | return s; 210 | } 211 | } 212 | 213 | 214 | Udata *luaS_newudata (lua_State *L, size_t s) { 215 | Udata *u; 216 | GCObject *o; 217 | if (s > MAX_SIZE - sizeof(Udata)) 218 | luaM_toobig(L); 219 | o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); 220 | u = gco2u(o); 221 | u->len = s; 222 | u->metatable = NULL; 223 | setuservalue(L, u, luaO_nilobject); 224 | return u; 225 | } 226 | 227 | -------------------------------------------------------------------------------- /src/lstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp $ 3 | ** String table (keep all strings handled by Lua) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lstring_h 8 | #define lstring_h 9 | 10 | #include "lgc.h" 11 | #include "lobject.h" 12 | #include "lstate.h" 13 | 14 | 15 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) 16 | 17 | #define sizeludata(l) (sizeof(union UUdata) + (l)) 18 | #define sizeudata(u) sizeludata((u)->len) 19 | 20 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 21 | (sizeof(s)/sizeof(char))-1)) 22 | 23 | 24 | /* 25 | ** test whether a string is a reserved word 26 | */ 27 | #define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) 28 | 29 | 30 | /* 31 | ** equality for short strings, which are always internalized 32 | */ 33 | #define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) 34 | 35 | 36 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); 37 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); 38 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); 39 | LUAI_FUNC void luaS_clearcache (global_State *g); 40 | LUAI_FUNC void luaS_init (lua_State *L); 41 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); 42 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); 43 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 44 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/ltable.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp $ 3 | ** Lua tables (hash) 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltable_h 8 | #define ltable_h 9 | 10 | #include "lobject.h" 11 | 12 | 13 | #define gnode(t,i) (&(t)->node[i]) 14 | #define gval(n) (&(n)->i_val) 15 | #define gnext(n) ((n)->i_key.nk.next) 16 | 17 | 18 | /* 'const' to avoid wrong writings that can mess up field 'next' */ 19 | #define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) 20 | 21 | #define wgkey(n) (&(n)->i_key.nk) 22 | 23 | #define invalidateTMcache(t) ((t)->flags = 0) 24 | 25 | 26 | /* returns the key, given the value of a table entry */ 27 | #define keyfromval(v) \ 28 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) 29 | 30 | 31 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); 32 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, 33 | TValue *value); 34 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); 35 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); 36 | LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); 37 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); 38 | LUAI_FUNC Table *luaH_new (lua_State *L); 39 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, 40 | unsigned int nhsize); 41 | LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); 42 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); 43 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 44 | LUAI_FUNC int luaH_getn (Table *t); 45 | 46 | 47 | #if defined(LUA_DEBUG) 48 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); 49 | LUAI_FUNC int luaH_isdummy (Node *n); 50 | #endif 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/ltm.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ltm_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lobject.h" 20 | #include "lstate.h" 21 | #include "lstring.h" 22 | #include "ltable.h" 23 | #include "ltm.h" 24 | #include "lvm.h" 25 | 26 | 27 | static const char udatatypename[] = "userdata"; 28 | 29 | LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { 30 | "no value", 31 | "nil", "boolean", udatatypename, "number", 32 | "string", "table", "function", udatatypename, "thread", 33 | "proto" /* this last case is used for tests only */ 34 | }; 35 | 36 | 37 | void luaT_init (lua_State *L) { 38 | static const char *const luaT_eventname[] = { /* ORDER TM */ 39 | "__index", "__newindex", 40 | "__gc", "__mode", "__len", "__eq", 41 | "__add", "__sub", "__mul", "__mod", "__pow", 42 | "__div", "__idiv", 43 | "__band", "__bor", "__bxor", "__shl", "__shr", 44 | "__unm", "__bnot", "__lt", "__le", 45 | "__concat", "__call" 46 | }; 47 | int i; 48 | for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); 50 | luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ 51 | } 52 | } 53 | 54 | 55 | /* 56 | ** function to be used with macro "fasttm": optimized for absence of 57 | ** tag methods 58 | */ 59 | const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { 60 | const TValue *tm = luaH_getstr(events, ename); 61 | lua_assert(event <= TM_EQ); 62 | if (ttisnil(tm)) { /* no tag method? */ 63 | events->flags |= cast_byte(1u<metatable; 75 | break; 76 | case LUA_TUSERDATA: 77 | mt = uvalue(o)->metatable; 78 | break; 79 | default: 80 | mt = G(L)->mt[ttnov(o)]; 81 | } 82 | return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); 83 | } 84 | 85 | 86 | void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 87 | const TValue *p2, TValue *p3, int hasres) { 88 | ptrdiff_t result = savestack(L, p3); 89 | setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */ 90 | setobj2s(L, L->top++, p1); /* 1st argument */ 91 | setobj2s(L, L->top++, p2); /* 2nd argument */ 92 | if (!hasres) /* no result? 'p3' is third argument */ 93 | setobj2s(L, L->top++, p3); /* 3rd argument */ 94 | /* metamethod may yield only when called from Lua code */ 95 | luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); 96 | if (hasres) { /* if has result, move it to its place */ 97 | p3 = restorestack(L, result); 98 | setobjs2s(L, p3, --L->top); 99 | } 100 | } 101 | 102 | 103 | int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 104 | StkId res, TMS event) { 105 | const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 106 | if (ttisnil(tm)) 107 | tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 108 | if (ttisnil(tm)) return 0; 109 | luaT_callTM(L, tm, p1, p2, res, 1); 110 | return 1; 111 | } 112 | 113 | 114 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 115 | StkId res, TMS event) { 116 | if (!luaT_callbinTM(L, p1, p2, res, event)) { 117 | switch (event) { 118 | case TM_CONCAT: 119 | luaG_concaterror(L, p1, p2); 120 | /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ 121 | case TM_BAND: case TM_BOR: case TM_BXOR: 122 | case TM_SHL: case TM_SHR: case TM_BNOT: { 123 | lua_Number dummy; 124 | if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) 125 | luaG_tointerror(L, p1, p2); 126 | else 127 | luaG_opinterror(L, p1, p2, "perform bitwise operation on"); 128 | } 129 | /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ 130 | default: 131 | luaG_opinterror(L, p1, p2, "perform arithmetic on"); 132 | } 133 | } 134 | } 135 | 136 | 137 | int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, 138 | TMS event) { 139 | if (!luaT_callbinTM(L, p1, p2, L->top, event)) 140 | return -1; /* no metamethod */ 141 | else 142 | return !l_isfalse(L->top); 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/ltm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltm.h,v 2.21 2014/10/25 11:50:46 roberto Exp $ 3 | ** Tag methods 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef ltm_h 8 | #define ltm_h 9 | 10 | 11 | #include "lobject.h" 12 | 13 | 14 | /* 15 | * WARNING: if you change the order of this enumeration, 16 | * grep "ORDER TM" and "ORDER OP" 17 | */ 18 | typedef enum { 19 | TM_INDEX, 20 | TM_NEWINDEX, 21 | TM_GC, 22 | TM_MODE, 23 | TM_LEN, 24 | TM_EQ, /* last tag method with fast access */ 25 | TM_ADD, 26 | TM_SUB, 27 | TM_MUL, 28 | TM_MOD, 29 | TM_POW, 30 | TM_DIV, 31 | TM_IDIV, 32 | TM_BAND, 33 | TM_BOR, 34 | TM_BXOR, 35 | TM_SHL, 36 | TM_SHR, 37 | TM_UNM, 38 | TM_BNOT, 39 | TM_LT, 40 | TM_LE, 41 | TM_CONCAT, 42 | TM_CALL, 43 | TM_N /* number of elements in the enum */ 44 | } TMS; 45 | 46 | 47 | 48 | #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ 49 | ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) 50 | 51 | #define fasttm(l,et,e) gfasttm(G(l), et, e) 52 | 53 | #define ttypename(x) luaT_typenames_[(x) + 1] 54 | #define objtypename(x) ttypename(ttnov(x)) 55 | 56 | LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; 57 | 58 | 59 | LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); 60 | LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, 61 | TMS event); 62 | LUAI_FUNC void luaT_init (lua_State *L); 63 | 64 | LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 65 | const TValue *p2, TValue *p3, int hasres); 66 | LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, 67 | StkId res, TMS event); 68 | LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 69 | StkId res, TMS event); 70 | LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, 71 | const TValue *p2, TMS event); 72 | 73 | 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/lua.hpp: -------------------------------------------------------------------------------- 1 | // lua.hpp 2 | // Lua header files for C++ 3 | // <> not supplied automatically because Lua also compiles as C++ 4 | 5 | extern "C" { 6 | #include "lua.h" 7 | #include "lualib.h" 8 | #include "lauxlib.h" 9 | } 10 | -------------------------------------------------------------------------------- /src/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | 15 | LUAMOD_API int (luaopen_base) (lua_State *L); 16 | 17 | #define LUA_COLIBNAME "coroutine" 18 | LUAMOD_API int (luaopen_coroutine) (lua_State *L); 19 | 20 | #define LUA_TABLIBNAME "table" 21 | LUAMOD_API int (luaopen_table) (lua_State *L); 22 | 23 | #define LUA_IOLIBNAME "io" 24 | LUAMOD_API int (luaopen_io) (lua_State *L); 25 | 26 | #define LUA_OSLIBNAME "os" 27 | LUAMOD_API int (luaopen_os) (lua_State *L); 28 | 29 | #define LUA_STRLIBNAME "string" 30 | LUAMOD_API int (luaopen_string) (lua_State *L); 31 | 32 | #define LUA_UTF8LIBNAME "utf8" 33 | LUAMOD_API int (luaopen_utf8) (lua_State *L); 34 | 35 | #define LUA_BITLIBNAME "bit32" 36 | LUAMOD_API int (luaopen_bit32) (lua_State *L); 37 | 38 | #define LUA_MATHLIBNAME "math" 39 | LUAMOD_API int (luaopen_math) (lua_State *L); 40 | 41 | #define LUA_DBLIBNAME "debug" 42 | LUAMOD_API int (luaopen_debug) (lua_State *L); 43 | 44 | #define LUA_LOADLIBNAME "package" 45 | LUAMOD_API int (luaopen_package) (lua_State *L); 46 | 47 | 48 | /* open all previous libraries */ 49 | LUALIB_API void (luaL_openlibs) (lua_State *L); 50 | 51 | 52 | 53 | #if !defined(lua_assert) 54 | #define lua_assert(x) ((void)0) 55 | #endif 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/lundump.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lundump_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "ldebug.h" 18 | #include "ldo.h" 19 | #include "lfunc.h" 20 | #include "lmem.h" 21 | #include "lobject.h" 22 | #include "lstring.h" 23 | #include "lundump.h" 24 | #include "lzio.h" 25 | 26 | 27 | #if !defined(luai_verifycode) 28 | #define luai_verifycode(L,b,f) /* empty */ 29 | #endif 30 | 31 | 32 | typedef struct { 33 | lua_State *L; 34 | ZIO *Z; 35 | Mbuffer *b; 36 | const char *name; 37 | } LoadState; 38 | 39 | 40 | static l_noret error(LoadState *S, const char *why) { 41 | luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); 42 | luaD_throw(S->L, LUA_ERRSYNTAX); 43 | } 44 | 45 | 46 | /* 47 | ** All high-level loads go through LoadVector; you can change it to 48 | ** adapt to the endianness of the input 49 | */ 50 | #define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) 51 | 52 | static void LoadBlock (LoadState *S, void *b, size_t size) { 53 | if (luaZ_read(S->Z, b, size) != 0) 54 | error(S, "truncated"); 55 | } 56 | 57 | 58 | #define LoadVar(S,x) LoadVector(S,&x,1) 59 | 60 | 61 | static lu_byte LoadByte (LoadState *S) { 62 | lu_byte x; 63 | LoadVar(S, x); 64 | return x; 65 | } 66 | 67 | 68 | static int LoadInt (LoadState *S) { 69 | int x; 70 | LoadVar(S, x); 71 | return x; 72 | } 73 | 74 | 75 | static lua_Number LoadNumber (LoadState *S) { 76 | lua_Number x; 77 | LoadVar(S, x); 78 | return x; 79 | } 80 | 81 | 82 | static lua_Integer LoadInteger (LoadState *S) { 83 | lua_Integer x; 84 | LoadVar(S, x); 85 | return x; 86 | } 87 | 88 | 89 | static TString *LoadString (LoadState *S) { 90 | size_t size = LoadByte(S); 91 | if (size == 0xFF) 92 | LoadVar(S, size); 93 | if (size == 0) 94 | return NULL; 95 | else { 96 | char *s = luaZ_openspace(S->L, S->b, --size); 97 | LoadVector(S, s, size); 98 | return luaS_newlstr(S->L, s, size); 99 | } 100 | } 101 | 102 | 103 | static void LoadCode (LoadState *S, Proto *f) { 104 | int n = LoadInt(S); 105 | f->code = luaM_newvector(S->L, n, Instruction); 106 | f->sizecode = n; 107 | LoadVector(S, f->code, n); 108 | } 109 | 110 | 111 | static void LoadFunction(LoadState *S, Proto *f, TString *psource); 112 | 113 | 114 | static void LoadConstants (LoadState *S, Proto *f) { 115 | int i; 116 | int n = LoadInt(S); 117 | f->k = luaM_newvector(S->L, n, TValue); 118 | f->sizek = n; 119 | for (i = 0; i < n; i++) 120 | setnilvalue(&f->k[i]); 121 | for (i = 0; i < n; i++) { 122 | TValue *o = &f->k[i]; 123 | int t = LoadByte(S); 124 | switch (t) { 125 | case LUA_TNIL: 126 | setnilvalue(o); 127 | break; 128 | case LUA_TBOOLEAN: 129 | setbvalue(o, LoadByte(S)); 130 | break; 131 | case LUA_TNUMFLT: 132 | setfltvalue(o, LoadNumber(S)); 133 | break; 134 | case LUA_TNUMINT: 135 | setivalue(o, LoadInteger(S)); 136 | break; 137 | case LUA_TSHRSTR: 138 | case LUA_TLNGSTR: 139 | setsvalue2n(S->L, o, LoadString(S)); 140 | break; 141 | default: 142 | lua_assert(0); 143 | } 144 | } 145 | } 146 | 147 | 148 | static void LoadProtos (LoadState *S, Proto *f) { 149 | int i; 150 | int n = LoadInt(S); 151 | f->p = luaM_newvector(S->L, n, Proto *); 152 | f->sizep = n; 153 | for (i = 0; i < n; i++) 154 | f->p[i] = NULL; 155 | for (i = 0; i < n; i++) { 156 | f->p[i] = luaF_newproto(S->L); 157 | LoadFunction(S, f->p[i], f->source); 158 | } 159 | } 160 | 161 | 162 | static void LoadUpvalues (LoadState *S, Proto *f) { 163 | int i, n; 164 | n = LoadInt(S); 165 | f->upvalues = luaM_newvector(S->L, n, Upvaldesc); 166 | f->sizeupvalues = n; 167 | for (i = 0; i < n; i++) 168 | f->upvalues[i].name = NULL; 169 | for (i = 0; i < n; i++) { 170 | f->upvalues[i].instack = LoadByte(S); 171 | f->upvalues[i].idx = LoadByte(S); 172 | } 173 | } 174 | 175 | 176 | static void LoadDebug (LoadState *S, Proto *f) { 177 | int i, n; 178 | n = LoadInt(S); 179 | f->lineinfo = luaM_newvector(S->L, n, int); 180 | f->sizelineinfo = n; 181 | LoadVector(S, f->lineinfo, n); 182 | n = LoadInt(S); 183 | f->locvars = luaM_newvector(S->L, n, LocVar); 184 | f->sizelocvars = n; 185 | for (i = 0; i < n; i++) 186 | f->locvars[i].varname = NULL; 187 | for (i = 0; i < n; i++) { 188 | f->locvars[i].varname = LoadString(S); 189 | f->locvars[i].startpc = LoadInt(S); 190 | f->locvars[i].endpc = LoadInt(S); 191 | } 192 | n = LoadInt(S); 193 | for (i = 0; i < n; i++) 194 | f->upvalues[i].name = LoadString(S); 195 | } 196 | 197 | 198 | static void LoadFunction (LoadState *S, Proto *f, TString *psource) { 199 | f->source = LoadString(S); 200 | if (f->source == NULL) /* no source in dump? */ 201 | f->source = psource; /* reuse parent's source */ 202 | f->linedefined = LoadInt(S); 203 | f->lastlinedefined = LoadInt(S); 204 | f->numparams = LoadByte(S); 205 | f->is_vararg = LoadByte(S); 206 | f->maxstacksize = LoadByte(S); 207 | LoadCode(S, f); 208 | LoadConstants(S, f); 209 | LoadUpvalues(S, f); 210 | LoadProtos(S, f); 211 | LoadDebug(S, f); 212 | } 213 | 214 | 215 | static void checkliteral (LoadState *S, const char *s, const char *msg) { 216 | char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ 217 | size_t len = strlen(s); 218 | LoadVector(S, buff, len); 219 | if (memcmp(s, buff, len) != 0) 220 | error(S, msg); 221 | } 222 | 223 | 224 | static void fchecksize (LoadState *S, size_t size, const char *tname) { 225 | if (LoadByte(S) != size) 226 | error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); 227 | } 228 | 229 | 230 | #define checksize(S,t) fchecksize(S,sizeof(t),#t) 231 | 232 | static void checkHeader (LoadState *S) { 233 | checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ 234 | if (LoadByte(S) != LUAC_VERSION) 235 | error(S, "version mismatch in"); 236 | if (LoadByte(S) != LUAC_FORMAT) 237 | error(S, "format mismatch in"); 238 | checkliteral(S, LUAC_DATA, "corrupted"); 239 | checksize(S, int); 240 | checksize(S, size_t); 241 | checksize(S, Instruction); 242 | checksize(S, lua_Integer); 243 | checksize(S, lua_Number); 244 | if (LoadInteger(S) != LUAC_INT) 245 | error(S, "endianness mismatch in"); 246 | if (LoadNumber(S) != LUAC_NUM) 247 | error(S, "float format mismatch in"); 248 | } 249 | 250 | 251 | /* 252 | ** load precompiled chunk 253 | */ 254 | LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, 255 | const char *name) { 256 | LoadState S; 257 | LClosure *cl; 258 | if (*name == '@' || *name == '=') 259 | S.name = name + 1; 260 | else if (*name == LUA_SIGNATURE[0]) 261 | S.name = "binary string"; 262 | else 263 | S.name = name; 264 | S.L = L; 265 | S.Z = Z; 266 | S.b = buff; 267 | checkHeader(&S); 268 | cl = luaF_newLclosure(L, LoadByte(&S)); 269 | setclLvalue(L, L->top, cl); 270 | incr_top(L); 271 | cl->p = luaF_newproto(L); 272 | LoadFunction(&S, cl->p, NULL); 273 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); 274 | luai_verifycode(L, buff, cl->p); 275 | return cl; 276 | } 277 | 278 | -------------------------------------------------------------------------------- /src/lundump.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp $ 3 | ** load precompiled Lua chunks 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lundump_h 8 | #define lundump_h 9 | 10 | #include "llimits.h" 11 | #include "lobject.h" 12 | #include "lzio.h" 13 | 14 | 15 | /* data to catch conversion errors */ 16 | #define LUAC_DATA "\x19\x93\r\n\x1a\n" 17 | 18 | #define LUAC_INT 0x5678 19 | #define LUAC_NUM cast_num(370.5) 20 | 21 | #define MYINT(s) (s[0]-'0') 22 | #define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) 23 | #define LUAC_FORMAT 0 /* this is the official format */ 24 | 25 | /* load one chunk; from lundump.c */ 26 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, 27 | const char* name); 28 | 29 | /* dump one chunk; from ldump.c */ 30 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 31 | void* data, int strip); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/lutf8lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lutf8lib.c,v 1.15 2015/03/28 19:16:55 roberto Exp $ 3 | ** Standard library for UTF-8 manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lutf8lib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "lua.h" 19 | 20 | #include "lauxlib.h" 21 | #include "lualib.h" 22 | 23 | #define MAXUNICODE 0x10FFFF 24 | 25 | #define iscont(p) ((*(p) & 0xC0) == 0x80) 26 | 27 | 28 | /* from strlib */ 29 | /* translate a relative string position: negative means back from end */ 30 | static lua_Integer u_posrelat (lua_Integer pos, size_t len) { 31 | if (pos >= 0) return pos; 32 | else if (0u - (size_t)pos > len) return 0; 33 | else return (lua_Integer)len + pos + 1; 34 | } 35 | 36 | 37 | /* 38 | ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. 39 | */ 40 | static const char *utf8_decode (const char *o, int *val) { 41 | static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; 42 | const unsigned char *s = (const unsigned char *)o; 43 | unsigned int c = s[0]; 44 | unsigned int res = 0; /* final result */ 45 | if (c < 0x80) /* ascii? */ 46 | res = c; 47 | else { 48 | int count = 0; /* to count number of continuation bytes */ 49 | while (c & 0x40) { /* still have continuation bytes? */ 50 | int cc = s[++count]; /* read next byte */ 51 | if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ 52 | return NULL; /* invalid byte sequence */ 53 | res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ 54 | c <<= 1; /* to test next bit */ 55 | } 56 | res |= ((c & 0x7F) << (count * 5)); /* add first byte */ 57 | if (count > 3 || res > MAXUNICODE || res <= limits[count]) 58 | return NULL; /* invalid byte sequence */ 59 | s += count; /* skip continuation bytes read */ 60 | } 61 | if (val) *val = res; 62 | return (const char *)s + 1; /* +1 to include first byte */ 63 | } 64 | 65 | 66 | /* 67 | ** utf8len(s [, i [, j]]) --> number of characters that start in the 68 | ** range [i,j], or nil + current position if 's' is not well formed in 69 | ** that interval 70 | */ 71 | static int utflen (lua_State *L) { 72 | int n = 0; 73 | size_t len; 74 | const char *s = luaL_checklstring(L, 1, &len); 75 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 76 | lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); 77 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, 78 | "initial position out of string"); 79 | luaL_argcheck(L, --posj < (lua_Integer)len, 3, 80 | "final position out of string"); 81 | while (posi <= posj) { 82 | const char *s1 = utf8_decode(s + posi, NULL); 83 | if (s1 == NULL) { /* conversion error? */ 84 | lua_pushnil(L); /* return nil ... */ 85 | lua_pushinteger(L, posi + 1); /* ... and current position */ 86 | return 2; 87 | } 88 | posi = s1 - s; 89 | n++; 90 | } 91 | lua_pushinteger(L, n); 92 | return 1; 93 | } 94 | 95 | 96 | /* 97 | ** codepoint(s, [i, [j]]) -> returns codepoints for all characters 98 | ** that start in the range [i,j] 99 | */ 100 | static int codepoint (lua_State *L) { 101 | size_t len; 102 | const char *s = luaL_checklstring(L, 1, &len); 103 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 104 | lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); 105 | int n; 106 | const char *se; 107 | luaL_argcheck(L, posi >= 1, 2, "out of range"); 108 | luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); 109 | if (posi > pose) return 0; /* empty interval; return no values */ 110 | if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ 111 | return luaL_error(L, "string slice too long"); 112 | n = (int)(pose - posi) + 1; 113 | luaL_checkstack(L, n, "string slice too long"); 114 | n = 0; 115 | se = s + pose; 116 | for (s += posi - 1; s < se;) { 117 | int code; 118 | s = utf8_decode(s, &code); 119 | if (s == NULL) 120 | return luaL_error(L, "invalid UTF-8 code"); 121 | lua_pushinteger(L, code); 122 | n++; 123 | } 124 | return n; 125 | } 126 | 127 | 128 | static void pushutfchar (lua_State *L, int arg) { 129 | lua_Integer code = luaL_checkinteger(L, arg); 130 | luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); 131 | lua_pushfstring(L, "%U", (long)code); 132 | } 133 | 134 | 135 | /* 136 | ** utfchar(n1, n2, ...) -> char(n1)..char(n2)... 137 | */ 138 | static int utfchar (lua_State *L) { 139 | int n = lua_gettop(L); /* number of arguments */ 140 | if (n == 1) /* optimize common case of single char */ 141 | pushutfchar(L, 1); 142 | else { 143 | int i; 144 | luaL_Buffer b; 145 | luaL_buffinit(L, &b); 146 | for (i = 1; i <= n; i++) { 147 | pushutfchar(L, i); 148 | luaL_addvalue(&b); 149 | } 150 | luaL_pushresult(&b); 151 | } 152 | return 1; 153 | } 154 | 155 | 156 | /* 157 | ** offset(s, n, [i]) -> index where n-th character counting from 158 | ** position 'i' starts; 0 means character at 'i'. 159 | */ 160 | static int byteoffset (lua_State *L) { 161 | size_t len; 162 | const char *s = luaL_checklstring(L, 1, &len); 163 | lua_Integer n = luaL_checkinteger(L, 2); 164 | lua_Integer posi = (n >= 0) ? 1 : len + 1; 165 | posi = u_posrelat(luaL_optinteger(L, 3, posi), len); 166 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, 167 | "position out of range"); 168 | if (n == 0) { 169 | /* find beginning of current byte sequence */ 170 | while (posi > 0 && iscont(s + posi)) posi--; 171 | } 172 | else { 173 | if (iscont(s + posi)) 174 | luaL_error(L, "initial position is a continuation byte"); 175 | if (n < 0) { 176 | while (n < 0 && posi > 0) { /* move back */ 177 | do { /* find beginning of previous character */ 178 | posi--; 179 | } while (posi > 0 && iscont(s + posi)); 180 | n++; 181 | } 182 | } 183 | else { 184 | n--; /* do not move for 1st character */ 185 | while (n > 0 && posi < (lua_Integer)len) { 186 | do { /* find beginning of next character */ 187 | posi++; 188 | } while (iscont(s + posi)); /* (cannot pass final '\0') */ 189 | n--; 190 | } 191 | } 192 | } 193 | if (n == 0) /* did it find given character? */ 194 | lua_pushinteger(L, posi + 1); 195 | else /* no such character */ 196 | lua_pushnil(L); 197 | return 1; 198 | } 199 | 200 | 201 | static int iter_aux (lua_State *L) { 202 | size_t len; 203 | const char *s = luaL_checklstring(L, 1, &len); 204 | lua_Integer n = lua_tointeger(L, 2) - 1; 205 | if (n < 0) /* first iteration? */ 206 | n = 0; /* start from here */ 207 | else if (n < (lua_Integer)len) { 208 | n++; /* skip current byte */ 209 | while (iscont(s + n)) n++; /* and its continuations */ 210 | } 211 | if (n >= (lua_Integer)len) 212 | return 0; /* no more codepoints */ 213 | else { 214 | int code; 215 | const char *next = utf8_decode(s + n, &code); 216 | if (next == NULL || iscont(next)) 217 | return luaL_error(L, "invalid UTF-8 code"); 218 | lua_pushinteger(L, n + 1); 219 | lua_pushinteger(L, code); 220 | return 2; 221 | } 222 | } 223 | 224 | 225 | static int iter_codes (lua_State *L) { 226 | luaL_checkstring(L, 1); 227 | lua_pushcfunction(L, iter_aux); 228 | lua_pushvalue(L, 1); 229 | lua_pushinteger(L, 0); 230 | return 3; 231 | } 232 | 233 | 234 | /* pattern to match a single UTF-8 character */ 235 | #define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" 236 | 237 | 238 | static const luaL_Reg funcs[] = { 239 | {"offset", byteoffset}, 240 | {"codepoint", codepoint}, 241 | {"char", utfchar}, 242 | {"len", utflen}, 243 | {"codes", iter_codes}, 244 | /* placeholders */ 245 | {"charpattern", NULL}, 246 | {NULL, NULL} 247 | }; 248 | 249 | 250 | LUAMOD_API int luaopen_utf8 (lua_State *L) { 251 | luaL_newlib(L, funcs); 252 | lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); 253 | lua_setfield(L, -2, "charpattern"); 254 | return 1; 255 | } 256 | 257 | -------------------------------------------------------------------------------- /src/lvm.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp $ 3 | ** Lua virtual machine 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lvm_h 8 | #define lvm_h 9 | 10 | 11 | #include "ldo.h" 12 | #include "lobject.h" 13 | #include "ltm.h" 14 | 15 | 16 | #if !defined(LUA_NOCVTN2S) 17 | #define cvt2str(o) ttisnumber(o) 18 | #else 19 | #define cvt2str(o) 0 /* no conversion from numbers to strings */ 20 | #endif 21 | 22 | 23 | #if !defined(LUA_NOCVTS2N) 24 | #define cvt2num(o) ttisstring(o) 25 | #else 26 | #define cvt2num(o) 0 /* no conversion from strings to numbers */ 27 | #endif 28 | 29 | 30 | /* 31 | ** You can define LUA_FLOORN2I if you want to convert floats to integers 32 | ** by flooring them (instead of raising an error if they are not 33 | ** integral values) 34 | */ 35 | #if !defined(LUA_FLOORN2I) 36 | #define LUA_FLOORN2I 0 37 | #endif 38 | 39 | 40 | #define tonumber(o,n) \ 41 | (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) 42 | 43 | #define tointeger(o,i) \ 44 | (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) 45 | 46 | #define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) 47 | 48 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) 49 | 50 | 51 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); 52 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); 53 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); 54 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); 55 | LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); 56 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, 57 | StkId val); 58 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, 59 | StkId val); 60 | LUAI_FUNC void luaV_finishOp (lua_State *L); 61 | LUAI_FUNC void luaV_execute (lua_State *L); 62 | LUAI_FUNC void luaV_concat (lua_State *L, int total); 63 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); 64 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); 65 | LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); 66 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/lzio.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lzio_c 8 | #define LUA_CORE 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | #include "llimits.h" 18 | #include "lmem.h" 19 | #include "lstate.h" 20 | #include "lzio.h" 21 | 22 | 23 | int luaZ_fill (ZIO *z) { 24 | size_t size; 25 | lua_State *L = z->L; 26 | const char *buff; 27 | lua_unlock(L); 28 | buff = z->reader(L, z->data, &size); 29 | lua_lock(L); 30 | if (buff == NULL || size == 0) 31 | return EOZ; 32 | z->n = size - 1; /* discount char being returned */ 33 | z->p = buff; 34 | return cast_uchar(*(z->p++)); 35 | } 36 | 37 | 38 | void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { 39 | z->L = L; 40 | z->reader = reader; 41 | z->data = data; 42 | z->n = 0; 43 | z->p = NULL; 44 | } 45 | 46 | 47 | /* --------------------------------------------------------------- read --- */ 48 | size_t luaZ_read (ZIO *z, void *b, size_t n) { 49 | while (n) { 50 | size_t m; 51 | if (z->n == 0) { /* no bytes in buffer? */ 52 | if (luaZ_fill(z) == EOZ) /* try to read more */ 53 | return n; /* no more input; return number of missing bytes */ 54 | else { 55 | z->n++; /* luaZ_fill consumed first byte; put it back */ 56 | z->p--; 57 | } 58 | } 59 | m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ 60 | memcpy(b, z->p, m); 61 | z->n -= m; 62 | z->p += m; 63 | b = (char *)b + m; 64 | n -= m; 65 | } 66 | return 0; 67 | } 68 | 69 | /* ------------------------------------------------------------------------ */ 70 | char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { 71 | if (n > buff->buffsize) { 72 | if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; 73 | luaZ_resizebuffer(L, buff, n); 74 | } 75 | return buff->buffer; 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/lzio.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp $ 3 | ** Buffered streams 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lzio_h 9 | #define lzio_h 10 | 11 | #include "lua.h" 12 | 13 | #include "lmem.h" 14 | 15 | 16 | #define EOZ (-1) /* end of stream */ 17 | 18 | typedef struct Zio ZIO; 19 | 20 | #define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) 21 | 22 | 23 | typedef struct Mbuffer { 24 | char *buffer; 25 | size_t n; 26 | size_t buffsize; 27 | } Mbuffer; 28 | 29 | #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) 30 | 31 | #define luaZ_buffer(buff) ((buff)->buffer) 32 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) 33 | #define luaZ_bufflen(buff) ((buff)->n) 34 | 35 | #define luaZ_buffremove(buff,i) ((buff)->n -= (i)) 36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) 37 | 38 | 39 | #define luaZ_resizebuffer(L, buff, size) \ 40 | ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ 41 | (buff)->buffsize, size), \ 42 | (buff)->buffsize = size) 43 | 44 | #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) 45 | 46 | 47 | LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); 48 | LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, 49 | void *data); 50 | LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ 51 | 52 | 53 | 54 | /* --------- Private Part ------------------ */ 55 | 56 | struct Zio { 57 | size_t n; /* bytes still unread */ 58 | const char *p; /* current position in buffer */ 59 | lua_Reader reader; /* reader function */ 60 | void *data; /* additional data */ 61 | lua_State *L; /* Lua state (for reader) */ 62 | }; 63 | 64 | 65 | LUAI_FUNC int luaZ_fill (ZIO *z); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/modsample/1_make.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | gcc -Os -shared -static -o ../../bin/modsample.dll modsample.c -------------------------------------------------------------------------------- /src/modsample/1_make.sh: -------------------------------------------------------------------------------- 1 | # No make required just gcc and standard C library 2 | # . 3 | gcc -Os -shared -static -DLUA_USE_LINUX -o ../../bin/modsample.so modsample.c 4 | -------------------------------------------------------------------------------- /src/modsample/jxapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jual Native C module API interface 3 | 4 | This is the only file you need to include in your module file to interface with the jual module system 5 | */ 6 | 7 | typedef struct usrObject { 8 | size_t size; // Variable data size 9 | void *ptr; // Generic pointer 10 | unsigned char values[1]; // Variable data 11 | } usrObject; 12 | 13 | typedef struct jual_xapi_ { 14 | int STRBUFFER_SIZE; 15 | void *LS; 16 | void *fnGetNumber; 17 | void *fnGetString; 18 | void *fnGetObject; 19 | void *fnNumberPush; 20 | void *fnStrInit; 21 | void *fnStrAppend; 22 | void *fnStrPush; 23 | } jual_xapi; 24 | 25 | typedef int defGetNumber(void *LS, int argnum); 26 | typedef const char *defGetString(void *LS, int argnum, size_t *tSize); 27 | typedef void *defGetObject(void *LS, int argnum); 28 | 29 | typedef int defNumberPush(void *LS, int iValue); 30 | typedef char *defStrInit(void *LS, void *strBuf, size_t tSize); 31 | typedef int defStrAppend(void *strBuf, const char *szValue, size_t tSize); 32 | typedef void defStrPush(void *strBuf); 33 | 34 | /* 35 | 36 | Your exported C functions should look something like this: 37 | 38 | int myfunc(jual_xapi *JXAPI) 39 | { 40 | void *L = JXAPI->LS; 41 | // Map functions as required 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 44 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 45 | 46 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 47 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 48 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 49 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 50 | 51 | int iArgument1 = GetNumber(L, 1); 52 | 53 | NumberPush(L, 123456789); 54 | return 1; // always 1 to indicate number of variables returned or 0 if returning nothing. 55 | }; 56 | */ 57 | -------------------------------------------------------------------------------- /src/modsample/modsample.c: -------------------------------------------------------------------------------- 1 | /* 2 | This is a sample Jual Native C module 3 | You can use this as a template for your modules 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "jxapi.h" 10 | 11 | int myfunc(jual_xapi *JXAPI) 12 | { 13 | void *L = JXAPI->LS; 14 | // Map functions as required 15 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 16 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 17 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 18 | 19 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 20 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 21 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 22 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 23 | 24 | int iNum = GetNumber(L, 1); 25 | 26 | size_t tSize; 27 | const char *szParm2 = GetString(L, 2, &tSize); 28 | 29 | printf("you entered %d %s %d\n", iNum, szParm2, tSize); 30 | 31 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 32 | char *cResult = StrInit(L, strBuffer, 16); 33 | 34 | const char text[]="Hello from the C language"; 35 | StrAppend(strBuffer, text, sizeof(text)-1); 36 | 37 | const char text2[]="More greeting from the C language"; 38 | StrAppend(strBuffer, text2, sizeof(text2)-1); 39 | 40 | StrPush(strBuffer); 41 | 42 | return 1; 43 | } 44 | 45 | 46 | const char initString[]="\ 47 | ffi_func1 = ffi_map('modsample', 'myfunc');\n\ 48 | function friendlyCall(num,str){return ffi_call(ffi_func1,num,str)};\n\ 49 | "; 50 | 51 | // ** 52 | // init function name must always be in the format of _init 53 | // the init function must always return 0 54 | // ** 55 | int modsample_init(jual_xapi *JXAPI) { 56 | void *L = JXAPI->LS; 57 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 58 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 59 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 60 | 61 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 62 | char *cResult = StrInit(L, strBuffer, 32); 63 | StrAppend(strBuffer, initString, sizeof(initString)-1); 64 | StrPush(strBuffer); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/sqlite/1_make.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | gcc -Os -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -c sqlite3.c 4 | ar rcs -o libsqlite_3.a sqlite3.o 5 | gcc -shared -static -Os -o ../../bin/libsqlite3.dll libsqlite3.c -L. -lsqlite_3 6 | del libsqlite_3.a sqlite3.o 7 | -------------------------------------------------------------------------------- /src/sqlite/1_make.sh: -------------------------------------------------------------------------------- 1 | # No make required just gcc and standard C library 2 | # . 3 | gcc -Os -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -c sqlite3.c 4 | ar rcs libsqlite_3.a sqlite3.o 5 | gcc -Os -ldl -lm -DLUA_USE_LINUX -shared -o ../../bin/libsqlite3.so libsqlite3.c -L. -lsqlite_3 6 | # rm libsqlite_3.a sqlite3.o 7 | -------------------------------------------------------------------------------- /src/sqlite/jxapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jual Native C module API interface 3 | 4 | This is the only file you need to include in your module file to interface with the jual module system 5 | */ 6 | 7 | typedef struct usrObject { 8 | size_t size; // Variable data size 9 | void *ptr; // Generic pointer 10 | unsigned char values[1]; // Variable data 11 | } usrObject; 12 | 13 | typedef struct jual_xapi_ { 14 | int STRBUFFER_SIZE; 15 | void *LS; 16 | void *fnGetNumber; 17 | void *fnGetString; 18 | void *fnGetObject; 19 | void *fnNumberPush; 20 | void *fnStrInit; 21 | void *fnStrAppend; 22 | void *fnStrPush; 23 | } jual_xapi; 24 | 25 | typedef int defGetNumber(void *LS, int argnum); 26 | typedef const char *defGetString(void *LS, int argnum, size_t *tSize); 27 | typedef void *defGetObject(void *LS, int argnum); 28 | 29 | typedef int defNumberPush(void *LS, int iValue); 30 | typedef char *defStrInit(void *LS, void *strBuf, size_t tSize); 31 | typedef int defStrAppend(void *strBuf, const char *szValue, size_t tSize); 32 | typedef void defStrPush(void *strBuf); 33 | 34 | /* 35 | 36 | Your exported C functions should look something like this: 37 | 38 | int myfunc(jual_xapi *JXAPI) 39 | { 40 | void *L = JXAPI->LS; 41 | // Map functions as required 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 44 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 45 | 46 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 47 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 48 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 49 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 50 | 51 | int iArgument1 = GetNumber(L, 1); 52 | 53 | NumberPush(L, 123456789); 54 | return 1; // always 1 to indicate number of variables returned or 0 if returning nothing. 55 | }; 56 | */ 57 | -------------------------------------------------------------------------------- /src/sqlite/libsqlite3.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Sajon Oso 3 | Jual Native C module - SQLite3 module 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "jxapi.h" 10 | #include "sqlite3.h" 11 | 12 | const char *szFIELDSEP = "\t"; 13 | const char *szRECSEP = "\n"; 14 | 15 | int sql3_execute(jual_xapi *JXAPI) 16 | { 17 | void *L = JXAPI->LS; 18 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 19 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 20 | 21 | int iResult = -1; 22 | 23 | const char *sqldbname = GetString(L, 1, NULL); 24 | const char *sqlstatement = GetString(L, 2, NULL); 25 | 26 | sqlite3 *sql3db; 27 | 28 | if ( sqlite3_open( sqldbname, &sql3db ) == SQLITE_OK ) { 29 | if (sqlite3_exec( sql3db, sqlstatement, 0, 0, 0 ) == SQLITE_OK ) 30 | iResult = sqlite3_changes(sql3db); 31 | }; 32 | sqlite3_close( sql3db ); 33 | 34 | NumberPush(L, iResult); 35 | return 1; 36 | } 37 | 38 | 39 | int sql3_query(jual_xapi *JXAPI) 40 | { 41 | void *L = JXAPI->LS; 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 44 | 45 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 46 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 47 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 48 | 49 | const char *sqldbname = GetString(L, 1, NULL); 50 | const char *sqlstatement = GetString(L, 2, NULL); 51 | int blFirstRowOnly = GetNumber(L, 3); 52 | 53 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 54 | char *cResult = StrInit(L, strBuffer, 32); 55 | 56 | sqlite3 *sql3db; 57 | sqlite3_stmt *stmt; 58 | int iLenFIELDSEP = strlen(szFIELDSEP); 59 | int iLenRECSEP = strlen(szRECSEP); 60 | 61 | if ( sqlite3_open( sqldbname, &sql3db ) == SQLITE_OK ) 62 | { 63 | if ( sqlite3_prepare( sql3db, sqlstatement, -1,&stmt,0 ) == SQLITE_OK ) 64 | { 65 | int iNumColumns = sqlite3_column_count(stmt); 66 | int retval = sqlite3_step(stmt); 67 | 68 | while (retval == SQLITE_ROW) 69 | { 70 | int col; 71 | for ( col=0; col 0) StrAppend(strBuffer, szFIELDSEP, iLenFIELDSEP); 75 | if (val) StrAppend(strBuffer, val, strlen(val)); 76 | }; 77 | 78 | if (blFirstRowOnly) { 79 | retval = !SQLITE_ROW; 80 | } else { 81 | StrAppend(strBuffer, szRECSEP, iLenRECSEP); 82 | retval = sqlite3_step(stmt); 83 | }; 84 | }; 85 | }; 86 | }; 87 | 88 | sqlite3_close( sql3db ); 89 | 90 | StrPush(strBuffer); 91 | return 1; 92 | } 93 | 94 | 95 | const char initString[]="\ 96 | lib_sqlite3_execute = ffi_map('libsqlite3', 'sql3_execute'); \ 97 | lib_sqlite3_query = ffi_map('libsqlite3', 'sql3_query'); \ 98 | function sqlite3_execute(db,sql){return ffi_call(lib_sqlite3_execute,db,sql)}; \ 99 | function sqlite3_query(db,sql,nos){return ffi_call(lib_sqlite3_query,db,sql,nos)}; \ 100 | "; 101 | 102 | int libsqlite3_init(jual_xapi *JXAPI) { 103 | void *L = JXAPI->LS; 104 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 105 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 106 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 107 | 108 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 109 | StrInit(L, strBuffer, 32); 110 | StrAppend(strBuffer, initString, sizeof(initString)-1); 111 | StrPush(strBuffer); 112 | 113 | return 0; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /src/uint8array/1_make.cmd: -------------------------------------------------------------------------------- 1 | @cls 2 | @gcc -Wall -DLUA_USE_WINDOWS -DWINVER=0x0501 -Os -shared -static -o ../../bin/uint8array.dll uint8array.c -------------------------------------------------------------------------------- /src/uint8array/1_make.sh: -------------------------------------------------------------------------------- 1 | # No make required just gcc and standard C library 2 | # . 3 | gcc -Os -ldl -lm -DLUA_USE_LINUX -shared -o ../../bin/uint8array.so uint8array.c 4 | -------------------------------------------------------------------------------- /src/uint8array/jxapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | Jual Native C module API interface 3 | 4 | This is the only file you need to include in your module file to interface with the jual module system 5 | */ 6 | 7 | typedef struct usrObject { 8 | size_t size; // Variable data size 9 | void *ptr; // Generic pointer 10 | unsigned char values[1]; // Variable data 11 | } usrObject; 12 | 13 | typedef struct jual_xapi_ { 14 | int STRBUFFER_SIZE; 15 | void *LS; 16 | void *fnGetNumber; 17 | void *fnGetString; 18 | void *fnGetObject; 19 | void *fnNumberPush; 20 | void *fnStrInit; 21 | void *fnStrAppend; 22 | void *fnStrPush; 23 | } jual_xapi; 24 | 25 | typedef int defGetNumber(void *LS, int argnum); 26 | typedef const char *defGetString(void *LS, int argnum, size_t *tSize); 27 | typedef void *defGetObject(void *LS, int argnum); 28 | 29 | typedef int defNumberPush(void *LS, int iValue); 30 | typedef char *defStrInit(void *LS, void *strBuf, size_t tSize); 31 | typedef int defStrAppend(void *strBuf, const char *szValue, size_t tSize); 32 | typedef void defStrPush(void *strBuf); 33 | 34 | /* 35 | 36 | Your exported C functions should look something like this: 37 | 38 | int myfunc(jual_xapi *JXAPI) 39 | { 40 | void *L = JXAPI->LS; 41 | // Map functions as required 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetString *GetString = (defGetString *)JXAPI->fnGetString; 44 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 45 | 46 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 47 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 48 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 49 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 50 | 51 | int iArgument1 = GetNumber(L, 1); 52 | 53 | NumberPush(L, 123456789); 54 | return 1; // always 1 to indicate number of variables returned or 0 if returning nothing. 55 | }; 56 | */ 57 | -------------------------------------------------------------------------------- /src/uint8array/uint8array.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Sajon Oso 3 | Jual Native C module - Uint8Array module 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "jxapi.h" 10 | 11 | 12 | int zeroarray (jual_xapi *JXAPI) { 13 | void *L = JXAPI->LS; 14 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 15 | 16 | usrObject *uObj = (usrObject *)GetObject(L, 1); 17 | 18 | memset (uObj->values,'\0',uObj->size); 19 | return 0; 20 | } 21 | 22 | 23 | int setarray (jual_xapi *JXAPI) { 24 | void *L = JXAPI->LS; 25 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 26 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 27 | 28 | usrObject *uObj = (usrObject *)GetObject(L, 1); 29 | int index = GetNumber(L, 2); 30 | int value = GetNumber(L, 3); 31 | 32 | if (uObj == NULL) return 0; 33 | if (index < 0 || index >= uObj->size) return 0; 34 | 35 | uObj->values[index] = value &0xFF; 36 | return 0; 37 | } 38 | 39 | 40 | int getarray (jual_xapi *JXAPI) { 41 | void *L = JXAPI->LS; 42 | defGetNumber *GetNumber = (defGetNumber *)JXAPI->fnGetNumber; 43 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 44 | 45 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 46 | 47 | usrObject *uObj = (usrObject *)GetObject(L, 1); 48 | int index = GetNumber(L, 2); 49 | 50 | if (uObj == NULL) return 0; 51 | if (index < 0 || index >= uObj->size) return 0; 52 | 53 | NumberPush(L, uObj->values[index]); 54 | return 1; 55 | } 56 | 57 | 58 | int getasize (jual_xapi *JXAPI) { 59 | void *L = JXAPI->LS; 60 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 61 | defNumberPush *NumberPush = (defNumberPush *)JXAPI->fnNumberPush; 62 | 63 | usrObject *uObj = (usrObject *)GetObject(L, 1); 64 | 65 | NumberPush(L, uObj->size); 66 | return 1; 67 | } 68 | 69 | 70 | int getstring (jual_xapi *JXAPI) { 71 | void *L = JXAPI->LS; 72 | defGetObject *GetObject = (defGetObject *)JXAPI->fnGetObject; 73 | 74 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 75 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 76 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 77 | 78 | usrObject *uObj = (usrObject *)GetObject(L, 1); 79 | 80 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 81 | (void)StrInit(L, strBuffer, uObj->size+1); 82 | 83 | StrAppend(strBuffer, (const char *)uObj->values, uObj->size); 84 | StrPush(strBuffer); 85 | 86 | return 1; 87 | } 88 | 89 | 90 | const char initString[]="\ 91 | uint8array_zeroarray = ffi_map('uint8array', 'zeroarray'); \ 92 | uint8array_setarray = ffi_map('uint8array', 'setarray'); \ 93 | uint8array_getarray = ffi_map('uint8array', 'getarray'); \ 94 | uint8array_arraysize = ffi_map('uint8array', 'getasize'); \ 95 | uint8array_arraystring = ffi_map('uint8array', 'getstring'); \ 96 | uint8array = {}; \ 97 | uint8array.__index=function(key) { \ 98 | return ffi_call(uint8array_getarray,this.Z,key); \ 99 | }; \ 100 | uint8array.__newindex=function(key,value) { \ 101 | return ffi_call(uint8array_setarray,this.Z,key, value); \ 102 | }; \ 103 | uint8array.size=function() { \ 104 | return ffi_call(uint8array_arraysize,this.Z); \ 105 | }; \ 106 | uint8array.toString=function() { \ 107 | return ffi_call(uint8array_arraystring,this.Z); \ 108 | }; \ 109 | uint8array.zero=function() { \ 110 | return ffi_call(uint8array_zeroarray,this.Z); \ 111 | }; \ 112 | function Uint8Array(iSize) { \ 113 | var ob = {}; \ 114 | ob.Z = ffi_newobject(iSize); \ 115 | setmetatable(ob, {__index:uint8array} ); \ 116 | return ob; \ 117 | }; \ 118 | "; 119 | 120 | // ** 121 | // init function name must always be in the format of _init 122 | // the init function must always return 0 123 | // ** 124 | int uint8array_init(jual_xapi *JXAPI) { 125 | void *L = JXAPI->LS; 126 | defStrInit *StrInit = (defStrInit *)JXAPI->fnStrInit; 127 | defStrAppend *StrAppend = (defStrAppend *)JXAPI->fnStrAppend; 128 | defStrPush *StrPush = (defStrPush *)JXAPI->fnStrPush; 129 | 130 | char strBuffer[JXAPI->STRBUFFER_SIZE]; 131 | (void)StrInit(L, strBuffer, 32); 132 | StrAppend(strBuffer, initString, sizeof(initString)-1); 133 | StrPush(strBuffer); 134 | 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /testsuite/10_functions.js: -------------------------------------------------------------------------------- 1 | 2 | // This script tests function statements 3 | 4 | // no parameters 5 | function myfunc0() { 6 | print("myfunc0"); 7 | } 8 | 9 | // one parameter 10 | function myfunc1(parm1) { 11 | print(parm1); 12 | } 13 | 14 | // two parameter 15 | function myfunc2(parm1, parm2) { 16 | print(parm1); 17 | print(parm2); 18 | } 19 | 20 | // returning number 21 | function myfunc3(one, two) { 22 | return ((one + two) * 21); 23 | } 24 | 25 | // returning string 26 | function myfunc4(one, two) { 27 | return ( "hello world" + one + two ); 28 | } 29 | 30 | myfunc0(); 31 | myfunc1("hello", "world"); 32 | myfunc2("hello", "world"); 33 | 34 | print( myfunc3(16,12) ); 35 | print( myfunc4("one","two") ); 36 | -------------------------------------------------------------------------------- /testsuite/11_arrays.js: -------------------------------------------------------------------------------- 1 | 2 | // test of arrays 3 | 4 | // There are two ways to declare an array 5 | var arrayLiteral = [1, 3, "one", 2, "three", 4, 5, 6, 7, '8']; 6 | var arrayConstructor = new Array("mon", "tue", "wed", "thu", "fri", "sat", "sun"); 7 | 8 | function printa(a) { 9 | var i; var sz=""; var L=a.size(); 10 | for (i=0; i 0) { 10 | i = inc; 11 | while (i=inc && a[j-inc]>tmp) { 15 | a[j] = a[j-inc]; 16 | j -= inc; 17 | } 18 | a[j] = tmp; 19 | i+=1; 20 | }; 21 | inc = Math.floor(inc/2); 22 | }; 23 | return a; 24 | } 25 | 26 | function printArray(oArray) { 27 | var iLen=oArray.size(); 28 | var out= "["; 29 | for (i=0; i 0) { 7 | var mult = Math.pow(10, iDecimalPlaces); 8 | var value = Math.floor((fNumber*mult)+0.5) / mult; 9 | if (value%1==0) { // if integer result set to integer 10 | return value|0; 11 | } else { 12 | return value; 13 | }; 14 | }; 15 | 16 | return Math.floor(fNumber+0.5)|0; 17 | }; 18 | 19 | var iDec = 12; 20 | 21 | szOut = ""; 22 | szOut = (szOut + "\nMath.abs: " + RoundTo(iDec, Math.abs(-135)) ); 23 | szOut = (szOut + "\nMath.acos: " + RoundTo(iDec, Math.acos(0.235)) ); 24 | szOut = (szOut + "\nMath.asin: " + RoundTo(iDec, Math.asin(0.34)) ); 25 | szOut = (szOut + "\nMath.atan: " + RoundTo(iDec, Math.atan(0.34)) ); 26 | szOut = (szOut + "\nMath.atan2: " + RoundTo(iDec, Math.atan2(2, 1.5)) ); 27 | szOut = (szOut + "\nMath.ceil: " + RoundTo(iDec, Math.ceil(0.34)) ); 28 | szOut = (szOut + "\nMath.cos: " + RoundTo(iDec, Math.cos(0.34)) ); 29 | szOut = (szOut + "\nMath.exp: " + RoundTo(iDec, Math.exp(0.34)) ); 30 | szOut = (szOut + "\nMath.floor: " + RoundTo(iDec, Math.floor(356.34)) ); 31 | szOut = (szOut + "\nMath.log: " + RoundTo(iDec, Math.log(10)) ); 32 | szOut = (szOut + "\nMath.max: " + RoundTo(iDec, Math.max(456,456,757,564,234)) ); 33 | szOut = (szOut + "\nMath.min: " + RoundTo(iDec, Math.min(456,456,757,564,234)) ); 34 | szOut = (szOut + "\nMath.pow: " + RoundTo(iDec, Math.pow(2,8)) ); 35 | 36 | // Testing the random function will cause the test to fail. 37 | // szOut = szOut + "\nMath.random:" + RoundTo(iDec, Math.random() ); 38 | 39 | szOut = szOut + "\nMath.round: " + Math.round(2.60); 40 | szOut = szOut + "\nMath.round: " + Math.round(2.50); 41 | szOut = szOut + "\nMath.round: " + Math.round(2.49); 42 | szOut = szOut + "\nMath.round: " + Math.round(-2.60); 43 | szOut = szOut + "\nMath.round: " + Math.round(-2.50); 44 | szOut = szOut + "\nMath.round: " + Math.round(-2.49); 45 | 46 | szOut = (szOut + "\nMath.sin: " + RoundTo(iDec, Math.sin(135)) ); 47 | szOut = (szOut + "\nMath.sqrt: " + RoundTo(iDec, Math.sqrt(25)) ); 48 | szOut = (szOut + "\nMath.tan: " + RoundTo(iDec, Math.tan(135)) ); 49 | 50 | print (szOut); 51 | -------------------------------------------------------------------------------- /testsuite/2_vars_numbers.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // This script tests interpretation of numerical constants 4 | 5 | var iTest1 = 3; // integers 6 | var iTest2 = 3.1416; // floats 7 | var iTest3 = 0xFF; // hexadecimal 8 | var iTest4 = 0xF00F; // hexadecimal 9 | var iTest5 = 314.16e-2; // scientific 10 | var iTest6 = 0.31416E1; // scientific 11 | // var iTest7 = 0377; // octal number constants is not supported in JualScript 12 | 13 | print (iTest1); 14 | print (iTest2); 15 | print (iTest3); 16 | print (iTest4); 17 | print (iTest5); 18 | print (iTest6); 19 | // print (iTest7); 20 | 21 | // testing variable case sensitivity 22 | var iCasesensitiveVariables = "hello"; 23 | var icasesensitivevariables = "world"; 24 | var variablewithnumber1 = "works1"; 25 | var variable_with_under_scores = 12345; 26 | 27 | print(iCasesensitiveVariables); 28 | print(variablewithnumber1); 29 | print(variable_with_under_scores); 30 | 31 | // testing variable scope 32 | var iScope = "Global"; 33 | 34 | function localfunc(szText) { 35 | // if (iScope == null) { iScope = "null" }; 36 | // print ( "I am " + iScope) ); 37 | var iScope = "Local"; 38 | print ( "I am " + iScope ); 39 | } 40 | 41 | localfunc("I am Spartacus!"); 42 | 43 | print ( "No I am Spartacus! " + iScope ); 44 | -------------------------------------------------------------------------------- /testsuite/3_strings.js: -------------------------------------------------------------------------------- 1 | 2 | // This script tests implementation of strings 3 | // For this file to work correctly under unix or linux make sure end 4 | // of line character is \n rather than \n 5 | 6 | 7 | var szSimple = "This is a simple string"; 8 | var szEscaped1 = "Escaped characters - new line test\nnext line\twith tab and slash \\"; 9 | var szEscaped2 = "double slash \\\\"; 10 | var szEscaped3 = "escape sequences \x64\x65\x66"; 11 | var szMultilineString = "Helloworld\n\ 12 | this is a multiline string\ 13 | with more lines"; 14 | 15 | print (szSimple); 16 | print (szEscaped1); 17 | print (szEscaped2); 18 | print (szEscaped3); 19 | print (szMultilineString); 20 | 21 | print (""); 22 | 23 | 24 | // same as above with single quotes 25 | szTest1 = 'This is a simple string'; 26 | szTest2 = 'Escaped characters - new line test\nnext line\twith tab and slash \\'; 27 | szTest3 = 'double slash \\\\'; 28 | szTest4 = 'Helloworld\n\ 29 | this is a multiline string \ 30 | with more lines'; 31 | szTest5 = "test \n\r \n interpretation of new line characters \r \n"; 32 | szTest6 = "test \n\n\r interpretation of new line characters\n\r"; 33 | szTest7 = "Quotation test \"Double quotes\" and \'single quotes\' it works!"; 34 | 35 | print (szTest1); 36 | print (szTest2); 37 | print (szTest3); 38 | print (szTest4); 39 | print (szTest5); 40 | print (szTest6); 41 | print (szTest7); 42 | print ( szTest1.concat("one","two", 3, "four") ); 43 | -------------------------------------------------------------------------------- /testsuite/4_operators.js: -------------------------------------------------------------------------------- 1 | 2 | // testing javascript operators 3 | 4 | // arithmetic 5 | var num1 = 276328; 6 | var num2 = 32654; 7 | var test1=((123+56-89)/12*167) % 15; 8 | var test2=num1 * 98374 - num2; 9 | var test3=num1 / 4 % num2; 10 | var test4=num1 + 98374 - num2; 11 | 12 | print (test1); 13 | print (test2); 14 | print (test3); 15 | print (test4); 16 | 17 | // logical operators 18 | var t = true; 19 | var f = false; 20 | print (t && t); 21 | print (t && f); 22 | print (f && t); 23 | print (f && f); 24 | print (t && t && f); 25 | print (t && f && t); 26 | print (t && t && t); 27 | 28 | print (t || t); 29 | print (t || f); 30 | print (f || t); 31 | print (f || f); 32 | print (!f); 33 | print (!t); 34 | 35 | // comparisons 36 | var higher = 123; 37 | var lower = 12; 38 | var equalh = 123; 39 | 40 | print (higher > lower); 41 | print (higher >= lower); 42 | print (higher >= equalh); 43 | print (higher < lower); 44 | print (higher <= lower); 45 | print (higher <= equalh); 46 | print (higher == lower); 47 | print (higher == equalh); 48 | print (higher != lower); 49 | print (higher != equalh); 50 | 51 | print (higher == higher); 52 | print (lower == lower); 53 | 54 | //bitwise operators 55 | print (higher & lower); 56 | print (higher | lower); 57 | print (higher ^ equalh); 58 | print (~higher); 59 | print (~lower); 60 | print (higher << 2); 61 | print (higher >> 2); 62 | -------------------------------------------------------------------------------- /testsuite/5_compound_ops.js: -------------------------------------------------------------------------------- 1 | // This file tests the engines compound operators 2 | 3 | var t = 15; 4 | t += 20; 5 | print(t); 6 | t -= 20; 7 | print(t); 8 | t /= 5; 9 | print(t); 10 | t *= 5; 11 | print(t); 12 | t %= 13; 13 | print(t); 14 | 15 | var k=4; 16 | t=16; 17 | t += 16+k; 18 | print(t); 19 | t *= k+2; 20 | print(t); 21 | t /= (k/2); 22 | print(t); 23 | -------------------------------------------------------------------------------- /testsuite/6_ifstat.js: -------------------------------------------------------------------------------- 1 | 2 | // This script tests implementation of the if statement 3 | 4 | var j = 20; 5 | var k = 1; 6 | var p = 1; 7 | 8 | // single if statement 9 | if (j == 20) { print("YES1"); }; 10 | 11 | // multiple statements 12 | if (j == 20) { 13 | print("YES2"); 14 | print("YES3"); 15 | }; 16 | 17 | // single else statement 18 | if (j == 20) { 19 | print("YES4"); 20 | } else { 21 | print("NO"); 22 | }; 23 | 24 | // single if and else statement 25 | if (j == 16) { 26 | print("NO"); 27 | } else if (k == 1) { 28 | print("YES5"); 29 | }; 30 | 31 | // multiple else if statements 32 | 33 | var i; 34 | for (i=0; i<3; i = i + 1) { 35 | 36 | if (i == 2) { 37 | print("YES8"); 38 | } else if (i == 0) { 39 | print("YES6"); 40 | } else if (i == 1) { 41 | print("YES7"); 42 | }; 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /testsuite/7_whilestat.js: -------------------------------------------------------------------------------- 1 | 2 | // Test of the while statement 3 | 4 | var j = 0; 5 | while (j < 4) { 6 | j += 1; 7 | print (j); 8 | }; 9 | 10 | while (false) { 11 | print("this should never run"); 12 | }; 13 | 14 | // testing break statment 15 | var szOut = "*"; 16 | j = 0; 17 | while (j < 50) { 18 | szOut = (szOut + " " + j); 19 | if (j == 20) { break; }; 20 | j += 1; 21 | }; 22 | print (szOut); 23 | 24 | var szOut = "*"; 25 | var x = 0; 26 | var y; 27 | while (x < 10) { 28 | y = 0; 29 | while (y < 50) { 30 | szOut = (szOut + " " + y); 31 | if (y == 20) { break; }; 32 | y += 1; 33 | }; 34 | szOut = (szOut + "\n"); 35 | x += 1; 36 | 37 | if (x == 6) { break; }; 38 | }; 39 | print (szOut); 40 | 41 | var k = 19; 42 | print(""); 43 | 44 | j = 1; 45 | while ( j < 4 && k == 19) { 46 | j += 1; 47 | print (j); 48 | }; 49 | -------------------------------------------------------------------------------- /testsuite/8_dostat.js: -------------------------------------------------------------------------------- 1 | 2 | // Test of do statement 3 | 4 | var j = 1; 5 | do { 6 | j = j + 1; 7 | } while (j==15); 8 | print (j); 9 | 10 | print(""); 11 | 12 | do { 13 | j = j + 1; 14 | } while (j<=15); 15 | print (j); 16 | 17 | var x =0; 18 | var y =0; 19 | var szOut = "*"; 20 | do { 21 | y = 0; 22 | do { 23 | szOut = (szOut + " " + y); 24 | y = y + 1; 25 | if (y == 25) { break; }; 26 | } while (y < 50); 27 | 28 | szOut = (szOut + "\n"); 29 | x = x + 1; 30 | if (x == 8) { break; }; 31 | } while (x < 10); 32 | 33 | print (szOut); 34 | -------------------------------------------------------------------------------- /testsuite/99_cmdargs.js: -------------------------------------------------------------------------------- 1 | // This file tests the command line arguments variable "arg" 2 | 3 | if (isJUALSCRIPT) { arg.size = Array_MT.size; }; 4 | 5 | var iNumArgs = arg.size(); 6 | var i; 7 | print("You entered: " + iNumArgs + " parameters\n"); 8 | for (i=0; i1; k=k-1) { 14 | szOut = (szOut + " " + k); 15 | if (k == 10) { break; }; 16 | } 17 | print( (szOut + "\n") ); 18 | 19 | szOut = "*"; 20 | for (k=1; k<2000; k=k*2) { 21 | szOut = (szOut + " " + k); 22 | } 23 | print( (szOut + "\n") ); 24 | 25 | // test break statement with multiple for loops 26 | 27 | var x=0; 28 | var y=0; 29 | szOut = "*"; 30 | for (x=0; x<50; x+=1) { 31 | for (y=0; y<50; y+=1) { 32 | szOut = (szOut + " " + y); 33 | if (y == 15) { break; }; 34 | }; 35 | szOut = (szOut + "\n"); 36 | if (x == 10) { break; }; 37 | }; 38 | print( (szOut + "\n") ); 39 | 40 | --------------------------------------------------------------------------------