/ Check-in [81b5253abf]
DEMO | DOWNLOAD | DEPLOY | SEARCH
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Release "2.5.23". Fix new RegExp arg 2 bug. Expand module -m to support templates. Fix File.chmod bug. Add SqliteUI -dump option.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:81b5253abfcc24ec596da735932dd2c9da058787
User & Date: pmacdona 2018-10-18 23:00:21
Context
2018-10-26
15:28
Release "2.5.24". Windows fixes. check-in: 5b595c6944 user: pmacdona tags: trunk
2018-10-18
23:00
Release "2.5.23". Fix new RegExp arg 2 bug. Expand module -m to support templates. Fix File.chmod bug. Add SqliteUI -dump option. check-in: 81b5253abf user: pmacdona tags: trunk
2018-10-17
01:36
Release "2.5.22". To exec add "chdir" option. check-in: 1cd1d600a3 user: pmacdona tags: trunk
Changes

Added lib/Jsi_Module.jsi.





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#! /usr/bin/env jsish

require('Jsi', '2.4');

function Jsi_Module(args:array, conf:object=void) {

    var options = { // Run or create a Jsi module.
        create     :'',        // Create a Jsi module template with this name.
        web     :false      // Use websock server template.
    };
    var self = {
        rootdir      :''    // Root directory.
    };

    parseOpts(self, options, conf);
    
    function main() {
        LogDebug('Starting');
        if (self.rootdir === '')
            self.rootdir=Info.scriptDir();
        debugger;
        var fn = self.create;
        if (fn === '')
            throw('must specify create');
        var ext = File.extension(fn);
        if (ext !== '.jsi')
            fn += '.jsi';
        if (File.exists(fn))
            throw('file exists: '+fn);
        var pat = File.rootname(File.tail(fn));
        var pref = (self.web?'WebApp':'module');
        var tmpl = File.read('/zvfs/lib/templates/'+(self.web?'WebApp':'module')+'.jsi');
        var re = new RegExp(pref,'g');
        tmpl = tmpl.replace(re, pat);
        File.write(fn, tmpl);
        File.chmod(fn, 0744);
        LogDebug('Done');
    }
    
    return main();
}

provide(Jsi_Module, 1);

if (isMain())
    runModule(Jsi_Module);

Changes to lib/Jsi_SqliteUI/Jsi_SqliteUI.jsi.

8
9
10
11
12
13
14

15
16
17
18
19
20
21
...
562
563
564
565
566
567
568


