jsish
Check-in [973645aa81]
Not logged in

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

Overview
Comment:Release "2.5.20". Fix issue [a86dc1c04b]: Heap use after free in Jsi_ObjFree. Increase floating point precision to max-1 (default) and make it changable.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:973645aa8124d94cd72fd5ee745b766f0b7a917c
User & Date: pmacdona 2018-10-11 17:31:06
References
2018-10-11
17:35 Closed ticket [a86dc1c04b]: Heap use after free in Jsi_ObjFree plus 6 other changes artifact: 6a7afb043c user: pcmacdon
Context
2018-10-15
22:48
Release "2.5.21". Fix Sqlite select "insert" mode for query. Swap -m and -M. Make --module source file then invoke runModule(). check-in: e82becfd14 user: pmacdona tags: trunk
2018-10-11
17:31
Release "2.5.20". Fix issue [a86dc1c04b]: Heap use after free in Jsi_ObjFree. Increase floating point precision to max-1 (default) and make it changable. check-in: 973645aa81 user: pmacdona tags: trunk
02:26
Fix VFS bug check-in: ebcd5f87dd user: pmacdona tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/jsi.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
.....
12436
12437
12438
12439
12440
12441
12442

12443
12444
12445
12446
12447
12448
12449
.....
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
.....
13328
13329
13330
13331
13332
13333
13334

13335
13336
13337
13338
13339
13340
13341
.....
14403
14404
14405
14406
14407
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417
.....
14422
14423
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
.....
14452
14453
14454
14455
14456
14457
14458
14459
14460
14461
14462
14463
14464
14465
14466
14467
14468
14469
14470
14471
14472
14473
14474
14475
14476
14477
14478
14479
14480
14481
14482
.....
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574
16575
16576
16577
16578
16579
16580
16581
16582
16583
16584
.....
16616
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626
16627
16628
16629
16630
.....
18496
18497
18498
18499
18500
18501
18502

18503
18504
18505
18506
18507
18508
18509
.....
19155
19156
19157
19158
19159
19160
19161
19162
19163
19164
19165
19166
19167
19168
19169
.....
19460
19461
19462
19463
19464
19465
19466

19467
19468
19469
19470
19471
19472
19473
.....
20012
20013
20014
20015
20016
20017
20018
20019
20020
20021
20022
20023
20024
20025
20026
.....
20053
20054
20055
20056
20057
20058
20059
20060
20061
20062
20063
20064
20065
20066
20067
.....
21772
21773
21774
21775
21776
21777
21778
21779
21780
21781
21782
21783
21784
21785
21786
21787
.....
21810
21811
21812
21813
21814
21815
21816
21817
21818
21819
21820
21821
21822
21823
21824
.....
22298
22299
22300
22301
22302
22303
22304




22305
22306
22307
22308
22309
22310
22311
.....
26958
26959
26960
26961
26962
26963
26964
26965
26966
26967
26968
26969
26970
26971
26972
26973
.....
27020
27021
27022
27023
27024
27025
27026
27027
27028



27029


27030
27031
27032
27033
27034
27035
27036
27037
.....
33041
33042
33043
33044
33045
33046
33047
33048
33049
33050
33051
33052
33053
33054
33055
.....
33137
33138
33139
33140
33141
33142
33143
33144
33145
33146
33147
33148
33149
33150
33151
.....
47417
47418
47419
47420
47421
47422
47423
47424
47425
47426
47427
47428
47429
47430
47431
.....
47433
47434
47435
47436
47437
47438
47439

47440
47441
47442
47443
47444
47445
47446
.....
47458
47459
47460
47461
47462
47463
47464
47465
47466
47467
47468
47469
47470
47471
47472
.....
54101
54102
54103
54104
54105
54106
54107
54108
54109
54110
54111
54112
54113
54114
54115
54116
54117
54118
54119
54120
54121
54122
54123
.....
54163
54164
54165
54166
54167
54168
54169
54170
54171
54172
54173
54174
54175
54176
54177
54178
54179
54180
54181
54182
.....
63326
63327
63328
63329
63330
63331
63332
63333
63334
63335
63336
63337
63338
63339
63340
/* 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 19

#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

................................................................................
JSI_EXTERN int Jsi_UserObjNew    (Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data); /*STUB = 180*/
JSI_EXTERN void* Jsi_UserObjGetData(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr); /*STUB = 181*/
/* -- */


/* --UTILITY-- */
#define JSI_NOTUSED(n) (void)n /* Eliminate annoying compiler warning. */
JSI_EXTERN char* Jsi_NumberToString(Jsi_Number d, char *buf, int bsiz); /*STUB = 182*/
JSI_EXTERN Jsi_Number Jsi_Version(void); /*STUB = 183*/
JSI_EXTERN Jsi_Value* Jsi_ReturnValue(Jsi_Interp *interp); /*STUB = 184*/
JSI_EXTERN Jsi_RC Jsi_Mount( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret); /*STUB = 185*/
JSI_EXTERN Jsi_Value* Jsi_Executable(Jsi_Interp *interp); /*STUB = 186*/
JSI_EXTERN Jsi_Regex* Jsi_RegExpNew(Jsi_Interp *interp, const char *regtxt, int flag); /*STUB = 187*/
JSI_EXTERN void Jsi_RegExpFree(Jsi_Regex* re); /*STUB = 188*/
JSI_EXTERN Jsi_RC Jsi_RegExpMatch( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr); /*STUB = 189*/
................................................................................
JSI_EXTERN bool Jsi_NumberIsInteger(Jsi_Number n);  /*STUB = 238*/
JSI_EXTERN bool Jsi_NumberIsNaN(Jsi_Number a);  /*STUB = 239*/
JSI_EXTERN bool Jsi_NumberIsNormal(Jsi_Number a);  /*STUB = 240*/
JSI_EXTERN bool Jsi_NumberIsSubnormal(Jsi_Number a);  /*STUB = 241*/
JSI_EXTERN bool Jsi_NumberIsWide(Jsi_Number n);  /*STUB = 242*/
JSI_EXTERN Jsi_Number Jsi_NumberInfinity(int i);  /*STUB = 243*/
JSI_EXTERN Jsi_Number Jsi_NumberNaN(void);  /*STUB = 244*/
JSI_EXTERN void Jsi_NumberDtoA(Jsi_Number value, char* buf, int bsiz, int prec);  /*STUB = 245*/
JSI_EXTERN void Jsi_NumberItoA10(Jsi_Wide value, char* buf, int bsiz);  /*STUB = 246*/
JSI_EXTERN void Jsi_NumberUtoA10(Jsi_UWide, char* buf, int bsiz);  /*STUB = 247*/

/* -- */

#define JSI_WORDKEY_CAST (void*)(uintptr_t)

................................................................................
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>


#ifdef __WIN32 /* TODO: support windows signal??? */
#define JSI__MINIZ 1
#define JSI_OMIT_SIGNAL
#endif

#ifndef JSI_AMALGAMATION
................................................................................
} jsi_JmpPopInfo;

#define RES_CONTINUE    1
#define RES_BREAK       2
typedef struct YYLTYPE jsi_Pline;

//void jsi_codes_print(Jsi_OpCodes *ops);
void jsi_code_decode(jsi_OpCode *op, int currentip, char *buf, int bsiz);
const char* jsi_opcode_string(uint opCode);

#ifdef JSI_MEM_DEBUG
typedef struct 
{
    const char *fname;
    int line;
................................................................................
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;

    const char *blacklist;
} jsi_SubOptions;

extern Jsi_OptionSpec jsi_InterpLogOptions[];

