NullLogic Embedded Scripting Language - Reference |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
copy()
eval() exec() serialize() iname() include() ival() print() runtime() sizeof() sleep() system() tonumber() tostring() typeof() write() zlink()
math.abs()
math.acos() math.asin() math.atan() math.atan2() math.ceil() math.cos() math.cosh() math.exp() math.floor() math.log() math.log10() math.rand() math.sin() math.sinh() math.sqrt() math.tan() math.tanh()
string.atoi()
string.cat() string.cmp() string.icmp() string.istr() string.itoa() string.join() string.len() string.ncmp() string.nicmp() string.replace() string.split() string.str() string.sub() string.tolower() string.toupper()
data.cdb.read()
data.cdb.write() data.dbf.reader() data.firebird.client() data.firebird.escape() data.mysql.query() data.odbc.client() data.pgsql.query() data.sqlite3.client() data.sqlite3.escape() data.xml.read()
net.dns.name2addr()
net.dns.addr2name() net.ftp.client() net.http.client() net.ldap.search() net.mime.read() net.mime.write() net.mime.decode_qp() net.mime.decode_rfc2047() net.pop3.client() net.smtp.client() net.ssh.auth() net.ssh.close() net.ssh.cmd() net.ssh.hostkey() net.ssh.open() net.ssh.sftp.get() net.ssh.sftp.ls() net.ssh.sftp.mkdir() net.ssh.sftp.put() net.ssh.sftp.put_mem() net.ssh.sftp.rename() net.ssh.sftp.rmdir() net.ssh.sftp.unlink() net.tcp.accept() net.tcp.bind() net.tcp.close() net.tcp.gets() net.tcp.info() net.tcp.open() net.tcp.read() net.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: class str(val) {
size = function () { return sizeof(this.value); };
lower = function () { return string.tolower(this.value); };
upper = function () { return string.toupper(this.value); };
get = function () { return this.value;
set = function (val) { return this.value=tostring(val); };
value = tostring(val);
}
x=new str("AbC");
print("["+x.size()+"]\n"); // will print 3
x.set("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 serializeDescriptionPrint the provided var in a format appropriate for use in a nesla script. This will recursively print entire tables. Syntaxserialize(object var)
Return ValueReturns zero. RemarksAny 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 example "var x={}; x.y=x; serialize(x);" is valid code. It also recurses infinitely. Be careful, or you may be cursing infinitely yourself. ExamplesThe following examples demonstrate the difference between print and serialize.
includeDescriptionInclude (and interpret) the code in the specified file. Syntaxboolean = include(filename)
Return ValueReturns true if the file has been successfully included. Any false return code indicates an error. RemarksReturn codes indicating failure are almost always caused by a nonexistent or unreadable script file, not errors in the script itself. ExampleThe following example demonstrates how to load a script and verify its success. DescriptionPrint the complete list of arguments to the standard output. Syntaxnumber = print(...)
Return ValueReturns the number of characters printed. RemarksAny 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. ExamplesThe following example demonstrates how to print multiple objects. The following example gives the same output as above, but note that using + to concatenate the strings means that print only receives one argument. See Alsoio.print() runtimeDescriptionReturns the elapsed time the parser has been running. Syntaxnumber = runtime() Return ValueReturns the time in seconds (with microsecond precision) the parser has been running. sizeofDescriptionReturns the size of the object. Syntaxnumber = sizeof(object)
Return ValueReturns the size of the object. For strings, this is the string length; for tables, the number of non-null objects in the table. Null values are zero size. sleepDescriptionSleep for a specified number of seconds. Syntaxsleep(number seconds)
Return ValueReturns zero. systemDescriptionPerforms an operating system call and returns the resulting errorcode. Syntax
Return ValueReturns the errorcode after execution of command. RemarksThis function does not include or easily allow any sophisticated methods such as piping, signal handling, or interactivity. ExamplesThe following example demonstrates a way to list a directory and then read the results. tonumberDescriptionReturns a number value equivalent of the source. Syntaxnumber = tonumber(object)
Return ValueReturns a numeric approximation of the object parameter. Objects such as tables and null will return zero since no other numeric value can be meaningfully representative. tostringDescriptionReturns a string value equivalent of the source. Syntaxstring = tostring(object[, number])
Return ValueReturns a string value equivalent of the source. If both arguments are numbers, the second allows the setting of a decimal precision. typeofDescriptionReturns the name of the type of object. Syntaxstring = typeof(object)
Return ValueReturns the name of the object type. Possible types include boolean, number, string, table, function and null. writeDescriptionWrites the entire object as a string and returns the result code. This function is binary safe. Syntaxnumber = write(object)
Return ValueReturns the number of bytes written. See Alsoio.write() 3 - file.*()
Writes the entire object to the end of an existing file as a string and returns the result code.
This function is binary safe.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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");
print()
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.
write()
(string) string.cat(string str1, string str2);(number) string.cmp(string str1, string str2);(number) string.icmp(string str1, string str2);(string) string.istr(string stack, string needle);(table) string.join(table str, string sep);(number) string.len(string str);(number) string.ncmp(string str1, string str2, number len);(number) string.nicmp(string str1, string str2, number len);(table) string.split(string str, string sep);(string) string.str(string stack, string needle);(string) string.sub(string stack, number offset[, number 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 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: "2010-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"
time.sqltime()
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"
time.sqldate()
(table) xml.read(string str);Read the supplied XML text and return a digested table. This is _not_ a pretty function.
(string) base64.decode(string encoded);(string) base64.encode(string decoded);(table) dirlist(string dirname);(string) rot13(string str);(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.
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);
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);
(sock4) tcp.info(sock4 socket);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-2010 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 _NSP_H
#define _NSP_H 1
#ifdef __cplusplus
extern "C" {
#endif
#define NSP_NAME "nesla"
#define NSP_VERSION "0.9.3"
#if defined(TINYCC)||defined(__TURBOC__)
struct timeval { long tv_sec; long tv_usec; };
struct timezone { int tz_minuteswest; int tz_dsttime; };
#endif
#if defined(_MSC_VER)
struct timezone { int tz_minuteswest; int tz_dsttime; };
//#define _CRT_SECURE_NO_DEPRECATE
//#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#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 MAX_OBJNAMELEN 64
#define MAX_OUTBUFLEN 4096
#define OUTBUFLOWAT 2048
/* 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
/* object status flags */
#define NST_HIDDEN 0x01
#define NST_READONLY 0x02
#define NST_SYSTEM 0x04
#define NST_AUTOSORT 0x08
#define NST_LINK 0x10
#define NST_STACKVAL 0x20
#define num_t double
#define uchar unsigned char
#define obj_t struct nsp_objrec
#define tab_t struct nsp_tablerec
#define val_t struct nsp_valrec
#define nsp_t struct nsp_state
/* should be typedef int(*NSP_CFUNC)(nsp_state *); */
typedef int(*NSP_CFUNC)(void *);
#define NSP_FUNCTION(name) int name(nsp_state *N)
#define NSP_CLASS(name) int name(nsp_state *N)
#define NSP_CLASSMETHOD(name) int name(nsp_state *N)
/*
* define a callback function type so CDATA objects
* can choose the terms of their own death.
*/
/* should be typedef void(*NSP_CFREE)(nsp_state *, obj_t *); */
typedef void(*NSP_CFREE)(void *, void *);
typedef struct NSP_CDATA {
/* standard header info for CDATA object */
char obj_type[16]; /* tell us all about yourself in 15 characters or less */
NSP_CFREE obj_term; /* now tell us how to kill you */
/* now begin the stuff that's type-specific */
} NSP_CDATA;
typedef struct nsp_tablerec {
obj_t *f;
obj_t *i;
obj_t *l;
} nsp_tablerec;
typedef struct nsp_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 */
obj_t *ztable; /* 'z' table for hierarchical lookups */
union {
num_t num;
char *str;
NSP_CFUNC cfunc;
NSP_CDATA *cdata;
tab_t table;
} d;
} nsp_valrec;
typedef struct nsp_objrec {
obj_t *prev;
obj_t *next;
val_t *val;
unsigned long hash;
char name[MAX_OBJNAMELEN+1];
} nsp_objrec;
typedef struct nsp_state {
uchar *blockptr;
uchar *blockend;
uchar *readptr;
obj_t g;
obj_t l;
obj_t r;
short brk;
short cnt;
short ret;
short err;
short signal; /* intended for external signals to the parser. for now, non-zero just means to shut down */
short debug;
short single;
short strict;
short warnings;
short maxwarnings;
char warnformat;
jmp_buf *savjmp;
struct timeval ttime;
unsigned short outbuflen;
char numbuf[128];
char outbuf[MAX_OUTBUFLEN+1];
char errbuf[256];
char *func;
char *tracefn;
/* debug info */
long int line_num;
long int allocs;
long int allocmem;
long int frees;
long int freemem;
long int peakmem;
long int counter1;
} nsp_state;
#ifndef NSP_NOFUNCTIONS
/* exec */
nsp_state *nsp_newstate (void);
nsp_state *nsp_endstate (nsp_state *N);
obj_t *nsp_exec (nsp_state *N, const char *string);
int nsp_execfile (nsp_state *N, char *file);
/* objects */
void nsp_setvaltype (nsp_state *N, obj_t *cobj, unsigned short type);
void nsp_linkval (nsp_state *N, obj_t *cobj1, obj_t *cobj2);
void nsp_unlinkval (nsp_state *N, obj_t *cobj);
void nsp_freetable (nsp_state *N, obj_t *tobj);
obj_t *nsp_getobj_ex (nsp_state *N, obj_t *tobj, char *oname, unsigned short followz, unsigned short *foundz);
obj_t *nsp_getobj (nsp_state *N, obj_t *tobj, char *oname);
obj_t *nsp_getiobj (nsp_state *N, obj_t *tobj, unsigned long oindex);
obj_t *nsp_setobj (nsp_state *N, obj_t *tobj, char *oname, unsigned short otype, NSP_CFUNC _fptr, num_t _num, char *_str, long _slen);
void nsp_strcat (nsp_state *N, obj_t *cobj, char *str, long len);
void nsp_strmul (nsp_state *N, obj_t *cobj, unsigned long n);
short nsp_tobool (nsp_state *N, obj_t *cobj);
num_t nsp_tonum (nsp_state *N, obj_t *cobj);
char *nsp_tostr (nsp_state *N, obj_t *cobj);
/* parser */
obj_t *nsp_eval (nsp_state *N, const char *string);
obj_t *nsp_evalf (nsp_state *N, const char *fmt, ...);
#endif
#define nsp_isnull(o) (o==NULL||o->val==NULL||o->val->type==NT_NULL)
#define nsp_isbool(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_BOOLEAN)
#define nsp_isnum(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_NUMBER)
#define nsp_isstr(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_STRING)
#define nsp_istable(o) (o!=NULL&&o->val!=NULL&&o->val->type==NT_TABLE)
#define nsp_istrue(o) (nsp_tobool(N, o)?1:0)
#define nsp_typeof(o) (nsp_isnull(o)?NT_NULL:o->val->type)
#define nsp_getnum(N,o,n) nsp_tonum(N, nsp_getobj(N,o,n))
#define nsp_getstr(N,o,n) nsp_tostr(N, nsp_getobj(N,o,n))
#define nsp_setnull(N,t,n) nsp_setobj(N, t, n, NT_NULL, (NSP_CFUNC)NULL, 0, NULL, 0)
#define nsp_setnum(N,t,n,v) nsp_setobj(N, t, n, NT_NUMBER, (NSP_CFUNC)NULL, v, NULL, 0)
#define nsp_setbool(N,t,n,v) nsp_setobj(N, t, n, NT_BOOLEAN, (NSP_CFUNC)NULL, v?1:0, NULL, 0)
#define nsp_setstr(N,t,n,s,l) nsp_setobj(N, t, n, NT_STRING, (NSP_CFUNC)NULL, 0, s, l)
#define nsp_settable(N,t,n) nsp_setobj(N, t, n, NT_TABLE, (NSP_CFUNC)NULL, 0, NULL, 0)
#define nsp_setcfunc(N,t,n,p) nsp_setobj(N, t, n, NT_CFUNC, (NSP_CFUNC)p, 0, NULL, 0)
#define nsp_setnfunc(N,t,n,s,l) nsp_setobj(N, t, n, NT_NFUNC, (NSP_CFUNC)NULL, 0, s, l)
#define nsp_setcdata(N,t,n,s,l) nsp_setobj(N, t, n, NT_CDATA, (NSP_CFUNC)NULL, 0, (void *)s, l)
#define nsp_setinum(N,t,n,v) nsp_setiobj(N, t, n, NT_NUMBER, (NSP_CFUNC)NULL, v, NULL, 0)
#define nsp_setistr(N,t,n,s,l) nsp_setiobj(N, t, n, NT_STRING, (NSP_CFUNC)NULL, 0, s, l)
#define nsp_setitable(N,t,n) nsp_setiobj(N, t, n, NT_TABLE, (NSP_CFUNC)NULL, 0, NULL, 0)
#define nsp_seticfunc(N,t,n,p) nsp_setiobj(N, t, n, NT_CFUNC, (NSP_CFUNC)p, 0, NULL, 0)
#define nsp_setinfunc(N,t,n,s,l) nsp_setiobj(N, t, n, NT_NFUNC, (NSP_CFUNC)NULL, 0, s, l)
#define nsp_seticdata(N,t,n,s,l) nsp_setiobj(N, t, n, NT_CDATA, (NSP_CFUNC)NULL, 0, (void *)s, l)
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
class NesObject {
public:
NesObject()
{
/* memset(O, 0, sizeof(O)); */
}
~NesObject()
{
/* nsp_unlink(O); */
}
const char *errbuf()
{
/* return this->N->errbuf; */
}
private:
obj_t O;
};
class NesState {
public:
NesState()
{
this->N=nsp_newstate();
}
~NesState()
{
nsp_endstate(this->N);
}
obj_t *exec(const char *string)
{
return nsp_exec(this->N, string);
}
int execfile(char *file)
{
return nsp_execfile(this->N, file);
}
obj_t *eval(const char *string)
{
return nsp_eval(this->N, string);
}
/*
obj_t *evalf(const char *fmt, ...)
{
return nsp_evalf(this->N, fmt, ...);
}
*/
obj_t *getG()
{
return &this->N->g;
}
obj_t *getL()
{
return &this->N->l;
}
nsp_t *getN()
{
return this->N;
}
void setdebug(int x)
{
this->N->debug=x;
}
int err()
{
return this->N->err;
}
int warnings()
{
return this->N->warnings;
}
const char *errbuf()
{
return this->N->errbuf;
}
private:
nsp_state *N;
};
#endif
#endif /* _NSP_H */
|
Please direct feedback to: nulllogic@users.sourceforge.net |
Copyright © 2010 NullLogic All rights reserved |