NullLogic Embedded Scripting Language - Reference |
![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Menu
eval();
iname(); include(); ival(); print(); printvar(); runtime(); sizeof(); sleep(); system(); tonumber(); tostring(); typeof(); write();
math.abs();
math.acos(); math.asin(); math.atan(); math.ceil(); math.cos(); math.floor(); math.rand(); math.sin(); math.sqrt(); math.tan();
string.cat();
string.cmp(); string.icmp(); string.join(); string.ncmp(); string.nicmp(); string.len(); string.split(); string.str(); string.istr(); string.sub(); string.tolower(); string.toupper();
ssh.open();
ssh.close(); ssh.hostkey(); ssh.auth(); ssh.cmd(); ssh.sftp_get(); ssh.sftp_ls(); ssh.sftp_mkdir(); ssh.sftp_put(); ssh.sftp_rename(); ssh.sftp_rmdir(); ssh.sftp_unlink();
http.get();
tcp.accept(); tcp.bind(); tcp.close(); tcp.gets(); tcp.info(); tcp.open(); tcp.read(); tcp.write(); |
1 - IntroductionI suck at writing documentation, so this will be short and bitter. For working samples, check out scripts/tests/*.ns Nesla's earliest lines of code were derived from all the configuration file parsers I kept writing over and over, and was never happy with. With the hassle of writing new functions to deal with different files, and adding callback functions to deal with subsections, and _then_ taking the parsed data and making that data accessible to other loaded functions and modules, not to mention the whole memory management part, and the need to keep track of not only the name and type of variable, but also the size... Well, I guess I'm just lucky I have a sense of humour. So here was a goal: A flexible config parser, a simple and universal data storage model, a short and simple command set, a zero effort memory management system that didn't suck, and a C api that wouldn't be painful or difficult to use in other projects. Whether or not it became a fully functional scripting language of its own was entirely incidental. What I ended up with is the Nesla core library; the scripting language for C programmers. Syntactically, Nesla probably looks more like javascript than it does any other language. Use of the word 'object' may be less than 100% accurate, there are no properties, methods, events, or classes in the javascript sense, but the C syntax rules are nearly identical. Nesla is not an emulation of javascript, but both language designs do agree that C syntax is good and dollar signs are ugly. OOPS So here's the deal on 'Object Oriented Programming'. I don't get it. I'm not saying it's bad or that people who do it are deviants. I'm just not sure what the working definition of OO is these days. Nesla's storage system is entirely object-based, but that doesn't make the language object oriented. I added a 'this' variable so functions could infer the context in which they were called. Does this make Nesla an OO language? Consider the following code: function new_str(val) { this = { size = function () { return sizeof(this.value); }; lower = function () { return string.tolower(this.value); }; upper = function () { return string.toupper(this.value); }; value = val; }; return this; } x=new_str("AbC"); print("["+x.size()+"]\n"); // will print 3 x.value="aBcDeF"; print("["+x.size()+"]\n"); // will print 6 print("["+x.lower()+"]\n"); // will print abcdef print("["+x.upper()+"]\n"); // will print ABCDEF Is that technically an example of OO? True, most OO code has nicer looking constructors and classes and stuff I don't get, but this is working Nesla code. 2 - The LanguageKeywordsbreak continue return function global local var if else for do while exit Working code looks a little like the following sample. function demo(arg1) { global x=1; # you don't actually need local or var, but it makes the code clearer local y=2; var z=3; for (i=0;i<10;i++) { if (i<5) { print("less than half ", i, "\n"); } else if (i==5) { print("half\n"); } else { print("more than half ", i, "\n"); } if (i==arg1) break; } return; } demo(8);
break (accepts an optional unbracketed number arg to define the number of levels to break) Operators= + ++ += - -- -= * *= / /= == != <= >= < > % & | ^ && || ! Strings can also be handled using the slightly shorter list of ops: = + += == != <= >= < > The statement var x="a"+"b"; will set x to "ab". Tables have considerably less ops: = {} function subf() { return 69; } var pi = math.asin(1)*2; var table = { { a1="x", b = pi, [12]=41, [1]=42, 43, 'blah', subf() }, { "x", 'y', x = 41, 42, 43, 'blah', [5]=12, heh=";-)" } }; setting a var's value to null will completely free the value and effectively make the var non-existant include
Description
Syntax
Return Value
Remarks
Example
print
Description
Syntax
Return Value
Remarks
Examples
See Also
printvar
Description
Syntax
Return Value
Remarks
Examples
runtime
Description
Syntax
Return Value
sizeof
Description
Syntax
Return Value
sleep
Description
Syntax
Return Value
system
Description
Syntax
Return Value
Remarks
Examples
tonumber
Description
Syntax
Return Value
tostring
Description
Syntax
Return Value
typeof
Description
Syntax
Return Value
write
Description
Syntax
Return Value
See Also
3 - file.*()
|
Parameter | Description |
... | List of objects to be printed. |
Returns the number of characters printed.
Any argument that is not a string will be formatted automatically. Boolean values will be 'true' or 'false' and numbers will have up to 6 digits past the decimal. Most string functions may be binary safe, but this function _will_ terminate its output at the first \0 character.
The following example demonstrates how to print multiple objects.
io.print("Hello", "world.\n");
The following example gives the same output as above, but note that using + to concatenate the strings means that print only receives one argument.
io.print("Hello"+"world.\n");
Writes the entire object as a string and returns the result code. This function is binary safe.
number = io.write(object)
Parameter Description object Object to be written to standard output.
Returns the number of bytes written.
(string) string.cat(string str1, string str2);
(table) string.join(table str, string sep);
This will merge the table str into a single string separated by sep.
(number) string.ncmp(string str1, string str2, number len);
Case sensitive substring comparison up to len characters.
(number) string.nicmp(string str1, string str2, number len);
Case insensitive substring comparison up to len characters.
(table) string.split(string str, string sep);
This will separate the string into substrings and put those substrings in the returned table.
(string) string.sub(string stack, number offset[, number maxlen]);
Returns a substring ranging from offset to maxlen.
Returns a table representation of timestamp. If timestamp is not defined, the function will use the current local system date.
Returns a table representation of timestamp. If timestamp is not defined, the function will use the current local system date.
Returns the elapsed time in seconds since January 1, 1970.
number = time()
Returns the time in seconds since the creation of the UNIXverse.
Returns a string representation of timestamp in the format 'YYYY-MM-DD'. If timestamp is not defined, the function will use the current system date.
The number of seconds since January 1, 1970 (commonly called a UNIX timestamp).
Returns a formatted date string in the format 'YYYY-MM-DD'.
Example 1. A strlen() example
|
Array ( [0] => f'oo [1] => b'ar [2] => Array ( [0] => fo'o [1] => b'ar ) ) |
count() |
mb_strlen() |
Returns a string representation of timestamp in the format 'YYYY-MM-DD'. If timestamp is not defined, the function will use the current local system date.
string = sqldate([number timestamp])
Parameter Description timestamp The number of seconds since January 1, 1970 UTC (commonly called a UNIX timestamp).
Returns a formatted date string in the format 'YYYY-MM-DD'.
No remarks.
print(sqldate());
The above example will output something similar to: "2009-01-01"
print(sqldate(0)+" "+sqltime(0));
The above example will output something similar to (note the adjustment for local time): "1969-12-31 19:00:00"
Returns a string representation of timestamp in the format 'HH:MM:SS'. If timestamp is not defined, the function will use the current local system time.
string = sqltime([number timestamp])
Parameter Description timestamp The number of seconds since January 1, 1970 UTC (commonly called a UNIX timestamp).
Returns a formatted time string in the format 'HH:MM:SS'.
No remarks.
print(sqltime());
The above example will output something similar to: "16:30:45"
print(sqldate(0)+" "+sqltime(0));
The above example will output something similar to (note the adjustment for local time): "1969-12-31 19:00:00"
(table) dirlist(string dirname);
Returns a table containing files and attributes in the supplied dirname.
(string) rot13(string str);
Returns a rot13 *cough* encoded string from str.
Double-rot13 encryption is so stealthy, you won't even know it's been encrypted.
(table) xml.read(string str);
Read the supplied XML text and return a digested table. This is _not_ a pretty function.
Open an SSH connection to a given host/port.
ssh-conn = ssh.open(hostname[, port])
Parameter Description hostname String containing the name of the server to connect to. port Number containing the server port to connect to (default is 22).
Returns an ssh-conn connection object if successful. Any number returned likely indicates an error.
None
The following example demonstrates how to connect to a host and verify success.
if (typeof(conn=ssh.open("192.168.0.1", 22))!='ssh-conn') {
print("failed connection");
exit;
}
/* checking the host's RSA key fingerprint is optional, but a good idea. */
key="ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff";
if ((k=ssh.hostkey(conn))!=key) {
print("expected = "+key+"\nrecieved = "+k+"\n");
print("Host key verification failed.\n");
exit;
}
print("RSA key fingerprint is "+k+".\n");
if (ssh.auth(conn, "username", "password")!=true) {
print("failed auth");
exit;
}
/*
* do something useful here
*/
ssh.close(conn);
Cloae an SSH connection.
number = ssh.close(conn)
Parameter Description conn Server connection object to be closed.
Always returns zero.
None
The following example demonstrates how to close a host connection.
ssh.close(conn);
Authenticate an SSH connection.
boolean = ssh.auth(sshconn, username, password | { pass, prv, pub })
Parameter Description sshconn An active ssh-conn connection. username String containing the account username to connect as. password String containing the account password. pass String containing the passphrase of the private key (used with key-based authentication). prv String containing the location of the private key (used with key-based authentication). pub String containing the location of the public key (used with key-based authentication).
Returns true if successful. Any failure to authenticate returns false.
None
The following example demonstrates how to authenticate via user/pass or a keypair.
global username = "user"; global password = "pass"; global rsa_keys = { pass="rsapass", prv="~/.ssh/id_rsa", pub="~/.ssh/id_rsa.pub" }; /* you can authenticate with a user/pass pair */ if (ssh.auth(conn, username, password)!=true) { print("failed auth"); exit; } /* or you can authenticate with keys */ if (ssh.auth(conn, username, rsa_keys)!=true) { print("failed auth"); exit; }
(table) http.get(number ssl, string host, number port, string uri);
Connect to an HTTP server and retrieve the requested uri. Returns a table with { head, body } elements.
I'm lazy, so here's the long ugly version. This is everything your C program will ever need to know about Nesla. Actually, it needs to know a lot less, but hey.
/* NESLA NullLogic Embedded Scripting Language Copyright (C) 2007-2009 Dan Cahill This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _NESLA_H #define _NESLA_H 1 #if defined(TINYCC)||defined(__TURBOC__) struct timeval { long tv_sec; long tv_usec; }; #endif #if defined(_MSC_VER) #define WIN32_LEAN_AND_MEAN /* always include winsock2 before windows */ #include <winsock2.h> #include <windows.h> #include <time.h> #elif !defined(__TURBOC__) #include <sys/time.h> #endif #include <setjmp.h> #define NESLA_NAME "nesla" #define NESLA_VERSION "0.9.1" #define MAX_OBJNAMELEN 64 #define MAX_OUTBUFLEN 8192 #define OUTBUFLOWAT 4096 /* nesla object types */ #define NT_NULL 0 #define NT_BOOLEAN 1 #define NT_NUMBER 2 #define NT_STRING 3 #define NT_NFUNC 4 #define NT_CFUNC 5 #define NT_TABLE 6 #define NT_CDATA 7 /* nesla object status flags */ #define NST_HIDDEN 0x01 #define NST_READONLY 0x02 #define NST_SYSTEM 0x04 #define NST_AUTOSORT 0x08 #define NST_LINK 0x10 #define num_t double #define uchar unsigned char #define obj_t struct nes_objrec #define val_t struct nes_valrec #define nes_t struct nes_state /* should be typedef int(*NES_CFUNC)(nes_state *); */ typedef int(*NES_CFUNC)(void *); #define NES_FUNCTION(name) int name(nes_state *N) /* * define a callback function type so CDATA objects * can choose the terms of their own death. */ /* should be typedef void(*NES_CFREE)(nes_state *, obj_t *); */ typedef void(*NES_CFREE)(void *, void *); typedef struct NES_CDATA { /* standard header info for CDATA object */ char obj_type[16]; /* tell us all about yourself in 15 characters or less */ NES_CFREE obj_term; /* now tell us how to kill you */ /* now begin the stuff that's type-specific */ } NES_CDATA; typedef struct nes_valrec { unsigned short type; /* val type */ unsigned short attr; /* status flags (hidden, readonly, system, autosort, etc...) */ unsigned short refs; /* number of references to this node */ unsigned long size; /* storage size of string, nfunc or cdata */ union { num_t num; char *str; NES_CFUNC cfunc; NES_CDATA *cdata; obj_t *table; } d; } nes_valrec; typedef struct nes_objrec { obj_t *prev; obj_t *next; val_t *val; char name[MAX_OBJNAMELEN+1]; } nes_objrec; typedef struct nes_state { uchar *blockptr; uchar *blockend; uchar *readptr; obj_t g; obj_t l; obj_t r; short brk; short cnt; short ret; short err; /* intended for external signals to the parser. for now, non-zero just means to shut down */ short signal; short debug; short single; short strict; short warnings; jmp_buf *savjmp; struct timeval ttime; unsigned short outbuflen; char numbuf[128]; char outbuf[MAX_OUTBUFLEN+1]; char errbuf[256]; } nes_state; #ifndef NESLA_NOFUNCTIONS /* exec */ nes_state *nes_newstate (void); nes_state *nes_endstate (nes_state *N); obj_t *nes_exec (nes_state *N, const char *string); int nes_execfile (nes_state *N, char *file); /* objects */ void nes_setvaltype (nes_state *N, obj_t *cobj, unsigned short type); void nes_linkval (nes_state *N, obj_t *cobj1, obj_t *cobj2); void nes_unlinkval (nes_state *N, obj_t *cobj); void nes_freetable (nes_state *N, obj_t *tobj); obj_t *nes_getobj (nes_state *N, obj_t *tobj, char *oname); obj_t *nes_getiobj (nes_state *N, obj_t *tobj, unsigned long oindex); obj_t *nes_setobj (nes_state *N, obj_t *tobj, char *oname, unsigned short otype, NES_CFUNC _fptr, num_t _num, char *_str, long _slen); void nes_strcat (nes_state *N, obj_t *cobj, char *str, long len); void nes_strmul (nes_state *N, obj_t *cobj, unsigned long n); short nes_tobool (nes_state *N, obj_t *cobj); num_t nes_tonum (nes_state *N, obj_t *cobj); char *nes_tostr (nes_state *N, obj_t *cobj); /* parser */ obj_t *nes_eval (nes_state *N, const char *string); obj_t *nes_evalf (nes_state *N, const char *fmt, ...); #endif #define nes_isnull(o) (o==NULL||o->val==NULL||o->val->type==NT_NULL) #define nes_isbool(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_BOOLEAN) #define nes_isnum(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_NUMBER) #define nes_isstr(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_STRING) #define nes_istable(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_TABLE) #define nes_istrue(o) nes_tobool(N, o)?1:0 #define nes_typeof(o) nes_isnull(o)?NT_NULL:o->val->type #define nes_getnum(N,o,n) nes_tonum(N, nes_getobj(N,o,n)) #define nes_getstr(N,o,n) nes_tostr(N, nes_getobj(N,o,n)) #define nes_setnum(N,t,n,v) nes_setobj(N, t, n, NT_NUMBER, (NES_CFUNC)NULL, v, NULL, 0) #define nes_setstr(N,t,n,s,l) nes_setobj(N, t, n, NT_STRING, (NES_CFUNC)NULL, 0, s, l) #define nes_settable(N,t,n) nes_setobj(N, t, n, NT_TABLE, (NES_CFUNC)NULL, 0, NULL, 0) #define nes_setcfunc(N,t,n,p) nes_setobj(N, t, n, NT_CFUNC, (NES_CFUNC)p, 0, NULL, 0) #define nes_setnfunc(N,t,n,s,l) nes_setobj(N, t, n, NT_NFUNC, (NES_CFUNC)NULL, 0, s, l) #define nes_setcdata(N,t,n,s,l) nes_setobj(N, t, n, NT_CDATA, (NES_CFUNC)NULL, 0, (void *)s, l) #define nes_setinum(N,t,n,v) nes_setiobj(N, t, n, NT_NUMBER, (NES_CFUNC)NULL, v, NULL, 0) #define nes_setistr(N,t,n,s,l) nes_setiobj(N, t, n, NT_STRING, (NES_CFUNC)NULL, 0, s, l) #define nes_setitable(N,t,n) nes_setiobj(N, t, n, NT_TABLE, (NES_CFUNC)NULL, 0, NULL, 0) #define nes_seticfunc(N,t,n,p) nes_setiobj(N, t, n, NT_CFUNC, (NES_CFUNC)p, 0, NULL, 0) #define nes_setinfunc(N,t,n,s,l) nes_setiobj(N, t, n, NT_NFUNC, (NES_CFUNC)NULL, 0, s, l) #define nes_seticdata(N,t,n,s,l) nes_setiobj(N, t, n, NT_CDATA, (NES_CFUNC)NULL, 0, (void *)s, l) #endif /* nesla.h */
Please direct feedback to: nulllogic@users.sourceforge.net |
Copyright © 2009 NullLogic All rights reserved |