typedef enum {
        jsi_TL_TRY,
................................................................................
const char* jsi_opcode_string(uint opCode)
{
    if (opCode >= (sizeof(jsi_op_names)/sizeof(jsi_op_names[0])))
        return "NULL";
    return jsi_op_names[opCode];
}

void jsi_code_decode(jsi_OpCode *op, int currentip, char *buf, int bsiz)
{
    if (_JSICASTINT(op->op) < 0 || op->op >= OP_LASTOP) {
        snprintf(buf, bsiz, "Bad opcode[%d] at %d", op->op, currentip);
    }
    char nbuf[100];
    snprintf(nbuf, sizeof(nbuf), "%d#%d", currentip, op->Line);
    snprintf(buf, bsiz, "%-8s %s ", nbuf, jsi_op_names[op->op]);
................................................................................
    if (op->op == OP_PUSHBOO || op->op == OP_FCALL || op->op == OP_EVAL ||
        op->op == OP_POP || op->op == OP_ASSIGN ||
        op->op == OP_RET || op->op == OP_NEWFCALL ||
        op->op == OP_DELETE || op->op == OP_CHTHIS ||
        op->op == OP_OBJECT || op->op == OP_ARRAY ||
        op->op == OP_SHF ||
        op->op == OP_INC || op->op == OP_DEC) snprintf(bp, bsiz, "%" PRId64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_PUSHNUM) snprintf(bp, bsiz, "%" JSI_NUMGFMT "", *((Jsi_Number *)op->data));
    else if (op->op == OP_PUSHSTR || op->op == OP_LOCAL ||
             op->op == OP_SCATCH) snprintf(bp, bsiz, "\"%s\"", op->data ? (char*)op->data:"(NoCatch)");
    else if (op->op == OP_PUSHVAR) snprintf(bp, bsiz, "var: \"%s\"", ((jsi_FastVar *)op->data)->varname);
    else if (op->op == OP_PUSHFUN) snprintf(bp, bsiz, "func: 0x%" PRIx64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_JTRUE || op->op == OP_JFALSE ||
             op->op == OP_JTRUE_NP || op->op == OP_JFALSE_NP ||
             op->op == OP_JMP) snprintf(bp, bsiz, "{%" PRIu64 "}\t#%" PRIu64 "", (Jsi_Wide)(uintptr_t)op->data, (Jsi_Wide)((uintptr_t)currentip + (uintptr_t)op->data));
................................................................................
        return;
    while (i < ops->code_len) {
        if (ops->codes[i].op == OP_PUSHVAR)
            ops->codes[i].local = 1;
        i++;
    }
}

/*
void jsi_codes_print(Jsi_OpCodes *ops)
{
    int i = 0;
    jsi_OpCode *opcodes = ops->codes;
    int opcodesi = ops->code_len;
    
    fprintf(stderr, "opcodes count = %d\n", opcodesi);
    
    while(i < opcodesi) {
        jsi_code_decode(&opcodes[i], i);
        i++;
    }
}*/



static jsi_ForinVar *forinvar_new(jsi_Pstate *pstate, const char *varname, Jsi_OpCodes *local, Jsi_OpCodes *lval)
{
    jsi_ForinVar *r = (jsi_ForinVar*)Jsi_Calloc(1,sizeof(*r));
    r->sig = JSI_SIG_FORINVAR;
    r->varname = varname;
    r->local = local;
................................................................................
    if (otype != JSI_OT_ARRAY)
        return (v->d.obj->ot == otype);
    if (v->d.obj->ot != JSI_OT_OBJECT || !v->d.obj->isarrlist)
        return 0;
    return 1;
}

char* Jsi_NumberToString(Jsi_Number d, char *buf, int bsiz)
{
     if (Jsi_NumberIsInteger(d)) {
        Jsi_NumberItoA10((Jsi_Wide)d, buf, bsiz);
    } else if (Jsi_NumberIsNormal(d)) {
        Jsi_NumberDtoA(d, buf, bsiz, 10);
    } else if (Jsi_NumberIsNaN(d)) {
        Jsi_Strcpy(buf, "NaN");
    } else {
        int s = Jsi_NumberIsInfinity(d);
        if (s > 0) Jsi_Strcpy(buf,  "Infinity");
        else if (s < 0) Jsi_Strcpy(buf, "-Infinity");
        else {
................................................................................
            d = v->d.num;
fmtnum:
            if (Jsi_NumberIsInteger(d)) {
                Jsi_NumberItoA10((Jsi_Wide)d, unibuf, sizeof(unibuf));
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNormal(d)) {
                Jsi_NumberDtoA(d, unibuf, sizeof(unibuf), 10);
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNaN(v->d.num)) {
                ntxt = "NaN";
            } else {
                int s = Jsi_NumberIsInfinity(d);
                if (s > 0) ntxt = "Infinity";
................................................................................
    JSI_OPT(STRKEY, jsi_LogOptions, timeFmt, .help="A format string to use with strftime" ),
    JSI_OPT(USEROBJ,jsi_LogOptions, chan,    .help="Channel to send output to", .flags=0, .custom=0, .data=(void*)"Channel" ),
    JSI_OPT_END(jsi_LogOptions, .help="Interp options for logging")
};
static Jsi_OptionSpec InterpSubOptions[] = {
    JSI_OPT(STRKEY,jsi_SubOptions, blacklist,   .help="Comma separated modules to disable loading for", jsi_IIOF ),
    JSI_OPT(BOOL,  jsi_SubOptions, compat,      .help="Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser" ),

    JSI_OPT(BOOL,  jsi_SubOptions, istty,       .help="Indicates interp is in interactive mode", jsi_IIRO),
    JSI_OPT(BOOL,  jsi_SubOptions, logColNums,  .help="Display column numbers in error messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, logAllowDups,.help="Log should not filter out duplicate messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, mutexUnlock, .help="Unlock own mutex when evaling in other interps (true)", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, noproto,     .help="Disable support of the OOP symbols:  __proto__, prototype, constructor, etc"),
    JSI_OPT(BOOL,  jsi_SubOptions, noReadline,  .help="In interactive mode disable use of readline" ),
    JSI_OPT(BOOL,  jsi_SubOptions, outUndef,     .help="In interactive mode output result values that are undefined"),
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--version")) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(interp, chan, str, sizeof(str));
            printf("%u.%u.%u %" JSI_NUMGFMT " %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            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_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;


    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
                refSum += vp->refCnt;
                if (vdLev>1) {
                    char ebuf[JSI_BUFSIZ], ebuf2[JSI_MAX_NUMBER_STRING];
                    ebuf[0] = 0;
                    if (vp->vt==JSI_VT_OBJECT)
                        snprintf(ebuf, sizeof(ebuf), " {obj=%p, otype=%s}", vp->d.obj, Jsi_ObjTypeStr(interp, vp->d.obj));
                    else if (vp->vt==JSI_VT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), " {num=%s}", Jsi_NumberToString(vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->vt==JSI_VT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), " {bool=%s}", vp->d.val?"true":"false");
                    else if (vp->vt==JSI_VT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), " {string=\"%.40s%s\"}", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    const char *pfx = "";
................................................................................
                    ebuf[0] = 0;
                    if (vp->ot==JSI_OT_OBJECT) {
                        if (vp->isarrlist)
                            snprintf(ebuf, sizeof(ebuf), "tree#%d, array#%d", (vp->tree?vp->tree->numEntries:0), vp->arrCnt);
                        else
                            snprintf(ebuf, sizeof(ebuf), "tree#%d", (vp->tree?vp->tree->numEntries:0));
                    } else if (vp->ot==JSI_OT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), "num=%s", Jsi_NumberToString(vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->ot==JSI_OT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), "bool=%s", vp->d.val?"true":"false");
                    else if (vp->ot==JSI_OT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), "string=\"%.40s%s\"", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    fprintf(stderr, "[*%p,#%d,%s,%d:%s%s%s]:%s @%s:%d in %s() {%s}\n",
................................................................................
    Jsi_DSAppend(dStr, ":", NULL);
    ow->depth++;
    Jsi_RC rc = jsiValueGetString(tree->opts.interp, v, dStr, ow);
    ow->depth--;
    return rc;
}

#include <float.h>

/* Format value into dStr.  Toplevel caller does init/free. */
static Jsi_RC jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
{
    char buf[100], *str;
    Jsi_DString eStr;
    Jsi_DSInit(&eStr);
    if (interp->maxDepth>0 && owPtr->depth > interp->maxDepth)
................................................................................
            } else if (Jsi_NumberIsInteger(num)) {
                Jsi_NumberItoA10((Jsi_Wide)num, buf, sizeof(buf));
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsWide(num)) {
                snprintf(buf, sizeof(buf), "%" PRId64, (Jsi_Wide)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNormal(num) || Jsi_NumberIsSubnormal(num)) {
                Jsi_NumberDtoA(num, buf, sizeof(buf), -1);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNaN(num)) {
                Jsi_DSAppend(dStr, "NaN", NULL);
            } else {
                int s = Jsi_NumberIsInfinity(num);
                if (s > 0) Jsi_DSAppend(dStr, "+Infinity", NULL);
                else if (s < 0) Jsi_DSAppend(dStr, "-Infinity", NULL);
................................................................................
    if (hist) {
        jsi_sh_stifle_history(100);
        jsi_sh_write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);




    if (interp->exited && interp->level <= 0)
    {
        rc = JSI_EXIT;
        Jsi_InterpDelete(interp);
    }
    jsi_interactiveInterp = NULL;
    return rc;
................................................................................
    if (!release)
        interp->Boolean_prototype = Jsi_CommandCreateSpecs(interp, "Boolean", booleanCmds, NULL, JSI_CMDSPEC_ISOBJ);
    return JSI_OK;
}
#endif

#include <math.h>
#include <float.h>
#include <stdio.h>
#ifndef JSI_AMALGAMATION
#include "jsiInt.h"
#endif

bool Jsi_NumberIsSubnormal(Jsi_Number a) { return fpclassify(a) == FP_SUBNORMAL; }

bool Jsi_NumberIsNormal(Jsi_Number a) { return (fpclassify(a) == FP_ZERO || isnormal(a)); }
................................................................................

bool Jsi_NumberIsFinite(Jsi_Number value)
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Number value, char* buf, int bsiz, int prec)
{



    if (prec<0)


        prec = DBL_DECIMAL_DIG;
    if (Jsi_NumberIsNaN(value))
        Jsi_Strcpy(buf,"NaN");
    else
        snprintf(buf, bsiz, "%.*" JSI_NUMGFMT, prec, value);
}

bool Jsi_NumberIsEqual(Jsi_Number n1, Jsi_Number n2)
................................................................................
Jsi_RC jsi_GetVerFromVal(Jsi_Interp *interp, Jsi_Value *val, Jsi_Number *nPtr, bool isProvide)
{
    Jsi_Number n = *nPtr;
    if (!val)
        return Jsi_LogError("missing version");
    if (Jsi_ValueIsNumber(interp, val)) {
        if (Jsi_GetDoubleFromValue(interp, val, &n) != JSI_OK || Jsi_NumberIsNaN(n) || (isProvide?n<=0.0:n<0.0) || n>=100.0)
            return Jsi_LogError("bad version: %" JSI_NUMGFMT, n);
        *nPtr = n;
        return JSI_OK;
    }
    const char *vstr = Jsi_ValueString(interp, val, NULL), *vs = vstr;
    if (!vstr)
        return Jsi_LogError("bad version");
    uint v[3] = {};
................................................................................
    Jsi_Number ver = Jsi_PkgRequire(interp, name, n);
    interp->isMain = isMain;
    if (ver < 0)
        return JSI_ERROR;
    Jsi_RC rc = JSI_OK;
    if (argc>1) {
        if (ver < n) 
            rc = Jsi_LogType("package '%s' downlevel: %" JSI_NUMGFMT " < %" JSI_NUMGFMT, name, ver, n);
        if (rc != JSI_OK)
            return rc;
        return jsi_PkgDumpInfo(interp, name, ret);
    }
    Jsi_ValueMakeNumber(interp, ret, ver);
    return rc;
}
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        Jsi_DSAppend(dStr, "null", NULL);
        return;
    }
................................................................................
    const char *str = (char*)sqlite3_column_text(pStmt, iCol );
    if (!str)
        str = p->jdb->optPtr->nullvalue;
    Jsi_JSONQuote(interp, str?str:"", -1, dStr);
}

static void dbEvalSetColumn(DbEvalContext *p, int iCol, Jsi_DString *dStr) {

    char nbuf[200];

    sqlite3_stmt *pStmt = p->pPreStmt->pStmt;

    switch( sqlite3_column_type(pStmt, iCol) ) {
    case SQLITE_BLOB: {
        int bytes = sqlite3_column_bytes(pStmt, iCol);
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        return;
    }
    }
................................................................................
        }
        case JSI_OPTION_INT64: {
            snprintf(nbuf, sizeof(nbuf), "%lld", field->buffer.vlonglong);
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_STRING:
            zBlob = field->buffer.vstring;
        default:
        {
................................................................................
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        default:
            Jsi_LogWarn("unknown type: %d", field->jsiTypeMap);
    
    }
................................................................................
}

static void DumpInstr(Jsi_Interp *interp, jsi_Pstate *ps, Jsi_Value *_this,
    jsi_TryList *trylist, jsi_OpCode *ip, Jsi_OpCodes *opcodes)
{
    int i;
    char buf[200];
    jsi_code_decode(ip, ip - opcodes->codes, buf, sizeof(buf));
    Jsi_Printf(interp, jsi_Stderr, "%p: %-30.200s : THIS=%s, STACK=[", ip, buf, vprint(_this));
    for (i = 0; i < interp->framePtr->Sp; ++i) {
        Jsi_Printf(interp, jsi_Stderr, "%s%s", (i>0?", ":""), vprint(_jsi_STACKIDX(i)));
    }
    Jsi_Printf(interp, jsi_Stderr, "]");
    if (ip->fname) {
        const char *fn = ip->fname,  *cp = Jsi_Strrchr(fn, '/');






|







 







|







 







|







 







>







 







|







 







>







 







|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|




|







 







|







 







>







 







|







 







>







 







|







 







|







 







<
<







 







|







 







>
>
>
>







 







<
<







 







|

>
>
>
|
>
>
|







 







|







 







|







 







|







 







>







 







|







 







|







|







 







|




|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
.....
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
.....
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
.....
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
.....
14405
14406
14407
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417
14418
14419
.....
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
.....
14454
14455
14456
14457
14458
14459
14460

















14461
14462
14463
14464
14465
14466
14467
.....
16550
16551
16552
16553
16554
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564
16565
16566
16567
16568
16569
.....
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
.....
18481
18482
18483
18484
18485
18486
18487
18488
18489
18490
18491
18492
18493
18494
18495
.....
19141
19142
19143
19144
19145
19146
19147
19148
19149
19150
19151
19152
19153
19154
19155
.....
19446
19447
19448
19449
19450
19451
19452
19453
19454
19455
19456
19457
19458
19459
19460
.....
19999
20000
20001
20002
20003
20004
20005
20006
20007
20008
20009
20010
20011
20012
20013
.....
20040
20041
20042
20043
20044
20045
20046
20047
20048
20049
20050
20051
20052
20053
20054
.....
21759
21760
21761
21762
21763
21764
21765


21766
21767
21768
21769
21770
21771
21772
.....
21795
21796
21797
21798
21799
21800
21801
21802
21803
21804
21805
21806
21807
21808
21809
.....
22283
22284
22285
22286
22287
22288
22289
22290
22291
22292
22293
22294
22295
22296
22297
22298
22299
22300
.....
26947
26948
26949
26950
26951
26952
26953


26954
26955
26956
26957
26958
26959
26960
.....
27007
27008
27009
27010
27011
27012
27013
27014
27015
27016
27017
27018
27019
27020
27021
27022
27023
27024
27025
27026
27027
27028
27029
.....
33033
33034
33035
33036
33037
33038
33039
33040
33041
33042
33043
33044
33045
33046
33047
.....
33129
33130
33131
33132
33133
33134
33135
33136
33137
33138
33139
33140
33141
33142
33143
.....
47409
47410
47411
47412
47413
47414
47415
47416
47417
47418
47419
47420
47421
47422
47423
.....
47425
47426
47427
47428
47429
47430
47431
47432
47433
47434
47435
47436
47437
47438
47439
.....
47451
47452
47453
47454
47455
47456
47457
47458
47459
47460
47461
47462
47463
47464
47465
.....
54094
54095
54096
54097
54098
54099
54100
54101
54102
54103
54104
54105
54106
54107
54108
54109
54110
54111
54112
54113
54114
54115
54116
.....
54156
54157
54158
54159
54160
54161
54162
54163
54164
54165
54166
54167
54168
54169
54170
54171
54172
54173
54174
54175
.....
63319
63320
63321
63322
63323
63324
63325
63326
63327
63328
63329
63330
63331
63332
63333
/* 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 20

#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

................................................................................
JSI_EXTERN int Jsi_UserObjNew    (Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data); /*STUB = 180*/
JSI_EXTERN void* Jsi_UserObjGetData(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr); /*STUB = 181*/
/* -- */


/* --UTILITY-- */
#define JSI_NOTUSED(n) (void)n /* Eliminate annoying compiler warning. */
JSI_EXTERN char* Jsi_NumberToString(Jsi_Interp *interp, Jsi_Number d, char *buf, int bsiz); /*STUB = 182*/
JSI_EXTERN Jsi_Number Jsi_Version(void); /*STUB = 183*/
JSI_EXTERN Jsi_Value* Jsi_ReturnValue(Jsi_Interp *interp); /*STUB = 184*/
JSI_EXTERN Jsi_RC Jsi_Mount( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret); /*STUB = 185*/
JSI_EXTERN Jsi_Value* Jsi_Executable(Jsi_Interp *interp); /*STUB = 186*/
JSI_EXTERN Jsi_Regex* Jsi_RegExpNew(Jsi_Interp *interp, const char *regtxt, int flag); /*STUB = 187*/
JSI_EXTERN void Jsi_RegExpFree(Jsi_Regex* re); /*STUB = 188*/
JSI_EXTERN Jsi_RC Jsi_RegExpMatch( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr); /*STUB = 189*/
................................................................................
JSI_EXTERN bool Jsi_NumberIsInteger(Jsi_Number n);  /*STUB = 238*/
JSI_EXTERN bool Jsi_NumberIsNaN(Jsi_Number a);  /*STUB = 239*/
JSI_EXTERN bool Jsi_NumberIsNormal(Jsi_Number a);  /*STUB = 240*/
JSI_EXTERN bool Jsi_NumberIsSubnormal(Jsi_Number a);  /*STUB = 241*/
JSI_EXTERN bool Jsi_NumberIsWide(Jsi_Number n);  /*STUB = 242*/
JSI_EXTERN Jsi_Number Jsi_NumberInfinity(int i);  /*STUB = 243*/
JSI_EXTERN Jsi_Number Jsi_NumberNaN(void);  /*STUB = 244*/
JSI_EXTERN void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec);  /*STUB = 245*/
JSI_EXTERN void Jsi_NumberItoA10(Jsi_Wide value, char* buf, int bsiz);  /*STUB = 246*/
JSI_EXTERN void Jsi_NumberUtoA10(Jsi_UWide, char* buf, int bsiz);  /*STUB = 247*/

/* -- */

#define JSI_WORDKEY_CAST (void*)(uintptr_t)

................................................................................
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <float.h>

#ifdef __WIN32 /* TODO: support windows signal??? */
#define JSI__MINIZ 1
#define JSI_OMIT_SIGNAL
#endif

#ifndef JSI_AMALGAMATION
................................................................................
} jsi_JmpPopInfo;

#define RES_CONTINUE    1
#define RES_BREAK       2
typedef struct YYLTYPE jsi_Pline;

//void jsi_codes_print(Jsi_OpCodes *ops);
void jsi_code_decode(Jsi_Interp *interp, jsi_OpCode *op, int currentip, char *buf, int bsiz);
const char* jsi_opcode_string(uint opCode);

#ifdef JSI_MEM_DEBUG
typedef struct 
{
    const char *fname;
    int line;
................................................................................
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;
} jsi_SubOptions;

extern Jsi_OptionSpec jsi_InterpLogOptions[];

typedef enum {
        jsi_TL_TRY,
................................................................................
const char* jsi_opcode_string(uint opCode)
{
    if (opCode >= (sizeof(jsi_op_names)/sizeof(jsi_op_names[0])))
        return "NULL";
    return jsi_op_names[opCode];
}

void jsi_code_decode(Jsi_Interp *interp, jsi_OpCode *op, int currentip, char *buf, int bsiz)
{
    if (_JSICASTINT(op->op) < 0 || op->op >= OP_LASTOP) {
        snprintf(buf, bsiz, "Bad opcode[%d] at %d", op->op, currentip);
    }
    char nbuf[100];
    snprintf(nbuf, sizeof(nbuf), "%d#%d", currentip, op->Line);
    snprintf(buf, bsiz, "%-8s %s ", nbuf, jsi_op_names[op->op]);
................................................................................
    if (op->op == OP_PUSHBOO || op->op == OP_FCALL || op->op == OP_EVAL ||
        op->op == OP_POP || op->op == OP_ASSIGN ||
        op->op == OP_RET || op->op == OP_NEWFCALL ||
        op->op == OP_DELETE || op->op == OP_CHTHIS ||
        op->op == OP_OBJECT || op->op == OP_ARRAY ||
        op->op == OP_SHF ||
        op->op == OP_INC || op->op == OP_DEC) snprintf(bp, bsiz, "%" PRId64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_PUSHNUM) Jsi_NumberDtoA(interp, *((Jsi_Number *)op->data), bp, bsiz, 0);
    else if (op->op == OP_PUSHSTR || op->op == OP_LOCAL ||
             op->op == OP_SCATCH) snprintf(bp, bsiz, "\"%s\"", op->data ? (char*)op->data:"(NoCatch)");
    else if (op->op == OP_PUSHVAR) snprintf(bp, bsiz, "var: \"%s\"", ((jsi_FastVar *)op->data)->varname);
    else if (op->op == OP_PUSHFUN) snprintf(bp, bsiz, "func: 0x%" PRIx64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_JTRUE || op->op == OP_JFALSE ||
             op->op == OP_JTRUE_NP || op->op == OP_JFALSE_NP ||
             op->op == OP_JMP) snprintf(bp, bsiz, "{%" PRIu64 "}\t#%" PRIu64 "", (Jsi_Wide)(uintptr_t)op->data, (Jsi_Wide)((uintptr_t)currentip + (uintptr_t)op->data));
................................................................................
        return;
    while (i < ops->code_len) {
        if (ops->codes[i].op == OP_PUSHVAR)
            ops->codes[i].local = 1;
        i++;
    }
}


















static jsi_ForinVar *forinvar_new(jsi_Pstate *pstate, const char *varname, Jsi_OpCodes *local, Jsi_OpCodes *lval)
{
    jsi_ForinVar *r = (jsi_ForinVar*)Jsi_Calloc(1,sizeof(*r));
    r->sig = JSI_SIG_FORINVAR;
    r->varname = varname;
    r->local = local;
................................................................................
    if (otype != JSI_OT_ARRAY)
        return (v->d.obj->ot == otype);
    if (v->d.obj->ot != JSI_OT_OBJECT || !v->d.obj->isarrlist)
        return 0;
    return 1;
}

char* Jsi_NumberToString(Jsi_Interp *interp, Jsi_Number d, char *buf, int bsiz)
{
     if (Jsi_NumberIsInteger(d)) {
        Jsi_NumberItoA10((Jsi_Wide)d, buf, bsiz);
    } else if (Jsi_NumberIsNormal(d)) {
        Jsi_NumberDtoA(interp, d, buf, bsiz, 0);
    } else if (Jsi_NumberIsNaN(d)) {
        Jsi_Strcpy(buf, "NaN");
    } else {
        int s = Jsi_NumberIsInfinity(d);
        if (s > 0) Jsi_Strcpy(buf,  "Infinity");
        else if (s < 0) Jsi_Strcpy(buf, "-Infinity");
        else {
................................................................................
            d = v->d.num;
fmtnum:
            if (Jsi_NumberIsInteger(d)) {
                Jsi_NumberItoA10((Jsi_Wide)d, unibuf, sizeof(unibuf));
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNormal(d)) {
                Jsi_NumberDtoA(interp, d, unibuf, sizeof(unibuf), 0);
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNaN(v->d.num)) {
                ntxt = "NaN";
            } else {
                int s = Jsi_NumberIsInfinity(d);
                if (s > 0) ntxt = "Infinity";
................................................................................
    JSI_OPT(STRKEY, jsi_LogOptions, timeFmt, .help="A format string to use with strftime" ),
    JSI_OPT(USEROBJ,jsi_LogOptions, chan,    .help="Channel to send output to", .flags=0, .custom=0, .data=(void*)"Channel" ),
    JSI_OPT_END(jsi_LogOptions, .help="Interp options for logging")
};
static Jsi_OptionSpec InterpSubOptions[] = {
    JSI_OPT(STRKEY,jsi_SubOptions, blacklist,   .help="Comma separated modules to disable loading for", jsi_IIOF ),
    JSI_OPT(BOOL,  jsi_SubOptions, compat,      .help="Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser" ),
    JSI_OPT(INT,   jsi_SubOptions, dblPrec,     .help="Format precision of double (-1): 0=max, -1=max-1, ..", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, istty,       .help="Indicates interp is in interactive mode", jsi_IIRO),
    JSI_OPT(BOOL,  jsi_SubOptions, logColNums,  .help="Display column numbers in error messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, logAllowDups,.help="Log should not filter out duplicate messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, mutexUnlock, .help="Unlock own mutex when evaling in other interps (true)", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, noproto,     .help="Disable support of the OOP symbols:  __proto__, prototype, constructor, etc"),
    JSI_OPT(BOOL,  jsi_SubOptions, noReadline,  .help="In interactive mode disable use of readline" ),
    JSI_OPT(BOOL,  jsi_SubOptions, outUndef,     .help="In interactive mode output result values that are undefined"),
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--version")) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(interp, chan, str, sizeof(str));
            printf("%u.%u.%u %.4" JSI_NUMGFMT " %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            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_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = -1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
                refSum += vp->refCnt;
                if (vdLev>1) {
                    char ebuf[JSI_BUFSIZ], ebuf2[JSI_MAX_NUMBER_STRING];
                    ebuf[0] = 0;
                    if (vp->vt==JSI_VT_OBJECT)
                        snprintf(ebuf, sizeof(ebuf), " {obj=%p, otype=%s}", vp->d.obj, Jsi_ObjTypeStr(interp, vp->d.obj));
                    else if (vp->vt==JSI_VT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), " {num=%s}", Jsi_NumberToString(interp, vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->vt==JSI_VT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), " {bool=%s}", vp->d.val?"true":"false");
                    else if (vp->vt==JSI_VT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), " {string=\"%.40s%s\"}", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    const char *pfx = "";
................................................................................
                    ebuf[0] = 0;
                    if (vp->ot==JSI_OT_OBJECT) {
                        if (vp->isarrlist)
                            snprintf(ebuf, sizeof(ebuf), "tree#%d, array#%d", (vp->tree?vp->tree->numEntries:0), vp->arrCnt);
                        else
                            snprintf(ebuf, sizeof(ebuf), "tree#%d", (vp->tree?vp->tree->numEntries:0));
                    } else if (vp->ot==JSI_OT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), "num=%s", Jsi_NumberToString(interp, vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->ot==JSI_OT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), "bool=%s", vp->d.val?"true":"false");
                    else if (vp->ot==JSI_OT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), "string=\"%.40s%s\"", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    fprintf(stderr, "[*%p,#%d,%s,%d:%s%s%s]:%s @%s:%d in %s() {%s}\n",
................................................................................
    Jsi_DSAppend(dStr, ":", NULL);
    ow->depth++;
    Jsi_RC rc = jsiValueGetString(tree->opts.interp, v, dStr, ow);
    ow->depth--;
    return rc;
}



/* Format value into dStr.  Toplevel caller does init/free. */
static Jsi_RC jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
{
    char buf[100], *str;
    Jsi_DString eStr;
    Jsi_DSInit(&eStr);
    if (interp->maxDepth>0 && owPtr->depth > interp->maxDepth)
................................................................................
            } else if (Jsi_NumberIsInteger(num)) {
                Jsi_NumberItoA10((Jsi_Wide)num, buf, sizeof(buf));
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsWide(num)) {
                snprintf(buf, sizeof(buf), "%" PRId64, (Jsi_Wide)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNormal(num) || Jsi_NumberIsSubnormal(num)) {
                Jsi_NumberDtoA(interp, num, buf, sizeof(buf), 0);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNaN(num)) {
                Jsi_DSAppend(dStr, "NaN", NULL);
            } else {
                int s = Jsi_NumberIsInfinity(num);
                if (s > 0) Jsi_DSAppend(dStr, "+Infinity", NULL);
                else if (s < 0) Jsi_DSAppend(dStr, "-Infinity", NULL);
................................................................................
    if (hist) {
        jsi_sh_stifle_history(100);
        jsi_sh_write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);
    if (interp->retValue) {
        Jsi_DecrRefCount(interp, interp->retValue);
        interp->retValue = NULL;
    }
    if (interp->exited && interp->level <= 0)
    {
        rc = JSI_EXIT;
        Jsi_InterpDelete(interp);
    }
    jsi_interactiveInterp = NULL;
    return rc;
................................................................................
    if (!release)
        interp->Boolean_prototype = Jsi_CommandCreateSpecs(interp, "Boolean", booleanCmds, NULL, JSI_CMDSPEC_ISOBJ);
    return JSI_OK;
}
#endif

#include <math.h>


#ifndef JSI_AMALGAMATION
#include "jsiInt.h"
#endif

bool Jsi_NumberIsSubnormal(Jsi_Number a) { return fpclassify(a) == FP_SUBNORMAL; }

bool Jsi_NumberIsNormal(Jsi_Number a) { return (fpclassify(a) == FP_ZERO || isnormal(a)); }
................................................................................

bool Jsi_NumberIsFinite(Jsi_Number value)
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = DBL_DECIMAL_DIG;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))
        Jsi_Strcpy(buf,"NaN");
    else
        snprintf(buf, bsiz, "%.*" JSI_NUMGFMT, prec, value);
}

bool Jsi_NumberIsEqual(Jsi_Number n1, Jsi_Number n2)
................................................................................
Jsi_RC jsi_GetVerFromVal(Jsi_Interp *interp, Jsi_Value *val, Jsi_Number *nPtr, bool isProvide)
{
    Jsi_Number n = *nPtr;
    if (!val)
        return Jsi_LogError("missing version");
    if (Jsi_ValueIsNumber(interp, val)) {
        if (Jsi_GetDoubleFromValue(interp, val, &n) != JSI_OK || Jsi_NumberIsNaN(n) || (isProvide?n<=0.0:n<0.0) || n>=100.0)
            return Jsi_LogError("bad version: %.4" JSI_NUMGFMT, n);
        *nPtr = n;
        return JSI_OK;
    }
    const char *vstr = Jsi_ValueString(interp, val, NULL), *vs = vstr;
    if (!vstr)
        return Jsi_LogError("bad version");
    uint v[3] = {};
................................................................................
    Jsi_Number ver = Jsi_PkgRequire(interp, name, n);
    interp->isMain = isMain;
    if (ver < 0)
        return JSI_ERROR;
    Jsi_RC rc = JSI_OK;
    if (argc>1) {
        if (ver < n) 
            rc = Jsi_LogType("package '%s' downlevel: %.4" JSI_NUMGFMT " < %.4" JSI_NUMGFMT, name, ver, n);
        if (rc != JSI_OK)
            return rc;
        return jsi_PkgDumpInfo(interp, name, ret);
    }
    Jsi_ValueMakeNumber(interp, ret, ver);
    return rc;
}
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(interp, sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        Jsi_DSAppend(dStr, "null", NULL);
        return;
    }
................................................................................
    const char *str = (char*)sqlite3_column_text(pStmt, iCol );
    if (!str)
        str = p->jdb->optPtr->nullvalue;
    Jsi_JSONQuote(interp, str?str:"", -1, dStr);
}

static void dbEvalSetColumn(DbEvalContext *p, int iCol, Jsi_DString *dStr) {
    Jsi_Interp *interp = p->jdb->interp;
    char nbuf[200];

    sqlite3_stmt *pStmt = p->pPreStmt->pStmt;

    switch( sqlite3_column_type(pStmt, iCol) ) {
    case SQLITE_BLOB: {
        int bytes = sqlite3_column_bytes(pStmt, iCol);
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(interp, sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        return;
    }
    }
................................................................................
        }
        case JSI_OPTION_INT64: {
            snprintf(nbuf, sizeof(nbuf), "%lld", field->buffer.vlonglong);
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(interp, field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(interp, jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_STRING:
            zBlob = field->buffer.vstring;
        default:
        {
................................................................................
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(interp, jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(interp, field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        default:
            Jsi_LogWarn("unknown type: %d", field->jsiTypeMap);
    
    }
................................................................................
}

static void DumpInstr(Jsi_Interp *interp, jsi_Pstate *ps, Jsi_Value *_this,
    jsi_TryList *trylist, jsi_OpCode *ip, Jsi_OpCodes *opcodes)
{
    int i;
    char buf[200];
    jsi_code_decode(interp, ip, ip - opcodes->codes, buf, sizeof(buf));
    Jsi_Printf(interp, jsi_Stderr, "%p: %-30.200s : THIS=%s, STACK=[", ip, buf, vprint(_this));
    for (i = 0; i < interp->framePtr->Sp; ++i) {
        Jsi_Printf(interp, jsi_Stderr, "%s%s", (i>0?", ":""), vprint(_jsi_STACKIDX(i)));
    }
    Jsi_Printf(interp, jsi_Stderr, "]");
    if (ip->fname) {
        const char *fn = ip->fname,  *cp = Jsi_Strrchr(fn, '/');

Changes to src/jsi.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
/* 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 19

#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

................................................................................
JSI_EXTERN int Jsi_UserObjNew    (Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data); /*STUB = 180*/
JSI_EXTERN void* Jsi_UserObjGetData(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr); /*STUB = 181*/
/* -- */


/* --UTILITY-- */
#define JSI_NOTUSED(n) (void)n /* Eliminate annoying compiler warning. */
JSI_EXTERN char* Jsi_NumberToString(Jsi_Number d, char *buf, int bsiz); /*STUB = 182*/
JSI_EXTERN Jsi_Number Jsi_Version(void); /*STUB = 183*/
JSI_EXTERN Jsi_Value* Jsi_ReturnValue(Jsi_Interp *interp); /*STUB = 184*/
JSI_EXTERN Jsi_RC Jsi_Mount( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret); /*STUB = 185*/
JSI_EXTERN Jsi_Value* Jsi_Executable(Jsi_Interp *interp); /*STUB = 186*/
JSI_EXTERN Jsi_Regex* Jsi_RegExpNew(Jsi_Interp *interp, const char *regtxt, int flag); /*STUB = 187*/
JSI_EXTERN void Jsi_RegExpFree(Jsi_Regex* re); /*STUB = 188*/
JSI_EXTERN Jsi_RC Jsi_RegExpMatch( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr); /*STUB = 189*/
................................................................................
JSI_EXTERN bool Jsi_NumberIsInteger(Jsi_Number n);  /*STUB = 238*/
JSI_EXTERN bool Jsi_NumberIsNaN(Jsi_Number a);  /*STUB = 239*/
JSI_EXTERN bool Jsi_NumberIsNormal(Jsi_Number a);  /*STUB = 240*/
JSI_EXTERN bool Jsi_NumberIsSubnormal(Jsi_Number a);  /*STUB = 241*/
JSI_EXTERN bool Jsi_NumberIsWide(Jsi_Number n);  /*STUB = 242*/
JSI_EXTERN Jsi_Number Jsi_NumberInfinity(int i);  /*STUB = 243*/
JSI_EXTERN Jsi_Number Jsi_NumberNaN(void);  /*STUB = 244*/
JSI_EXTERN void Jsi_NumberDtoA(Jsi_Number value, char* buf, int bsiz, int prec);  /*STUB = 245*/
JSI_EXTERN void Jsi_NumberItoA10(Jsi_Wide value, char* buf, int bsiz);  /*STUB = 246*/
JSI_EXTERN void Jsi_NumberUtoA10(Jsi_UWide, char* buf, int bsiz);  /*STUB = 247*/

/* -- */

#define JSI_WORDKEY_CAST (void*)(uintptr_t)







|







 







|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
/* 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 20

#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

................................................................................
JSI_EXTERN int Jsi_UserObjNew    (Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data); /*STUB = 180*/
JSI_EXTERN void* Jsi_UserObjGetData(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr); /*STUB = 181*/
/* -- */


/* --UTILITY-- */
#define JSI_NOTUSED(n) (void)n /* Eliminate annoying compiler warning. */
JSI_EXTERN char* Jsi_NumberToString(Jsi_Interp *interp, Jsi_Number d, char *buf, int bsiz); /*STUB = 182*/
JSI_EXTERN Jsi_Number Jsi_Version(void); /*STUB = 183*/
JSI_EXTERN Jsi_Value* Jsi_ReturnValue(Jsi_Interp *interp); /*STUB = 184*/
JSI_EXTERN Jsi_RC Jsi_Mount( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret); /*STUB = 185*/
JSI_EXTERN Jsi_Value* Jsi_Executable(Jsi_Interp *interp); /*STUB = 186*/
JSI_EXTERN Jsi_Regex* Jsi_RegExpNew(Jsi_Interp *interp, const char *regtxt, int flag); /*STUB = 187*/
JSI_EXTERN void Jsi_RegExpFree(Jsi_Regex* re); /*STUB = 188*/
JSI_EXTERN Jsi_RC Jsi_RegExpMatch( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr); /*STUB = 189*/
................................................................................
JSI_EXTERN bool Jsi_NumberIsInteger(Jsi_Number n);  /*STUB = 238*/
JSI_EXTERN bool Jsi_NumberIsNaN(Jsi_Number a);  /*STUB = 239*/
JSI_EXTERN bool Jsi_NumberIsNormal(Jsi_Number a);  /*STUB = 240*/
JSI_EXTERN bool Jsi_NumberIsSubnormal(Jsi_Number a);  /*STUB = 241*/
JSI_EXTERN bool Jsi_NumberIsWide(Jsi_Number n);  /*STUB = 242*/
JSI_EXTERN Jsi_Number Jsi_NumberInfinity(int i);  /*STUB = 243*/
JSI_EXTERN Jsi_Number Jsi_NumberNaN(void);  /*STUB = 244*/
JSI_EXTERN void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec);  /*STUB = 245*/
JSI_EXTERN void Jsi_NumberItoA10(Jsi_Wide value, char* buf, int bsiz);  /*STUB = 246*/
JSI_EXTERN void Jsi_NumberUtoA10(Jsi_UWide, char* buf, int bsiz);  /*STUB = 247*/

/* -- */

#define JSI_WORDKEY_CAST (void*)(uintptr_t)

Changes to src/jsiCmds.c.

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
Jsi_RC jsi_GetVerFromVal(Jsi_Interp *interp, Jsi_Value *val, Jsi_Number *nPtr, bool isProvide)
{
    Jsi_Number n = *nPtr;
    if (!val)
        return Jsi_LogError("missing version");
    if (Jsi_ValueIsNumber(interp, val)) {
        if (Jsi_GetDoubleFromValue(interp, val, &n) != JSI_OK || Jsi_NumberIsNaN(n) || (isProvide?n<=0.0:n<0.0) || n>=100.0)
            return Jsi_LogError("bad version: %" JSI_NUMGFMT, n);
        *nPtr = n;
        return JSI_OK;
    }
    const char *vstr = Jsi_ValueString(interp, val, NULL), *vs = vstr;
    if (!vstr)
        return Jsi_LogError("bad version");
    uint v[3] = {};
................................................................................
    Jsi_Number ver = Jsi_PkgRequire(interp, name, n);
    interp->isMain = isMain;
    if (ver < 0)
        return JSI_ERROR;
    Jsi_RC rc = JSI_OK;
    if (argc>1) {
        if (ver < n) 
            rc = Jsi_LogType("package '%s' downlevel: %" JSI_NUMGFMT " < %" JSI_NUMGFMT, name, ver, n);
        if (rc != JSI_OK)
            return rc;
        return jsi_PkgDumpInfo(interp, name, ret);
    }
    Jsi_ValueMakeNumber(interp, ret, ver);
    return rc;
}







|







 







|







774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
Jsi_RC jsi_GetVerFromVal(Jsi_Interp *interp, Jsi_Value *val, Jsi_Number *nPtr, bool isProvide)
{
    Jsi_Number n = *nPtr;
    if (!val)
        return Jsi_LogError("missing version");
    if (Jsi_ValueIsNumber(interp, val)) {
        if (Jsi_GetDoubleFromValue(interp, val, &n) != JSI_OK || Jsi_NumberIsNaN(n) || (isProvide?n<=0.0:n<0.0) || n>=100.0)
            return Jsi_LogError("bad version: %.4" JSI_NUMGFMT, n);
        *nPtr = n;
        return JSI_OK;
    }
    const char *vstr = Jsi_ValueString(interp, val, NULL), *vs = vstr;
    if (!vstr)
        return Jsi_LogError("bad version");
    uint v[3] = {};
................................................................................
    Jsi_Number ver = Jsi_PkgRequire(interp, name, n);
    interp->isMain = isMain;
    if (ver < 0)
        return JSI_ERROR;
    Jsi_RC rc = JSI_OK;
    if (argc>1) {
        if (ver < n) 
            rc = Jsi_LogType("package '%s' downlevel: %.4" JSI_NUMGFMT " < %.4" JSI_NUMGFMT, name, ver, n);
        if (rc != JSI_OK)
            return rc;
        return jsi_PkgDumpInfo(interp, name, ret);
    }
    Jsi_ValueMakeNumber(interp, ret, ver);
    return rc;
}

Changes to src/jsiCode.c.

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
...
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
const char* jsi_opcode_string(uint opCode)
{
    if (opCode >= (sizeof(jsi_op_names)/sizeof(jsi_op_names[0])))
        return "NULL";
    return jsi_op_names[opCode];
}

void jsi_code_decode(jsi_OpCode *op, int currentip, char *buf, int bsiz)
{
    if (_JSICASTINT(op->op) < 0 || op->op >= OP_LASTOP) {
        snprintf(buf, bsiz, "Bad opcode[%d] at %d", op->op, currentip);
    }
    char nbuf[100];
    snprintf(nbuf, sizeof(nbuf), "%d#%d", currentip, op->Line);
    snprintf(buf, bsiz, "%-8s %s ", nbuf, jsi_op_names[op->op]);
................................................................................
    if (op->op == OP_PUSHBOO || op->op == OP_FCALL || op->op == OP_EVAL ||
        op->op == OP_POP || op->op == OP_ASSIGN ||
        op->op == OP_RET || op->op == OP_NEWFCALL ||
        op->op == OP_DELETE || op->op == OP_CHTHIS ||
        op->op == OP_OBJECT || op->op == OP_ARRAY ||
        op->op == OP_SHF ||
        op->op == OP_INC || op->op == OP_DEC) snprintf(bp, bsiz, "%" PRId64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_PUSHNUM) snprintf(bp, bsiz, "%" JSI_NUMGFMT "", *((Jsi_Number *)op->data));
    else if (op->op == OP_PUSHSTR || op->op == OP_LOCAL ||
             op->op == OP_SCATCH) snprintf(bp, bsiz, "\"%s\"", op->data ? (char*)op->data:"(NoCatch)");
    else if (op->op == OP_PUSHVAR) snprintf(bp, bsiz, "var: \"%s\"", ((jsi_FastVar *)op->data)->varname);
    else if (op->op == OP_PUSHFUN) snprintf(bp, bsiz, "func: 0x%" PRIx64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_JTRUE || op->op == OP_JFALSE ||
             op->op == OP_JTRUE_NP || op->op == OP_JFALSE_NP ||
             op->op == OP_JMP) snprintf(bp, bsiz, "{%" PRIu64 "}\t#%" PRIu64 "", (Jsi_Wide)(uintptr_t)op->data, (Jsi_Wide)((uintptr_t)currentip + (uintptr_t)op->data));
................................................................................
        return;
    while (i < ops->code_len) {
        if (ops->codes[i].op == OP_PUSHVAR)
            ops->codes[i].local = 1;
        i++;
    }
}

/*
void jsi_codes_print(Jsi_OpCodes *ops)
{
    int i = 0;
    jsi_OpCode *opcodes = ops->codes;
    int opcodesi = ops->code_len;
    
    fprintf(stderr, "opcodes count = %d\n", opcodesi);
    
    while(i < opcodesi) {
        jsi_code_decode(&opcodes[i], i);
        i++;
    }
}*/



static jsi_ForinVar *forinvar_new(jsi_Pstate *pstate, const char *varname, Jsi_OpCodes *local, Jsi_OpCodes *lval)
{
    jsi_ForinVar *r = (jsi_ForinVar*)Jsi_Calloc(1,sizeof(*r));
    r->sig = JSI_SIG_FORINVAR;
    r->varname = varname;
    r->local = local;







|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
...
471
472
473
474
475
476
477

















478
479
480
481
482
483
484
const char* jsi_opcode_string(uint opCode)
{
    if (opCode >= (sizeof(jsi_op_names)/sizeof(jsi_op_names[0])))
        return "NULL";
    return jsi_op_names[opCode];
}

void jsi_code_decode(Jsi_Interp *interp, jsi_OpCode *op, int currentip, char *buf, int bsiz)
{
    if (_JSICASTINT(op->op) < 0 || op->op >= OP_LASTOP) {
        snprintf(buf, bsiz, "Bad opcode[%d] at %d", op->op, currentip);
    }
    char nbuf[100];
    snprintf(nbuf, sizeof(nbuf), "%d#%d", currentip, op->Line);
    snprintf(buf, bsiz, "%-8s %s ", nbuf, jsi_op_names[op->op]);
................................................................................
    if (op->op == OP_PUSHBOO || op->op == OP_FCALL || op->op == OP_EVAL ||
        op->op == OP_POP || op->op == OP_ASSIGN ||
        op->op == OP_RET || op->op == OP_NEWFCALL ||
        op->op == OP_DELETE || op->op == OP_CHTHIS ||
        op->op == OP_OBJECT || op->op == OP_ARRAY ||
        op->op == OP_SHF ||
        op->op == OP_INC || op->op == OP_DEC) snprintf(bp, bsiz, "%" PRId64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_PUSHNUM) Jsi_NumberDtoA(interp, *((Jsi_Number *)op->data), bp, bsiz, 0);
    else if (op->op == OP_PUSHSTR || op->op == OP_LOCAL ||
             op->op == OP_SCATCH) snprintf(bp, bsiz, "\"%s\"", op->data ? (char*)op->data:"(NoCatch)");
    else if (op->op == OP_PUSHVAR) snprintf(bp, bsiz, "var: \"%s\"", ((jsi_FastVar *)op->data)->varname);
    else if (op->op == OP_PUSHFUN) snprintf(bp, bsiz, "func: 0x%" PRIx64, (Jsi_Wide)(uintptr_t)op->data);
    else if (op->op == OP_JTRUE || op->op == OP_JFALSE ||
             op->op == OP_JTRUE_NP || op->op == OP_JFALSE_NP ||
             op->op == OP_JMP) snprintf(bp, bsiz, "{%" PRIu64 "}\t#%" PRIu64 "", (Jsi_Wide)(uintptr_t)op->data, (Jsi_Wide)((uintptr_t)currentip + (uintptr_t)op->data));
................................................................................
        return;
    while (i < ops->code_len) {
        if (ops->codes[i].op == OP_PUSHVAR)
            ops->codes[i].local = 1;
        i++;
    }
}


















static jsi_ForinVar *forinvar_new(jsi_Pstate *pstate, const char *varname, Jsi_OpCodes *local, Jsi_OpCodes *lval)
{
    jsi_ForinVar *r = (jsi_ForinVar*)Jsi_Calloc(1,sizeof(*r));
    r->sig = JSI_SIG_FORINVAR;
    r->varname = varname;
    r->local = local;

Changes to src/jsiEval.c.

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
}

static void DumpInstr(Jsi_Interp *interp, jsi_Pstate *ps, Jsi_Value *_this,
    jsi_TryList *trylist, jsi_OpCode *ip, Jsi_OpCodes *opcodes)
{
    int i;
    char buf[200];
    jsi_code_decode(ip, ip - opcodes->codes, buf, sizeof(buf));
    Jsi_Printf(interp, jsi_Stderr, "%p: %-30.200s : THIS=%s, STACK=[", ip, buf, vprint(_this));
    for (i = 0; i < interp->framePtr->Sp; ++i) {
        Jsi_Printf(interp, jsi_Stderr, "%s%s", (i>0?", ":""), vprint(_jsi_STACKIDX(i)));
    }
    Jsi_Printf(interp, jsi_Stderr, "]");
    if (ip->fname) {
        const char *fn = ip->fname,  *cp = Jsi_Strrchr(fn, '/');







|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
}

static void DumpInstr(Jsi_Interp *interp, jsi_Pstate *ps, Jsi_Value *_this,
    jsi_TryList *trylist, jsi_OpCode *ip, Jsi_OpCodes *opcodes)
{
    int i;
    char buf[200];
    jsi_code_decode(interp, ip, ip - opcodes->codes, buf, sizeof(buf));
    Jsi_Printf(interp, jsi_Stderr, "%p: %-30.200s : THIS=%s, STACK=[", ip, buf, vprint(_this));
    for (i = 0; i < interp->framePtr->Sp; ++i) {
        Jsi_Printf(interp, jsi_Stderr, "%s%s", (i>0?", ":""), vprint(_jsi_STACKIDX(i)));
    }
    Jsi_Printf(interp, jsi_Stderr, "]");
    if (ip->fname) {
        const char *fn = ip->fname,  *cp = Jsi_Strrchr(fn, '/');

Changes to src/jsiInt.h.

115
116
117
118
119
120
121

122
123
124
125
126
127
128
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
....
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>


#ifdef __WIN32 /* TODO: support windows signal??? */
#define JSI__MINIZ 1
#define JSI_OMIT_SIGNAL
#endif

#ifndef JSI_AMALGAMATION
................................................................................
} jsi_JmpPopInfo;

#define RES_CONTINUE    1
#define RES_BREAK       2
typedef struct YYLTYPE jsi_Pline;

//void jsi_codes_print(Jsi_OpCodes *ops);
void jsi_code_decode(jsi_OpCode *op, int currentip, char *buf, int bsiz);
const char* jsi_opcode_string(uint opCode);

#ifdef JSI_MEM_DEBUG
typedef struct 
{
    const char *fname;
    int line;
................................................................................
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;

    const char *blacklist;
} jsi_SubOptions;

extern Jsi_OptionSpec jsi_InterpLogOptions[];

typedef enum {
        jsi_TL_TRY,







>







 







|







 







>







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <float.h>

#ifdef __WIN32 /* TODO: support windows signal??? */
#define JSI__MINIZ 1
#define JSI_OMIT_SIGNAL
#endif

#ifndef JSI_AMALGAMATION
................................................................................
} jsi_JmpPopInfo;

#define RES_CONTINUE    1
#define RES_BREAK       2
typedef struct YYLTYPE jsi_Pline;

//void jsi_codes_print(Jsi_OpCodes *ops);
void jsi_code_decode(Jsi_Interp *interp, jsi_OpCode *op, int currentip, char *buf, int bsiz);
const char* jsi_opcode_string(uint opCode);

#ifdef JSI_MEM_DEBUG
typedef struct 
{
    const char *fname;
    int line;
................................................................................
    bool outUndef;
    bool strictFiles;
    bool logAllowDups;
    bool logColNums;
    bool privKeys;
    bool compat;
    bool mutexUnlock;
    int dblPrec;
    const char *blacklist;
} jsi_SubOptions;

extern Jsi_OptionSpec jsi_InterpLogOptions[];

typedef enum {
        jsi_TL_TRY,

Changes to src/jsiInterp.c.

52
53
54
55
56
57
58

59
60
61
62
63
64
65
...
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
....
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
....
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
....
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
    JSI_OPT(STRKEY, jsi_LogOptions, timeFmt, .help="A format string to use with strftime" ),
    JSI_OPT(USEROBJ,jsi_LogOptions, chan,    .help="Channel to send output to", .flags=0, .custom=0, .data=(void*)"Channel" ),
    JSI_OPT_END(jsi_LogOptions, .help="Interp options for logging")
};
static Jsi_OptionSpec InterpSubOptions[] = {
    JSI_OPT(STRKEY,jsi_SubOptions, blacklist,   .help="Comma separated modules to disable loading for", jsi_IIOF ),
    JSI_OPT(BOOL,  jsi_SubOptions, compat,      .help="Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser" ),

    JSI_OPT(BOOL,  jsi_SubOptions, istty,       .help="Indicates interp is in interactive mode", jsi_IIRO),
    JSI_OPT(BOOL,  jsi_SubOptions, logColNums,  .help="Display column numbers in error messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, logAllowDups,.help="Log should not filter out duplicate messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, mutexUnlock, .help="Unlock own mutex when evaling in other interps (true)", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, noproto,     .help="Disable support of the OOP symbols:  __proto__, prototype, constructor, etc"),
    JSI_OPT(BOOL,  jsi_SubOptions, noReadline,  .help="In interactive mode disable use of readline" ),
    JSI_OPT(BOOL,  jsi_SubOptions, outUndef,     .help="In interactive mode output result values that are undefined"),
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--version")) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(interp, chan, str, sizeof(str));
            printf("%u.%u.%u %" JSI_NUMGFMT " %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            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_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;


    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
                refSum += vp->refCnt;
                if (vdLev>1) {
                    char ebuf[JSI_BUFSIZ], ebuf2[JSI_MAX_NUMBER_STRING];
                    ebuf[0] = 0;
                    if (vp->vt==JSI_VT_OBJECT)
                        snprintf(ebuf, sizeof(ebuf), " {obj=%p, otype=%s}", vp->d.obj, Jsi_ObjTypeStr(interp, vp->d.obj));
                    else if (vp->vt==JSI_VT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), " {num=%s}", Jsi_NumberToString(vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->vt==JSI_VT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), " {bool=%s}", vp->d.val?"true":"false");
                    else if (vp->vt==JSI_VT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), " {string=\"%.40s%s\"}", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    const char *pfx = "";
................................................................................
                    ebuf[0] = 0;
                    if (vp->ot==JSI_OT_OBJECT) {
                        if (vp->isarrlist)
                            snprintf(ebuf, sizeof(ebuf), "tree#%d, array#%d", (vp->tree?vp->tree->numEntries:0), vp->arrCnt);
                        else
                            snprintf(ebuf, sizeof(ebuf), "tree#%d", (vp->tree?vp->tree->numEntries:0));
                    } else if (vp->ot==JSI_OT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), "num=%s", Jsi_NumberToString(vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->ot==JSI_OT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), "bool=%s", vp->d.val?"true":"false");
                    else if (vp->ot==JSI_OT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), "string=\"%.40s%s\"", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    fprintf(stderr, "[*%p,#%d,%s,%d:%s%s%s]:%s @%s:%d in %s() {%s}\n",







>







 







|







 







>







 







|







 







|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
....
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
....
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
....
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
    JSI_OPT(STRKEY, jsi_LogOptions, timeFmt, .help="A format string to use with strftime" ),
    JSI_OPT(USEROBJ,jsi_LogOptions, chan,    .help="Channel to send output to", .flags=0, .custom=0, .data=(void*)"Channel" ),
    JSI_OPT_END(jsi_LogOptions, .help="Interp options for logging")
};
static Jsi_OptionSpec InterpSubOptions[] = {
    JSI_OPT(STRKEY,jsi_SubOptions, blacklist,   .help="Comma separated modules to disable loading for", jsi_IIOF ),
    JSI_OPT(BOOL,  jsi_SubOptions, compat,      .help="Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser" ),
    JSI_OPT(INT,   jsi_SubOptions, dblPrec,     .help="Format precision of double (-1): 0=max, -1=max-1, ..", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, istty,       .help="Indicates interp is in interactive mode", jsi_IIRO),
    JSI_OPT(BOOL,  jsi_SubOptions, logColNums,  .help="Display column numbers in error messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, logAllowDups,.help="Log should not filter out duplicate messages"),
    JSI_OPT(BOOL,  jsi_SubOptions, mutexUnlock, .help="Unlock own mutex when evaling in other interps (true)", jsi_IIOF),
    JSI_OPT(BOOL,  jsi_SubOptions, noproto,     .help="Disable support of the OOP symbols:  __proto__, prototype, constructor, etc"),
    JSI_OPT(BOOL,  jsi_SubOptions, noReadline,  .help="In interactive mode disable use of readline" ),
    JSI_OPT(BOOL,  jsi_SubOptions, outUndef,     .help="In interactive mode output result values that are undefined"),
................................................................................
            return jsi_DoExit(interp, 1);
        }
        if (argc == 2 && !Jsi_Strcmp(argv[1], "--version")) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(interp, chan, str, sizeof(str));
            printf("%u.%u.%u %.4" JSI_NUMGFMT " %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            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_LogError("exceeded max subinterp depth");
            return NULL;
        }
    }
    interp->maxDepth = JSI_MAX_EVAL_DEPTH;
    interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
    interp->typeWarnMax = 50;
    interp->subOpts.dblPrec = -1;

    int iocnt;
    if (iopts) {
        iopts->interp = interp;
        interp->opts = *iopts;
    }
    interp->logOpts.file = 1;
................................................................................
                refSum += vp->refCnt;
                if (vdLev>1) {
                    char ebuf[JSI_BUFSIZ], ebuf2[JSI_MAX_NUMBER_STRING];
                    ebuf[0] = 0;
                    if (vp->vt==JSI_VT_OBJECT)
                        snprintf(ebuf, sizeof(ebuf), " {obj=%p, otype=%s}", vp->d.obj, Jsi_ObjTypeStr(interp, vp->d.obj));
                    else if (vp->vt==JSI_VT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), " {num=%s}", Jsi_NumberToString(interp, vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->vt==JSI_VT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), " {bool=%s}", vp->d.val?"true":"false");
                    else if (vp->vt==JSI_VT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), " {string=\"%.40s%s\"}", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    const char *pfx = "";
................................................................................
                    ebuf[0] = 0;
                    if (vp->ot==JSI_OT_OBJECT) {
                        if (vp->isarrlist)
                            snprintf(ebuf, sizeof(ebuf), "tree#%d, array#%d", (vp->tree?vp->tree->numEntries:0), vp->arrCnt);
                        else
                            snprintf(ebuf, sizeof(ebuf), "tree#%d", (vp->tree?vp->tree->numEntries:0));
                    } else if (vp->ot==JSI_OT_NUMBER)
                        snprintf(ebuf, sizeof(ebuf), "num=%s", Jsi_NumberToString(interp, vp->d.num, ebuf2, sizeof(ebuf2)));
                    else if (vp->ot==JSI_OT_BOOL)
                        snprintf(ebuf, sizeof(ebuf), "bool=%s", vp->d.val?"true":"false");
                    else if (vp->ot==JSI_OT_STRING) {
                        const char *sbuf = ((vp->d.s.str && Jsi_Strlen(vp->d.s.str)>40)?"...":"");
                        snprintf(ebuf, sizeof(ebuf), "string=\"%.40s%s\"", (vp->d.s.str?vp->d.s.str:""), sbuf);
                    }
                    fprintf(stderr, "[*%p,#%d,%s,%d:%s%s%s]:%s @%s:%d in %s() {%s}\n",

Changes to src/jsiMySql.c.

1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
....
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
        }
        case JSI_OPTION_INT64: {
            snprintf(nbuf, sizeof(nbuf), "%lld", field->buffer.vlonglong);
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_STRING:
            zBlob = field->buffer.vstring;
        default:
        {
................................................................................
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        default:
            Jsi_LogWarn("unknown type: %d", field->jsiTypeMap);
    
    }







|







|







 







|




|







1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
....
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
        }
        case JSI_OPTION_INT64: {
            snprintf(nbuf, sizeof(nbuf), "%lld", field->buffer.vlonglong);
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(interp, field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(interp, jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_STRING:
            zBlob = field->buffer.vstring;
        default:
        {
................................................................................
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        //case JSI_OPTION_TIME_T:
        case JSI_OPTION_TIME_D:
        case JSI_OPTION_TIME_W: {
            Jsi_Number jtime = mdbMyTimeToJS(&field->buffer.timestamp);
            Jsi_NumberToString(interp, jtime, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        case JSI_OPTION_DOUBLE: {
            Jsi_NumberToString(interp, field->buffer.vdouble, nbuf, sizeof(nbuf));
            Jsi_DSAppend(dStr, nbuf, NULL);
            return;
        }
        default:
            Jsi_LogWarn("unknown type: %d", field->jsiTypeMap);
    
    }

Changes to src/jsiNumber.c.

1
2
3
4
5
6
7
8
9
10
..
57
58
59
60
61
62
63
64
65



66


67
68
69
70
71
72
73
74
#include <math.h>
#include <float.h>
#include <stdio.h>
#ifndef JSI_AMALGAMATION
#include "jsiInt.h"
#endif

bool Jsi_NumberIsSubnormal(Jsi_Number a) { return fpclassify(a) == FP_SUBNORMAL; }

bool Jsi_NumberIsNormal(Jsi_Number a) { return (fpclassify(a) == FP_ZERO || isnormal(a)); }
................................................................................

bool Jsi_NumberIsFinite(Jsi_Number value)
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Number value, char* buf, int bsiz, int prec)
{



    if (prec<0)


        prec = DBL_DECIMAL_DIG;
    if (Jsi_NumberIsNaN(value))
        Jsi_Strcpy(buf,"NaN");
    else
        snprintf(buf, bsiz, "%.*" JSI_NUMGFMT, prec, value);
}

bool Jsi_NumberIsEqual(Jsi_Number n1, Jsi_Number n2)

<
<







 







|

>
>
>
|
>
>
|







1


2
3
4
5
6
7
8
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <math.h>


#ifndef JSI_AMALGAMATION
#include "jsiInt.h"
#endif

bool Jsi_NumberIsSubnormal(Jsi_Number a) { return fpclassify(a) == FP_SUBNORMAL; }

bool Jsi_NumberIsNormal(Jsi_Number a) { return (fpclassify(a) == FP_ZERO || isnormal(a)); }
................................................................................

bool Jsi_NumberIsFinite(Jsi_Number value)
{
    Jsi_Number r = INFINITY;
    return (Jsi_NumberIsNaN(value)==0 && value != r && r != -value);
}

void Jsi_NumberDtoA(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec)
{
    int dp = interp->subOpts.dblPrec, dm = DBL_DECIMAL_DIG;
    if (prec==0)
        prec = (dp<=0?dm+dp:dp);
    else if (prec<0)
            prec = dm+prec;
    if (prec<=0)
        prec = dm-1;
    if (Jsi_NumberIsNaN(value))
        Jsi_Strcpy(buf,"NaN");
    else
        snprintf(buf, bsiz, "%.*" JSI_NUMGFMT, prec, value);
}

bool Jsi_NumberIsEqual(Jsi_Number n1, Jsi_Number n2)

Changes to src/jsiSqlite.c.

1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
....
1743
1744
1745
1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
....
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        Jsi_DSAppend(dStr, "null", NULL);
        return;
    }
................................................................................
    const char *str = (char*)sqlite3_column_text(pStmt, iCol );
    if (!str)
        str = p->jdb->optPtr->nullvalue;
    Jsi_JSONQuote(interp, str?str:"", -1, dStr);
}

static void dbEvalSetColumn(DbEvalContext *p, int iCol, Jsi_DString *dStr) {

    char nbuf[200];

    sqlite3_stmt *pStmt = p->pPreStmt->pStmt;

    switch( sqlite3_column_type(pStmt, iCol) ) {
    case SQLITE_BLOB: {
        int bytes = sqlite3_column_bytes(pStmt, iCol);
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        return;
    }
    }







|







 







>







 







|







1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
....
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
....
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(interp, sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        Jsi_DSAppend(dStr, "null", NULL);
        return;
    }
................................................................................
    const char *str = (char*)sqlite3_column_text(pStmt, iCol );
    if (!str)
        str = p->jdb->optPtr->nullvalue;
    Jsi_JSONQuote(interp, str?str:"", -1, dStr);
}

static void dbEvalSetColumn(DbEvalContext *p, int iCol, Jsi_DString *dStr) {
    Jsi_Interp *interp = p->jdb->interp;
    char nbuf[200];

    sqlite3_stmt *pStmt = p->pPreStmt->pStmt;

    switch( sqlite3_column_type(pStmt, iCol) ) {
    case SQLITE_BLOB: {
        int bytes = sqlite3_column_bytes(pStmt, iCol);
................................................................................
#else
        snprintf(nbuf, sizeof(nbuf), "%lld", v);
#endif
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_FLOAT: {
        Jsi_NumberToString(interp, sqlite3_column_double(pStmt, iCol), nbuf, sizeof(nbuf));
        Jsi_DSAppend(dStr, nbuf, NULL);
        return;
    }
    case SQLITE_NULL: {
        return;
    }
    }

Changes to src/jsiStubs.h.

1
2
3
4
5
6
7
8
9
10
11
12
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
....
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
#ifndef __JSI_STUBS_H__
#define __JSI_STUBS_H__
#include "jsi.h"

#define JSI_STUBS_MD5 "cdb9ad7386a9d0519e79e25db2f53698"

#undef JSI_EXTENSION_INI
#define JSI_EXTENSION_INI Jsi_Stubs *jsiStubsPtr = NULL;

#ifdef JSI__MUSL
#define JSI_STUBS_BLDFLAGS 1
#else
................................................................................
    Jsi_Value*(*_Jsi_ValueDupJSON)(Jsi_Interp *interp, Jsi_Value *val);
    void(*_Jsi_ValueMove)(Jsi_Interp *interp, Jsi_Value *to, Jsi_Value *from);
    bool (*_Jsi_ValueIsEqual)(Jsi_Interp *interp, Jsi_Value *v1, Jsi_Value* v2);
    Jsi_Hash*(*_Jsi_UserObjRegister)(Jsi_Interp *interp, Jsi_UserObjReg *reg);
    Jsi_RC(*_Jsi_UserObjUnregister)(Jsi_Interp *interp, Jsi_UserObjReg *reg);
    int(*_Jsi_UserObjNew)(Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data);
    void*(*_Jsi_UserObjGetData)(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr);
    char*(*_Jsi_NumberToString)(Jsi_Number d, char *buf, int bsiz);
    Jsi_Number(*_Jsi_Version)(void);
    Jsi_Value*(*_Jsi_ReturnValue)(Jsi_Interp *interp);
    Jsi_RC(*_Jsi_Mount)( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret);
    Jsi_Value*(*_Jsi_Executable)(Jsi_Interp *interp);
    Jsi_Regex*(*_Jsi_RegExpNew)(Jsi_Interp *interp, const char *regtxt, int flag);
    void(*_Jsi_RegExpFree)(Jsi_Regex* re);
    Jsi_RC(*_Jsi_RegExpMatch)( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr);
................................................................................
    bool(*_Jsi_NumberIsInteger)(Jsi_Number n);
    bool(*_Jsi_NumberIsNaN)(Jsi_Number a);
    bool(*_Jsi_NumberIsNormal)(Jsi_Number a);
    bool(*_Jsi_NumberIsSubnormal)(Jsi_Number a);
    bool(*_Jsi_NumberIsWide)(Jsi_Number n);
    Jsi_Number(*_Jsi_NumberInfinity)(int i);
    Jsi_Number(*_Jsi_NumberNaN)(void);
    void(*_Jsi_NumberDtoA)(Jsi_Number value, char* buf, int bsiz, int prec);
    void(*_Jsi_NumberItoA10)(Jsi_Wide value, char* buf, int bsiz);
    void(*_Jsi_NumberUtoA10)(Jsi_UWide, char* buf, int bsiz);
    Jsi_Hash*(*_Jsi_HashNew)(Jsi_Interp *interp, uint keyType, Jsi_HashDeleteProc *freeProc);
    Jsi_RC(*_Jsi_HashConf)(Jsi_Hash *hashPtr, Jsi_MapOpts *opts, bool set);
    void(*_Jsi_HashDelete)(Jsi_Hash *hashPtr);
    void(*_Jsi_HashClear)(Jsi_Hash *hashPtr);
    Jsi_HashEntry*(*_Jsi_HashSet)(Jsi_Hash *hashPtr, const void *key, void *value);
................................................................................
#define Jsi_ValueDupJSON(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueDupJSON(n0,n1))
#define Jsi_ValueMove(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueMove(n0,n1,n2))
#define Jsi_ValueIsEqual(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueIsEqual(n0,n1,n2))
#define Jsi_UserObjRegister(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjRegister(n0,n1))
#define Jsi_UserObjUnregister(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjUnregister(n0,n1))
#define Jsi_UserObjNew(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjNew(n0,n1,n2,n3))
#define Jsi_UserObjGetData(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjGetData(n0,n1,n2))
#define Jsi_NumberToString(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberToString(n0,n1,n2))
#define Jsi_Version(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_Version(n0))
#define Jsi_ReturnValue(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_ReturnValue(n0))
#define Jsi_Mount(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_Mount(n0,n1,n2,n3))
#define Jsi_Executable(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_Executable(n0))
#define Jsi_RegExpNew(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpNew(n0,n1,n2))
#define Jsi_RegExpFree(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpFree(n0))
#define Jsi_RegExpMatch(n0,n1,n2,n3,n4) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpMatch(n0,n1,n2,n3,n4))
................................................................................
#define Jsi_NumberIsInteger(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsInteger(n0))
#define Jsi_NumberIsNaN(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsNaN(n0))
#define Jsi_NumberIsNormal(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsNormal(n0))
#define Jsi_NumberIsSubnormal(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsSubnormal(n0))
#define Jsi_NumberIsWide(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsWide(n0))
#define Jsi_NumberInfinity(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberInfinity(n0))
#define Jsi_NumberNaN(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberNaN(n0))
#define Jsi_NumberDtoA(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberDtoA(n0,n1,n2,n3))
#define Jsi_NumberItoA10(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberItoA10(n0,n1,n2))
#define Jsi_NumberUtoA10(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberUtoA10(n0,n1,n2))
#define Jsi_HashNew(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashNew(n0,n1,n2))
#define Jsi_HashConf(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashConf(n0,n1,n2))
#define Jsi_HashDelete(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_HashDelete(n0))
#define Jsi_HashClear(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_HashClear(n0))
#define Jsi_HashSet(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashSet(n0,n1,n2))




|







 







|







 







|







 







|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
....
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
....
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
#ifndef __JSI_STUBS_H__
#define __JSI_STUBS_H__
#include "jsi.h"

#define JSI_STUBS_MD5 "bd4e55a8383c3598c0344241217a1d53"

#undef JSI_EXTENSION_INI
#define JSI_EXTENSION_INI Jsi_Stubs *jsiStubsPtr = NULL;

#ifdef JSI__MUSL
#define JSI_STUBS_BLDFLAGS 1
#else
................................................................................
    Jsi_Value*(*_Jsi_ValueDupJSON)(Jsi_Interp *interp, Jsi_Value *val);
    void(*_Jsi_ValueMove)(Jsi_Interp *interp, Jsi_Value *to, Jsi_Value *from);
    bool (*_Jsi_ValueIsEqual)(Jsi_Interp *interp, Jsi_Value *v1, Jsi_Value* v2);
    Jsi_Hash*(*_Jsi_UserObjRegister)(Jsi_Interp *interp, Jsi_UserObjReg *reg);
    Jsi_RC(*_Jsi_UserObjUnregister)(Jsi_Interp *interp, Jsi_UserObjReg *reg);
    int(*_Jsi_UserObjNew)(Jsi_Interp *interp, Jsi_UserObjReg* reg, Jsi_Obj *obj, void *data);
    void*(*_Jsi_UserObjGetData)(Jsi_Interp *interp, Jsi_Value* value, Jsi_Func *funcPtr);
    char*(*_Jsi_NumberToString)(Jsi_Interp *interp, Jsi_Number d, char *buf, int bsiz);
    Jsi_Number(*_Jsi_Version)(void);
    Jsi_Value*(*_Jsi_ReturnValue)(Jsi_Interp *interp);
    Jsi_RC(*_Jsi_Mount)( Jsi_Interp *interp, Jsi_Value *archive, Jsi_Value *mount, Jsi_Value **ret);
    Jsi_Value*(*_Jsi_Executable)(Jsi_Interp *interp);
    Jsi_Regex*(*_Jsi_RegExpNew)(Jsi_Interp *interp, const char *regtxt, int flag);
    void(*_Jsi_RegExpFree)(Jsi_Regex* re);
    Jsi_RC(*_Jsi_RegExpMatch)( Jsi_Interp *interp,  Jsi_Value *pattern, const char *str, int *rc, Jsi_DString *dStr);
................................................................................
    bool(*_Jsi_NumberIsInteger)(Jsi_Number n);
    bool(*_Jsi_NumberIsNaN)(Jsi_Number a);
    bool(*_Jsi_NumberIsNormal)(Jsi_Number a);
    bool(*_Jsi_NumberIsSubnormal)(Jsi_Number a);
    bool(*_Jsi_NumberIsWide)(Jsi_Number n);
    Jsi_Number(*_Jsi_NumberInfinity)(int i);
    Jsi_Number(*_Jsi_NumberNaN)(void);
    void(*_Jsi_NumberDtoA)(Jsi_Interp *interp, Jsi_Number value, char* buf, int bsiz, int prec);
    void(*_Jsi_NumberItoA10)(Jsi_Wide value, char* buf, int bsiz);
    void(*_Jsi_NumberUtoA10)(Jsi_UWide, char* buf, int bsiz);
    Jsi_Hash*(*_Jsi_HashNew)(Jsi_Interp *interp, uint keyType, Jsi_HashDeleteProc *freeProc);
    Jsi_RC(*_Jsi_HashConf)(Jsi_Hash *hashPtr, Jsi_MapOpts *opts, bool set);
    void(*_Jsi_HashDelete)(Jsi_Hash *hashPtr);
    void(*_Jsi_HashClear)(Jsi_Hash *hashPtr);
    Jsi_HashEntry*(*_Jsi_HashSet)(Jsi_Hash *hashPtr, const void *key, void *value);
................................................................................
#define Jsi_ValueDupJSON(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueDupJSON(n0,n1))
#define Jsi_ValueMove(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueMove(n0,n1,n2))
#define Jsi_ValueIsEqual(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_ValueIsEqual(n0,n1,n2))
#define Jsi_UserObjRegister(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjRegister(n0,n1))
#define Jsi_UserObjUnregister(n0,n1) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjUnregister(n0,n1))
#define Jsi_UserObjNew(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjNew(n0,n1,n2,n3))
#define Jsi_UserObjGetData(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_UserObjGetData(n0,n1,n2))
#define Jsi_NumberToString(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberToString(n0,n1,n2,n3))
#define Jsi_Version(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_Version(n0))
#define Jsi_ReturnValue(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_ReturnValue(n0))
#define Jsi_Mount(n0,n1,n2,n3) JSISTUBCALL(jsiStubsPtr, _Jsi_Mount(n0,n1,n2,n3))
#define Jsi_Executable(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_Executable(n0))
#define Jsi_RegExpNew(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpNew(n0,n1,n2))
#define Jsi_RegExpFree(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpFree(n0))
#define Jsi_RegExpMatch(n0,n1,n2,n3,n4) JSISTUBCALL(jsiStubsPtr, _Jsi_RegExpMatch(n0,n1,n2,n3,n4))
................................................................................
#define Jsi_NumberIsInteger(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsInteger(n0))
#define Jsi_NumberIsNaN(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsNaN(n0))
#define Jsi_NumberIsNormal(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsNormal(n0))
#define Jsi_NumberIsSubnormal(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsSubnormal(n0))
#define Jsi_NumberIsWide(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberIsWide(n0))
#define Jsi_NumberInfinity(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberInfinity(n0))
#define Jsi_NumberNaN(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberNaN(n0))
#define Jsi_NumberDtoA(n0,n1,n2,n3,n4) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberDtoA(n0,n1,n2,n3,n4))
#define Jsi_NumberItoA10(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberItoA10(n0,n1,n2))
#define Jsi_NumberUtoA10(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_NumberUtoA10(n0,n1,n2))
#define Jsi_HashNew(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashNew(n0,n1,n2))
#define Jsi_HashConf(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashConf(n0,n1,n2))
#define Jsi_HashDelete(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_HashDelete(n0))
#define Jsi_HashClear(n0) JSISTUBCALL(jsiStubsPtr, _Jsi_HashClear(n0))
#define Jsi_HashSet(n0,n1,n2) JSISTUBCALL(jsiStubsPtr, _Jsi_HashSet(n0,n1,n2))

Changes to src/jsiUtils.c.

496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
....
1022
1023
1024
1025
1026
1027
1028




1029
1030
1031
1032
1033
1034
1035
    Jsi_DSAppend(dStr, ":", NULL);
    ow->depth++;
    Jsi_RC rc = jsiValueGetString(tree->opts.interp, v, dStr, ow);
    ow->depth--;
    return rc;
}

#include <float.h>

/* Format value into dStr.  Toplevel caller does init/free. */
static Jsi_RC jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
{
    char buf[100], *str;
    Jsi_DString eStr;
    Jsi_DSInit(&eStr);
    if (interp->maxDepth>0 && owPtr->depth > interp->maxDepth)
................................................................................
            } else if (Jsi_NumberIsInteger(num)) {
                Jsi_NumberItoA10((Jsi_Wide)num, buf, sizeof(buf));
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsWide(num)) {
                snprintf(buf, sizeof(buf), "%" PRId64, (Jsi_Wide)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNormal(num) || Jsi_NumberIsSubnormal(num)) {
                Jsi_NumberDtoA(num, buf, sizeof(buf), -1);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNaN(num)) {
                Jsi_DSAppend(dStr, "NaN", NULL);
            } else {
                int s = Jsi_NumberIsInfinity(num);
                if (s > 0) Jsi_DSAppend(dStr, "+Infinity", NULL);
                else if (s < 0) Jsi_DSAppend(dStr, "-Infinity", NULL);
................................................................................
    if (hist) {
        jsi_sh_stifle_history(100);
        jsi_sh_write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);




    if (interp->exited && interp->level <= 0)
    {
        rc = JSI_EXIT;
        Jsi_InterpDelete(interp);
    }
    jsi_interactiveInterp = NULL;
    return rc;







<
<







 







|







 







>
>
>
>







496
497
498
499
500
501
502


503
504
505
506
507
508
509
...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
    Jsi_DSAppend(dStr, ":", NULL);
    ow->depth++;
    Jsi_RC rc = jsiValueGetString(tree->opts.interp, v, dStr, ow);
    ow->depth--;
    return rc;
}



/* Format value into dStr.  Toplevel caller does init/free. */
static Jsi_RC jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
{
    char buf[100], *str;
    Jsi_DString eStr;
    Jsi_DSInit(&eStr);
    if (interp->maxDepth>0 && owPtr->depth > interp->maxDepth)
................................................................................
            } else if (Jsi_NumberIsInteger(num)) {
                Jsi_NumberItoA10((Jsi_Wide)num, buf, sizeof(buf));
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsWide(num)) {
                snprintf(buf, sizeof(buf), "%" PRId64, (Jsi_Wide)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNormal(num) || Jsi_NumberIsSubnormal(num)) {
                Jsi_NumberDtoA(interp, num, buf, sizeof(buf), 0);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (Jsi_NumberIsNaN(num)) {
                Jsi_DSAppend(dStr, "NaN", NULL);
            } else {
                int s = Jsi_NumberIsInfinity(num);
                if (s > 0) Jsi_DSAppend(dStr, "+Infinity", NULL);
                else if (s < 0) Jsi_DSAppend(dStr, "-Infinity", NULL);
................................................................................
    if (hist) {
        jsi_sh_stifle_history(100);
        jsi_sh_write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);
    if (interp->retValue) {
        Jsi_DecrRefCount(interp, interp->retValue);
        interp->retValue = NULL;
    }
    if (interp->exited && interp->level <= 0)
    {
        rc = JSI_EXIT;
        Jsi_InterpDelete(interp);
    }
    jsi_interactiveInterp = NULL;
    return rc;

Changes to src/jsiValue.c.

454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    if (otype != JSI_OT_ARRAY)
        return (v->d.obj->ot == otype);
    if (v->d.obj->ot != JSI_OT_OBJECT || !v->d.obj->isarrlist)
        return 0;
    return 1;
}

char* Jsi_NumberToString(Jsi_Number d, char *buf, int bsiz)
{
     if (Jsi_NumberIsInteger(d)) {
        Jsi_NumberItoA10((Jsi_Wide)d, buf, bsiz);
    } else if (Jsi_NumberIsNormal(d)) {
        Jsi_NumberDtoA(d, buf, bsiz, 10);
    } else if (Jsi_NumberIsNaN(d)) {
        Jsi_Strcpy(buf, "NaN");
    } else {
        int s = Jsi_NumberIsInfinity(d);
        if (s > 0) Jsi_Strcpy(buf,  "Infinity");
        else if (s < 0) Jsi_Strcpy(buf, "-Infinity");
        else {
................................................................................
            d = v->d.num;
fmtnum:
            if (Jsi_NumberIsInteger(d)) {
                Jsi_NumberItoA10((Jsi_Wide)d, unibuf, sizeof(unibuf));
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNormal(d)) {
                Jsi_NumberDtoA(d, unibuf, sizeof(unibuf), 10);
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNaN(v->d.num)) {
                ntxt = "NaN";
            } else {
                int s = Jsi_NumberIsInfinity(d);
                if (s > 0) ntxt = "Infinity";







|




|







 







|







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    if (otype != JSI_OT_ARRAY)
        return (v->d.obj->ot == otype);
    if (v->d.obj->ot != JSI_OT_OBJECT || !v->d.obj->isarrlist)
        return 0;
    return 1;
}

char* Jsi_NumberToString(Jsi_Interp *interp, Jsi_Number d, char *buf, int bsiz)
{
     if (Jsi_NumberIsInteger(d)) {
        Jsi_NumberItoA10((Jsi_Wide)d, buf, bsiz);
    } else if (Jsi_NumberIsNormal(d)) {
        Jsi_NumberDtoA(interp, d, buf, bsiz, 0);
    } else if (Jsi_NumberIsNaN(d)) {
        Jsi_Strcpy(buf, "NaN");
    } else {
        int s = Jsi_NumberIsInfinity(d);
        if (s > 0) Jsi_Strcpy(buf,  "Infinity");
        else if (s < 0) Jsi_Strcpy(buf, "-Infinity");
        else {
................................................................................
            d = v->d.num;
fmtnum:
            if (Jsi_NumberIsInteger(d)) {
                Jsi_NumberItoA10((Jsi_Wide)d, unibuf, sizeof(unibuf));
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNormal(d)) {
                Jsi_NumberDtoA(interp, d, unibuf, sizeof(unibuf), 0);
                kflag = 0;
                ntxt = unibuf;
            } else if (Jsi_NumberIsNaN(v->d.num)) {
                ntxt = "NaN";
            } else {
                int s = Jsi_NumberIsInfinity(d);
                if (s > 0) ntxt = "Infinity";

Changes to tests/math.jsi.

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
Number.toPrecision(9.1234,2) ==> 9.1
Number.toExponential(9.1234,2) ==> 9.12e+00
Number.toFixed(9.1234,2) ==> 9.12
j = new Number(9.1234) ==> 9.1234
j.toPrecision(2) ==> 9.1
j.toExponential(2) ==> 9.12e+00
j.toFixed(2) ==> 9.12
Math.tan(9) ==> -0.452316
Number.toPrecision(k,2) ==> -0.4
Number.toPrecision(Math.tan(9),2) ==> -0.4
Number.toExponential(k,2) ==> -4.52e-01
Number.toFixed(k,2) ==> -0.45
Math.abs(-1) ==> 1
Math.acos(1) ==> 0
Math.asin(1) ==> 1.5708
Math.atan(1) ==> 0.785398
Math.atan2(0.4,5) ==> 0.07983
Math.cos(1) ==> 0.540302
Math.sin(1) ==> 0.841471
Math.exp(2) ==> 7.38906
Math.ceil(5.33) ==> 6
Math.floor(5.33) ==> 5
Math.log(5.33) ==> 1.67335
Math.max(1,2,3) ==> 3
Math.min(1,2,3) ==> 1
Math.pow(2,3) ==> 8
Math.round(5.33) ==> 5
Math.sqrt(5.33) ==> 2.30868
1/0 ==> +Infinity
-1/0 ==> -Infinity
x = Math.pow(2,6) ==> 64
x.toString(16) ==> 40
x.toString(10) ==> 64
x.toString(8) ==> 100
x.toString(2) ==> 64
=!EXPECTEND!=
*/







|






|
|
|
|
|
|


|




|









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
Number.toPrecision(9.1234,2) ==> 9.1
Number.toExponential(9.1234,2) ==> 9.12e+00
Number.toFixed(9.1234,2) ==> 9.12
j = new Number(9.1234) ==> 9.1234
j.toPrecision(2) ==> 9.1
j.toExponential(2) ==> 9.12e+00
j.toFixed(2) ==> 9.12
Math.tan(9) ==> -0.4523156594418098
Number.toPrecision(k,2) ==> -0.4
Number.toPrecision(Math.tan(9),2) ==> -0.4
Number.toExponential(k,2) ==> -4.52e-01
Number.toFixed(k,2) ==> -0.45
Math.abs(-1) ==> 1
Math.acos(1) ==> 0
Math.asin(1) ==> 1.570796326794897
Math.atan(1) ==> 0.7853981633974483
Math.atan2(0.4,5) ==> 0.07982998571223732
Math.cos(1) ==> 0.5403023058681398
Math.sin(1) ==> 0.8414709848078965
Math.exp(2) ==> 7.38905609893065
Math.ceil(5.33) ==> 6
Math.floor(5.33) ==> 5
Math.log(5.33) ==> 1.673351238177753
Math.max(1,2,3) ==> 3
Math.min(1,2,3) ==> 1
Math.pow(2,3) ==> 8
Math.round(5.33) ==> 5
Math.sqrt(5.33) ==> 2.308679276123039
1/0 ==> +Infinity
-1/0 ==> -Infinity
x = Math.pow(2,6) ==> 64
x.toString(16) ==> 40
x.toString(10) ==> 64
x.toString(8) ==> 100
x.toString(2) ==> 64
=!EXPECTEND!=
*/

Changes to tests/time.jsi.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
t = strptime(s, {utc:true, fmt:'%Y-%m-%d %H:%M:%S'}) ==> 0
t = strptime('1970-01-01 10:00:00', {utc:true}) ==> 36000000
s = strftime(t, {utc:true}) ==> 1970-01-01 10:00:00
'
===Use of seconds vs ms==='
t = strptime('2010-01-01 10:00:00.123', {utc:true}) ==> 1262340000123
s = strftime(t, {utc:true}) ==> 2010-01-01 10:00:00
t/1000 ==> 1.26234e+09
Math.floor(t/1000) ==> 1262340000
'
===Coerce to seconds==='
t = strptime('2010-01-01 10:00:00.123', {utc:true, secs:true}) ==> 1262340000
s = strftime(t, {utc:true, secs:true}) ==> 2010-01-01 10:00:00
'
===Now and future dates==='
strptime('1970-01-01 10:00:00')-ofs ==> 36000000
strftime(ofs) ==> 1970-01-01 00:00:00
n=strptime('2020-03-04 12:34:56.123')-ofs ==> 1583325296123
strftime(n, {utc:true, fmt:'%Y-%m-%d %H:%M:%S.%f'}) ==> 2020-03-04 12:34:56.123
=!EXPECTEND!=
*/







|













48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
t = strptime(s, {utc:true, fmt:'%Y-%m-%d %H:%M:%S'}) ==> 0
t = strptime('1970-01-01 10:00:00', {utc:true}) ==> 36000000
s = strftime(t, {utc:true}) ==> 1970-01-01 10:00:00
'
===Use of seconds vs ms==='
t = strptime('2010-01-01 10:00:00.123', {utc:true}) ==> 1262340000123
s = strftime(t, {utc:true}) ==> 2010-01-01 10:00:00
t/1000 ==> 1262340000.123
Math.floor(t/1000) ==> 1262340000
'
===Coerce to seconds==='
t = strptime('2010-01-01 10:00:00.123', {utc:true, secs:true}) ==> 1262340000
s = strftime(t, {utc:true, secs:true}) ==> 2010-01-01 10:00:00
'
===Now and future dates==='
strptime('1970-01-01 10:00:00')-ofs ==> 36000000
strftime(ofs) ==> 1970-01-01 00:00:00
n=strptime('2020-03-04 12:34:56.123')-ofs ==> 1583325296123
strftime(n, {utc:true, fmt:'%Y-%m-%d %H:%M:%S.%f'}) ==> 2020-03-04 12:34:56.123
=!EXPECTEND!=
*/

Changes to tools/protos.jsi.

1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.5.19
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 {};
|







1
2
3
4
5
6
7
8
//JSI Command Prototypes: version 2.5.20
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 {};

Changes to www/reference.wiki.

702
703
704
705
706
707
708

709
710
711
712
713
714
715

<a name="subOptsOptions"></a>
<h2>Options for "subOpts"</h2>
<table border="1" class="optstbl table">
<tr><th>Option</th> <th>Type</th> <th>Description</th><th>Flags</th></tr>
<tr><td>blacklist</td><td><i>STRKEY</i></td><td>Comma separated modules to disable loading for.</td><td><i>initOnly</i></td></tr>
<tr><td>compat</td><td><i>BOOL</i></td><td>Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser.</td><td><i></i></td></tr>

<tr><td>istty</td><td><i>BOOL</i></td><td>Indicates interp is in interactive mode.</td><td><i>readOnly</i></td></tr>
<tr><td>logColNums</td><td><i>BOOL</i></td><td>Display column numbers in error messages.</td><td><i></i></td></tr>
<tr><td>logAllowDups</td><td><i>BOOL</i></td><td>Log should not filter out duplicate messages.</td><td><i></i></td></tr>
<tr><td>mutexUnlock</td><td><i>BOOL</i></td><td>Unlock own mutex when evaling in other interps (true).</td><td><i>initOnly</i></td></tr>
<tr><td>noproto</td><td><i>BOOL</i></td><td>Disable support of the OOP symbols:  __proto__, prototype, constructor, etc.</td><td><i></i></td></tr>
<tr><td>noReadline</td><td><i>BOOL</i></td><td>In interactive mode disable use of readline.</td><td><i></i></td></tr>
<tr><td>outUndef</td><td><i>BOOL</i></td><td>In interactive mode output result values that are undefined.</td><td><i></i></td></tr>







>







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716

<a name="subOptsOptions"></a>
<h2>Options for "subOpts"</h2>
<table border="1" class="optstbl table">
<tr><th>Option</th> <th>Type</th> <th>Description</th><th>Flags</th></tr>
<tr><td>blacklist</td><td><i>STRKEY</i></td><td>Comma separated modules to disable loading for.</td><td><i>initOnly</i></td></tr>
<tr><td>compat</td><td><i>BOOL</i></td><td>Ignore unknown options via JSI_OPTS_IGNORE_EXTRA in option parser.</td><td><i></i></td></tr>
<tr><td>dblPrec</td><td><i>INT</i></td><td>Format precision of double (-1): 0=max, -1=max-1, ...</td><td><i>initOnly</i></td></tr>
<tr><td>istty</td><td><i>BOOL</i></td><td>Indicates interp is in interactive mode.</td><td><i>readOnly</i></td></tr>
<tr><td>logColNums</td><td><i>BOOL</i></td><td>Display column numbers in error messages.</td><td><i></i></td></tr>
<tr><td>logAllowDups</td><td><i>BOOL</i></td><td>Log should not filter out duplicate messages.</td><td><i></i></td></tr>
<tr><td>mutexUnlock</td><td><i>BOOL</i></td><td>Unlock own mutex when evaling in other interps (true).</td><td><i>initOnly</i></td></tr>
<tr><td>noproto</td><td><i>BOOL</i></td><td>Disable support of the OOP symbols:  __proto__, prototype, constructor, etc.</td><td><i></i></td></tr>
<tr><td>noReadline</td><td><i>BOOL</i></td><td>In interactive mode disable use of readline.</td><td><i></i></td></tr>
<tr><td>outUndef</td><td><i>BOOL</i></td><td>In interactive mode output result values that are undefined.</td><td><i></i></td></tr>