569
570
571
572
573
574
575
function Jsi_SqliteUI(files:array|string, conf:object=void)
{
    var options = { // Provide an sqlite user interface via a browser.
        Debug       :false,             // LogDebug output.
        Trace       :false,             // LogTrace output.
        closeTimeout:5000,              // Time til exit after close of final client websocket (ms).
        browser     :'',                // Browser program to use.

        foreignkey  :true,              // Enable foreign key constraints.
        integrity   :true,              // Do integrity check on startup.
        local       :true,              // Web server is to listen only on localhost.
        noCheck     :false,             // Disable typechecking.
        noGui       :false,             // Disable starting local browser.
        noUpdate    :false,             // Caller will provide update calls.
        noIO        :false,             // Disable disk io operations, other than to db.
................................................................................
            throw("expected a db file argument");
        if (typeof(files) === 'string')
            self.dbfile = files;
        else
            self.dbfile = files[0];
        if (!File.exists(self.dbfile))
            throw("db file not found");


        self.db = new Sqlite(self.dbfile, {queryOpts: {nullvalue:'NULL'}, readonly:self.readonly});
        if (self.foreignkey) {
            self.db.query('PRAGMA foreign_keys = ON');
        }
        if (self.integrity)
            CheckIntegrity();
        var i;







>







 







>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
function Jsi_SqliteUI(files:array|string, conf:object=void)
{
    var options = { // Provide an sqlite user interface via a browser.
        Debug       :false,             // LogDebug output.
        Trace       :false,             // LogTrace output.
        closeTimeout:5000,              // Time til exit after close of final client websocket (ms).
        browser     :'',                // Browser program to use.
        dump        :false,             // Dump database.
        foreignkey  :true,              // Enable foreign key constraints.
        integrity   :true,              // Do integrity check on startup.
        local       :true,              // Web server is to listen only on localhost.
        noCheck     :false,             // Disable typechecking.
        noGui       :false,             // Disable starting local browser.
        noUpdate    :false,             // Caller will provide update calls.
        noIO        :false,             // Disable disk io operations, other than to db.
................................................................................
            throw("expected a db file argument");
        if (typeof(files) === 'string')
            self.dbfile = files;
        else
            self.dbfile = files[0];
        if (!File.exists(self.dbfile))
            throw("db file not found");
        if (self.dump)
            return DumpSql(self.dbfile);
        self.db = new Sqlite(self.dbfile, {queryOpts: {nullvalue:'NULL'}, readonly:self.readonly});
        if (self.foreignkey) {
            self.db.query('PRAGMA foreign_keys = ON');
        }
        if (self.integrity)
            CheckIntegrity();
        var i;

Changes to lib/Jsi_Vfs.jsi.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
            parseOpts(info, moptions, mnt.param);
            if (self.version === '')
                self.version = mnt.version;
            
            var ver = self.version;
            var sfx = ' -R '+repoFile;
            var noPatches = mnt.noPatches;
        puts("MNT:", mnt);
            info.subDir = info.subDir.trim('/');
            info = dosplit(self.exec('fossil info -v' + sfx), info);
            var tags = self.exec('fossil tag list' + sfx);
            info.tags = tags.trim().split('\n');
            if (ver === '') {
                var vtags = tagsMatch(info.tags, /^ver-[0-9]+\.[0-9]+$/, noPatches);
                var prtags = tagsMatch(info.tags, /^jsireq-[0-9]+\.[0-9]+$/);







<







63
64
65
66
67
68
69

70
71
72
73
74
75
76
            parseOpts(info, moptions, mnt.param);
            if (self.version === '')
                self.version = mnt.version;
            
            var ver = self.version;
            var sfx = ' -R '+repoFile;
            var noPatches = mnt.noPatches;

            info.subDir = info.subDir.trim('/');
            info = dosplit(self.exec('fossil info -v' + sfx), info);
            var tags = self.exec('fossil tag list' + sfx);
            info.tags = tags.trim().split('\n');
            if (ver === '') {
                var vtags = tagsMatch(info.tags, /^ver-[0-9]+\.[0-9]+$/, noPatches);
                var prtags = tagsMatch(info.tags, /^jsireq-[0-9]+\.[0-9]+$/);

Changes to lib/autoload.jsi.

27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
Jsi_Auto.Jsi_Zip        = 'source("'+Info.scriptDir()+'/Jsi_Zip.jsi")';
Jsi_Auto.Jsi_UnitTest   = 'source("'+Info.scriptDir()+'/Jsi_UnitTest.jsi")';
Jsi_Auto.Jsi_DebugUI    = 'source("'+Info.scriptDir()+'/Jsi_DebugUI/Jsi_DebugUI.jsi")';
Jsi_Auto.Jsi_SqliteUI   = 'source("'+Info.scriptDir()+'/Jsi_SqliteUI/Jsi_SqliteUI.jsi")';
Jsi_Auto.Jsi_Make       = 'source("'+Info.scriptDir()+'/Jsi_Make.jsi")';
Jsi_Auto.Jsi_Vfs        = 'source("'+Info.scriptDir()+'/Jsi_Vfs.jsi")';
Jsi_Auto.Jsi_Archive    = 'source("'+Info.scriptDir()+'/Jsi_Archive.jsi")';

Jsi_Auto.Jsi_Help       = 'source("'+Info.scriptDir()+'/Jsi_Help.jsi")';

Jsi_Auto.Sqlite         = 'require("Sqlite");';
Jsi_Auto.MySql          = 'require("MySql");';
Jsi_Auto.Websocket      = 'require("WebSocket");';
Jsi_Auto.Socket         = 'require("Socket");';
Jsi_Auto.DebugUI        = 'require("DebugUI");';

source(Info.scriptDir()+'/JsiCompat.jsi');

Jsi_Auto.__autoloaded__ =true;








>












27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Jsi_Auto.Jsi_Zip        = 'source("'+Info.scriptDir()+'/Jsi_Zip.jsi")';
Jsi_Auto.Jsi_UnitTest   = 'source("'+Info.scriptDir()+'/Jsi_UnitTest.jsi")';
Jsi_Auto.Jsi_DebugUI    = 'source("'+Info.scriptDir()+'/Jsi_DebugUI/Jsi_DebugUI.jsi")';
Jsi_Auto.Jsi_SqliteUI   = 'source("'+Info.scriptDir()+'/Jsi_SqliteUI/Jsi_SqliteUI.jsi")';
Jsi_Auto.Jsi_Make       = 'source("'+Info.scriptDir()+'/Jsi_Make.jsi")';
Jsi_Auto.Jsi_Vfs        = 'source("'+Info.scriptDir()+'/Jsi_Vfs.jsi")';
Jsi_Auto.Jsi_Archive    = 'source("'+Info.scriptDir()+'/Jsi_Archive.jsi")';
Jsi_Auto.Jsi_Module     = 'source("'+Info.scriptDir()+'/Jsi_Module.jsi")';
Jsi_Auto.Jsi_Help       = 'source("'+Info.scriptDir()+'/Jsi_Help.jsi")';

Jsi_Auto.Sqlite         = 'require("Sqlite");';
Jsi_Auto.MySql          = 'require("MySql");';
Jsi_Auto.Websocket      = 'require("WebSocket");';
Jsi_Auto.Socket         = 'require("Socket");';
Jsi_Auto.DebugUI        = 'require("DebugUI");';

source(Info.scriptDir()+'/JsiCompat.jsi');

Jsi_Auto.__autoloaded__ =true;

Changes to lib/templates/WebApp.jsi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env jsish
require('Jsish');
require('WebSocket');

function WebApp(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A minimal WebSocket server module
        file        :'html/main.htmli', // Source file.
        server      :false,         // Just the server: do not open a browser.
        port        :0,             // Port number for server.
        quiet       :false,         // No info messages.
        rootdir     :'',            // Root directory
        useridPass  :'',            // USER:PASS for web GUI.
        wsdebug     :0,             // WebSockets debug level.

|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env jsish
require('Jsi');
require('WebSocket');

function WebApp(args:array|string=void, conf:object=void) {
    
    var self = { done:false };
    var options = { // A  WebSocket server module
        file        :'html/main.htmli', // Source file.
        server      :false,         // Just the server: do not open a browser.
        port        :0,             // Port number for server.
        quiet       :false,         // No info messages.
        rootdir     :'',            // Root directory
        useridPass  :'',            // USER:PASS for web GUI.
        wsdebug     :0,             // WebSockets debug level.

Name change from lib/templates/Module.jsi to lib/templates/module.jsi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
..
19
20
21
22
23
24
25
26
27
28
29
#! /usr/bin/env jsish

require('Jsi', '2.4');

function Example(args:array, conf:object=void) {

    var options = { // An example Jsi module that does nothing.
        rootdir      :''      // Root directory.
    };
    var self = {
    };

    parseOpts(self, options, conf);
    
................................................................................
        debugger;
        LogDebug('Done');
    }
    
    return main();
}

provide(Example, 1);

if (isMain())
    runModule(Example);
|

|

|

|







 







|


|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
..
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env jsish

require('Jsi');

function module(args:array, conf:object=void) {

    var options = { // module description.
        rootdir      :''      // Root directory.
    };
    var self = {
    };

    parseOpts(self, options, conf);
    
................................................................................
        debugger;
        LogDebug('Done');
    }
    
    return main();
}

provide(module, 1);

if (isMain())
    runModule(module);

Changes to src/jsi.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
18150
18151
18152
18153
18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
.....
19149
19150
19151
19152
19153
19154
19155



19156
19157
19158
19159
19160
19161

19162
19163
19164
19165
19166
19167
19168
.....
33498
33499
33500
33501
33502
33503
33504
33505
33506
33507
33508
33509
33510
33511
33512
33513
33514
33515
33516
33517
33518
33519
33520
33521
33522
33523
33524
33525
.....
33530
33531
33532
33533
33534
33535
33536
33537
33538
33539
33540
33541
33542
33543
33544
.....
37755
37756
37757
37758
37759
37760
37761
37762
37763
37764
37765
37766
37767
37768
37769
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 22

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
    if (Jsi_RegExpMatch(interp, v, str, &rc, NULL) != JSI_OK)
        return JSI_ERROR;    
    Jsi_ValueMakeBool(interp, ret, rc != 0);
    return JSI_OK;
}

static Jsi_CmdSpec regexpCmds[] = {
    { "RegExp",  RegExp_constructor,    1, 1, "val:regexp|string", .help="Create a regexp object", .retType=(uint)JSI_TT_REGEXP, .flags=JSI_CMD_IS_CONSTRUCTOR  },
    { "exec",    RegexpExecCmd,         1, 1, "val:string", .help="return matching string", .retType=(uint)JSI_TT_ARRAY|JSI_TT_OBJECT|JSI_TT_NULL, 0, .info=FN_regexec  },
    { "test",    RegexpTestCmd,         1, 1, "val:string", .help="test if a string matches", .retType=(uint)JSI_TT_BOOLEAN },
    { NULL, 0,0,0,0,.help="Commands for managing reqular expression objects" }
};

Jsi_RC jsi_InitRegexp(Jsi_Interp *interp, int release)
{
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-v" )) {
            printf("%u.%u.%u\n", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE);
            return jsi_DoExit(interp, 1);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {



            Jsi_DString dStr = {};
            const char* cpe = Jsi_Strrchr(argv[2], '.');
            int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
            Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
            rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
            Jsi_DSFree(&dStr);

        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);

        else if (interp->selfZvfs && argc > 1 && (Jsi_Strcmp(argv[1], "--debug")==0 || Jsi_Strcmp(argv[1], "-d" )==0)) {
            interp->debugOpts.isDebugger = 1;
            rc = Jsi_EvalString(interp, "runModule('Jsi_Debug');", JSI_EVAL_ISMAIN);
................................................................................
        if (opt->vt == JSI_VT_OBJECT && opt->d.obj->ot == JSI_OT_OBJECT) {
            hasopts = 1;
            if (Jsi_OptionsProcess(interp, ExecOptions, &edata, opt, 0) < 0) {
                return JSI_ERROR;
            }
            if (edata.retCode)
                edata.retval = 0;
        } else if ((cp2=Jsi_ValueString(interp, opt, &sLen2))) {
            edata.inputStr = opt;
        } else 
            return Jsi_LogError("expected: string?,null|instr?");
    }
    if (restricted || edata.noRedir) {
        // Sanity check command string to disallow shell escapes, redirection, etc.
        cp2 = cp;
        while (*cp2) {
            if (*cp2 != '>' && *cp2 != '<' &&*cp2 != '|' &&*cp2 != ';' && *cp2 != '&' && *cp2 != '$' && *cp2 != '`' && *cp2 != '=')
                cp2++;
            else 
                return Jsi_LogError("restricted exec at char '%c' in string: %s", *cp2, cp);
        }
    }
    int isbg = 0, ec = 0;
    const char *ocd = NULL, *cd = (edata.chdir ? Jsi_ValueString(interp, edata.chdir, NULL) : NULL);
    if (cd && interp->isSafe) {
        cd = NULL;
        rc = Jsi_LogError("no chdir in safe mode");
        goto done;        
................................................................................
            cd = NULL;
            rc = Jsi_LogError("chdir failed");
            goto done;        
        }
    }
    if (edata.bg || (isbg=((sLen>1 && cp[sLen-1] == '&')))) {
        if (edata.inputStr) {
            rc = Jsi_LogError("inputStr can not used with bg");
            goto done;
        }
        if (!isbg) {
            Jsi_DSAppend(&dStr, cp, " &", NULL);
            cp = Jsi_DSValue(&dStr);
        }
        edata.bg = 1;
................................................................................
        Jsi_OptionsFree(interp, GlobOptions, &Data, 0);
    return rc;
}

static Jsi_CmdSpec fileCmds[] = {
    { "atime",      FileAtimeCmd,       1,  1, "file:string",  .help="Return file Jsi_Access time", .retType=(uint)JSI_TT_NUMBER },
    { "chdir",      FileChdirCmd,       1,  1, "file:string",  .help="Change current directory" },
    { "chmod",      FileChmodCmd,       2,  2, "file:string, mode:string",  .help="Set file permissions" },
    { "copy",       FileCopyCmd,        2,  3, "src:string, dest:string, force:boolean=false",  .help="Copy a file to destination", .retType=0, .flags=0, .info=FN_copy },
    { "dirname",    FileDirnameCmd,     1,  1, "file:string",  .help="Return directory path", .retType=(uint)JSI_TT_STRING },
    { "executable", FileExecutableCmd,  1,  1, "file:string",  .help="Return true if file is executable", .retType=(uint)JSI_TT_BOOLEAN },
    { "exists",     FileExistsCmd,      1,  1, "file:string",  .help="Return true if file exists", .retType=(uint)JSI_TT_BOOLEAN },
    { "extension",  FileExtensionCmd,   1,  1, "file:string",  .help="Return file extension", .retType=(uint)JSI_TT_STRING },
    { "join",       FileJoinCmd,        2,  2, "path:string, path:string",  .help="Join two file realpaths, or just second if an absolute path", .retType=(uint)JSI_TT_STRING },
    { "isdir",      FileIsdirCmd,       1,  1, "file:string",  .help="Return true if file is a directory", .retType=(uint)JSI_TT_BOOLEAN },






|







 







|







 







>
>
>
|
|
|
|
|
|
>







 







|


|



|
<
<
<
<
|
<







 







|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
18150
18151
18152
18153
18154
18155
18156
18157
18158
18159
18160
18161
18162
18163
18164
.....
19149
19150
19151
19152
19153
19154
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
19169
19170
19171
19172
.....
33502
33503
33504
33505
33506
33507
33508
33509
33510
33511
33512
33513
33514
33515
33516




33517

33518
33519
33520
33521
33522
33523
33524
.....
33529
33530
33531
33532
33533
33534
33535
33536
33537
33538
33539
33540
33541
33542
33543
.....
37754
37755
37756
37757
37758
37759
37760
37761
37762
37763
37764
37765
37766
37767
37768
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 23

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

................................................................................
    if (Jsi_RegExpMatch(interp, v, str, &rc, NULL) != JSI_OK)
        return JSI_ERROR;    
    Jsi_ValueMakeBool(interp, ret, rc != 0);
    return JSI_OK;
}

static Jsi_CmdSpec regexpCmds[] = {
    { "RegExp",  RegExp_constructor,    1, 2, "val:regexp|string, flags:string", .help="Create a regexp object", .retType=(uint)JSI_TT_REGEXP, .flags=JSI_CMD_IS_CONSTRUCTOR  },
    { "exec",    RegexpExecCmd,         1, 1, "val:string", .help="return matching string", .retType=(uint)JSI_TT_ARRAY|JSI_TT_OBJECT|JSI_TT_NULL, 0, .info=FN_regexec  },
    { "test",    RegexpTestCmd,         1, 1, "val:string", .help="test if a string matches", .retType=(uint)JSI_TT_BOOLEAN },
    { NULL, 0,0,0,0,.help="Commands for managing reqular expression objects" }
};

Jsi_RC jsi_InitRegexp(Jsi_Interp *interp, int release)
{
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-v" )) {
            printf("%u.%u.%u\n", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE);
            return jsi_DoExit(interp, 1);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);

        else if (interp->selfZvfs && argc > 1 && (Jsi_Strcmp(argv[1], "--debug")==0 || Jsi_Strcmp(argv[1], "-d" )==0)) {
            interp->debugOpts.isDebugger = 1;
            rc = Jsi_EvalString(interp, "runModule('Jsi_Debug');", JSI_EVAL_ISMAIN);
................................................................................
        if (opt->vt == JSI_VT_OBJECT && opt->d.obj->ot == JSI_OT_OBJECT) {
            hasopts = 1;
            if (Jsi_OptionsProcess(interp, ExecOptions, &edata, opt, 0) < 0) {
                return JSI_ERROR;
            }
            if (edata.retCode)
                edata.retval = 0;
        } else if (Jsi_ValueString(interp, opt, NULL)) {
            edata.inputStr = opt;
        } else 
            return Jsi_LogError("arg 2: expected options or input string?");
    }
    if (restricted || edata.noRedir) {
        // Sanity check command string to disallow shell escapes, redirection, etc.
        if (strcspn(cp, "<>|;&$`=") != strlen(cp))




            return Jsi_LogError("restricted chars in exec string: %s", cp);

    }
    int isbg = 0, ec = 0;
    const char *ocd = NULL, *cd = (edata.chdir ? Jsi_ValueString(interp, edata.chdir, NULL) : NULL);
    if (cd && interp->isSafe) {
        cd = NULL;
        rc = Jsi_LogError("no chdir in safe mode");
        goto done;        
................................................................................
            cd = NULL;
            rc = Jsi_LogError("chdir failed");
            goto done;        
        }
    }
    if (edata.bg || (isbg=((sLen>1 && cp[sLen-1] == '&')))) {
        if (edata.inputStr) {
            rc = Jsi_LogError("input string may not used with bg");
            goto done;
        }
        if (!isbg) {
            Jsi_DSAppend(&dStr, cp, " &", NULL);
            cp = Jsi_DSValue(&dStr);
        }
        edata.bg = 1;
................................................................................
        Jsi_OptionsFree(interp, GlobOptions, &Data, 0);
    return rc;
}

static Jsi_CmdSpec fileCmds[] = {
    { "atime",      FileAtimeCmd,       1,  1, "file:string",  .help="Return file Jsi_Access time", .retType=(uint)JSI_TT_NUMBER },
    { "chdir",      FileChdirCmd,       1,  1, "file:string",  .help="Change current directory" },
    { "chmod",      FileChmodCmd,       2,  2, "file:string, mode:number",  .help="Set file permissions" },
    { "copy",       FileCopyCmd,        2,  3, "src:string, dest:string, force:boolean=false",  .help="Copy a file to destination", .retType=0, .flags=0, .info=FN_copy },
    { "dirname",    FileDirnameCmd,     1,  1, "file:string",  .help="Return directory path", .retType=(uint)JSI_TT_STRING },
    { "executable", FileExecutableCmd,  1,  1, "file:string",  .help="Return true if file is executable", .retType=(uint)JSI_TT_BOOLEAN },
    { "exists",     FileExistsCmd,      1,  1, "file:string",  .help="Return true if file exists", .retType=(uint)JSI_TT_BOOLEAN },
    { "extension",  FileExtensionCmd,   1,  1, "file:string",  .help="Return file extension", .retType=(uint)JSI_TT_STRING },
    { "join",       FileJoinCmd,        2,  2, "path:string, path:string",  .help="Join two file realpaths, or just second if an absolute path", .retType=(uint)JSI_TT_STRING },
    { "isdir",      FileIsdirCmd,       1,  1, "file:string",  .help="Return true if file is a directory", .retType=(uint)JSI_TT_BOOLEAN },

Changes to src/jsi.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 22

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* jsi.h : External API header file for Jsi. */
#ifndef __JSI_H__
#define __JSI_H__

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 23

#define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

Changes to src/jsiCmds.c.

1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
        if (opt->vt == JSI_VT_OBJECT && opt->d.obj->ot == JSI_OT_OBJECT) {
            hasopts = 1;
            if (Jsi_OptionsProcess(interp, ExecOptions, &edata, opt, 0) < 0) {
                return JSI_ERROR;
            }
            if (edata.retCode)
                edata.retval = 0;
        } else if ((cp2=Jsi_ValueString(interp, opt, &sLen2))) {
            edata.inputStr = opt;
        } else 
            return Jsi_LogError("expected: string?,null|instr?");
    }
    if (restricted || edata.noRedir) {
        // Sanity check command string to disallow shell escapes, redirection, etc.
        cp2 = cp;
        while (*cp2) {
            if (*cp2 != '>' && *cp2 != '<' &&*cp2 != '|' &&*cp2 != ';' && *cp2 != '&' && *cp2 != '$' && *cp2 != '`' && *cp2 != '=')
                cp2++;
            else 
                return Jsi_LogError("restricted exec at char '%c' in string: %s", *cp2, cp);
        }
    }
    int isbg = 0, ec = 0;
    const char *ocd = NULL, *cd = (edata.chdir ? Jsi_ValueString(interp, edata.chdir, NULL) : NULL);
    if (cd && interp->isSafe) {
        cd = NULL;
        rc = Jsi_LogError("no chdir in safe mode");
        goto done;        
................................................................................
            cd = NULL;
            rc = Jsi_LogError("chdir failed");
            goto done;        
        }
    }
    if (edata.bg || (isbg=((sLen>1 && cp[sLen-1] == '&')))) {
        if (edata.inputStr) {
            rc = Jsi_LogError("inputStr can not used with bg");
            goto done;
        }
        if (!isbg) {
            Jsi_DSAppend(&dStr, cp, " &", NULL);
            cp = Jsi_DSValue(&dStr);
        }
        edata.bg = 1;







|


|



|
<
<
<
<
|
<







 







|







1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251




1252

1253
1254
1255
1256
1257
1258
1259
....
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
        if (opt->vt == JSI_VT_OBJECT && opt->d.obj->ot == JSI_OT_OBJECT) {
            hasopts = 1;
            if (Jsi_OptionsProcess(interp, ExecOptions, &edata, opt, 0) < 0) {
                return JSI_ERROR;
            }
            if (edata.retCode)
                edata.retval = 0;
        } else if (Jsi_ValueString(interp, opt, NULL)) {
            edata.inputStr = opt;
        } else 
            return Jsi_LogError("arg 2: expected options or input string?");
    }
    if (restricted || edata.noRedir) {
        // Sanity check command string to disallow shell escapes, redirection, etc.
        if (strcspn(cp, "<>|;&$`=") != strlen(cp))




            return Jsi_LogError("restricted chars in exec string: %s", cp);

    }
    int isbg = 0, ec = 0;
    const char *ocd = NULL, *cd = (edata.chdir ? Jsi_ValueString(interp, edata.chdir, NULL) : NULL);
    if (cd && interp->isSafe) {
        cd = NULL;
        rc = Jsi_LogError("no chdir in safe mode");
        goto done;        
................................................................................
            cd = NULL;
            rc = Jsi_LogError("chdir failed");
            goto done;        
        }
    }
    if (edata.bg || (isbg=((sLen>1 && cp[sLen-1] == '&')))) {
        if (edata.inputStr) {
            rc = Jsi_LogError("input string may not used with bg");
            goto done;
        }
        if (!isbg) {
            Jsi_DSAppend(&dStr, cp, " &", NULL);
            cp = Jsi_DSValue(&dStr);
        }
        edata.bg = 1;

Changes to src/jsiFileCmds.c.

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
        Jsi_OptionsFree(interp, GlobOptions, &Data, 0);
    return rc;
}

static Jsi_CmdSpec fileCmds[] = {
    { "atime",      FileAtimeCmd,       1,  1, "file:string",  .help="Return file Jsi_Access time", .retType=(uint)JSI_TT_NUMBER },
    { "chdir",      FileChdirCmd,       1,  1, "file:string",  .help="Change current directory" },
    { "chmod",      FileChmodCmd,       2,  2, "file:string, mode:string",  .help="Set file permissions" },
    { "copy",       FileCopyCmd,        2,  3, "src:string, dest:string, force:boolean=false",  .help="Copy a file to destination", .retType=0, .flags=0, .info=FN_copy },
    { "dirname",    FileDirnameCmd,     1,  1, "file:string",  .help="Return directory path", .retType=(uint)JSI_TT_STRING },
    { "executable", FileExecutableCmd,  1,  1, "file:string",  .help="Return true if file is executable", .retType=(uint)JSI_TT_BOOLEAN },
    { "exists",     FileExistsCmd,      1,  1, "file:string",  .help="Return true if file exists", .retType=(uint)JSI_TT_BOOLEAN },
    { "extension",  FileExtensionCmd,   1,  1, "file:string",  .help="Return file extension", .retType=(uint)JSI_TT_STRING },
    { "join",       FileJoinCmd,        2,  2, "path:string, path:string",  .help="Join two file realpaths, or just second if an absolute path", .retType=(uint)JSI_TT_STRING },
    { "isdir",      FileIsdirCmd,       1,  1, "file:string",  .help="Return true if file is a directory", .retType=(uint)JSI_TT_BOOLEAN },







|







1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
        Jsi_OptionsFree(interp, GlobOptions, &Data, 0);
    return rc;
}

static Jsi_CmdSpec fileCmds[] = {
    { "atime",      FileAtimeCmd,       1,  1, "file:string",  .help="Return file Jsi_Access time", .retType=(uint)JSI_TT_NUMBER },
    { "chdir",      FileChdirCmd,       1,  1, "file:string",  .help="Change current directory" },
    { "chmod",      FileChmodCmd,       2,  2, "file:string, mode:number",  .help="Set file permissions" },
    { "copy",       FileCopyCmd,        2,  3, "src:string, dest:string, force:boolean=false",  .help="Copy a file to destination", .retType=0, .flags=0, .info=FN_copy },
    { "dirname",    FileDirnameCmd,     1,  1, "file:string",  .help="Return directory path", .retType=(uint)JSI_TT_STRING },
    { "executable", FileExecutableCmd,  1,  1, "file:string",  .help="Return true if file is executable", .retType=(uint)JSI_TT_BOOLEAN },
    { "exists",     FileExistsCmd,      1,  1, "file:string",  .help="Return true if file exists", .retType=(uint)JSI_TT_BOOLEAN },
    { "extension",  FileExtensionCmd,   1,  1, "file:string",  .help="Return file extension", .retType=(uint)JSI_TT_STRING },
    { "join",       FileJoinCmd,        2,  2, "path:string, path:string",  .help="Join two file realpaths, or just second if an absolute path", .retType=(uint)JSI_TT_STRING },
    { "isdir",      FileIsdirCmd,       1,  1, "file:string",  .help="Return true if file is a directory", .retType=(uint)JSI_TT_BOOLEAN },

Changes to src/jsiInterp.c.

720
721
722
723
724
725
726



727
728
729
730
731
732

733
734
735
736
737
738
739
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-v" )) {
            printf("%u.%u.%u\n", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE);
            return jsi_DoExit(interp, 1);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {



            Jsi_DString dStr = {};
            const char* cpe = Jsi_Strrchr(argv[2], '.');
            int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
            Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
            rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
            Jsi_DSFree(&dStr);

        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);

        else if (interp->selfZvfs && argc > 1 && (Jsi_Strcmp(argv[1], "--debug")==0 || Jsi_Strcmp(argv[1], "-d" )==0)) {
            interp->debugOpts.isDebugger = 1;
            rc = Jsi_EvalString(interp, "runModule('Jsi_Debug');", JSI_EVAL_ISMAIN);







>
>
>
|
|
|
|
|
|
>







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "-v" )) {
            printf("%u.%u.%u\n", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE);
            return jsi_DoExit(interp, 1);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--module")==0 || Jsi_Strcmp(argv[1], "-m" )==0)) {
            if (argv[2][0] == '-')
                rc = Jsi_EvalString(interp, "runModule('Jsi_Module');", JSI_EVAL_ISMAIN);
            else {
                Jsi_DString dStr = {};
                const char* cpe = Jsi_Strrchr(argv[2], '.');
                int len = (cpe?cpe-argv[2]:Jsi_Strlen(argv[2]));
                Jsi_DSPrintf(&dStr, "source(\"%s\"); puts(runModule(\"%.*s\",console.args.slice(1)));", argv[2], len, argv[2]);
                rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
                Jsi_DSFree(&dStr);
            }
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);

        else if (interp->selfZvfs && argc > 1 && (Jsi_Strcmp(argv[1], "--debug")==0 || Jsi_Strcmp(argv[1], "-d" )==0)) {
            interp->debugOpts.isDebugger = 1;
            rc = Jsi_EvalString(interp, "runModule('Jsi_Debug');", JSI_EVAL_ISMAIN);

Changes to src/jsiRegexp.c.

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    if (Jsi_RegExpMatch(interp, v, str, &rc, NULL) != JSI_OK)
        return JSI_ERROR;    
    Jsi_ValueMakeBool(interp, ret, rc != 0);
    return JSI_OK;
}

static Jsi_CmdSpec regexpCmds[] = {
    { "RegExp",  RegExp_constructor,    1, 1, "val:regexp|string", .help="Create a regexp object", .retType=(uint)JSI_TT_REGEXP, .flags=JSI_CMD_IS_CONSTRUCTOR  },
    { "exec",    RegexpExecCmd,         1, 1, "val:string", .help="return matching string", .retType=(uint)JSI_TT_ARRAY|JSI_TT_OBJECT|JSI_TT_NULL, 0, .info=FN_regexec  },
    { "test",    RegexpTestCmd,         1, 1, "val:string", .help="test if a string matches", .retType=(uint)JSI_TT_BOOLEAN },
    { NULL, 0,0,0,0,.help="Commands for managing reqular expression objects" }
};

Jsi_RC jsi_InitRegexp(Jsi_Interp *interp, int release)
{
    if (!release)
        interp->RegExp_prototype = Jsi_CommandCreateSpecs(interp, "RegExp", regexpCmds, NULL, JSI_CMDSPEC_ISOBJ);
    return JSI_OK;
}

#endif







|













309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    if (Jsi_RegExpMatch(interp, v, str, &rc, NULL) != JSI_OK)
        return JSI_ERROR;    
    Jsi_ValueMakeBool(interp, ret, rc != 0);
    return JSI_OK;
}

static Jsi_CmdSpec regexpCmds[] = {
    { "RegExp",  RegExp_constructor,    1, 2, "val:regexp|string, flags:string", .help="Create a regexp object", .retType=(uint)JSI_TT_REGEXP, .flags=JSI_CMD_IS_CONSTRUCTOR  },
    { "exec",    RegexpExecCmd,         1, 1, "val:string", .help="return matching string", .retType=(uint)JSI_TT_ARRAY|JSI_TT_OBJECT|JSI_TT_NULL, 0, .info=FN_regexec  },
    { "test",    RegexpTestCmd,         1, 1, "val:string", .help="test if a string matches", .retType=(uint)JSI_TT_BOOLEAN },
    { NULL, 0,0,0,0,.help="Commands for managing reqular expression objects" }
};

Jsi_RC jsi_InitRegexp(Jsi_Interp *interp, int release)
{
    if (!release)
        interp->RegExp_prototype = Jsi_CommandCreateSpecs(interp, "RegExp", regexpCmds, NULL, JSI_CMDSPEC_ISOBJ);
    return JSI_OK;
}

#endif

Changes to tools/protos.jsi.

1
2
3
4
5
6
7
8
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//JSI Command Prototypes: version 2.5.22
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};
................................................................................
Event.prototype.names = function():array {};
Event.prototype.setInterval = function(callback:function, millisecs:number):number {};
Event.prototype.setTimeout = function(callback:function, millisecs:number):number {};
Event.prototype.update = function(options:number|object=void):number {};
var File = function(cmd,args) {};
File.prototype.atime = function(file:string):number {};
File.prototype.chdir = function(file:string):any {};
File.prototype.chmod = function(file:string, mode:string):any {};
File.prototype.copy = function(src:string, dest:string, force:boolean=false):any {};
File.prototype.dirname = function(file:string):string {};
File.prototype.executable = function(file:string):boolean {};
File.prototype.exists = function(file:string):boolean {};
File.prototype.extension = function(file:string):string {};
File.prototype.glob = function(pattern:regexp|string|null='*', options:function|object|null=void):array {};
File.prototype.isdir = function(file:string):boolean {};
|







 







|







1
2
3
4
5
6
7
8
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//JSI Command Prototypes: version 2.5.23
throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");

var Array = function(cmd,args) {};
Array.prototype.concat = function(...):array {};
Array.prototype.every = function(callback:function):any {};
Array.prototype.fill = function(value:any, start:number=0, end:number=-1):array {};
Array.prototype.filter = function(callback:function, this:object=void):array {};
................................................................................
Event.prototype.names = function():array {};
Event.prototype.setInterval = function(callback:function, millisecs:number):number {};
Event.prototype.setTimeout = function(callback:function, millisecs:number):number {};
Event.prototype.update = function(options:number|object=void):number {};
var File = function(cmd,args) {};
File.prototype.atime = function(file:string):number {};
File.prototype.chdir = function(file:string):any {};
File.prototype.chmod = function(file:string, mode:number):any {};
File.prototype.copy = function(src:string, dest:string, force:boolean=false):any {};
File.prototype.dirname = function(file:string):string {};
File.prototype.executable = function(file:string):boolean {};
File.prototype.exists = function(file:string):boolean {};
File.prototype.extension = function(file:string):string {};
File.prototype.glob = function(pattern:regexp|string|null='*', options:function|object|null=void):array {};
File.prototype.isdir = function(file:string):boolean {};

Changes to www/reference.wiki.

432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969


<h2>Methods for "File"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>atime</td><td>atime(file:string):number </td><td>Return file Jsi_Access time.</td></tr>
<tr><td>chdir</td><td>chdir(file:string) </td><td>Change current directory.</td></tr>
<tr><td>chmod</td><td>chmod(file:string, mode:string) </td><td>Set file permissions.</td></tr>
<tr><td>copy</td><td>copy(src:string, dest:string, force:boolean=false) </td><td>Copy a file to destination. Directories are not handled.
The third argument if given is a boolean force value which if true allows overwrite of an existing file. </td></tr>
<tr><td>dirname</td><td>dirname(file:string):string </td><td>Return directory path.</td></tr>
<tr><td>executable</td><td>executable(file:string):boolean </td><td>Return true if file is executable.</td></tr>
<tr><td>exists</td><td>exists(file:string):boolean </td><td>Return true if file exists.</td></tr>
<tr><td>extension</td><td>extension(file:string):string </td><td>Return file extension.</td></tr>
<tr><td>glob</td><td>glob(pattern:regexp|string|null='*', <a href='#File.globOptions'>options</a>:function|object|null=void):array </td><td>Return list of files in dir with optional pattern match. With no arguments (or null) returns all files/directories in current directory.
................................................................................
<a name="RegExp"></a>

<hr>


<h1>RegExp</h1>

<font color=red>Synopsis:new RegExp(val:regexp|string):regexp

</font><p>Commands for managing reqular expression objects.


<h2>Methods for "RegExp"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>RegExp</td><td>new RegExp(val:regexp|string):regexp </td><td>Create a regexp object.</td></tr>
<tr><td>exec</td><td>exec(val:string):array|object|null </td><td>return matching string. Perform regexp match checking.  Returns the array of matches.With the global flag g, sets lastIndex and returns next match.</td></tr>
<tr><td>test</td><td>test(val:string):boolean </td><td>test if a string matches.</td></tr>
</table>
<a name="RegExpend"></a>
<p><a href="#TOC">Return to top</a>
<a name="Signal"></a>








|







 







|







|







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969


<h2>Methods for "File"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>atime</td><td>atime(file:string):number </td><td>Return file Jsi_Access time.</td></tr>
<tr><td>chdir</td><td>chdir(file:string) </td><td>Change current directory.</td></tr>
<tr><td>chmod</td><td>chmod(file:string, mode:number) </td><td>Set file permissions.</td></tr>
<tr><td>copy</td><td>copy(src:string, dest:string, force:boolean=false) </td><td>Copy a file to destination. Directories are not handled.
The third argument if given is a boolean force value which if true allows overwrite of an existing file. </td></tr>
<tr><td>dirname</td><td>dirname(file:string):string </td><td>Return directory path.</td></tr>
<tr><td>executable</td><td>executable(file:string):boolean </td><td>Return true if file is executable.</td></tr>
<tr><td>exists</td><td>exists(file:string):boolean </td><td>Return true if file exists.</td></tr>
<tr><td>extension</td><td>extension(file:string):string </td><td>Return file extension.</td></tr>
<tr><td>glob</td><td>glob(pattern:regexp|string|null='*', <a href='#File.globOptions'>options</a>:function|object|null=void):array </td><td>Return list of files in dir with optional pattern match. With no arguments (or null) returns all files/directories in current directory.
................................................................................
<a name="RegExp"></a>

<hr>


<h1>RegExp</h1>

<font color=red>Synopsis:new RegExp(val:regexp|string, flags:string):regexp

</font><p>Commands for managing reqular expression objects.


<h2>Methods for "RegExp"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>RegExp</td><td>new RegExp(val:regexp|string, flags:string):regexp </td><td>Create a regexp object.</td></tr>
<tr><td>exec</td><td>exec(val:string):array|object|null </td><td>return matching string. Perform regexp match checking.  Returns the array of matches.With the global flag g, sets lastIndex and returns next match.</td></tr>
<tr><td>test</td><td>test(val:string):boolean </td><td>test if a string matches.</td></tr>
</table>
<a name="RegExpend"></a>
<p><a href="#TOC">Return to top</a>
<a name="Signal"></a>