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

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

Overview
Comment:Release "2.5.18". Cleanup option parse messages. Implement CData checking of function option argument. Various cleanups. Fix bit fields.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f99f5411321f03992c41ee0386c903a569bedde6
User & Date: pmacdona 2018-10-06 23:38:58
Context
2018-10-11
00:59
Release "2.5.19". Fix JSON double format precision. CData changes. check-in: 2630f8db5e user: pmacdona tags: trunk
2018-10-06
23:38
Release "2.5.18". Cleanup option parse messages. Implement CData checking of function option argument. Various cleanups. Fix bit fields. check-in: f99f541132 user: pmacdona tags: trunk
2018-10-05
18:28
Release "2.5.17". Warning is now on for all .jsi files. Remove extraneous "use strict". Fix WebSocket crash bug in client get. Fix bug in parseOpts not setting Trace/Test. Backout rounding in parseInt(). LogDebug etc now all use puts instead of printf semantics. Remove logf and and change LogDebug etc to use log. Vfs add noPatches option disallow mounting patchlevel change versions. Continue conversion to markdeep check-in: 85445ff80d user: pmacdona tags: trunk
Changes

Changes to src/jsi.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
13413
13414
13415
13416
13417
13418
13419

13420
13421
13422
13423
13424
13425
13426
.....
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548
13549

13550
13551



13552
13553
13554
13555
13556
13557
13558
.....
18420
18421
18422
18423
18424
18425
18426

18427

18428

18429
18430
18431
18432
18433
18434
18435
18436
.....
20215
20216
20217
20218
20219
20220
20221
20222
20223
20224
20225
20226
20227
20228
20229
.....
21409
21410
21411
21412
21413
21414
21415
21416
21417
21418
21419
21420
21421
21422
21423
21424
21425
21426
21427
21428


21429
21430
21431
21432
21433
21434



21435
21436
21437
21438
21439
21440
21441
.....
21451
21452
21453
21454
21455
21456
21457






21458
21459
21460
21461
21462

21463












21464
21465
21466
21467
21468
21469
21470
21471

21472
21473
21474
21475
21476
21477
21478
.....
25771
25772
25773
25774
25775
25776
25777
25778
25779
25780
25781
25782
25783
25784
25785
25786
.....
29564
29565
29566
29567
29568
29569
29570
29571
29572
29573
29574
29575
29576
29577
29578


29579
29580
29581
29582
29583
29584



29585

29586
29587


29588
29589

29590
29591
29592
29593
29594
29595
29596
29597
29598
29599
29600
29601
29602


29603
29604
29605
29606
29607
29608
29609
29610
29611
29612
29613
.....
29623
29624
29625
29626
29627
29628
29629



29630
29631
29632
29633
29634
29635
29636
.....
29662
29663
29664
29665
29666
29667
29668


29669
29670
29671
29672
29673
29674
29675
29676
29677
29678
29679
29680
29681
29682
29683
29684
.....
29698
29699
29700
29701
29702
29703
29704
29705
29706
29707
29708



29709
29710
29711
29712
29713
29714
29715
29716
29717
.....
29726
29727
29728
29729
29730
29731
29732
29733
29734
29735
29736
29737
29738
29739
29740
29741
29742
29743
29744
29745

29746
29747
29748
29749
29750
29751
29752
29753
.....
29809
29810
29811
29812
29813
29814
29815
29816
29817
29818
29819
29820
29821
29822
29823
29824
29825
29826
29827
29828
29829
29830
29831
29832
29833
29834
29835
29836
29837
29838
29839
29840
29841
29842
29843
29844
29845
29846
29847
29848
29849
29850
29851
29852
29853
29854
29855
29856
29857
29858
29859
29860
29861
29862
29863
29864
29865
29866
.....
29867
29868
29869
29870
29871
29872
29873

















29874
29875
29876
29877
29878
29879
29880
.....
30281
30282
30283
30284
30285
30286
30287
30288
30289
30290
30291
30292
30293
30294
30295
30296
30297
30298
30299
30300
30301
30302
30303
30304
30305
30306
30307
30308
30309
30310
30311
30312
30313
30314
30315
30316
30317
30318
.....
30340
30341
30342
30343
30344
30345
30346
30347
30348
30349
30350
30351
30352
30353
30354
.....
30834
30835
30836
30837
30838
30839
30840
30841
30842
30843
30844
30845
30846
30847
30848
.....
31092
31093
31094
31095
31096
31097
31098
31099
31100
31101
31102
31103
31104
31105
31106
.....
31107
31108
31109
31110
31111
31112
31113
31114
31115
31116
31117
31118
31119
31120
31121
.....
31123
31124
31125
31126
31127
31128
31129
31130
31131
31132
31133
31134
31135
31136
31137
.....
31142
31143
31144
31145
31146
31147
31148
31149
31150
31151
31152
31153
31154
31155
31156
.....
31168
31169
31170
31171
31172
31173
31174
31175
31176
31177
31178
31179
31180
31181
31182
.....
31185
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
31199
.....
32012
32013
32014
32015
32016
32017
32018
32019
32020
32021
32022
32023
32024
32025
32026
.....
32031
32032
32033
32034
32035
32036
32037
32038
32039
32040
32041
32042
32043
32044
32045
.....
36495
36496
36497
36498
36499
36500
36501
36502
36503
36504
36505
36506
36507
36508
36509
.....
46574
46575
46576
46577
46578
46579
46580

46581
46582
46583
46584
46585
46586
46587
46588
.....
48113
48114
48115
48116
48117
48118
48119
48120
48121
48122
48123
48124
48125
48126
48127
.....
48171
48172
48173
48174
48175
48176
48177
48178
48179
48180
48181
48182
48183
48184
48185
.....
55463
55464
55465
55466
55467
55468
55469


55470
55471
55472
55473
55474
55475
55476
.....
55483
55484
55485
55486
55487
55488
55489
55490
55491
55492
55493
55494
55495
55496
55497
.....
56464
56465
56466
56467
56468
56469
56470
56471
56472
56473
56474
56475
56476
56477
56478
.....
56713
56714
56715
56716
56717
56718
56719
56720
56721
56722
56723
56724
56725
56726
56727
.....
56748
56749
56750
56751
56752
56753
56754
56755
56756
56757
56758
56759
56760
56761
56762
56763
.....
56941
56942
56943
56944
56945
56946
56947
56948


































































































56949







56950
56951
56952
56953
56954
56955
56956
56957
56958
56959
56960
.....
56966
56967
56968
56969
56970
56971
56972

56973
56974

56975
56976
56977
56978
56979
56980
56981
.....
57037
57038
57039
57040
57041
57042
57043


57044
57045
57046
57047
57048
57049
57050
57051
57052
57053
57054
57055
57056
57057
57058
57059
.....
57268
57269
57270
57271
57272
57273
57274
57275
57276
57277



57278
57279
57280
57281
57282
57283
57284
.....
57299
57300
57301
57302
57303
57304
57305





57306
57307
57308










57309
57310
57311
57312
57313
57314
57315
57316
57317
57318
57319



57320
57321
57322
57323
57324
57325
57326
57327
/* 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 17

#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

................................................................................
    bool isMain;
    bool hasCallee;
    bool subthread;
    bool strict;
    bool protoInit;
    bool hasOpenSSL;
    bool isHelp;

    jsi_SubOptions subOpts;
    bool isInteractive;
    const char *confArgs;
    Jsi_Value *stdinStr;
    Jsi_Value *stdoutStr;
    Jsi_TypeCheck typeCheck;
    jsi_LogOptions logOpts;
................................................................................
    Jsi_Obj* cleanObjs[4];

    Jsi_Value *busyCallback;
    int busyInterval;
    int isInCallback;
    int objId;
    Jsi_Value *Top_object;
        Jsi_ScopeStrs *scopes[JSI_MAX_SCOPE];
    int cur_scope;
    int maxArrayList;
    int delRBCnt;
    Jsi_Func *activeFunc;  // Currently active function call.
    Jsi_Func *prevActiveFunc;  // Prev active function call.
    jsi_OpCode *curIp;  /* Used for debug Log msgs. */
    
    char *lastPushStr;  // Used by error handling and Jsi_LogMsg.   TODO: cleanup/rationalize.

    Jsi_Value* lastSubscriptFail;
    const char* lastSubscriptFailStr;




    Jsi_Wide sigmask;
    char errMsgBuf[JSI_BUFSIZ];  /* Error message space for when in try. */
    int errLine;
    int errCol;
    const char *errFile;
    Jsi_Mutex* Mutex;
................................................................................
    /* TODO: when do we free opcodes */
    jsi_PstateClear(ps);
    Jsi_Free(ps->lexer);
    if (ps->opcodes)
        jsi_FreeOpcodes(ps->opcodes);
    if (ps->hPtr)
        Jsi_HashEntryDelete(ps->hPtr);

    Jsi_HashDelete(ps->argsTbl);

    Jsi_HashDelete(ps->strTbl);

    Jsi_HashDelete(ps->fastVarTbl);
    if (ps->last_exception)
        Jsi_DecrRefCount(ps->interp, ps->last_exception);
    _JSI_MEMCLEAR(ps);
    Jsi_Free(ps);
}

#endif
................................................................................
            interp->parent?" ::":"", (interp->parent&&interp->name?interp->name:""));
    }
    if (isMainInt || interp->strKeyTbl != jsiIntData.mainInterp->strKeyTbl)
        Jsi_MapDelete(interp->strKeyTbl);
    if (isMainInt)
        jsiIntData.mainInterp = NULL;

    SIGASSERT(interp,INTERP);
    _JSI_MEMCLEAR(interp);
    jsiIntData.delInterp = NULL;
    Jsi_Free(interp);
    return JSI_OK;
}

void Jsi_InterpDelete(Jsi_Interp* interp)
................................................................................
        else {
            vfprintf(stderr, format, va);
            fputc('\n', stderr);
        }
        va_end(va);
        return JSI_ERROR;
    }
        
    if (code == JSI_LOG_ERROR && (interp->framePtr->tryDepth - interp->framePtr->withDepth)>0 && interp->inParse<=0 
        && (!interp->tryList || !(interp->tryList->inCatch|interp->tryList->inFinal))) { 
        /* Should only do the first or traceback? */
        if (!interp->errMsgBuf[0]) {
            vsnprintf(interp->errMsgBuf, sizeof(interp->errMsgBuf), format, va);
            //interp->errMsgBuf[sizeof(interp->errMsgBuf)-1] = 0;
            interp->errFile = curFile;
            interp->errLine = (interp->curIp?interp->curIp->Line:0);
            emsg = interp->errMsgBuf;
        }
        goto done;
    }


    mt = (code <= JSI_LOG_PARSE ? jsi_LogCodes[code] : "");
    if (isHelp) mt = "help";
    assert((JSI_LOG_PARSE+2) == (sizeof(jsi_LogCodes)/sizeof(jsi_LogCodes[0])));
    if (!Jsi_Strchr(format,'\n')) term = "\n";
    if (code != JSI_LOG_INFO && interp && interp->lastPushStr && interp->lastPushStr[0]) {
        char *ss = interp->lastPushStr;



        char psbuf[JSI_BUFSIZ/6];
        if (Jsi_Strchr(ss,'%')) {
            char *s = ss, *sd = psbuf;
            int plen=0, llen = sizeof(psbuf)-2;
            while (*s && plen<llen) {
                if (*s == '%')
                    sd[plen++] = '%';
................................................................................
            snprintf(pbuf, sizeof(pbuf), "    (at or near \"%s\")\n", ss);
    }
    pbuf[sizeof(pbuf)-1] = 0;
    if (interp->inParse && interp->parseLine) {
        line = interp->parseLine->first_line;
        lofs = interp->parseLine->first_column;
    } else if (interp->curIp) {






        line = interp->curIp->Line;
        lofs = interp->curIp->Lofs;
        if (line<=0)
            line = interp->framePtr->line;
    }

    islog = (interp->parent && interp->debugOpts.msgCallback && code != JSI_LOG_BUG);












    if (interp && curFile && curFile[0] && Jsi_Strchr(curFile,'%')==0 && !islog) {
        if (!interp->subOpts.logColNums)
            snprintf(buf, sizeof(buf), "%s:%d: %s: %s%s%s",  curFile, line, mt,format, pterm, term);
        else
            snprintf(buf, sizeof(buf), "%s:%d.%d: %s: %s%s%s",  curFile, line, lofs, mt,format, pterm, term);
    } else {
        snprintf(buf, sizeof(buf), "%s: %s%s%s", mt, format, pterm, term);
    }

    buf[sizeof(buf)-1]=0;

    if (logHook)
        (*logHook)(buf, va);
    else if (interp->subOpts.logAllowDups)
        vfprintf(stderr, buf, va);
    else {
................................................................................
char *Jsi_Strdup(const char *str) {
    return strdup(str);
}

char *Jsi_StrdupLen(const char *str, int len) {
    if (len<0)
        len = Jsi_Strlen(str);
    char *cp = Jsi_Malloc(len+1);
    cp = memcpy(cp, str, len);
    cp[len] = 0;
    return cp;
}

char *jsi_SubstrDup(const char *a, int start, int len)
{
    if (len == 0) return Jsi_Strdup("");
................................................................................
        return (Jsi_OptionSpec *) NULL;
    }
    return matchPtr;
}


Jsi_RC
jsi_SetOption(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Wide wcount = 0;
    bool bn;
    Jsi_Number nv;
    bool isIncr = (flags & JSI_OPTS_INCR);
    const char *expType = NULL;
    char *record = (char*)rec, *ptr = record + specPtr->offset;


    
    if (specPtr->id<JSI_OPTION_BOOL || specPtr->id>=JSI_OPTION_END) 
        return Jsi_LogError("unknown option id \"%d\" for \"%s\"", specPtr->id, specPtr->name);
    if (specPtr->custom) {
        Jsi_OptionCustom* cust = Jsi_OptionCustomBuiltin(specPtr->custom);
        if (cust && cust->parseProc) {



            if ((*cust->parseProc)(interp, specPtr, argValue, NULL, record, flags) != JSI_OK) {

                if (!interp->csc)
                    Jsi_LogError("failed parse for option \"%s\"", specPtr->name);


                return JSI_ERROR;
            }

        } else 
            return Jsi_LogError("missing or bad custom for \"%s\"", specPtr->name);
        goto done;
    }

    switch (specPtr->id) {
    case JSI_OPTION_CUSTOM:
        if (!specPtr->custom) 
            return Jsi_LogError("missing or custom for \"%s\"", specPtr->name);

    case JSI_OPTION_BOOL: {
        if (!argValue)
            *(char*)ptr = 0;


        else if (Jsi_GetBoolFromValue(interp, argValue, &bn) != JSI_OK)
            return JSI_ERROR;
        else
            *(char*)ptr = bn;
        break;
    }

    case JSI_OPTION_INT:
    case JSI_OPTION_UINT:
    case JSI_OPTION_LONG:
    case JSI_OPTION_INTPTR_T:
................................................................................
    case JSI_OPTION_UINT8:
    case JSI_OPTION_INT16:
    case JSI_OPTION_UINT16:
    case JSI_OPTION_INT32:
    case JSI_OPTION_UINT32:
        wcount = 0;
        if (argValue) {



            if (Jsi_GetWideFromValue(interp, argValue, &wcount) != JSI_OK) {
                return JSI_ERROR;
            }
            
        }
        switch (specPtr->id) {
#define _JSI_OPTSETTYP(typ, n, ptr) if (isIncr) n += *((typ *)ptr); \
................................................................................

    case JSI_OPTION_NUMBER:
    case JSI_OPTION_DOUBLE:
    case JSI_OPTION_LDOUBLE:
    case JSI_OPTION_FLOAT:
        nv = 0;
        if (argValue) {


            if (Jsi_GetNumberFromValue(interp, argValue, &nv) != JSI_OK) {
                return JSI_ERROR;
            }
        }
            
        switch (specPtr->id) {
#define _JSI_OPTSETNTYP(typ, n, ptr) if (!argValue) *(typ*)ptr = 0; else { if (isIncr) n += *((typ *)ptr); \
            interp->cdataIncrVal = *((typ *)ptr) = (typ)(n); \
            if (jsi_IsStrictMode(interp) && !Jsi_NumberIsNaN((Jsi_Number)(*((typ *)ptr)))) return Jsi_LogError("not a number"); }

            case JSI_OPTION_NUMBER: _JSI_OPTSETNTYP(Jsi_Number, nv, ptr); break;
            case JSI_OPTION_LDOUBLE: _JSI_OPTSETNTYP(ldouble, nv, ptr); break;
            case JSI_OPTION_FLOAT: _JSI_OPTSETNTYP(float, nv, ptr); break;
            case JSI_OPTION_DOUBLE: _JSI_OPTSETNTYP(double, nv, ptr); break;
            default: break;
        }
................................................................................
    }
    break;
    case JSI_OPTION_STRBUF:
    {
        if (argValue == NULL || Jsi_ValueIsNull(interp, argValue))
            *(char*)ptr = 0;
        else {
            const char *scp;
            if (Jsi_GetStringFromValue(interp, argValue, &scp) != JSI_OK) {
                return JSI_ERROR;
            }



            Jsi_Strncpy((char*)ptr, scp, specPtr->size);
            ((char*)ptr)[specPtr->size-1] = 0;
        }
    }
    break;
    
#define _JSI_OPT_CHECKNULL(argValue) if (!argValue || Jsi_ValueIsNull(interp, argValue)) { \
         if (*((Jsi_Value **)ptr)) \
            Jsi_DecrRefCount(interp, *((Jsi_Value **)ptr)); \
................................................................................
    }\
    *((Jsi_Value **)ptr) = argValue;
    
    case JSI_OPTION_STRING:
        if (argValue == *((Jsi_Value **)ptr))
            break;
        _JSI_OPT_CHECKNULL(argValue);
        if (!Jsi_ValueIsString(interp, argValue)) 
            return Jsi_LogError("expected a string");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_DSTRING:
        Jsi_DSInit((Jsi_DString *)ptr);
        if (argValue && !Jsi_ValueIsNull(interp, argValue))
        {
            const char *scp;
            if (Jsi_GetStringFromValue(interp, argValue, &scp) != JSI_OK) {
                return JSI_ERROR;
            }

            Jsi_DSAppend((Jsi_DString *)ptr, scp, NULL);
        }
        break;
    
    case JSI_OPTION_TIME_D: {
       if (argValue)
        {
            Jsi_Number nv = 0;
................................................................................
            *(time_t*)ptr = 0;
        }
        break;
    }
    case JSI_OPTION_VAR:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_NULL && argValue->vt != JSI_VT_VARIABLE) 
            return Jsi_LogError("expected a var");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_FUNC:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_FUNCTION) 
            return Jsi_LogError("expected a func value");
        if (specPtr->data && (interp->typeCheck.run|interp->typeCheck.all))
            if (!jsi_FuncArgCheck(interp, argValue->d.obj->d.fobj->func, (char*)specPtr->data)) 
                return Jsi_LogError("failed setting func pointer for %s", specPtr->name);

        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_USEROBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_USEROBJ) 
            return Jsi_LogError("expected a userobj value");
        if (specPtr->data && Jsi_Strcmp((char*)specPtr->data, argValue->d.obj->d.uobj->reg->name)) 
            return Jsi_LogError("expected id %s for %s",(char*)specPtr->data,  specPtr->name);
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_REGEXP:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_REGEXP) 
            return Jsi_LogError("expected a regexp value");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_OBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT) 
            return Jsi_LogError("expected an object");

    case JSI_OPTION_VALUE:
         _JSI_OPT_CHECKNULL(argValue);
         _JSI_OPT_ARGSET(argValue, ptr);
        break;
    case JSI_OPTION_ARRAY:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || !argValue->d.obj->isarrlist) 
            return Jsi_LogError("expected an array");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
#ifdef __cplusplus
    case JSI_OPTION_END:
#else
    default:
#endif
................................................................................
        Jsi_LogBug("invalid option id: %d", specPtr->id);
    }
done:
    specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    if (isIncr)
        return Jsi_LogError("incr invalid for %s", specPtr->name);
    return JSI_OK;

















}

Jsi_RC
Jsi_OptionsSet(Jsi_Interp *interp, Jsi_OptionSpec *specs, void* rec, const char *option, Jsi_Value *valuePtr, Jsi_Wide flags)
{
    char *record = (char*)rec;
    Jsi_OptionSpec *specPtr;
................................................................................
            goto done;
        }
        if (((JSI_OPT_PASS2&flags) && !(JSI_OPT_PASS2&specPtr->flags))
            || ((JSI_OPT_PASS2&specPtr->flags) && !(JSI_OPT_PASS2&flags)))
            continue;
            
        if ((JSI_OPT_READ_ONLY&specPtr->flags)) {
            Jsi_LogWarn("Error option is readonly: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
        if ((JSI_OPTS_IS_UPDATE&flags) && (JSI_OPT_INIT_ONLY&specPtr->flags)) {
            Jsi_LogWarn("Error can not update option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }

        if (jsi_SetOption(interp, specPtr, (char*)arg, record, optval, flags) != JSI_OK) {
            Jsi_LogWarn("Error processing option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
 
        specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    }
    if (reqCnt) {
        for (specPtr = specs; specPtr->id>=JSI_OPTION_BOOL && specPtr->id < JSI_OPTION_END && specPtr->name; specPtr++) {
            if (specPtr->flags &  JSI_OPT_REQUIRED &&
                !(specPtr->flags&JSI_OPT_IS_SPECIFIED)) {

                Jsi_LogWarn("Error required field not specified: \"%.40s\"", specPtr->name);
                count = -1;
            }
        }
    }

done:
    Jsi_TreeSearchDone(&search);
................................................................................
        Jsi_Value *svalue = Jsi_ValueMakeObject(interp, NULL, sobj);
        jsi_DumpOptionSpecs(interp, sobj, specs);
        Jsi_ValueReplace(interp, ret, svalue);
        return JSI_OK;
    }
    if (val->vt != JSI_VT_OBJECT) 
        return Jsi_LogError("expected string, object, or null");
    if (Jsi_OptionsProcess(interp, specs, rec, val, JSI_OPTS_IS_UPDATE) < 0)
        return JSI_ERROR;
    return JSI_OK;
}

static const char **jsi_OptGetEnumList(Jsi_OptionSpec* spec) {
    const char **list = (const char**)spec->data;
    Jsi_OptionSpec* es=NULL;
................................................................................
            for (i=0; i<n && list[i]; i++) ; /* Look forward til n */
        if (list[i])
            Jsi_DSAppendLen(outStr, list[i], -1);
        else if ((spec->flags&JSI_OPT_COERCE)) {
            Jsi_DSPrintf(outStr, "%" PRIu64, (uint64_t)n);
            return JSI_OK;
        } else
            return Jsi_LogWarn("enum has unknown value: %d", *s);
        return JSI_OK;
    }
#ifndef JSI_LITE_ONLY
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
    Jsi_RC rc = jsi_EnumToValue(interp, spec, NULL, &dStr, record, flags);
    if (rc == JSI_OK)
................................................................................
    if (!interp->parent) return;
    if (*v)
        Jsi_DecrRefCount(interp->parent, *v);
    *v = NULL;
}

static Jsi_OptionCustom jsi_OptSwitchParentFunc = {
    .name="suboption", .parseProc=jsi_ValueToParentFunc, .formatProc=jsi_ParentFuncToValue, .freeProc=jsi_ParentFuncFree,
};

/* Scanning function */
static Jsi_RC jsi_ValueToBitfield(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue,
    const char *inStr, void *record, Jsi_Wide flags)
{
    Jsi_csgset *bsget = spec->init.OPT_BITS;
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    Jsi_Number num;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogError("invalid bitfield");
    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = {};
        Jsi_OptionSpec eSpec[] = {
            JSI_OPT(CUSTOM, typeof(nval), numVal, .help=spec->help, .flags=JSI_OPT_ENUM_SPEC,
                .custom=Jsi_Opt_SwitchEnum, .data=(void*)enumSpec, .info=0, .tname=spec->tname, .value=0, .bits=0, .boffset=8*sizeof(int64_t) ),
            JSI_OPT_END(typeof(nval))
        };
................................................................................
            return JSI_ERROR;
        num = (Jsi_Number)nval.numVal;
    } else if (inStr) {
        if (Jsi_GetDouble(interp, inStr, &num) != JSI_OK)
            return JSI_ERROR;
    } else {
        if (inValue && !Jsi_ValueIsNumber(interp, inValue)) 
            return Jsi_LogError("expected number");
        Jsi_ValueGetNumber(interp, inValue, &num);
    }
    int64_t inum = (int64_t)num;
    return (*bsget)(interp, data, &inum, spec, idx, 1);
}

/* Printing function. */
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    int64_t inum;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogError("invalid bitfield");
    Jsi_RC rc = (*bsget)(interp, data, &inum, spec, idx, 0);
    if (rc != JSI_OK)
        return JSI_ERROR;

    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = { inum };
        Jsi_OptionSpec eSpec[] = {
................................................................................
        Jsi_Number num = (Jsi_Number)inum;
        Jsi_ValueMakeNumber(interp, outValue, num);
    }
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchBitfield = {
    .name="suboption", .parseProc=jsi_ValueToBitfield, .formatProc=jsi_BitfieldToValue
};

/* Scanning function */
static Jsi_RC jsi_ValueToNull(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue, const char *inStr, void *record, Jsi_Wide flags)
{
    return JSI_OK;
}
................................................................................
static Jsi_RC jsi_NullToValue(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value **outValue, Jsi_DString *outStr, void *record, Jsi_Wide flags)
{
    Jsi_ValueMakeNull(interp, outValue);
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchNull = {
    .name="suboption", .parseProc=jsi_ValueToNull, .formatProc=jsi_NullToValue
};

#endif

typedef struct {
    Jsi_OptionInitVal init;
} jsi_IniValStruct;
................................................................................
    if (tok->size%2 || tok->type != JSI_JTYPE_OBJECT) {
        result = -1;
        goto done;
    }
    v = Jsi_ValueNew1(interp);
    for (i=1; i<p->toknext && i<tok->size; i++) {
        if (p->tokens[i].type != JSI_JTYPE_STRING) {
            Jsi_LogWarn("expected string at %d", i-1);
            goto bail;
        }
        name = Jsi_JsonGetTokstr(p, json, i, &len);
        Jsi_DSSetLength(&nStr, 0);
        Jsi_DSAppendLen(&nStr, name, len);
        name = Jsi_DSValue(&nStr);
        i++;
................................................................................
                    Jsi_ValueMakeBool(interp, &v, (bool)(len==4?1:0));
                } else if (len == 4 && Jsi_Strncmp(t, "null", len)==0) {
                    Jsi_ValueMakeNull(interp, &v);
                } else {
                    char *ep;
                    Jsi_Number d = strtod(t,&ep);
                    if (ep>(t+len)) {
                        Jsi_LogWarn("bad number %*s", len, t);
                        goto bail;
                    }
                    Jsi_ValueMakeNumber(interp, &v, d);
                }
                break;
            case JSI_JTYPE_STRING:
                t = Jsi_JsonGetTokstr(p, json, i, &len);
................................................................................
#ifndef JSI_OMIT_LOAD
    { "load",       jsi_LoadLoadCmd, 1,  1, "shlib:string", .help="Load a shared executable and invoke its _Init call", .retType=(uint)JSI_TT_VOID },
#endif
    { "log",        SysLogCmd,       1, -1, "val, ...", .help="Same as puts, but includes file:line", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "noOp",       jsi_NoOpCmd,     0, -1, "", .help="A No-Op. A zero overhead command call that is useful for debugging" },
    { "parseInt",   parseIntCmd,     1,  2, "val:any, base:number=10", .help="Convert string to an integer", .retType=(uint)JSI_TT_NUMBER },
    { "parseFloat", parseFloatCmd,   1,  1, "val", .help="Convert string to a double", .retType=(uint)JSI_TT_NUMBER },
    { "parseOpts",  SysParseOptsCmd, 2,  3, "self:object, options:object, conf:object|null|undefined", .help="Parse options", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "printf",     SysPrintfCmd,    1, -1, "format:string, ...", .help="Formatted output to stdout", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "provide",    SysProvideCmd,   0,  2, "name:string|function=void, version:number|string=1.0", .help="Provide a package for use with require. Default is the file tail-rootname", .retType=(uint)JSI_TT_VOID },
    { "puts",       SysPutsCmd,      1, -1, "val, ...", .help="Output one or more values to stdout", .retType=(uint)JSI_TT_VOID, .flags=0, .info=FN_puts },
    { "quote",      SysQuoteCmd,     1,  1, "val:string", .help="Return quoted string", .retType=(uint)JSI_TT_STRING },
    { "require",    SysRequireCmd,   0,  2, "name:string=void, version:number|string=1", .help="Load/query packages", .retType=(uint)JSI_TT_NUMBER|JSI_TT_OBJECT|JSI_TT_ARRAY, .flags=0, .info=FN_require },
    { "runModule",  SysRunModuleCmd, 0,  2, "cmd:string|function=void, conf:array=undefined", .help="Invoke named module. If name is empty, uses file basename. If isMain and no args givine parses console.args", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "sleep",      SysSleepCmd,     0,  1, "secs:number=1.0",  .help="sleep for N milliseconds, minimum .001", .retType=(uint)JSI_TT_VOID },
................................................................................
//  Jsi_Interp *interp = p->jdb->interp;

    if( p->pPreStmt ) {
        sqlite3_reset(p->pPreStmt->pStmt);
        dbReleaseStmt(p->jdb, p->pPreStmt, p->nocache);
        p->pPreStmt = 0;
    }

    Jsi_DSFree(p->dSql);
    dbReleaseColumnNames(p);
}

static void DbClose(sqlite3 *db) {
        sqlite3_close(db);
}

................................................................................
#endif
    const char *zSql = Jsi_ValueGetDString(interp, vSql, &eStr, 0);
    Jsi_Value *arg = Jsi_ValueArrayIndex(interp, args, 1);
    int cnt = 0;
    char **apColName = NULL;
    int *apColType = NULL, isopts = 0;
    DbEvalContext sEval = {};
    QueryOpts opts, *oEopt = NULL;
    opts = jdb->queryOpts;
    opts.callback = NULL;
    opts.width = NULL;
    Jsi_Value *callback = NULL, *width = NULL;
            
    if (jdb->echo && zSql)
        Jsi_LogInfo("SQL-QUERY: %s\n", zSql); 
................................................................................
    }
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    sEval.nocache = opts.nocache;
    if ((rc = dbEvalInit(interp, &sEval, jdb, zSql, &sStr, 0, 0)) != JSI_OK)
        goto bail;
    sEval.ret = *ret;
    oEopt = jdb->optPtr;
    jdb->optPtr = &opts;
    if (callback) {
        sEval.tocall = callback;
        if (opts.mode != _JSI_EF_ROWS) {
            Jsi_LogError("'mode' must be 'rows' with 'callback'");
            rc = JSI_ERROR;
            goto bail;
................................................................................
            sf->type = Jsi_TypeLookup(interp, sf->tname);
        int isbitset = ((sf->flags&JSI_OPT_BITSET_ENUM)!=0);
        if (sf->type && sf->type->extData && (sf->type->flags&(jsi_CTYP_ENUM|jsi_CTYP_STRUCT))) {
            // A struct sub-field or a bit field mapped to an ENUM.
            Jsi_OptionSpec *es = (typeof(es))sf->type->extData;
            es->value++;
            if ((sf->type->flags&jsi_CTYP_ENUM)) {


                sf->custom = (isbitset ? Jsi_Opt_SwitchBitset : Jsi_Opt_SwitchEnum);
                sf->data = (void*)es->data;
                sf->id = JSI_OPTION_CUSTOM;
            }
            else if (sf->type->flags & jsi_CTYP_STRUCT) {
                sf->custom = Jsi_Opt_SwitchSuboption;
                sf->data = es->extData;
................................................................................
            sf->tname = sf->type->cName;
            sf->size = (isbitset?(int)sizeof(int):sf->type->size);
            if (sf->arrSize)
                sf->size *= sf->arrSize;
            sf->idx = cnt;
            sf->boffset = boffset;
            if (sf->bits) {
                if (sf->bits>64)
                    return Jsi_LogError("bits too large");
                boffset += sf->bits;
                sf->id = JSI_OPTION_CUSTOM;
                sf->custom=Jsi_Opt_SwitchBitfield;
                sf->init.OPT_BITS=&jsi_csBitGetSet;
            } else {
                sf->offset = (boffset+7)/8;
................................................................................
    if (argc>200)
        return Jsi_LogError("too many fields: %d>200", argc);
    Jsi_StructSpec *sl, *sf, recs[argc+2];
    memset(recs, 0, sizeof(recs));
    sl = recs+argc+1;
    sf = recs;
    SIGINIT(sl, OPTS_STRUCT);
        if (vstr) {
        sl->name = Jsi_KeyAdd(interp, vstr);
    } else if (Jsi_OptionsProcess(interp, StructOptions, sl, val, 0) < 0) {
        rc = JSI_ERROR;
        goto bail;
    }
    if (!jsi_IsAlnumStr(sl->name)) {
        rc = Jsi_LogError("invalid struct name: %s", sl->name);
................................................................................
                             Jsi_Value **ret, Jsi_Func *funcPtr)
{
    UdcGet(cd, _this, funcPtr);
    uchar *dptr = NULL;
    Jsi_Value *karg = Jsi_ValueArrayIndex(interp, args, 0);
    char kbuf[BUFSIZ];
    void *key = kbuf;
    bool isNull = Jsi_ValueIsNull(interp, karg);
    if (isNull) {
        if (cd->mapPtr || cd->arrSize>1)
            return Jsi_LogError("null key used with c-array/map");
    } else {
        if (!cd->mapPtr && cd->arrSize<=0)
            return Jsi_LogError("must be array/map");
        if (JSI_OK != jsi_csGetKey(interp, cd, karg, &key, sizeof(kbuf), 1))
................................................................................
            dptr = ((uchar*)cd->data) + sizeof(void*)*kind;
        else if (cd->isPtr2) {
            dptr = (uchar*)(*(void**)dptr);
            dptr += sizeof(void*)*kind;
        }
    }
    int argc = Jsi_ValueGetLength(interp, args);
    if (argc != 2 && argc != 1)
        return Jsi_LogError("expected 1 or 2 args");
    Jsi_Value *arg2 = Jsi_ValueArrayIndex(interp, args, 1);
    return Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, dptr, arg2, ret, 0);
}

#define FN_dataSet JSI_INFO("Sets data value for given a name argument.")
static Jsi_RC CDataSetCmd_(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
                             Jsi_Value **ret, Jsi_Func *funcPtr, int op)
................................................................................
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}



































































































static Jsi_RC jsi_csBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {







    Jsi_UWide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef unsigned __int128 utvalType;
#else
................................................................................
    Jsi_UWide mval;
    Jsi_UWide amask = ((1LL<<(bits-1))-1LL);
    utvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;

        mval = (Jsi_UWide)tval;
        *(Jsi_UWide*)bptr = mval;

    } else
         mval = *valPtr;
        
    if (!isSet) { // Get value.
        if (!jsi_csBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
................................................................................
    }
    Jsi_Free(dptr);
    Jsi_MapEntryDelete(mPtr);
    return JSI_OK;

}



static Jsi_RC CDataConstructor(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr);
    
/* Defines: Handles the "Data" subcommand */
static Jsi_CmdSpec cdataCmds[] =
{
    {"CData",     CDataConstructor,1, 1, "options:string|object=void",.help="Create a new struct or map/array of structs", .retType=(uint)JSI_TT_USEROBJ, .flags=JSI_CMD_IS_CONSTRUCTOR, .info=0, .opts=CDataOptions},
    {"conf",      CDataConfCmd,    0, 1, "options:object|string=void",.help="Configure options for c-data", .retType=0, .flags=0, .info=0, .opts=CDataOptions},
    {"get"   ,    CDataGetCmd,     1, 2, "key:string|number|object|null, field:string=void", .help="Get struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"incr",      CDataIncrCmd,    3, 3, "key:string|number|object|null, field:object|string, value:number", .help="Increment a numeric field: returns the new value", .retType=(uint)JSI_TT_NUMBER},
    {"info",      CDataInfoCmd,    0, 0, "", .help="Return info for data", .retType=(uint)JSI_TT_OBJECT},
    {"names",     CDataNamesCmd,   0, 0, "", .help="Return keys for map", .retType=(uint)JSI_TT_ARRAY },
    {"set",       CDataSetCmd,     2, 3, "key:string|number|object|null, field:object|string, value:any=void", .help="Set a struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"unset",     CDataUnsetCmd,   1, 1, "key:string|number|object", .help="Remove entry from map/array", .retType=(uint)JSI_TT_ANY},
    {NULL}
};
................................................................................
        that = *ret;
    }

    CDataObj *cd = (typeof(cd))Jsi_Calloc(1,sizeof(*cd));
    cd->interp = interp;
    Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
    Jsi_vtype vtyp = Jsi_ValueTypeGet(val);
    int vlen;
    const char *vstr = Jsi_ValueString(interp, val, &vlen);
    Jsi_DString dStr = {};



    if (vstr && vlen) {
        char ech = 0;
        const char *nstr = vstr, *cp = vstr;
        while (*cp && (isalnum(*cp) || *cp=='_')) cp++;
        if (*cp) {
            int slen = cp-vstr;
            Jsi_DString sStr = {};
................................................................................
    } else if (vtyp != JSI_VT_OBJECT) {
        Jsi_LogError("expected string, object");
        goto errout;
    }
    if (val && Jsi_OptionsProcess(interp, CDataOptions, cd, val, 0) < 0)
        goto errout;






    if (JSI_OK != jsi_csNewCData(interp, cd, JSI_OPT_NO_SIG))
        goto errout;











    nobj = (Jsi_Obj*)Jsi_ValueGetObj(interp, that);
    cd->objId = Jsi_UserObjNew(interp, &cdataobject, nobj, cd);
    if (cd->objId<0) {
        goto errout;
    }
    cd->fobj = nobj;
    return JSI_OK;
    
errout:
    Jsi_DSFree(&dStr);
    Jsi_OptionsFree(interp, CDataOptions, cd, 0);



    Jsi_Free(cd);
    return JSI_ERROR;

}

// Globals

static Jsi_RC jsi_DoneCData(Jsi_Interp *interp)






|







 







>







 







|








>


>
>
>







 







>
|
>
|
>
|







 







<







 







<












>
>




<
|
>
>
>







 







>
>
>
>
>
>
|
|
|
|
|
>

>
>
>
>
>
>
>
>
>
>
>
>


|

|

|

>







 







|
|







 







|







>
>
|

|
|
|

>
>
>
|
>
|
<
>
>


>

|






|




>
>
|
<
<
|







 







>
>
>







 







>
>








|







 







|
|
|
<
>
>
>
|
|







 







|
|







|
|
|
<
>
|







 







|






|










|







|
|





|
|







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|




|





<











|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







>
|







 







|







 







<







 







>
>







 







|







 







|







 







|







 







|
|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>



|







 







>
|
|
>







 







>
>






|

|







 







|


>
>
>







 







>
>
>
>
>



>
>
>
>
>
>
>
>
>
>











>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
.....
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
.....
18425
18426
18427
18428
18429
18430
18431
18432
18433
18434
18435
18436
18437
18438
18439
18440
18441
18442
18443
18444
.....
20223
20224
20225
20226
20227
20228
20229

20230
20231
20232
20233
20234
20235
20236
.....
21416
21417
21418
21419
21420
21421
21422

21423
21424
21425
21426
21427
21428
21429
21430
21431
21432
21433
21434
21435
21436
21437
21438
21439
21440

21441
21442
21443
21444
21445
21446
21447
21448
21449
21450
21451
.....
21461
21462
21463
21464
21465
21466
21467
21468
21469
21470
21471
21472
21473
21474
21475
21476
21477
21478
21479
21480
21481
21482
21483
21484
21485
21486
21487
21488
21489
21490
21491
21492
21493
21494
21495
21496
21497
21498
21499
21500
21501
21502
21503
21504
21505
21506
21507
21508
.....
25801
25802
25803
25804
25805
25806
25807
25808
25809
25810
25811
25812
25813
25814
25815
25816
.....
29594
29595
29596
29597
29598
29599
29600
29601
29602
29603
29604
29605
29606
29607
29608
29609
29610
29611
29612
29613
29614
29615
29616
29617
29618
29619
29620
29621
29622

29623
29624
29625
29626
29627
29628
29629
29630
29631
29632
29633
29634
29635
29636
29637
29638
29639
29640
29641
29642
29643


29644
29645
29646
29647
29648
29649
29650
29651
.....
29661
29662
29663
29664
29665
29666
29667
29668
29669
29670
29671
29672
29673
29674
29675
29676
29677
.....
29703
29704
29705
29706
29707
29708
29709
29710
29711
29712
29713
29714
29715
29716
29717
29718
29719
29720
29721
29722
29723
29724
29725
29726
29727
.....
29741
29742
29743
29744
29745
29746
29747
29748
29749
29750

29751
29752
29753
29754
29755
29756
29757
29758
29759
29760
29761
29762
.....
29771
29772
29773
29774
29775
29776
29777
29778
29779
29780
29781
29782
29783
29784
29785
29786
29787
29788
29789

29790
29791
29792
29793
29794
29795
29796
29797
29798
.....
29854
29855
29856
29857
29858
29859
29860
29861
29862
29863
29864
29865
29866
29867
29868
29869
29870
29871
29872
29873
29874
29875
29876
29877
29878
29879
29880
29881
29882
29883
29884
29885
29886
29887
29888
29889
29890
29891
29892
29893
29894
29895
29896
29897
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908
29909
29910
29911
.....
29912
29913
29914
29915
29916
29917
29918
29919
29920
29921
29922
29923
29924
29925
29926
29927
29928
29929
29930
29931
29932
29933
29934
29935
29936
29937
29938
29939
29940
29941
29942
.....
30343
30344
30345
30346
30347
30348
30349
30350
30351
30352
30353
30354
30355
30356
30357
30358
30359
30360

30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379
.....
30401
30402
30403
30404
30405
30406
30407
30408
30409
30410
30411
30412
30413
30414
30415
.....
30895
30896
30897
30898
30899
30900
30901
30902
30903
30904
30905
30906
30907
30908
30909
.....
31153
31154
31155
31156
31157
31158
31159
31160
31161
31162
31163
31164
31165
31166
31167
.....
31168
31169
31170
31171
31172
31173
31174
31175
31176
31177
31178
31179
31180
31181
31182
.....
31184
31185
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
.....
31203
31204
31205
31206
31207
31208
31209
31210
31211
31212
31213
31214
31215
31216
31217
.....
31229
31230
31231
31232
31233
31234
31235
31236
31237
31238
31239
31240
31241
31242
31243
.....
31246
31247
31248
31249
31250
31251
31252
31253
31254
31255
31256
31257
31258
31259
31260
.....
32073
32074
32075
32076
32077
32078
32079
32080
32081
32082
32083
32084
32085
32086
32087
.....
32092
32093
32094
32095
32096
32097
32098
32099
32100
32101
32102
32103
32104
32105
32106
.....
36556
36557
36558
36559
36560
36561
36562
36563
36564
36565
36566
36567
36568
36569
36570
.....
46635
46636
46637
46638
46639
46640
46641
46642
46643
46644
46645
46646
46647
46648
46649
46650
.....
48175
48176
48177
48178
48179
48180
48181
48182
48183
48184
48185
48186
48187
48188
48189
.....
48233
48234
48235
48236
48237
48238
48239

48240
48241
48242
48243
48244
48245
48246
.....
55524
55525
55526
55527
55528
55529
55530
55531
55532
55533
55534
55535
55536
55537
55538
55539
.....
55546
55547
55548
55549
55550
55551
55552
55553
55554
55555
55556
55557
55558
55559
55560
.....
56527
56528
56529
56530
56531
56532
56533
56534
56535
56536
56537
56538
56539
56540
56541
.....
56776
56777
56778
56779
56780
56781
56782
56783
56784
56785
56786
56787
56788
56789
56790
.....
56811
56812
56813
56814
56815
56816
56817
56818
56819
56820
56821
56822
56823
56824
56825
56826
.....
57004
57005
57006
57007
57008
57009
57010
57011
57012
57013
57014
57015
57016
57017
57018
57019
57020
57021
57022
57023
57024
57025
57026
57027
57028
57029
57030
57031
57032
57033
57034
57035
57036
57037
57038
57039
57040
57041
57042
57043
57044
57045
57046
57047
57048
57049
57050
57051
57052
57053
57054
57055
57056
57057
57058
57059
57060
57061
57062
57063
57064
57065
57066
57067
57068
57069
57070
57071
57072
57073
57074
57075
57076
57077
57078
57079
57080
57081
57082
57083
57084
57085
57086
57087
57088
57089
57090
57091
57092
57093
57094
57095
57096
57097
57098
57099
57100
57101
57102
57103
57104
57105
57106
57107
57108
57109
57110
57111
57112
57113
57114
57115
57116
57117
57118
57119
57120
57121
57122
57123
57124
57125
57126
57127
57128
.....
57134
57135
57136
57137
57138
57139
57140
57141
57142
57143
57144
57145
57146
57147
57148
57149
57150
57151
.....
57207
57208
57209
57210
57211
57212
57213
57214
57215
57216
57217
57218
57219
57220
57221
57222
57223
57224
57225
57226
57227
57228
57229
57230
57231
.....
57440
57441
57442
57443
57444
57445
57446
57447
57448
57449
57450
57451
57452
57453
57454
57455
57456
57457
57458
57459
.....
57474
57475
57476
57477
57478
57479
57480
57481
57482
57483
57484
57485
57486
57487
57488
57489
57490
57491
57492
57493
57494
57495
57496
57497
57498
57499
57500
57501
57502
57503
57504
57505
57506
57507
57508
57509
57510
57511
57512
57513
57514
57515
57516
57517
57518
57519
57520
/* 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 18

#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

................................................................................
    bool isMain;
    bool hasCallee;
    bool subthread;
    bool strict;
    bool protoInit;
    bool hasOpenSSL;
    bool isHelp;
    bool callerErr;
    jsi_SubOptions subOpts;
    bool isInteractive;
    const char *confArgs;
    Jsi_Value *stdinStr;
    Jsi_Value *stdoutStr;
    Jsi_TypeCheck typeCheck;
    jsi_LogOptions logOpts;
................................................................................
    Jsi_Obj* cleanObjs[4];

    Jsi_Value *busyCallback;
    int busyInterval;
    int isInCallback;
    int objId;
    Jsi_Value *Top_object;
    Jsi_ScopeStrs *scopes[JSI_MAX_SCOPE];
    int cur_scope;
    int maxArrayList;
    int delRBCnt;
    Jsi_Func *activeFunc;  // Currently active function call.
    Jsi_Func *prevActiveFunc;  // Prev active function call.
    jsi_OpCode *curIp;  /* Used for debug Log msgs. */
    
    char *lastPushStr;  // Used by error handling and Jsi_LogMsg.   TODO: cleanup/rationalize.
    Jsi_Value* lastParseOpt;
    Jsi_Value* lastSubscriptFail;
    const char* lastSubscriptFailStr;
    int logErrorCnt;
    Jsi_OptionSpec *parseMsgSpec;


    Jsi_Wide sigmask;
    char errMsgBuf[JSI_BUFSIZ];  /* Error message space for when in try. */
    int errLine;
    int errCol;
    const char *errFile;
    Jsi_Mutex* Mutex;
................................................................................
    /* TODO: when do we free opcodes */
    jsi_PstateClear(ps);
    Jsi_Free(ps->lexer);
    if (ps->opcodes)
        jsi_FreeOpcodes(ps->opcodes);
    if (ps->hPtr)
        Jsi_HashEntryDelete(ps->hPtr);
    if (ps->argsTbl)
        Jsi_HashDelete(ps->argsTbl);
    if (ps->strTbl)
        Jsi_HashDelete(ps->strTbl);
    if (ps->fastVarTbl)
        Jsi_HashDelete(ps->fastVarTbl);
    if (ps->last_exception)
        Jsi_DecrRefCount(ps->interp, ps->last_exception);
    _JSI_MEMCLEAR(ps);
    Jsi_Free(ps);
}

#endif
................................................................................
            interp->parent?" ::":"", (interp->parent&&interp->name?interp->name:""));
    }
    if (isMainInt || interp->strKeyTbl != jsiIntData.mainInterp->strKeyTbl)
        Jsi_MapDelete(interp->strKeyTbl);
    if (isMainInt)
        jsiIntData.mainInterp = NULL;


    _JSI_MEMCLEAR(interp);
    jsiIntData.delInterp = NULL;
    Jsi_Free(interp);
    return JSI_OK;
}

void Jsi_InterpDelete(Jsi_Interp* interp)
................................................................................
        else {
            vfprintf(stderr, format, va);
            fputc('\n', stderr);
        }
        va_end(va);
        return JSI_ERROR;
    }

    if (code == JSI_LOG_ERROR && (interp->framePtr->tryDepth - interp->framePtr->withDepth)>0 && interp->inParse<=0 
        && (!interp->tryList || !(interp->tryList->inCatch|interp->tryList->inFinal))) { 
        /* Should only do the first or traceback? */
        if (!interp->errMsgBuf[0]) {
            vsnprintf(interp->errMsgBuf, sizeof(interp->errMsgBuf), format, va);
            //interp->errMsgBuf[sizeof(interp->errMsgBuf)-1] = 0;
            interp->errFile = curFile;
            interp->errLine = (interp->curIp?interp->curIp->Line:0);
            emsg = interp->errMsgBuf;
        }
        goto done;
    }
    if (code == JSI_LOG_ERROR)
        interp->logErrorCnt++;
    mt = (code <= JSI_LOG_PARSE ? jsi_LogCodes[code] : "");
    if (isHelp) mt = "help";
    assert((JSI_LOG_PARSE+2) == (sizeof(jsi_LogCodes)/sizeof(jsi_LogCodes[0])));
    if (!Jsi_Strchr(format,'\n')) term = "\n";

    char *ss = interp->lastPushStr;
    if (jsi_IsStrictMode(interp) && interp->lastParseOpt)
        ss = (char*)Jsi_ValueToString(interp, interp->lastParseOpt, NULL);
    if (code != JSI_LOG_INFO && interp && ss && ss[0]) {
        char psbuf[JSI_BUFSIZ/6];
        if (Jsi_Strchr(ss,'%')) {
            char *s = ss, *sd = psbuf;
            int plen=0, llen = sizeof(psbuf)-2;
            while (*s && plen<llen) {
                if (*s == '%')
                    sd[plen++] = '%';
................................................................................
            snprintf(pbuf, sizeof(pbuf), "    (at or near \"%s\")\n", ss);
    }
    pbuf[sizeof(pbuf)-1] = 0;
    if (interp->inParse && interp->parseLine) {
        line = interp->parseLine->first_line;
        lofs = interp->parseLine->first_column;
    } else if (interp->curIp) {
        if (interp->callerErr && interp->framePtr && interp->framePtr->parent) {
            jsi_Frame *fptr = interp->framePtr->parent;
            line = fptr->line;
            lofs = 0;
            curFile = fptr->fileName;
        } else {
            line = interp->curIp->Line;
            lofs = interp->curIp->Lofs;
            if (line<=0)
                line = interp->framePtr->line;
        }
    }
    islog = (interp->parent && interp->debugOpts.msgCallback && code != JSI_LOG_BUG);
    Jsi_OptionSpec *oep = interp->parseMsgSpec;
    const char *pps = "";
    Jsi_DString pStr;
    Jsi_DSInit(&pStr);
    if (oep) {
        if (oep->id != JSI_OPTION_CUSTOM || !oep->custom)
            pps = Jsi_DSPrintf(&pStr, "for option \"%s\": ", oep->name);
        else {
            Jsi_OptionCustom* cust = Jsi_OptionCustomBuiltin(oep->custom);
            pps = Jsi_DSPrintf(&pStr, "for %s option \"%s\": ", (cust?cust->name:""), oep->name);
        }
    }
    if (interp && curFile && curFile[0] && Jsi_Strchr(curFile,'%')==0 && !islog) {
        if (!interp->subOpts.logColNums)
            snprintf(buf, sizeof(buf), "%s:%d: %s: %s%s%s%s",  curFile, line, mt, pps, format, pterm, term);
        else
            snprintf(buf, sizeof(buf), "%s:%d.%d: %s: %s%s%s%s",  curFile, line, lofs, pps, mt,format, pterm, term);
    } else {
        snprintf(buf, sizeof(buf), "%s: %s%s%s%s", mt, pps, format, pterm, term);
    }
    Jsi_DSFree(&pStr);
    buf[sizeof(buf)-1]=0;

    if (logHook)
        (*logHook)(buf, va);
    else if (interp->subOpts.logAllowDups)
        vfprintf(stderr, buf, va);
    else {
................................................................................
char *Jsi_Strdup(const char *str) {
    return strdup(str);
}

char *Jsi_StrdupLen(const char *str, int len) {
    if (len<0)
        len = Jsi_Strlen(str);
    char *cp = (char*)Jsi_Malloc(len+1);
    memcpy(cp, str, len);
    cp[len] = 0;
    return cp;
}

char *jsi_SubstrDup(const char *a, int start, int len)
{
    if (len == 0) return Jsi_Strdup("");
................................................................................
        return (Jsi_OptionSpec *) NULL;
    }
    return matchPtr;
}


Jsi_RC
jsi_SetOption_(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Wide wcount = 0;
    bool bn;
    Jsi_Number nv;
    bool isIncr = (flags & JSI_OPTS_INCR);
    const char *expType = NULL;
    char *record = (char*)rec, *ptr = record + specPtr->offset;
    Jsi_OptionCustom* cust = NULL;
    const char *emsg = NULL, *epre = "";

    if (specPtr->id<JSI_OPTION_BOOL || specPtr->id>=JSI_OPTION_END) 
        return Jsi_LogBug("unknown option id \"%d\" for \"%s\"", specPtr->id, specPtr->name);
    if (specPtr->custom  && specPtr->id == JSI_OPTION_CUSTOM) {
        cust = Jsi_OptionCustomBuiltin(specPtr->custom);
        if (cust && cust->parseProc) {
            int lastErrCnt = interp->logErrorCnt;
            Jsi_OptionSpec *oep = interp->parseMsgSpec;
            interp->parseMsgSpec = specPtr;
            Jsi_RC rc = (*cust->parseProc)(interp, specPtr, argValue, NULL, record, flags);
            if (rc != JSI_OK) {
                if (!interp->csc || lastErrCnt == interp->logErrorCnt)

                    Jsi_LogError("invalid value");
                interp->parseMsgSpec = oep;
                return JSI_ERROR;
            }
            interp->parseMsgSpec = oep;
        } else 
            return Jsi_LogBug("missing or bad custom for \"%s\"", specPtr->name);
        goto done;
    }

    switch (specPtr->id) {
    case JSI_OPTION_CUSTOM:
        if (!specPtr->custom) 
            return Jsi_LogBug("missing or custom for \"%s\"", specPtr->name);

    case JSI_OPTION_BOOL: {
        if (!argValue)
            *(char*)ptr = 0;
        else if (!Jsi_ValueIsBoolean(interp, argValue))
            goto bail;
        Jsi_GetBoolFromValue(interp, argValue, &bn);


        *(char*)ptr = bn;
        break;
    }

    case JSI_OPTION_INT:
    case JSI_OPTION_UINT:
    case JSI_OPTION_LONG:
    case JSI_OPTION_INTPTR_T:
................................................................................
    case JSI_OPTION_UINT8:
    case JSI_OPTION_INT16:
    case JSI_OPTION_UINT16:
    case JSI_OPTION_INT32:
    case JSI_OPTION_UINT32:
        wcount = 0;
        if (argValue) {
            if (!Jsi_ValueIsNumber(interp, argValue))
                goto bail;

            if (Jsi_GetWideFromValue(interp, argValue, &wcount) != JSI_OK) {
                return JSI_ERROR;
            }
            
        }
        switch (specPtr->id) {
#define _JSI_OPTSETTYP(typ, n, ptr) if (isIncr) n += *((typ *)ptr); \
................................................................................

    case JSI_OPTION_NUMBER:
    case JSI_OPTION_DOUBLE:
    case JSI_OPTION_LDOUBLE:
    case JSI_OPTION_FLOAT:
        nv = 0;
        if (argValue) {
            if (!Jsi_ValueIsNumber(interp, argValue))
                goto bail;
            if (Jsi_GetNumberFromValue(interp, argValue, &nv) != JSI_OK) {
                return JSI_ERROR;
            }
        }
            
        switch (specPtr->id) {
#define _JSI_OPTSETNTYP(typ, n, ptr) if (!argValue) *(typ*)ptr = 0; else { if (isIncr) n += *((typ *)ptr); \
            interp->cdataIncrVal = *((typ *)ptr) = (typ)(n); \
            if (jsi_IsStrictMode(interp) && Jsi_NumberIsNaN((Jsi_Number)(*((typ *)ptr)))) return Jsi_LogError("not a number"); }

            case JSI_OPTION_NUMBER: _JSI_OPTSETNTYP(Jsi_Number, nv, ptr); break;
            case JSI_OPTION_LDOUBLE: _JSI_OPTSETNTYP(ldouble, nv, ptr); break;
            case JSI_OPTION_FLOAT: _JSI_OPTSETNTYP(float, nv, ptr); break;
            case JSI_OPTION_DOUBLE: _JSI_OPTSETNTYP(double, nv, ptr); break;
            default: break;
        }
................................................................................
    }
    break;
    case JSI_OPTION_STRBUF:
    {
        if (argValue == NULL || Jsi_ValueIsNull(interp, argValue))
            *(char*)ptr = 0;
        else {
            int sLen;
            const char *scp = Jsi_ValueString(interp, argValue, &sLen);
            if (!scp)

                goto bail;
            if (sLen>(int)(specPtr->size-1))
                sLen = specPtr->size-1;
            memcpy((char*)ptr, scp, sLen);
            ((char*)ptr)[sLen] = 0;
        }
    }
    break;
    
#define _JSI_OPT_CHECKNULL(argValue) if (!argValue || Jsi_ValueIsNull(interp, argValue)) { \
         if (*((Jsi_Value **)ptr)) \
            Jsi_DecrRefCount(interp, *((Jsi_Value **)ptr)); \
................................................................................
    }\
    *((Jsi_Value **)ptr) = argValue;
    
    case JSI_OPTION_STRING:
        if (argValue == *((Jsi_Value **)ptr))
            break;
        _JSI_OPT_CHECKNULL(argValue);
        if (!Jsi_ValueIsString(interp, argValue))
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_DSTRING:
        Jsi_DSInit((Jsi_DString *)ptr);
        if (argValue && !Jsi_ValueIsNull(interp, argValue))
        {
            int sLen;
            const char *scp = Jsi_ValueString(interp, argValue, &sLen);
            if (!scp)

                goto bail;
            Jsi_DSAppendLen((Jsi_DString *)ptr, scp, sLen);
        }
        break;
    
    case JSI_OPTION_TIME_D: {
       if (argValue)
        {
            Jsi_Number nv = 0;
................................................................................
            *(time_t*)ptr = 0;
        }
        break;
    }
    case JSI_OPTION_VAR:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_NULL && argValue->vt != JSI_VT_VARIABLE) 
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_FUNC:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_FUNCTION) 
            goto bail;
        if (specPtr->data && (interp->typeCheck.run|interp->typeCheck.all))
            if (!jsi_FuncArgCheck(interp, argValue->d.obj->d.fobj->func, (char*)specPtr->data)) 
                return Jsi_LogError("failed setting func pointer for %s", specPtr->name);

        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_USEROBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_USEROBJ) 
            goto bail;
        if (specPtr->data && Jsi_Strcmp((char*)specPtr->data, argValue->d.obj->d.uobj->reg->name)) 
            return Jsi_LogError("expected id %s for %s",(char*)specPtr->data,  specPtr->name);
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_REGEXP:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_REGEXP)
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_OBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT)
            goto bail;

    case JSI_OPTION_VALUE:
         _JSI_OPT_CHECKNULL(argValue);
         _JSI_OPT_ARGSET(argValue, ptr);
        break;
    case JSI_OPTION_ARRAY:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || !argValue->d.obj->isarrlist)
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
#ifdef __cplusplus
    case JSI_OPTION_END:
#else
    default:
#endif
................................................................................
        Jsi_LogBug("invalid option id: %d", specPtr->id);
    }
done:
    specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    if (isIncr)
        return Jsi_LogError("incr invalid for %s", specPtr->name);
    return JSI_OK;

bail:
    if (!emsg) {
        emsg = jsi_OptTypeInfo[specPtr->id].cName;
        epre = "expected ";
    }
    return Jsi_LogError("%s%s: for %s option \"%.40s\"", epre, emsg, (cust?cust->name:""), specPtr->name);
}

Jsi_RC
jsi_SetOption(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Value *oa = interp->lastParseOpt;
    interp->lastParseOpt = argValue;
    Jsi_RC rc = jsi_SetOption_(interp, specPtr, string, rec, argValue, flags);
    interp->lastParseOpt = oa;
    return rc;
}

Jsi_RC
Jsi_OptionsSet(Jsi_Interp *interp, Jsi_OptionSpec *specs, void* rec, const char *option, Jsi_Value *valuePtr, Jsi_Wide flags)
{
    char *record = (char*)rec;
    Jsi_OptionSpec *specPtr;
................................................................................
            goto done;
        }
        if (((JSI_OPT_PASS2&flags) && !(JSI_OPT_PASS2&specPtr->flags))
            || ((JSI_OPT_PASS2&specPtr->flags) && !(JSI_OPT_PASS2&flags)))
            continue;
            
        if ((JSI_OPT_READ_ONLY&specPtr->flags)) {
            Jsi_LogError("Error option is readonly: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
        if ((JSI_OPTS_IS_UPDATE&flags) && (JSI_OPT_INIT_ONLY&specPtr->flags)) {
            Jsi_LogError("Error can not update option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }

        if (jsi_SetOption(interp, specPtr, (char*)arg, record, optval, flags) != JSI_OK) {

            count = -1;
            goto done;
        }
 
        specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    }
    if (reqCnt) {
        for (specPtr = specs; specPtr->id>=JSI_OPTION_BOOL && specPtr->id < JSI_OPTION_END && specPtr->name; specPtr++) {
            if (specPtr->flags &  JSI_OPT_REQUIRED &&
                !(specPtr->flags&JSI_OPT_IS_SPECIFIED)) {

                Jsi_LogError("Error required field not specified: \"%.40s\"", specPtr->name);
                count = -1;
            }
        }
    }

done:
    Jsi_TreeSearchDone(&search);
................................................................................
        Jsi_Value *svalue = Jsi_ValueMakeObject(interp, NULL, sobj);
        jsi_DumpOptionSpecs(interp, sobj, specs);
        Jsi_ValueReplace(interp, ret, svalue);
        return JSI_OK;
    }
    if (val->vt != JSI_VT_OBJECT) 
        return Jsi_LogError("expected string, object, or null");
    if (Jsi_OptionsProcess(interp, specs, rec, val, JSI_OPTS_IS_UPDATE|flags) < 0)
        return JSI_ERROR;
    return JSI_OK;
}

static const char **jsi_OptGetEnumList(Jsi_OptionSpec* spec) {
    const char **list = (const char**)spec->data;
    Jsi_OptionSpec* es=NULL;
................................................................................
            for (i=0; i<n && list[i]; i++) ; /* Look forward til n */
        if (list[i])
            Jsi_DSAppendLen(outStr, list[i], -1);
        else if ((spec->flags&JSI_OPT_COERCE)) {
            Jsi_DSPrintf(outStr, "%" PRIu64, (uint64_t)n);
            return JSI_OK;
        } else
            return Jsi_LogError("enum has unknown value: %d", *s);
        return JSI_OK;
    }
#ifndef JSI_LITE_ONLY
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
    Jsi_RC rc = jsi_EnumToValue(interp, spec, NULL, &dStr, record, flags);
    if (rc == JSI_OK)
................................................................................
    if (!interp->parent) return;
    if (*v)
        Jsi_DecrRefCount(interp->parent, *v);
    *v = NULL;
}

static Jsi_OptionCustom jsi_OptSwitchParentFunc = {
    .name="funcinparent", .parseProc=jsi_ValueToParentFunc, .formatProc=jsi_ParentFuncToValue, .freeProc=jsi_ParentFuncFree,
};

/* Scanning function */
static Jsi_RC jsi_ValueToBitfield(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue,
    const char *inStr, void *record, Jsi_Wide flags)
{
    Jsi_csgset *bsget = spec->init.OPT_BITS;
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    Jsi_Number num;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogBug("invalid bitfield");
    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = {};
        Jsi_OptionSpec eSpec[] = {
            JSI_OPT(CUSTOM, typeof(nval), numVal, .help=spec->help, .flags=JSI_OPT_ENUM_SPEC,
                .custom=Jsi_Opt_SwitchEnum, .data=(void*)enumSpec, .info=0, .tname=spec->tname, .value=0, .bits=0, .boffset=8*sizeof(int64_t) ),
            JSI_OPT_END(typeof(nval))
        };
................................................................................
            return JSI_ERROR;
        num = (Jsi_Number)nval.numVal;
    } else if (inStr) {
        if (Jsi_GetDouble(interp, inStr, &num) != JSI_OK)
            return JSI_ERROR;
    } else {
        if (inValue && !Jsi_ValueIsNumber(interp, inValue)) 
            return JSI_ERROR;
        Jsi_ValueGetNumber(interp, inValue, &num);
    }
    int64_t inum = (int64_t)num;
    return (*bsget)(interp, data, &inum, spec, idx, 1);
}

/* Printing function. */
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    int64_t inum;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogBug("invalid bitfield");
    Jsi_RC rc = (*bsget)(interp, data, &inum, spec, idx, 0);
    if (rc != JSI_OK)
        return JSI_ERROR;

    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = { inum };
        Jsi_OptionSpec eSpec[] = {
................................................................................
        Jsi_Number num = (Jsi_Number)inum;
        Jsi_ValueMakeNumber(interp, outValue, num);
    }
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchBitfield = {
    .name="bitfield", .parseProc=jsi_ValueToBitfield, .formatProc=jsi_BitfieldToValue
};

/* Scanning function */
static Jsi_RC jsi_ValueToNull(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue, const char *inStr, void *record, Jsi_Wide flags)
{
    return JSI_OK;
}
................................................................................
static Jsi_RC jsi_NullToValue(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value **outValue, Jsi_DString *outStr, void *record, Jsi_Wide flags)
{
    Jsi_ValueMakeNull(interp, outValue);
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchNull = {
    .name="null", .parseProc=jsi_ValueToNull, .formatProc=jsi_NullToValue
};

#endif

typedef struct {
    Jsi_OptionInitVal init;
} jsi_IniValStruct;
................................................................................
    if (tok->size%2 || tok->type != JSI_JTYPE_OBJECT) {
        result = -1;
        goto done;
    }
    v = Jsi_ValueNew1(interp);
    for (i=1; i<p->toknext && i<tok->size; i++) {
        if (p->tokens[i].type != JSI_JTYPE_STRING) {
            result = Jsi_LogError("expected string at %d", i-1);
            goto bail;
        }
        name = Jsi_JsonGetTokstr(p, json, i, &len);
        Jsi_DSSetLength(&nStr, 0);
        Jsi_DSAppendLen(&nStr, name, len);
        name = Jsi_DSValue(&nStr);
        i++;
................................................................................
                    Jsi_ValueMakeBool(interp, &v, (bool)(len==4?1:0));
                } else if (len == 4 && Jsi_Strncmp(t, "null", len)==0) {
                    Jsi_ValueMakeNull(interp, &v);
                } else {
                    char *ep;
                    Jsi_Number d = strtod(t,&ep);
                    if (ep>(t+len)) {
                        result = Jsi_LogError("bad number %*s", len, t);
                        goto bail;
                    }
                    Jsi_ValueMakeNumber(interp, &v, d);
                }
                break;
            case JSI_JTYPE_STRING:
                t = Jsi_JsonGetTokstr(p, json, i, &len);
................................................................................
#ifndef JSI_OMIT_LOAD
    { "load",       jsi_LoadLoadCmd, 1,  1, "shlib:string", .help="Load a shared executable and invoke its _Init call", .retType=(uint)JSI_TT_VOID },
#endif
    { "log",        SysLogCmd,       1, -1, "val, ...", .help="Same as puts, but includes file:line", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "noOp",       jsi_NoOpCmd,     0, -1, "", .help="A No-Op. A zero overhead command call that is useful for debugging" },
    { "parseInt",   parseIntCmd,     1,  2, "val:any, base:number=10", .help="Convert string to an integer", .retType=(uint)JSI_TT_NUMBER },
    { "parseFloat", parseFloatCmd,   1,  1, "val", .help="Convert string to a double", .retType=(uint)JSI_TT_NUMBER },
    { "parseOpts",  SysParseOptsCmd, 2,  3, "self:object|userobj, options:object, conf:object|null|undefined", .help="Parse options", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "printf",     SysPrintfCmd,    1, -1, "format:string, ...", .help="Formatted output to stdout", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "provide",    SysProvideCmd,   0,  2, "name:string|function=void, version:number|string=1.0", .help="Provide a package for use with require. Default is the file tail-rootname", .retType=(uint)JSI_TT_VOID },
    { "puts",       SysPutsCmd,      1, -1, "val, ...", .help="Output one or more values to stdout", .retType=(uint)JSI_TT_VOID, .flags=0, .info=FN_puts },
    { "quote",      SysQuoteCmd,     1,  1, "val:string", .help="Return quoted string", .retType=(uint)JSI_TT_STRING },
    { "require",    SysRequireCmd,   0,  2, "name:string=void, version:number|string=1", .help="Load/query packages", .retType=(uint)JSI_TT_NUMBER|JSI_TT_OBJECT|JSI_TT_ARRAY, .flags=0, .info=FN_require },
    { "runModule",  SysRunModuleCmd, 0,  2, "cmd:string|function=void, conf:array=undefined", .help="Invoke named module. If name is empty, uses file basename. If isMain and no args givine parses console.args", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "sleep",      SysSleepCmd,     0,  1, "secs:number=1.0",  .help="sleep for N milliseconds, minimum .001", .retType=(uint)JSI_TT_VOID },
................................................................................
//  Jsi_Interp *interp = p->jdb->interp;

    if( p->pPreStmt ) {
        sqlite3_reset(p->pPreStmt->pStmt);
        dbReleaseStmt(p->jdb, p->pPreStmt, p->nocache);
        p->pPreStmt = 0;
    }
    if (p->dSql)
        Jsi_DSFree(p->dSql);
    dbReleaseColumnNames(p);
}

static void DbClose(sqlite3 *db) {
        sqlite3_close(db);
}

................................................................................
#endif
    const char *zSql = Jsi_ValueGetDString(interp, vSql, &eStr, 0);
    Jsi_Value *arg = Jsi_ValueArrayIndex(interp, args, 1);
    int cnt = 0;
    char **apColName = NULL;
    int *apColType = NULL, isopts = 0;
    DbEvalContext sEval = {};
    QueryOpts opts, *oEopt = jdb->optPtr;
    opts = jdb->queryOpts;
    opts.callback = NULL;
    opts.width = NULL;
    Jsi_Value *callback = NULL, *width = NULL;
            
    if (jdb->echo && zSql)
        Jsi_LogInfo("SQL-QUERY: %s\n", zSql); 
................................................................................
    }
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    sEval.nocache = opts.nocache;
    if ((rc = dbEvalInit(interp, &sEval, jdb, zSql, &sStr, 0, 0)) != JSI_OK)
        goto bail;
    sEval.ret = *ret;

    jdb->optPtr = &opts;
    if (callback) {
        sEval.tocall = callback;
        if (opts.mode != _JSI_EF_ROWS) {
            Jsi_LogError("'mode' must be 'rows' with 'callback'");
            rc = JSI_ERROR;
            goto bail;
................................................................................
            sf->type = Jsi_TypeLookup(interp, sf->tname);
        int isbitset = ((sf->flags&JSI_OPT_BITSET_ENUM)!=0);
        if (sf->type && sf->type->extData && (sf->type->flags&(jsi_CTYP_ENUM|jsi_CTYP_STRUCT))) {
            // A struct sub-field or a bit field mapped to an ENUM.
            Jsi_OptionSpec *es = (typeof(es))sf->type->extData;
            es->value++;
            if ((sf->type->flags&jsi_CTYP_ENUM)) {
                if (sf->bits)
                    return Jsi_LogError("enum of bits unsupported: %s", sl->name); //TODO: get working again...
                sf->custom = (isbitset ? Jsi_Opt_SwitchBitset : Jsi_Opt_SwitchEnum);
                sf->data = (void*)es->data;
                sf->id = JSI_OPTION_CUSTOM;
            }
            else if (sf->type->flags & jsi_CTYP_STRUCT) {
                sf->custom = Jsi_Opt_SwitchSuboption;
                sf->data = es->extData;
................................................................................
            sf->tname = sf->type->cName;
            sf->size = (isbitset?(int)sizeof(int):sf->type->size);
            if (sf->arrSize)
                sf->size *= sf->arrSize;
            sf->idx = cnt;
            sf->boffset = boffset;
            if (sf->bits) {
                if (sf->bits>=64)
                    return Jsi_LogError("bits too large");
                boffset += sf->bits;
                sf->id = JSI_OPTION_CUSTOM;
                sf->custom=Jsi_Opt_SwitchBitfield;
                sf->init.OPT_BITS=&jsi_csBitGetSet;
            } else {
                sf->offset = (boffset+7)/8;
................................................................................
    if (argc>200)
        return Jsi_LogError("too many fields: %d>200", argc);
    Jsi_StructSpec *sl, *sf, recs[argc+2];
    memset(recs, 0, sizeof(recs));
    sl = recs+argc+1;
    sf = recs;
    SIGINIT(sl, OPTS_STRUCT);
    if (vstr) {
        sl->name = Jsi_KeyAdd(interp, vstr);
    } else if (Jsi_OptionsProcess(interp, StructOptions, sl, val, 0) < 0) {
        rc = JSI_ERROR;
        goto bail;
    }
    if (!jsi_IsAlnumStr(sl->name)) {
        rc = Jsi_LogError("invalid struct name: %s", sl->name);
................................................................................
                             Jsi_Value **ret, Jsi_Func *funcPtr)
{
    UdcGet(cd, _this, funcPtr);
    uchar *dptr = NULL;
    Jsi_Value *karg = Jsi_ValueArrayIndex(interp, args, 0);
    char kbuf[BUFSIZ];
    void *key = kbuf;
    bool isNull = (!karg || Jsi_ValueIsNull(interp, karg));
    if (isNull) {
        if (cd->mapPtr || cd->arrSize>1)
            return Jsi_LogError("null key used with c-array/map");
    } else {
        if (!cd->mapPtr && cd->arrSize<=0)
            return Jsi_LogError("must be array/map");
        if (JSI_OK != jsi_csGetKey(interp, cd, karg, &key, sizeof(kbuf), 1))
................................................................................
            dptr = ((uchar*)cd->data) + sizeof(void*)*kind;
        else if (cd->isPtr2) {
            dptr = (uchar*)(*(void**)dptr);
            dptr += sizeof(void*)*kind;
        }
    }
    int argc = Jsi_ValueGetLength(interp, args);
    if (argc > 2)
        return Jsi_LogError("expected 0 - 2 args");
    Jsi_Value *arg2 = Jsi_ValueArrayIndex(interp, args, 1);
    return Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, dptr, arg2, ret, 0);
}

#define FN_dataSet JSI_INFO("Sets data value for given a name argument.")
static Jsi_RC CDataSetCmd_(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
                             Jsi_Value **ret, Jsi_Func *funcPtr, int op)
................................................................................
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}

static bool jsi_csSBitSetGet(int isSet, uchar *tbuf, int bits, Jsi_Wide *valPtr) {
    union bitfield *bms = (union bitfield *)tbuf;
    Jsi_Wide val = *valPtr;
    union bitfield {
        Jsi_Wide b1:1; Jsi_Wide b2:2; Jsi_Wide b3:3; Jsi_Wide b4:4; Jsi_Wide b5:5; Jsi_Wide b6:6;
        Jsi_Wide b7:7; Jsi_Wide b8:8; Jsi_Wide b9:9; Jsi_Wide b10:10; Jsi_Wide b11:11; Jsi_Wide b12:12;
        Jsi_Wide b13:13; Jsi_Wide b14:14; Jsi_Wide b15:15; Jsi_Wide b16:16; Jsi_Wide b17:17; 
        Jsi_Wide b18:18; Jsi_Wide b19:19; Jsi_Wide b20:20; Jsi_Wide b21:21; Jsi_Wide b22:22;
        Jsi_Wide b23:23; Jsi_Wide b24:24; Jsi_Wide b25:25; Jsi_Wide b26:26; Jsi_Wide b27:27;
        Jsi_Wide b28:28; Jsi_Wide b29:29; Jsi_Wide b30:30; Jsi_Wide b31:31; Jsi_Wide b32:32;
        Jsi_Wide b33:33; Jsi_Wide b34:34; Jsi_Wide b35:35; Jsi_Wide b36:36; Jsi_Wide b37:37;
        Jsi_Wide b38:38; Jsi_Wide b39:39; Jsi_Wide b40:40; Jsi_Wide b41:41; Jsi_Wide b42:42;
        Jsi_Wide b43:43; Jsi_Wide b44:44; Jsi_Wide b45:45; Jsi_Wide b46:46; Jsi_Wide b47:47;
        Jsi_Wide b48:48; Jsi_Wide b49:49; Jsi_Wide b50:50; Jsi_Wide b51:51; Jsi_Wide b52:52;
        Jsi_Wide b53:53; Jsi_Wide b54:54; Jsi_Wide b55:55; Jsi_Wide b56:56; Jsi_Wide b57:57;
        Jsi_Wide b58:58; Jsi_Wide b59:59; Jsi_Wide b60:60; Jsi_Wide b61:61; Jsi_Wide b62:62;
        Jsi_Wide b63:63; Jsi_Wide b64:64;
    };
    if (isSet) {
        switch (bits) {
           CBSN(1); CBSN(2); CBSN(3); CBSN(4); CBSN(5); CBSN(6); CBSN(7); CBSN(8);
           CBSN(9); CBSN(10); CBSN(11); CBSN(12); CBSN(13); CBSN(14); CBSN(15); CBSN(16);
           CBSN(17); CBSN(18); CBSN(19); CBSN(20); CBSN(21); CBSN(22); CBSN(23); CBSN(24);
           CBSN(25); CBSN(26); CBSN(27); CBSN(28); CBSN(29); CBSN(30); CBSN(31); CBSN(32);
           CBSN(33); CBSN(34); CBSN(35); CBSN(36); CBSN(37); CBSN(38); CBSN(39); CBSN(40);
           CBSN(41); CBSN(42); CBSN(43); CBSN(44); CBSN(45); CBSN(46); CBSN(47); CBSN(48);
           CBSN(49); CBSN(50); CBSN(51); CBSN(52); CBSN(53); CBSN(54); CBSN(55); CBSN(56);
           CBSN(57); CBSN(58); CBSN(59); CBSN(60); CBSN(61); CBSN(62); CBSN(63); CBSN(64);
        }
        assert(0);
    }
    switch (bits) {
       CBGN(1); CBGN(2); CBGN(3); CBGN(4); CBGN(5); CBGN(6); CBGN(7); CBGN(8);
       CBGN(9); CBGN(10); CBGN(11); CBGN(12); CBGN(13); CBGN(14); CBGN(15); CBGN(16);
       CBGN(17); CBGN(18); CBGN(19); CBGN(20); CBGN(21); CBGN(22); CBGN(23); CBGN(24);
       CBGN(25); CBGN(26); CBGN(27); CBGN(28); CBGN(29); CBGN(30); CBGN(31); CBGN(32);
       CBGN(33); CBGN(34); CBGN(35); CBGN(36); CBGN(37); CBGN(38); CBGN(39); CBGN(40);
       CBGN(41); CBGN(42); CBGN(43); CBGN(44); CBGN(45); CBGN(46); CBGN(47); CBGN(48);
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}

static Jsi_RC jsi_csSBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {
    Jsi_Wide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>=64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef __int128 stvalType;
#else
    typedef Jsi_Wide stvalType;
#endif
    stvalType tbuf[2] = {};
    uchar sbuf[20], *bptr = (uchar*)tbuf;
    memcpy(tbuf, rec+ofs, Bsz);
    Jsi_Wide mval = *valPtr;
    Jsi_Wide amask = ((1LL<<(bits-1))-1LL);
    stvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;
        if (!isSet) {
            mval = (Jsi_Wide)tval;
            *(Jsi_Wide*)bptr = mval;
        }
    }
        
    if (!isSet) { // Get value.
        if (!jsi_csSBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
        return JSI_OK;
    }
    
    if (!jsi_csSBitSetGet(1, bptr, bits, &mval))
        return JSI_ERROR;
    if (bo) {
        tval = (typeof(tval))mval;
        lmask=(amask<<bo);
        kval &= ~lmask;
        tval <<= bo;
        tval = (kval | tval);
        *(typeof(tval)*)tbuf = tval;
    }
    memcpy(rec+ofs, tbuf, Bsz);

    return JSI_OK;    
}

static Jsi_RC jsi_csBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {
    bool us = (spec->tname && spec->tname[0] == 'u');
    if (!us)        
        return jsi_csSBitGetSet(interp, vrec, vPtr, spec, idx, isSet);

    if (*vPtr<0)
        return JSI_ERROR;

    Jsi_UWide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>=64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef unsigned __int128 utvalType;
#else
................................................................................
    Jsi_UWide mval;
    Jsi_UWide amask = ((1LL<<(bits-1))-1LL);
    utvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;
        if (!isSet) {
            mval = (Jsi_UWide)tval;
            *(Jsi_UWide*)bptr = mval;
        }
    } else
         mval = *valPtr;
        
    if (!isSet) { // Get value.
        if (!jsi_csBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
................................................................................
    }
    Jsi_Free(dptr);
    Jsi_MapEntryDelete(mPtr);
    return JSI_OK;

}

#define FN_cdataConstructor JSI_INFO("\
The 2nd arg is used for function option parsing and will report errors at the callers file:line")
static Jsi_RC CDataConstructor(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr);
    
/* Defines: Handles the "Data" subcommand */
static Jsi_CmdSpec cdataCmds[] =
{
    {"CData",     CDataConstructor,1, 2, "options:string|object=void, inits:object=void",.help="Create a new struct or map/array of structs", .retType=(uint)JSI_TT_USEROBJ, .flags=JSI_CMD_IS_CONSTRUCTOR, .info=FN_cdataConstructor, .opts=CDataOptions},
    {"conf",      CDataConfCmd,    0, 1, "options:object|string=void",.help="Configure options for c-data", .retType=0, .flags=0, .info=0, .opts=CDataOptions},
    {"get"   ,    CDataGetCmd,     0, 2, "key:string|number|object=null, field:string=void", .help="Get struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"incr",      CDataIncrCmd,    3, 3, "key:string|number|object|null, field:object|string, value:number", .help="Increment a numeric field: returns the new value", .retType=(uint)JSI_TT_NUMBER},
    {"info",      CDataInfoCmd,    0, 0, "", .help="Return info for data", .retType=(uint)JSI_TT_OBJECT},
    {"names",     CDataNamesCmd,   0, 0, "", .help="Return keys for map", .retType=(uint)JSI_TT_ARRAY },
    {"set",       CDataSetCmd,     2, 3, "key:string|number|object|null, field:object|string, value:any=void", .help="Set a struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"unset",     CDataUnsetCmd,   1, 1, "key:string|number|object", .help="Remove entry from map/array", .retType=(uint)JSI_TT_ANY},
    {NULL}
};
................................................................................
        that = *ret;
    }

    CDataObj *cd = (typeof(cd))Jsi_Calloc(1,sizeof(*cd));
    cd->interp = interp;
    Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
    Jsi_vtype vtyp = Jsi_ValueTypeGet(val);
    int vlen, isNew = 0;
    const char *vstr = Jsi_ValueString(interp, val, &vlen);
    Jsi_DString dStr = {};
    Jsi_Value *ival = Jsi_ValueArrayIndex(interp, args, 1);
    if (ival && !Jsi_ValueIsObjType(interp, ival, JSI_OT_OBJECT))
        return Jsi_LogError("arg 2: expected object");
    if (vstr && vlen) {
        char ech = 0;
        const char *nstr = vstr, *cp = vstr;
        while (*cp && (isalnum(*cp) || *cp=='_')) cp++;
        if (*cp) {
            int slen = cp-vstr;
            Jsi_DString sStr = {};
................................................................................
    } else if (vtyp != JSI_VT_OBJECT) {
        Jsi_LogError("expected string, object");
        goto errout;
    }
    if (val && Jsi_OptionsProcess(interp, CDataOptions, cd, val, 0) < 0)
        goto errout;

    if (ival && (cd->mapPtr || cd->arrSize)) {
        Jsi_LogError("init can not be used with c-array/map");
        goto errout;
     }
  
    if (JSI_OK != jsi_csNewCData(interp, cd, JSI_OPT_NO_SIG))
        goto errout;

    if (ival) {
        interp->callerErr = 1;
        Jsi_RC rc = Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, cd->data, ival, ret, 0);
        interp->callerErr = 0;
        if (rc != JSI_OK) {
            isNew = 1;
            goto errout;
        }
    }
        
    nobj = (Jsi_Obj*)Jsi_ValueGetObj(interp, that);
    cd->objId = Jsi_UserObjNew(interp, &cdataobject, nobj, cd);
    if (cd->objId<0) {
        goto errout;
    }
    cd->fobj = nobj;
    return JSI_OK;
    
errout:
    Jsi_DSFree(&dStr);
    Jsi_OptionsFree(interp, CDataOptions, cd, 0);
    if (isNew)
       jsi_csObjFree(interp, cd);
    else
        Jsi_Free(cd);
    return JSI_ERROR;

}

// Globals

static Jsi_RC jsi_DoneCData(Jsi_Interp *interp)

Changes to src/jsi.h.

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

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 17

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

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif







|







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

#define JSI_VERSION_MAJOR   2
#define JSI_VERSION_MINOR   5
#define JSI_VERSION_RELEASE 18

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

#ifndef JSI_EXTERN
#define JSI_EXTERN extern
#endif

Changes to src/jsiCData.c.

134
135
136
137
138
139
140


141
142
143
144
145
146
147
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
....
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
....
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
....
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
....
1612
1613
1614
1615
1616
1617
1618
1619


































































































1620







1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
....
1637
1638
1639
1640
1641
1642
1643

1644
1645

1646
1647
1648
1649
1650
1651
1652
....
1708
1709
1710
1711
1712
1713
1714


1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
....
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948



1949
1950
1951
1952
1953
1954
1955
....
1970
1971
1972
1973
1974
1975
1976





1977
1978
1979










1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990



1991
1992
1993
1994
1995
1996
1997
1998
            sf->type = Jsi_TypeLookup(interp, sf->tname);
        int isbitset = ((sf->flags&JSI_OPT_BITSET_ENUM)!=0);
        if (sf->type && sf->type->extData && (sf->type->flags&(jsi_CTYP_ENUM|jsi_CTYP_STRUCT))) {
            // A struct sub-field or a bit field mapped to an ENUM.
            Jsi_OptionSpec *es = (typeof(es))sf->type->extData;
            es->value++;
            if ((sf->type->flags&jsi_CTYP_ENUM)) {


                sf->custom = (isbitset ? Jsi_Opt_SwitchBitset : Jsi_Opt_SwitchEnum);
                sf->data = (void*)es->data;
                sf->id = JSI_OPTION_CUSTOM;
            }
            else if (sf->type->flags & jsi_CTYP_STRUCT) {
                sf->custom = Jsi_Opt_SwitchSuboption;
                sf->data = es->extData;
................................................................................
            sf->tname = sf->type->cName;
            sf->size = (isbitset?(int)sizeof(int):sf->type->size);
            if (sf->arrSize)
                sf->size *= sf->arrSize;
            sf->idx = cnt;
            sf->boffset = boffset;
            if (sf->bits) {
                if (sf->bits>64)
                    return Jsi_LogError("bits too large");
                boffset += sf->bits;
                sf->id = JSI_OPTION_CUSTOM;
                sf->custom=Jsi_Opt_SwitchBitfield;
                sf->init.OPT_BITS=&jsi_csBitGetSet;
            } else {
                sf->offset = (boffset+7)/8;
................................................................................
    if (argc>200)
        return Jsi_LogError("too many fields: %d>200", argc);
    Jsi_StructSpec *sl, *sf, recs[argc+2];
    memset(recs, 0, sizeof(recs));
    sl = recs+argc+1;
    sf = recs;
    SIGINIT(sl, OPTS_STRUCT);
        if (vstr) {
        sl->name = Jsi_KeyAdd(interp, vstr);
    } else if (Jsi_OptionsProcess(interp, StructOptions, sl, val, 0) < 0) {
        rc = JSI_ERROR;
        goto bail;
    }
    if (!jsi_IsAlnumStr(sl->name)) {
        rc = Jsi_LogError("invalid struct name: %s", sl->name);
................................................................................
                             Jsi_Value **ret, Jsi_Func *funcPtr)
{
    UdcGet(cd, _this, funcPtr);
    uchar *dptr = NULL;
    Jsi_Value *karg = Jsi_ValueArrayIndex(interp, args, 0);
    char kbuf[BUFSIZ];
    void *key = kbuf;
    bool isNull = Jsi_ValueIsNull(interp, karg);
    if (isNull) {
        if (cd->mapPtr || cd->arrSize>1)
            return Jsi_LogError("null key used with c-array/map");
    } else {
        if (!cd->mapPtr && cd->arrSize<=0)
            return Jsi_LogError("must be array/map");
        if (JSI_OK != jsi_csGetKey(interp, cd, karg, &key, sizeof(kbuf), 1))
................................................................................
            dptr = ((uchar*)cd->data) + sizeof(void*)*kind;
        else if (cd->isPtr2) {
            dptr = (uchar*)(*(void**)dptr);
            dptr += sizeof(void*)*kind;
        }
    }
    int argc = Jsi_ValueGetLength(interp, args);
    if (argc != 2 && argc != 1)
        return Jsi_LogError("expected 1 or 2 args");
    Jsi_Value *arg2 = Jsi_ValueArrayIndex(interp, args, 1);
    return Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, dptr, arg2, ret, 0);
}

#define FN_dataSet JSI_INFO("Sets data value for given a name argument.")
static Jsi_RC CDataSetCmd_(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
                             Jsi_Value **ret, Jsi_Func *funcPtr, int op)
................................................................................
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}



































































































static Jsi_RC jsi_csBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {







    Jsi_UWide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef unsigned __int128 utvalType;
#else
................................................................................
    Jsi_UWide mval;
    Jsi_UWide amask = ((1LL<<(bits-1))-1LL);
    utvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;

        mval = (Jsi_UWide)tval;
        *(Jsi_UWide*)bptr = mval;

    } else
         mval = *valPtr;
        
    if (!isSet) { // Get value.
        if (!jsi_csBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
................................................................................
    }
    Jsi_Free(dptr);
    Jsi_MapEntryDelete(mPtr);
    return JSI_OK;

}



static Jsi_RC CDataConstructor(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr);
    
/* Defines: Handles the "Data" subcommand */
static Jsi_CmdSpec cdataCmds[] =
{
    {"CData",     CDataConstructor,1, 1, "options:string|object=void",.help="Create a new struct or map/array of structs", .retType=(uint)JSI_TT_USEROBJ, .flags=JSI_CMD_IS_CONSTRUCTOR, .info=0, .opts=CDataOptions},
    {"conf",      CDataConfCmd,    0, 1, "options:object|string=void",.help="Configure options for c-data", .retType=0, .flags=0, .info=0, .opts=CDataOptions},
    {"get"   ,    CDataGetCmd,     1, 2, "key:string|number|object|null, field:string=void", .help="Get struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"incr",      CDataIncrCmd,    3, 3, "key:string|number|object|null, field:object|string, value:number", .help="Increment a numeric field: returns the new value", .retType=(uint)JSI_TT_NUMBER},
    {"info",      CDataInfoCmd,    0, 0, "", .help="Return info for data", .retType=(uint)JSI_TT_OBJECT},
    {"names",     CDataNamesCmd,   0, 0, "", .help="Return keys for map", .retType=(uint)JSI_TT_ARRAY },
    {"set",       CDataSetCmd,     2, 3, "key:string|number|object|null, field:object|string, value:any=void", .help="Set a struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"unset",     CDataUnsetCmd,   1, 1, "key:string|number|object", .help="Remove entry from map/array", .retType=(uint)JSI_TT_ANY},
    {NULL}
};
................................................................................
        that = *ret;
    }

    CDataObj *cd = (typeof(cd))Jsi_Calloc(1,sizeof(*cd));
    cd->interp = interp;
    Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
    Jsi_vtype vtyp = Jsi_ValueTypeGet(val);
    int vlen;
    const char *vstr = Jsi_ValueString(interp, val, &vlen);
    Jsi_DString dStr = {};



    if (vstr && vlen) {
        char ech = 0;
        const char *nstr = vstr, *cp = vstr;
        while (*cp && (isalnum(*cp) || *cp=='_')) cp++;
        if (*cp) {
            int slen = cp-vstr;
            Jsi_DString sStr = {};
................................................................................
    } else if (vtyp != JSI_VT_OBJECT) {
        Jsi_LogError("expected string, object");
        goto errout;
    }
    if (val && Jsi_OptionsProcess(interp, CDataOptions, cd, val, 0) < 0)
        goto errout;






    if (JSI_OK != jsi_csNewCData(interp, cd, JSI_OPT_NO_SIG))
        goto errout;











    nobj = (Jsi_Obj*)Jsi_ValueGetObj(interp, that);
    cd->objId = Jsi_UserObjNew(interp, &cdataobject, nobj, cd);
    if (cd->objId<0) {
        goto errout;
    }
    cd->fobj = nobj;
    return JSI_OK;
    
errout:
    Jsi_DSFree(&dStr);
    Jsi_OptionsFree(interp, CDataOptions, cd, 0);



    Jsi_Free(cd);
    return JSI_ERROR;

}

// Globals

static Jsi_RC jsi_DoneCData(Jsi_Interp *interp)







>
>







 







|







 







|







 







|







 







|
|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>



|







 







>
|
|
>







 







>
>






|

|







 







|


>
>
>







 







>
>
>
>
>



>
>
>
>
>
>
>
>
>
>











>
>
>
|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
....
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
....
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
....
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
....
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
....
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
....
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
....
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
....
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
            sf->type = Jsi_TypeLookup(interp, sf->tname);
        int isbitset = ((sf->flags&JSI_OPT_BITSET_ENUM)!=0);
        if (sf->type && sf->type->extData && (sf->type->flags&(jsi_CTYP_ENUM|jsi_CTYP_STRUCT))) {
            // A struct sub-field or a bit field mapped to an ENUM.
            Jsi_OptionSpec *es = (typeof(es))sf->type->extData;
            es->value++;
            if ((sf->type->flags&jsi_CTYP_ENUM)) {
                if (sf->bits)
                    return Jsi_LogError("enum of bits unsupported: %s", sl->name); //TODO: get working again...
                sf->custom = (isbitset ? Jsi_Opt_SwitchBitset : Jsi_Opt_SwitchEnum);
                sf->data = (void*)es->data;
                sf->id = JSI_OPTION_CUSTOM;
            }
            else if (sf->type->flags & jsi_CTYP_STRUCT) {
                sf->custom = Jsi_Opt_SwitchSuboption;
                sf->data = es->extData;
................................................................................
            sf->tname = sf->type->cName;
            sf->size = (isbitset?(int)sizeof(int):sf->type->size);
            if (sf->arrSize)
                sf->size *= sf->arrSize;
            sf->idx = cnt;
            sf->boffset = boffset;
            if (sf->bits) {
                if (sf->bits>=64)
                    return Jsi_LogError("bits too large");
                boffset += sf->bits;
                sf->id = JSI_OPTION_CUSTOM;
                sf->custom=Jsi_Opt_SwitchBitfield;
                sf->init.OPT_BITS=&jsi_csBitGetSet;
            } else {
                sf->offset = (boffset+7)/8;
................................................................................
    if (argc>200)
        return Jsi_LogError("too many fields: %d>200", argc);
    Jsi_StructSpec *sl, *sf, recs[argc+2];
    memset(recs, 0, sizeof(recs));
    sl = recs+argc+1;
    sf = recs;
    SIGINIT(sl, OPTS_STRUCT);
    if (vstr) {
        sl->name = Jsi_KeyAdd(interp, vstr);
    } else if (Jsi_OptionsProcess(interp, StructOptions, sl, val, 0) < 0) {
        rc = JSI_ERROR;
        goto bail;
    }
    if (!jsi_IsAlnumStr(sl->name)) {
        rc = Jsi_LogError("invalid struct name: %s", sl->name);
................................................................................
                             Jsi_Value **ret, Jsi_Func *funcPtr)
{
    UdcGet(cd, _this, funcPtr);
    uchar *dptr = NULL;
    Jsi_Value *karg = Jsi_ValueArrayIndex(interp, args, 0);
    char kbuf[BUFSIZ];
    void *key = kbuf;
    bool isNull = (!karg || Jsi_ValueIsNull(interp, karg));
    if (isNull) {
        if (cd->mapPtr || cd->arrSize>1)
            return Jsi_LogError("null key used with c-array/map");
    } else {
        if (!cd->mapPtr && cd->arrSize<=0)
            return Jsi_LogError("must be array/map");
        if (JSI_OK != jsi_csGetKey(interp, cd, karg, &key, sizeof(kbuf), 1))
................................................................................
            dptr = ((uchar*)cd->data) + sizeof(void*)*kind;
        else if (cd->isPtr2) {
            dptr = (uchar*)(*(void**)dptr);
            dptr += sizeof(void*)*kind;
        }
    }
    int argc = Jsi_ValueGetLength(interp, args);
    if (argc > 2)
        return Jsi_LogError("expected 0 - 2 args");
    Jsi_Value *arg2 = Jsi_ValueArrayIndex(interp, args, 1);
    return Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, dptr, arg2, ret, 0);
}

#define FN_dataSet JSI_INFO("Sets data value for given a name argument.")
static Jsi_RC CDataSetCmd_(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
                             Jsi_Value **ret, Jsi_Func *funcPtr, int op)
................................................................................
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}

static bool jsi_csSBitSetGet(int isSet, uchar *tbuf, int bits, Jsi_Wide *valPtr) {
    union bitfield *bms = (union bitfield *)tbuf;
    Jsi_Wide val = *valPtr;
    union bitfield {
        Jsi_Wide b1:1; Jsi_Wide b2:2; Jsi_Wide b3:3; Jsi_Wide b4:4; Jsi_Wide b5:5; Jsi_Wide b6:6;
        Jsi_Wide b7:7; Jsi_Wide b8:8; Jsi_Wide b9:9; Jsi_Wide b10:10; Jsi_Wide b11:11; Jsi_Wide b12:12;
        Jsi_Wide b13:13; Jsi_Wide b14:14; Jsi_Wide b15:15; Jsi_Wide b16:16; Jsi_Wide b17:17; 
        Jsi_Wide b18:18; Jsi_Wide b19:19; Jsi_Wide b20:20; Jsi_Wide b21:21; Jsi_Wide b22:22;
        Jsi_Wide b23:23; Jsi_Wide b24:24; Jsi_Wide b25:25; Jsi_Wide b26:26; Jsi_Wide b27:27;
        Jsi_Wide b28:28; Jsi_Wide b29:29; Jsi_Wide b30:30; Jsi_Wide b31:31; Jsi_Wide b32:32;
        Jsi_Wide b33:33; Jsi_Wide b34:34; Jsi_Wide b35:35; Jsi_Wide b36:36; Jsi_Wide b37:37;
        Jsi_Wide b38:38; Jsi_Wide b39:39; Jsi_Wide b40:40; Jsi_Wide b41:41; Jsi_Wide b42:42;
        Jsi_Wide b43:43; Jsi_Wide b44:44; Jsi_Wide b45:45; Jsi_Wide b46:46; Jsi_Wide b47:47;
        Jsi_Wide b48:48; Jsi_Wide b49:49; Jsi_Wide b50:50; Jsi_Wide b51:51; Jsi_Wide b52:52;
        Jsi_Wide b53:53; Jsi_Wide b54:54; Jsi_Wide b55:55; Jsi_Wide b56:56; Jsi_Wide b57:57;
        Jsi_Wide b58:58; Jsi_Wide b59:59; Jsi_Wide b60:60; Jsi_Wide b61:61; Jsi_Wide b62:62;
        Jsi_Wide b63:63; Jsi_Wide b64:64;
    };
    if (isSet) {
        switch (bits) {
           CBSN(1); CBSN(2); CBSN(3); CBSN(4); CBSN(5); CBSN(6); CBSN(7); CBSN(8);
           CBSN(9); CBSN(10); CBSN(11); CBSN(12); CBSN(13); CBSN(14); CBSN(15); CBSN(16);
           CBSN(17); CBSN(18); CBSN(19); CBSN(20); CBSN(21); CBSN(22); CBSN(23); CBSN(24);
           CBSN(25); CBSN(26); CBSN(27); CBSN(28); CBSN(29); CBSN(30); CBSN(31); CBSN(32);
           CBSN(33); CBSN(34); CBSN(35); CBSN(36); CBSN(37); CBSN(38); CBSN(39); CBSN(40);
           CBSN(41); CBSN(42); CBSN(43); CBSN(44); CBSN(45); CBSN(46); CBSN(47); CBSN(48);
           CBSN(49); CBSN(50); CBSN(51); CBSN(52); CBSN(53); CBSN(54); CBSN(55); CBSN(56);
           CBSN(57); CBSN(58); CBSN(59); CBSN(60); CBSN(61); CBSN(62); CBSN(63); CBSN(64);
        }
        assert(0);
    }
    switch (bits) {
       CBGN(1); CBGN(2); CBGN(3); CBGN(4); CBGN(5); CBGN(6); CBGN(7); CBGN(8);
       CBGN(9); CBGN(10); CBGN(11); CBGN(12); CBGN(13); CBGN(14); CBGN(15); CBGN(16);
       CBGN(17); CBGN(18); CBGN(19); CBGN(20); CBGN(21); CBGN(22); CBGN(23); CBGN(24);
       CBGN(25); CBGN(26); CBGN(27); CBGN(28); CBGN(29); CBGN(30); CBGN(31); CBGN(32);
       CBGN(33); CBGN(34); CBGN(35); CBGN(36); CBGN(37); CBGN(38); CBGN(39); CBGN(40);
       CBGN(41); CBGN(42); CBGN(43); CBGN(44); CBGN(45); CBGN(46); CBGN(47); CBGN(48);
       CBGN(49); CBGN(50); CBGN(51); CBGN(52); CBGN(53); CBGN(54); CBGN(55); CBGN(56);
       CBGN(57); CBGN(58); CBGN(59); CBGN(60); CBGN(61); CBGN(62); CBGN(63); CBGN(64);
       default: assert(0);
    }
    *valPtr = val;
    return 1;
}

static Jsi_RC jsi_csSBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {
    Jsi_Wide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>=64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef __int128 stvalType;
#else
    typedef Jsi_Wide stvalType;
#endif
    stvalType tbuf[2] = {};
    uchar sbuf[20], *bptr = (uchar*)tbuf;
    memcpy(tbuf, rec+ofs, Bsz);
    Jsi_Wide mval = *valPtr;
    Jsi_Wide amask = ((1LL<<(bits-1))-1LL);
    stvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;
        if (!isSet) {
            mval = (Jsi_Wide)tval;
            *(Jsi_Wide*)bptr = mval;
        }
    }
        
    if (!isSet) { // Get value.
        if (!jsi_csSBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
        return JSI_OK;
    }
    
    if (!jsi_csSBitSetGet(1, bptr, bits, &mval))
        return JSI_ERROR;
    if (bo) {
        tval = (typeof(tval))mval;
        lmask=(amask<<bo);
        kval &= ~lmask;
        tval <<= bo;
        tval = (kval | tval);
        *(typeof(tval)*)tbuf = tval;
    }
    memcpy(rec+ofs, tbuf, Bsz);

    return JSI_OK;    
}

static Jsi_RC jsi_csBitGetSet(Jsi_Interp *interp, void *vrec,  Jsi_Wide* vPtr, Jsi_OptionSpec *spec, int idx, bool isSet) {
    bool us = (spec->tname && spec->tname[0] == 'u');
    if (!us)        
        return jsi_csSBitGetSet(interp, vrec, vPtr, spec, idx, isSet);

    if (*vPtr<0)
        return JSI_ERROR;

    Jsi_UWide *valPtr = (typeof(valPtr))vPtr;
    int bits = spec->bits;
    int boffs = spec->boffset;
    if (bits<1 || bits>=64) return JSI_ERROR;
    int ofs = (boffs/8);
    int bo = (boffs%8); // 0 if byte-aligned
    int Bsz = ((bits+bo+7)/8);
    uchar *rec = (uchar*)vrec;
#ifdef __SIZEOF_INT128__
    typedef unsigned __int128 utvalType;
#else
................................................................................
    Jsi_UWide mval;
    Jsi_UWide amask = ((1LL<<(bits-1))-1LL);
    utvalType tval = 0, kval = 0, lmask;
    if (bo) { // If not byte aligned, get tval and shift
        bptr = sbuf;
        kval = tval = *(typeof(tval)*)tbuf;
        tval >>= bo;
        if (!isSet) {
            mval = (Jsi_UWide)tval;
            *(Jsi_UWide*)bptr = mval;
        }
    } else
         mval = *valPtr;
        
    if (!isSet) { // Get value.
        if (!jsi_csBitSetGet(0, bptr, bits, &mval))
            return JSI_ERROR;
        *valPtr = mval;
................................................................................
    }
    Jsi_Free(dptr);
    Jsi_MapEntryDelete(mPtr);
    return JSI_OK;

}

#define FN_cdataConstructor JSI_INFO("\
The 2nd arg is used for function option parsing and will report errors at the callers file:line")
static Jsi_RC CDataConstructor(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
    Jsi_Value **ret, Jsi_Func *funcPtr);
    
/* Defines: Handles the "Data" subcommand */
static Jsi_CmdSpec cdataCmds[] =
{
    {"CData",     CDataConstructor,1, 2, "options:string|object=void, inits:object=void",.help="Create a new struct or map/array of structs", .retType=(uint)JSI_TT_USEROBJ, .flags=JSI_CMD_IS_CONSTRUCTOR, .info=FN_cdataConstructor, .opts=CDataOptions},
    {"conf",      CDataConfCmd,    0, 1, "options:object|string=void",.help="Configure options for c-data", .retType=0, .flags=0, .info=0, .opts=CDataOptions},
    {"get"   ,    CDataGetCmd,     0, 2, "key:string|number|object=null, field:string=void", .help="Get struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"incr",      CDataIncrCmd,    3, 3, "key:string|number|object|null, field:object|string, value:number", .help="Increment a numeric field: returns the new value", .retType=(uint)JSI_TT_NUMBER},
    {"info",      CDataInfoCmd,    0, 0, "", .help="Return info for data", .retType=(uint)JSI_TT_OBJECT},
    {"names",     CDataNamesCmd,   0, 0, "", .help="Return keys for map", .retType=(uint)JSI_TT_ARRAY },
    {"set",       CDataSetCmd,     2, 3, "key:string|number|object|null, field:object|string, value:any=void", .help="Set a struct/map/array value", .retType=(uint)JSI_TT_ANY},
    {"unset",     CDataUnsetCmd,   1, 1, "key:string|number|object", .help="Remove entry from map/array", .retType=(uint)JSI_TT_ANY},
    {NULL}
};
................................................................................
        that = *ret;
    }

    CDataObj *cd = (typeof(cd))Jsi_Calloc(1,sizeof(*cd));
    cd->interp = interp;
    Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
    Jsi_vtype vtyp = Jsi_ValueTypeGet(val);
    int vlen, isNew = 0;
    const char *vstr = Jsi_ValueString(interp, val, &vlen);
    Jsi_DString dStr = {};
    Jsi_Value *ival = Jsi_ValueArrayIndex(interp, args, 1);
    if (ival && !Jsi_ValueIsObjType(interp, ival, JSI_OT_OBJECT))
        return Jsi_LogError("arg 2: expected object");
    if (vstr && vlen) {
        char ech = 0;
        const char *nstr = vstr, *cp = vstr;
        while (*cp && (isalnum(*cp) || *cp=='_')) cp++;
        if (*cp) {
            int slen = cp-vstr;
            Jsi_DString sStr = {};
................................................................................
    } else if (vtyp != JSI_VT_OBJECT) {
        Jsi_LogError("expected string, object");
        goto errout;
    }
    if (val && Jsi_OptionsProcess(interp, CDataOptions, cd, val, 0) < 0)
        goto errout;

    if (ival && (cd->mapPtr || cd->arrSize)) {
        Jsi_LogError("init can not be used with c-array/map");
        goto errout;
     }
  
    if (JSI_OK != jsi_csNewCData(interp, cd, JSI_OPT_NO_SIG))
        goto errout;

    if (ival) {
        interp->callerErr = 1;
        Jsi_RC rc = Jsi_OptionsConf(interp, (Jsi_OptionSpec*)cd->sf, cd->data, ival, ret, 0);
        interp->callerErr = 0;
        if (rc != JSI_OK) {
            isNew = 1;
            goto errout;
        }
    }
        
    nobj = (Jsi_Obj*)Jsi_ValueGetObj(interp, that);
    cd->objId = Jsi_UserObjNew(interp, &cdataobject, nobj, cd);
    if (cd->objId<0) {
        goto errout;
    }
    cd->fobj = nobj;
    return JSI_OK;
    
errout:
    Jsi_DSFree(&dStr);
    Jsi_OptionsFree(interp, CDataOptions, cd, 0);
    if (isNew)
       jsi_csObjFree(interp, cd);
    else
        Jsi_Free(cd);
    return JSI_ERROR;

}

// Globals

static Jsi_RC jsi_DoneCData(Jsi_Interp *interp)

Changes to src/jsiChar.c.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
char *Jsi_Strdup(const char *str) {
    return strdup(str);
}

char *Jsi_StrdupLen(const char *str, int len) {
    if (len<0)
        len = Jsi_Strlen(str);
    char *cp = Jsi_Malloc(len+1);
    cp = memcpy(cp, str, len);
    cp[len] = 0;
    return cp;
}

char *jsi_SubstrDup(const char *a, int start, int len)
{
    if (len == 0) return Jsi_Strdup("");







|
|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
char *Jsi_Strdup(const char *str) {
    return strdup(str);
}

char *Jsi_StrdupLen(const char *str, int len) {
    if (len<0)
        len = Jsi_Strlen(str);
    char *cp = (char*)Jsi_Malloc(len+1);
    memcpy(cp, str, len);
    cp[len] = 0;
    return cp;
}

char *jsi_SubstrDup(const char *a, int start, int len)
{
    if (len == 0) return Jsi_Strdup("");

Changes to src/jsiCmds.c.

4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
#ifndef JSI_OMIT_LOAD
    { "load",       jsi_LoadLoadCmd, 1,  1, "shlib:string", .help="Load a shared executable and invoke its _Init call", .retType=(uint)JSI_TT_VOID },
#endif
    { "log",        SysLogCmd,       1, -1, "val, ...", .help="Same as puts, but includes file:line", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "noOp",       jsi_NoOpCmd,     0, -1, "", .help="A No-Op. A zero overhead command call that is useful for debugging" },
    { "parseInt",   parseIntCmd,     1,  2, "val:any, base:number=10", .help="Convert string to an integer", .retType=(uint)JSI_TT_NUMBER },
    { "parseFloat", parseFloatCmd,   1,  1, "val", .help="Convert string to a double", .retType=(uint)JSI_TT_NUMBER },
    { "parseOpts",  SysParseOptsCmd, 2,  3, "self:object, options:object, conf:object|null|undefined", .help="Parse options", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "printf",     SysPrintfCmd,    1, -1, "format:string, ...", .help="Formatted output to stdout", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "provide",    SysProvideCmd,   0,  2, "name:string|function=void, version:number|string=1.0", .help="Provide a package for use with require. Default is the file tail-rootname", .retType=(uint)JSI_TT_VOID },
    { "puts",       SysPutsCmd,      1, -1, "val, ...", .help="Output one or more values to stdout", .retType=(uint)JSI_TT_VOID, .flags=0, .info=FN_puts },
    { "quote",      SysQuoteCmd,     1,  1, "val:string", .help="Return quoted string", .retType=(uint)JSI_TT_STRING },
    { "require",    SysRequireCmd,   0,  2, "name:string=void, version:number|string=1", .help="Load/query packages", .retType=(uint)JSI_TT_NUMBER|JSI_TT_OBJECT|JSI_TT_ARRAY, .flags=0, .info=FN_require },
    { "runModule",  SysRunModuleCmd, 0,  2, "cmd:string|function=void, conf:array=undefined", .help="Invoke named module. If name is empty, uses file basename. If isMain and no args givine parses console.args", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "sleep",      SysSleepCmd,     0,  1, "secs:number=1.0",  .help="sleep for N milliseconds, minimum .001", .retType=(uint)JSI_TT_VOID },







|







4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
#ifndef JSI_OMIT_LOAD
    { "load",       jsi_LoadLoadCmd, 1,  1, "shlib:string", .help="Load a shared executable and invoke its _Init call", .retType=(uint)JSI_TT_VOID },
#endif
    { "log",        SysLogCmd,       1, -1, "val, ...", .help="Same as puts, but includes file:line", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "noOp",       jsi_NoOpCmd,     0, -1, "", .help="A No-Op. A zero overhead command call that is useful for debugging" },
    { "parseInt",   parseIntCmd,     1,  2, "val:any, base:number=10", .help="Convert string to an integer", .retType=(uint)JSI_TT_NUMBER },
    { "parseFloat", parseFloatCmd,   1,  1, "val", .help="Convert string to a double", .retType=(uint)JSI_TT_NUMBER },
    { "parseOpts",  SysParseOptsCmd, 2,  3, "self:object|userobj, options:object, conf:object|null|undefined", .help="Parse options", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "printf",     SysPrintfCmd,    1, -1, "format:string, ...", .help="Formatted output to stdout", .retType=(uint)JSI_TT_VOID, .flags=0 },
    { "provide",    SysProvideCmd,   0,  2, "name:string|function=void, version:number|string=1.0", .help="Provide a package for use with require. Default is the file tail-rootname", .retType=(uint)JSI_TT_VOID },
    { "puts",       SysPutsCmd,      1, -1, "val, ...", .help="Output one or more values to stdout", .retType=(uint)JSI_TT_VOID, .flags=0, .info=FN_puts },
    { "quote",      SysQuoteCmd,     1,  1, "val:string", .help="Return quoted string", .retType=(uint)JSI_TT_STRING },
    { "require",    SysRequireCmd,   0,  2, "name:string=void, version:number|string=1", .help="Load/query packages", .retType=(uint)JSI_TT_NUMBER|JSI_TT_OBJECT|JSI_TT_ARRAY, .flags=0, .info=FN_require },
    { "runModule",  SysRunModuleCmd, 0,  2, "cmd:string|function=void, conf:array=undefined", .help="Invoke named module. If name is empty, uses file basename. If isMain and no args givine parses console.args", .retType=(uint)JSI_TT_ANY, .flags=0},
    { "sleep",      SysSleepCmd,     0,  1, "secs:number=1.0",  .help="sleep for N milliseconds, minimum .001", .retType=(uint)JSI_TT_VOID },

Changes to src/jsiInt.h.

1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
....
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230



1231
1232
1233
1234
1235
1236
1237
    bool isMain;
    bool hasCallee;
    bool subthread;
    bool strict;
    bool protoInit;
    bool hasOpenSSL;
    bool isHelp;

    jsi_SubOptions subOpts;
    bool isInteractive;
    const char *confArgs;
    Jsi_Value *stdinStr;
    Jsi_Value *stdoutStr;
    Jsi_TypeCheck typeCheck;
    jsi_LogOptions logOpts;
................................................................................
    Jsi_Obj* cleanObjs[4];

    Jsi_Value *busyCallback;
    int busyInterval;
    int isInCallback;
    int objId;
    Jsi_Value *Top_object;
        Jsi_ScopeStrs *scopes[JSI_MAX_SCOPE];
    int cur_scope;
    int maxArrayList;
    int delRBCnt;
    Jsi_Func *activeFunc;  // Currently active function call.
    Jsi_Func *prevActiveFunc;  // Prev active function call.
    jsi_OpCode *curIp;  /* Used for debug Log msgs. */
    
    char *lastPushStr;  // Used by error handling and Jsi_LogMsg.   TODO: cleanup/rationalize.

    Jsi_Value* lastSubscriptFail;
    const char* lastSubscriptFailStr;




    Jsi_Wide sigmask;
    char errMsgBuf[JSI_BUFSIZ];  /* Error message space for when in try. */
    int errLine;
    int errCol;
    const char *errFile;
    Jsi_Mutex* Mutex;







>







 







|








>


>
>
>







1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
....
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
    bool isMain;
    bool hasCallee;
    bool subthread;
    bool strict;
    bool protoInit;
    bool hasOpenSSL;
    bool isHelp;
    bool callerErr;
    jsi_SubOptions subOpts;
    bool isInteractive;
    const char *confArgs;
    Jsi_Value *stdinStr;
    Jsi_Value *stdoutStr;
    Jsi_TypeCheck typeCheck;
    jsi_LogOptions logOpts;
................................................................................
    Jsi_Obj* cleanObjs[4];

    Jsi_Value *busyCallback;
    int busyInterval;
    int isInCallback;
    int objId;
    Jsi_Value *Top_object;
    Jsi_ScopeStrs *scopes[JSI_MAX_SCOPE];
    int cur_scope;
    int maxArrayList;
    int delRBCnt;
    Jsi_Func *activeFunc;  // Currently active function call.
    Jsi_Func *prevActiveFunc;  // Prev active function call.
    jsi_OpCode *curIp;  /* Used for debug Log msgs. */
    
    char *lastPushStr;  // Used by error handling and Jsi_LogMsg.   TODO: cleanup/rationalize.
    Jsi_Value* lastParseOpt;
    Jsi_Value* lastSubscriptFail;
    const char* lastSubscriptFailStr;
    int logErrorCnt;
    Jsi_OptionSpec *parseMsgSpec;


    Jsi_Wide sigmask;
    char errMsgBuf[JSI_BUFSIZ];  /* Error message space for when in try. */
    int errLine;
    int errCol;
    const char *errFile;
    Jsi_Mutex* Mutex;

Changes to src/jsiInterp.c.

1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
            interp->parent?" ::":"", (interp->parent&&interp->name?interp->name:""));
    }
    if (isMainInt || interp->strKeyTbl != jsiIntData.mainInterp->strKeyTbl)
        Jsi_MapDelete(interp->strKeyTbl);
    if (isMainInt)
        jsiIntData.mainInterp = NULL;

    SIGASSERT(interp,INTERP);
    _JSI_MEMCLEAR(interp);
    jsiIntData.delInterp = NULL;
    Jsi_Free(interp);
    return JSI_OK;
}

void Jsi_InterpDelete(Jsi_Interp* interp)







<







1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
            interp->parent?" ::":"", (interp->parent&&interp->name?interp->name:""));
    }
    if (isMainInt || interp->strKeyTbl != jsiIntData.mainInterp->strKeyTbl)
        Jsi_MapDelete(interp->strKeyTbl);
    if (isMainInt)
        jsiIntData.mainInterp = NULL;


    _JSI_MEMCLEAR(interp);
    jsiIntData.delInterp = NULL;
    Jsi_Free(interp);
    return JSI_OK;
}

void Jsi_InterpDelete(Jsi_Interp* interp)

Changes to src/jsiJSON.c.

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
    if (tok->size%2 || tok->type != JSI_JTYPE_OBJECT) {
        result = -1;
        goto done;
    }
    v = Jsi_ValueNew1(interp);
    for (i=1; i<p->toknext && i<tok->size; i++) {
        if (p->tokens[i].type != JSI_JTYPE_STRING) {
            Jsi_LogWarn("expected string at %d", i-1);
            goto bail;
        }
        name = Jsi_JsonGetTokstr(p, json, i, &len);
        Jsi_DSSetLength(&nStr, 0);
        Jsi_DSAppendLen(&nStr, name, len);
        name = Jsi_DSValue(&nStr);
        i++;
................................................................................
                    Jsi_ValueMakeBool(interp, &v, (bool)(len==4?1:0));
                } else if (len == 4 && Jsi_Strncmp(t, "null", len)==0) {
                    Jsi_ValueMakeNull(interp, &v);
                } else {
                    char *ep;
                    Jsi_Number d = strtod(t,&ep);
                    if (ep>(t+len)) {
                        Jsi_LogWarn("bad number %*s", len, t);
                        goto bail;
                    }
                    Jsi_ValueMakeNumber(interp, &v, d);
                }
                break;
            case JSI_JTYPE_STRING:
                t = Jsi_JsonGetTokstr(p, json, i, &len);







|







 







|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
    if (tok->size%2 || tok->type != JSI_JTYPE_OBJECT) {
        result = -1;
        goto done;
    }
    v = Jsi_ValueNew1(interp);
    for (i=1; i<p->toknext && i<tok->size; i++) {
        if (p->tokens[i].type != JSI_JTYPE_STRING) {
            result = Jsi_LogError("expected string at %d", i-1);
            goto bail;
        }
        name = Jsi_JsonGetTokstr(p, json, i, &len);
        Jsi_DSSetLength(&nStr, 0);
        Jsi_DSAppendLen(&nStr, name, len);
        name = Jsi_DSValue(&nStr);
        i++;
................................................................................
                    Jsi_ValueMakeBool(interp, &v, (bool)(len==4?1:0));
                } else if (len == 4 && Jsi_Strncmp(t, "null", len)==0) {
                    Jsi_ValueMakeNull(interp, &v);
                } else {
                    char *ep;
                    Jsi_Number d = strtod(t,&ep);
                    if (ep>(t+len)) {
                        result = Jsi_LogError("bad number %*s", len, t);
                        goto bail;
                    }
                    Jsi_ValueMakeNumber(interp, &v, d);
                }
                break;
            case JSI_JTYPE_STRING:
                t = Jsi_JsonGetTokstr(p, json, i, &len);

Changes to src/jsiOptions.c.

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224


225
226
227
228
229
230



231

232
233


234
235

236
237
238
239
240
241
242
243
244
245
246
247
248


249
250
251
252
253
254
255
256
257
258
259
...
269
270
271
272
273
274
275



276
277
278
279
280
281
282
...
308
309
310
311
312
313
314


315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
344
345
346
347
348
349
350
351
352
353
354



355
356
357
358
359
360
361
362
363
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399
...
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
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
502
503
504
505
506
507
508
509
510
511
512
...
513
514
515
516
517
518
519

















520
521
522
523
524
525
526
...
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
....
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
....
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
....
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
....
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
....
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
....
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
....
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
        return (Jsi_OptionSpec *) NULL;
    }
    return matchPtr;
}


Jsi_RC
jsi_SetOption(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Wide wcount = 0;
    bool bn;
    Jsi_Number nv;
    bool isIncr = (flags & JSI_OPTS_INCR);
    const char *expType = NULL;
    char *record = (char*)rec, *ptr = record + specPtr->offset;


    
    if (specPtr->id<JSI_OPTION_BOOL || specPtr->id>=JSI_OPTION_END) 
        return Jsi_LogError("unknown option id \"%d\" for \"%s\"", specPtr->id, specPtr->name);
    if (specPtr->custom) {
        Jsi_OptionCustom* cust = Jsi_OptionCustomBuiltin(specPtr->custom);
        if (cust && cust->parseProc) {



            if ((*cust->parseProc)(interp, specPtr, argValue, NULL, record, flags) != JSI_OK) {

                if (!interp->csc)
                    Jsi_LogError("failed parse for option \"%s\"", specPtr->name);


                return JSI_ERROR;
            }

        } else 
            return Jsi_LogError("missing or bad custom for \"%s\"", specPtr->name);
        goto done;
    }

    switch (specPtr->id) {
    case JSI_OPTION_CUSTOM:
        if (!specPtr->custom) 
            return Jsi_LogError("missing or custom for \"%s\"", specPtr->name);

    case JSI_OPTION_BOOL: {
        if (!argValue)
            *(char*)ptr = 0;


        else if (Jsi_GetBoolFromValue(interp, argValue, &bn) != JSI_OK)
            return JSI_ERROR;
        else
            *(char*)ptr = bn;
        break;
    }

    case JSI_OPTION_INT:
    case JSI_OPTION_UINT:
    case JSI_OPTION_LONG:
    case JSI_OPTION_INTPTR_T:
................................................................................
    case JSI_OPTION_UINT8:
    case JSI_OPTION_INT16:
    case JSI_OPTION_UINT16:
    case JSI_OPTION_INT32:
    case JSI_OPTION_UINT32:
        wcount = 0;
        if (argValue) {



            if (Jsi_GetWideFromValue(interp, argValue, &wcount) != JSI_OK) {
                return JSI_ERROR;
            }
            
        }
        switch (specPtr->id) {
#define _JSI_OPTSETTYP(typ, n, ptr) if (isIncr) n += *((typ *)ptr); \
................................................................................

    case JSI_OPTION_NUMBER:
    case JSI_OPTION_DOUBLE:
    case JSI_OPTION_LDOUBLE:
    case JSI_OPTION_FLOAT:
        nv = 0;
        if (argValue) {


            if (Jsi_GetNumberFromValue(interp, argValue, &nv) != JSI_OK) {
                return JSI_ERROR;
            }
        }
            
        switch (specPtr->id) {
#define _JSI_OPTSETNTYP(typ, n, ptr) if (!argValue) *(typ*)ptr = 0; else { if (isIncr) n += *((typ *)ptr); \
            interp->cdataIncrVal = *((typ *)ptr) = (typ)(n); \
            if (jsi_IsStrictMode(interp) && !Jsi_NumberIsNaN((Jsi_Number)(*((typ *)ptr)))) return Jsi_LogError("not a number"); }

            case JSI_OPTION_NUMBER: _JSI_OPTSETNTYP(Jsi_Number, nv, ptr); break;
            case JSI_OPTION_LDOUBLE: _JSI_OPTSETNTYP(ldouble, nv, ptr); break;
            case JSI_OPTION_FLOAT: _JSI_OPTSETNTYP(float, nv, ptr); break;
            case JSI_OPTION_DOUBLE: _JSI_OPTSETNTYP(double, nv, ptr); break;
            default: break;
        }
................................................................................
    }
    break;
    case JSI_OPTION_STRBUF:
    {
        if (argValue == NULL || Jsi_ValueIsNull(interp, argValue))
            *(char*)ptr = 0;
        else {
            const char *scp;
            if (Jsi_GetStringFromValue(interp, argValue, &scp) != JSI_OK) {
                return JSI_ERROR;
            }



            Jsi_Strncpy((char*)ptr, scp, specPtr->size);
            ((char*)ptr)[specPtr->size-1] = 0;
        }
    }
    break;
    
#define _JSI_OPT_CHECKNULL(argValue) if (!argValue || Jsi_ValueIsNull(interp, argValue)) { \
         if (*((Jsi_Value **)ptr)) \
            Jsi_DecrRefCount(interp, *((Jsi_Value **)ptr)); \
................................................................................
    }\
    *((Jsi_Value **)ptr) = argValue;
    
    case JSI_OPTION_STRING:
        if (argValue == *((Jsi_Value **)ptr))
            break;
        _JSI_OPT_CHECKNULL(argValue);
        if (!Jsi_ValueIsString(interp, argValue)) 
            return Jsi_LogError("expected a string");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_DSTRING:
        Jsi_DSInit((Jsi_DString *)ptr);
        if (argValue && !Jsi_ValueIsNull(interp, argValue))
        {
            const char *scp;
            if (Jsi_GetStringFromValue(interp, argValue, &scp) != JSI_OK) {
                return JSI_ERROR;
            }

            Jsi_DSAppend((Jsi_DString *)ptr, scp, NULL);
        }
        break;
    
    case JSI_OPTION_TIME_D: {
       if (argValue)
        {
            Jsi_Number nv = 0;
................................................................................
            *(time_t*)ptr = 0;
        }
        break;
    }
    case JSI_OPTION_VAR:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_NULL && argValue->vt != JSI_VT_VARIABLE) 
            return Jsi_LogError("expected a var");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_FUNC:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_FUNCTION) 
            return Jsi_LogError("expected a func value");
        if (specPtr->data && (interp->typeCheck.run|interp->typeCheck.all))
            if (!jsi_FuncArgCheck(interp, argValue->d.obj->d.fobj->func, (char*)specPtr->data)) 
                return Jsi_LogError("failed setting func pointer for %s", specPtr->name);

        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_USEROBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_USEROBJ) 
            return Jsi_LogError("expected a userobj value");
        if (specPtr->data && Jsi_Strcmp((char*)specPtr->data, argValue->d.obj->d.uobj->reg->name)) 
            return Jsi_LogError("expected id %s for %s",(char*)specPtr->data,  specPtr->name);
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_REGEXP:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_REGEXP) 
            return Jsi_LogError("expected a regexp value");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_OBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT) 
            return Jsi_LogError("expected an object");

    case JSI_OPTION_VALUE:
         _JSI_OPT_CHECKNULL(argValue);
         _JSI_OPT_ARGSET(argValue, ptr);
        break;
    case JSI_OPTION_ARRAY:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || !argValue->d.obj->isarrlist) 
            return Jsi_LogError("expected an array");
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
#ifdef __cplusplus
    case JSI_OPTION_END:
#else
    default:
#endif
................................................................................
        Jsi_LogBug("invalid option id: %d", specPtr->id);
    }
done:
    specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    if (isIncr)
        return Jsi_LogError("incr invalid for %s", specPtr->name);
    return JSI_OK;

















}

Jsi_RC
Jsi_OptionsSet(Jsi_Interp *interp, Jsi_OptionSpec *specs, void* rec, const char *option, Jsi_Value *valuePtr, Jsi_Wide flags)
{
    char *record = (char*)rec;
    Jsi_OptionSpec *specPtr;
................................................................................
            goto done;
        }
        if (((JSI_OPT_PASS2&flags) && !(JSI_OPT_PASS2&specPtr->flags))
            || ((JSI_OPT_PASS2&specPtr->flags) && !(JSI_OPT_PASS2&flags)))
            continue;
            
        if ((JSI_OPT_READ_ONLY&specPtr->flags)) {
            Jsi_LogWarn("Error option is readonly: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
        if ((JSI_OPTS_IS_UPDATE&flags) && (JSI_OPT_INIT_ONLY&specPtr->flags)) {
            Jsi_LogWarn("Error can not update option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }

        if (jsi_SetOption(interp, specPtr, (char*)arg, record, optval, flags) != JSI_OK) {
            Jsi_LogWarn("Error processing option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
 
        specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    }
    if (reqCnt) {
        for (specPtr = specs; specPtr->id>=JSI_OPTION_BOOL && specPtr->id < JSI_OPTION_END && specPtr->name; specPtr++) {
            if (specPtr->flags &  JSI_OPT_REQUIRED &&
                !(specPtr->flags&JSI_OPT_IS_SPECIFIED)) {

                Jsi_LogWarn("Error required field not specified: \"%.40s\"", specPtr->name);
                count = -1;
            }
        }
    }

done:
    Jsi_TreeSearchDone(&search);
................................................................................
        Jsi_Value *svalue = Jsi_ValueMakeObject(interp, NULL, sobj);
        jsi_DumpOptionSpecs(interp, sobj, specs);
        Jsi_ValueReplace(interp, ret, svalue);
        return JSI_OK;
    }
    if (val->vt != JSI_VT_OBJECT) 
        return Jsi_LogError("expected string, object, or null");
    if (Jsi_OptionsProcess(interp, specs, rec, val, JSI_OPTS_IS_UPDATE) < 0)
        return JSI_ERROR;
    return JSI_OK;
}

static const char **jsi_OptGetEnumList(Jsi_OptionSpec* spec) {
    const char **list = (const char**)spec->data;
    Jsi_OptionSpec* es=NULL;
................................................................................
            for (i=0; i<n && list[i]; i++) ; /* Look forward til n */
        if (list[i])
            Jsi_DSAppendLen(outStr, list[i], -1);
        else if ((spec->flags&JSI_OPT_COERCE)) {
            Jsi_DSPrintf(outStr, "%" PRIu64, (uint64_t)n);
            return JSI_OK;
        } else
            return Jsi_LogWarn("enum has unknown value: %d", *s);
        return JSI_OK;
    }
#ifndef JSI_LITE_ONLY
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
    Jsi_RC rc = jsi_EnumToValue(interp, spec, NULL, &dStr, record, flags);
    if (rc == JSI_OK)
................................................................................
    if (!interp->parent) return;
    if (*v)
        Jsi_DecrRefCount(interp->parent, *v);
    *v = NULL;
}

static Jsi_OptionCustom jsi_OptSwitchParentFunc = {
    .name="suboption", .parseProc=jsi_ValueToParentFunc, .formatProc=jsi_ParentFuncToValue, .freeProc=jsi_ParentFuncFree,
};

/* Scanning function */
static Jsi_RC jsi_ValueToBitfield(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue,
    const char *inStr, void *record, Jsi_Wide flags)
{
    Jsi_csgset *bsget = spec->init.OPT_BITS;
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    Jsi_Number num;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogError("invalid bitfield");
    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = {};
        Jsi_OptionSpec eSpec[] = {
            JSI_OPT(CUSTOM, typeof(nval), numVal, .help=spec->help, .flags=JSI_OPT_ENUM_SPEC,
                .custom=Jsi_Opt_SwitchEnum, .data=(void*)enumSpec, .info=0, .tname=spec->tname, .value=0, .bits=0, .boffset=8*sizeof(int64_t) ),
            JSI_OPT_END(typeof(nval))
        };
................................................................................
            return JSI_ERROR;
        num = (Jsi_Number)nval.numVal;
    } else if (inStr) {
        if (Jsi_GetDouble(interp, inStr, &num) != JSI_OK)
            return JSI_ERROR;
    } else {
        if (inValue && !Jsi_ValueIsNumber(interp, inValue)) 
            return Jsi_LogError("expected number");
        Jsi_ValueGetNumber(interp, inValue, &num);
    }
    int64_t inum = (int64_t)num;
    return (*bsget)(interp, data, &inum, spec, idx, 1);
}

/* Printing function. */
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    int64_t inum;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogError("invalid bitfield");
    Jsi_RC rc = (*bsget)(interp, data, &inum, spec, idx, 0);
    if (rc != JSI_OK)
        return JSI_ERROR;

    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = { inum };
        Jsi_OptionSpec eSpec[] = {
................................................................................
        Jsi_Number num = (Jsi_Number)inum;
        Jsi_ValueMakeNumber(interp, outValue, num);
    }
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchBitfield = {
    .name="suboption", .parseProc=jsi_ValueToBitfield, .formatProc=jsi_BitfieldToValue
};

/* Scanning function */
static Jsi_RC jsi_ValueToNull(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue, const char *inStr, void *record, Jsi_Wide flags)
{
    return JSI_OK;
}
................................................................................
static Jsi_RC jsi_NullToValue(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value **outValue, Jsi_DString *outStr, void *record, Jsi_Wide flags)
{
    Jsi_ValueMakeNull(interp, outValue);
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchNull = {
    .name="suboption", .parseProc=jsi_ValueToNull, .formatProc=jsi_NullToValue
};

#endif

typedef struct {
    Jsi_OptionInitVal init;
} jsi_IniValStruct;







|







>
>
|

|
|
|

>
>
>
|
>
|
<
>
>


>

|






|




>
>
|
<
<
|







 







>
>
>







 







>
>








|







 







|
|
|
<
>
>
>
|
|







 







|
|







|
|
|
<
>
|







 







|






|










|







|
|





|
|







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|




|





<











|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259


260
261
262
263
264
265
266
267
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
...
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
...
470
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
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
....
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
....
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
....
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
....
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
....
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
....
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
....
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
....
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
        return (Jsi_OptionSpec *) NULL;
    }
    return matchPtr;
}


Jsi_RC
jsi_SetOption_(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Wide wcount = 0;
    bool bn;
    Jsi_Number nv;
    bool isIncr = (flags & JSI_OPTS_INCR);
    const char *expType = NULL;
    char *record = (char*)rec, *ptr = record + specPtr->offset;
    Jsi_OptionCustom* cust = NULL;
    const char *emsg = NULL, *epre = "";

    if (specPtr->id<JSI_OPTION_BOOL || specPtr->id>=JSI_OPTION_END) 
        return Jsi_LogBug("unknown option id \"%d\" for \"%s\"", specPtr->id, specPtr->name);
    if (specPtr->custom  && specPtr->id == JSI_OPTION_CUSTOM) {
        cust = Jsi_OptionCustomBuiltin(specPtr->custom);
        if (cust && cust->parseProc) {
            int lastErrCnt = interp->logErrorCnt;
            Jsi_OptionSpec *oep = interp->parseMsgSpec;
            interp->parseMsgSpec = specPtr;
            Jsi_RC rc = (*cust->parseProc)(interp, specPtr, argValue, NULL, record, flags);
            if (rc != JSI_OK) {
                if (!interp->csc || lastErrCnt == interp->logErrorCnt)

                    Jsi_LogError("invalid value");
                interp->parseMsgSpec = oep;
                return JSI_ERROR;
            }
            interp->parseMsgSpec = oep;
        } else 
            return Jsi_LogBug("missing or bad custom for \"%s\"", specPtr->name);
        goto done;
    }

    switch (specPtr->id) {
    case JSI_OPTION_CUSTOM:
        if (!specPtr->custom) 
            return Jsi_LogBug("missing or custom for \"%s\"", specPtr->name);

    case JSI_OPTION_BOOL: {
        if (!argValue)
            *(char*)ptr = 0;
        else if (!Jsi_ValueIsBoolean(interp, argValue))
            goto bail;
        Jsi_GetBoolFromValue(interp, argValue, &bn);


        *(char*)ptr = bn;
        break;
    }

    case JSI_OPTION_INT:
    case JSI_OPTION_UINT:
    case JSI_OPTION_LONG:
    case JSI_OPTION_INTPTR_T:
................................................................................
    case JSI_OPTION_UINT8:
    case JSI_OPTION_INT16:
    case JSI_OPTION_UINT16:
    case JSI_OPTION_INT32:
    case JSI_OPTION_UINT32:
        wcount = 0;
        if (argValue) {
            if (!Jsi_ValueIsNumber(interp, argValue))
                goto bail;

            if (Jsi_GetWideFromValue(interp, argValue, &wcount) != JSI_OK) {
                return JSI_ERROR;
            }
            
        }
        switch (specPtr->id) {
#define _JSI_OPTSETTYP(typ, n, ptr) if (isIncr) n += *((typ *)ptr); \
................................................................................

    case JSI_OPTION_NUMBER:
    case JSI_OPTION_DOUBLE:
    case JSI_OPTION_LDOUBLE:
    case JSI_OPTION_FLOAT:
        nv = 0;
        if (argValue) {
            if (!Jsi_ValueIsNumber(interp, argValue))
                goto bail;
            if (Jsi_GetNumberFromValue(interp, argValue, &nv) != JSI_OK) {
                return JSI_ERROR;
            }
        }
            
        switch (specPtr->id) {
#define _JSI_OPTSETNTYP(typ, n, ptr) if (!argValue) *(typ*)ptr = 0; else { if (isIncr) n += *((typ *)ptr); \
            interp->cdataIncrVal = *((typ *)ptr) = (typ)(n); \
            if (jsi_IsStrictMode(interp) && Jsi_NumberIsNaN((Jsi_Number)(*((typ *)ptr)))) return Jsi_LogError("not a number"); }

            case JSI_OPTION_NUMBER: _JSI_OPTSETNTYP(Jsi_Number, nv, ptr); break;
            case JSI_OPTION_LDOUBLE: _JSI_OPTSETNTYP(ldouble, nv, ptr); break;
            case JSI_OPTION_FLOAT: _JSI_OPTSETNTYP(float, nv, ptr); break;
            case JSI_OPTION_DOUBLE: _JSI_OPTSETNTYP(double, nv, ptr); break;
            default: break;
        }
................................................................................
    }
    break;
    case JSI_OPTION_STRBUF:
    {
        if (argValue == NULL || Jsi_ValueIsNull(interp, argValue))
            *(char*)ptr = 0;
        else {
            int sLen;
            const char *scp = Jsi_ValueString(interp, argValue, &sLen);
            if (!scp)

                goto bail;
            if (sLen>(int)(specPtr->size-1))
                sLen = specPtr->size-1;
            memcpy((char*)ptr, scp, sLen);
            ((char*)ptr)[sLen] = 0;
        }
    }
    break;
    
#define _JSI_OPT_CHECKNULL(argValue) if (!argValue || Jsi_ValueIsNull(interp, argValue)) { \
         if (*((Jsi_Value **)ptr)) \
            Jsi_DecrRefCount(interp, *((Jsi_Value **)ptr)); \
................................................................................
    }\
    *((Jsi_Value **)ptr) = argValue;
    
    case JSI_OPTION_STRING:
        if (argValue == *((Jsi_Value **)ptr))
            break;
        _JSI_OPT_CHECKNULL(argValue);
        if (!Jsi_ValueIsString(interp, argValue))
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_DSTRING:
        Jsi_DSInit((Jsi_DString *)ptr);
        if (argValue && !Jsi_ValueIsNull(interp, argValue))
        {
            int sLen;
            const char *scp = Jsi_ValueString(interp, argValue, &sLen);
            if (!scp)

                goto bail;
            Jsi_DSAppendLen((Jsi_DString *)ptr, scp, sLen);
        }
        break;
    
    case JSI_OPTION_TIME_D: {
       if (argValue)
        {
            Jsi_Number nv = 0;
................................................................................
            *(time_t*)ptr = 0;
        }
        break;
    }
    case JSI_OPTION_VAR:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_NULL && argValue->vt != JSI_VT_VARIABLE) 
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_FUNC:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_FUNCTION) 
            goto bail;
        if (specPtr->data && (interp->typeCheck.run|interp->typeCheck.all))
            if (!jsi_FuncArgCheck(interp, argValue->d.obj->d.fobj->func, (char*)specPtr->data)) 
                return Jsi_LogError("failed setting func pointer for %s", specPtr->name);

        _JSI_OPT_ARGSET(argValue, ptr);
        break;
        
    case JSI_OPTION_USEROBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_USEROBJ) 
            goto bail;
        if (specPtr->data && Jsi_Strcmp((char*)specPtr->data, argValue->d.obj->d.uobj->reg->name)) 
            return Jsi_LogError("expected id %s for %s",(char*)specPtr->data,  specPtr->name);
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_REGEXP:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || argValue->d.obj->ot != JSI_OT_REGEXP)
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;

    case JSI_OPTION_OBJ:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT)
            goto bail;

    case JSI_OPTION_VALUE:
         _JSI_OPT_CHECKNULL(argValue);
         _JSI_OPT_ARGSET(argValue, ptr);
        break;
    case JSI_OPTION_ARRAY:
        _JSI_OPT_CHECKNULL(argValue);
        if (argValue->vt != JSI_VT_OBJECT || !argValue->d.obj->isarrlist)
            goto bail;
        _JSI_OPT_ARGSET(argValue, ptr);
        break;
#ifdef __cplusplus
    case JSI_OPTION_END:
#else
    default:
#endif
................................................................................
        Jsi_LogBug("invalid option id: %d", specPtr->id);
    }
done:
    specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    if (isIncr)
        return Jsi_LogError("incr invalid for %s", specPtr->name);
    return JSI_OK;

bail:
    if (!emsg) {
        emsg = jsi_OptTypeInfo[specPtr->id].cName;
        epre = "expected ";
    }
    return Jsi_LogError("%s%s: for %s option \"%.40s\"", epre, emsg, (cust?cust->name:""), specPtr->name);
}

Jsi_RC
jsi_SetOption(Jsi_Interp *interp, Jsi_OptionSpec *specPtr, const char *string /*UNUSED*/, void* rec, Jsi_Value *argValue, Jsi_Wide flags)
{
    Jsi_Value *oa = interp->lastParseOpt;
    interp->lastParseOpt = argValue;
    Jsi_RC rc = jsi_SetOption_(interp, specPtr, string, rec, argValue, flags);
    interp->lastParseOpt = oa;
    return rc;
}

Jsi_RC
Jsi_OptionsSet(Jsi_Interp *interp, Jsi_OptionSpec *specs, void* rec, const char *option, Jsi_Value *valuePtr, Jsi_Wide flags)
{
    char *record = (char*)rec;
    Jsi_OptionSpec *specPtr;
................................................................................
            goto done;
        }
        if (((JSI_OPT_PASS2&flags) && !(JSI_OPT_PASS2&specPtr->flags))
            || ((JSI_OPT_PASS2&specPtr->flags) && !(JSI_OPT_PASS2&flags)))
            continue;
            
        if ((JSI_OPT_READ_ONLY&specPtr->flags)) {
            Jsi_LogError("Error option is readonly: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }
        if ((JSI_OPTS_IS_UPDATE&flags) && (JSI_OPT_INIT_ONLY&specPtr->flags)) {
            Jsi_LogError("Error can not update option: \"%.40s\"", specPtr->name);
            count = -1;
            goto done;
        }

        if (jsi_SetOption(interp, specPtr, (char*)arg, record, optval, flags) != JSI_OK) {

            count = -1;
            goto done;
        }
 
        specPtr->flags |= JSI_OPT_IS_SPECIFIED;
    }
    if (reqCnt) {
        for (specPtr = specs; specPtr->id>=JSI_OPTION_BOOL && specPtr->id < JSI_OPTION_END && specPtr->name; specPtr++) {
            if (specPtr->flags &  JSI_OPT_REQUIRED &&
                !(specPtr->flags&JSI_OPT_IS_SPECIFIED)) {

                Jsi_LogError("Error required field not specified: \"%.40s\"", specPtr->name);
                count = -1;
            }
        }
    }

done:
    Jsi_TreeSearchDone(&search);
................................................................................
        Jsi_Value *svalue = Jsi_ValueMakeObject(interp, NULL, sobj);
        jsi_DumpOptionSpecs(interp, sobj, specs);
        Jsi_ValueReplace(interp, ret, svalue);
        return JSI_OK;
    }
    if (val->vt != JSI_VT_OBJECT) 
        return Jsi_LogError("expected string, object, or null");
    if (Jsi_OptionsProcess(interp, specs, rec, val, JSI_OPTS_IS_UPDATE|flags) < 0)
        return JSI_ERROR;
    return JSI_OK;
}

static const char **jsi_OptGetEnumList(Jsi_OptionSpec* spec) {
    const char **list = (const char**)spec->data;
    Jsi_OptionSpec* es=NULL;
................................................................................
            for (i=0; i<n && list[i]; i++) ; /* Look forward til n */
        if (list[i])
            Jsi_DSAppendLen(outStr, list[i], -1);
        else if ((spec->flags&JSI_OPT_COERCE)) {
            Jsi_DSPrintf(outStr, "%" PRIu64, (uint64_t)n);
            return JSI_OK;
        } else
            return Jsi_LogError("enum has unknown value: %d", *s);
        return JSI_OK;
    }
#ifndef JSI_LITE_ONLY
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
    Jsi_RC rc = jsi_EnumToValue(interp, spec, NULL, &dStr, record, flags);
    if (rc == JSI_OK)
................................................................................
    if (!interp->parent) return;
    if (*v)
        Jsi_DecrRefCount(interp->parent, *v);
    *v = NULL;
}

static Jsi_OptionCustom jsi_OptSwitchParentFunc = {
    .name="funcinparent", .parseProc=jsi_ValueToParentFunc, .formatProc=jsi_ParentFuncToValue, .freeProc=jsi_ParentFuncFree,
};

/* Scanning function */
static Jsi_RC jsi_ValueToBitfield(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue,
    const char *inStr, void *record, Jsi_Wide flags)
{
    Jsi_csgset *bsget = spec->init.OPT_BITS;
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    Jsi_Number num;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogBug("invalid bitfield");
    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = {};
        Jsi_OptionSpec eSpec[] = {
            JSI_OPT(CUSTOM, typeof(nval), numVal, .help=spec->help, .flags=JSI_OPT_ENUM_SPEC,
                .custom=Jsi_Opt_SwitchEnum, .data=(void*)enumSpec, .info=0, .tname=spec->tname, .value=0, .bits=0, .boffset=8*sizeof(int64_t) ),
            JSI_OPT_END(typeof(nval))
        };
................................................................................
            return JSI_ERROR;
        num = (Jsi_Number)nval.numVal;
    } else if (inStr) {
        if (Jsi_GetDouble(interp, inStr, &num) != JSI_OK)
            return JSI_ERROR;
    } else {
        if (inValue && !Jsi_ValueIsNumber(interp, inValue)) 
            return JSI_ERROR;
        Jsi_ValueGetNumber(interp, inValue, &num);
    }
    int64_t inum = (int64_t)num;
    return (*bsget)(interp, data, &inum, spec, idx, 1);
}

/* Printing function. */
................................................................................
    Jsi_Interp *d = interp;
    int idx = spec->idx;
    uchar *data = (uchar*)record;
    int64_t inum;
    Jsi_OptionSpec* enumSpec = (typeof(enumSpec))spec->data;

    if (!d || !bsget || idx<0) 
        return Jsi_LogBug("invalid bitfield");
    Jsi_RC rc = (*bsget)(interp, data, &inum, spec, idx, 0);
    if (rc != JSI_OK)
        return JSI_ERROR;

    if (enumSpec) {
        struct numStruct { int64_t numVal; } nval = { inum };
        Jsi_OptionSpec eSpec[] = {
................................................................................
        Jsi_Number num = (Jsi_Number)inum;
        Jsi_ValueMakeNumber(interp, outValue, num);
    }
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchBitfield = {
    .name="bitfield", .parseProc=jsi_ValueToBitfield, .formatProc=jsi_BitfieldToValue
};

/* Scanning function */
static Jsi_RC jsi_ValueToNull(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value *inValue, const char *inStr, void *record, Jsi_Wide flags)
{
    return JSI_OK;
}
................................................................................
static Jsi_RC jsi_NullToValue(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_Value **outValue, Jsi_DString *outStr, void *record, Jsi_Wide flags)
{
    Jsi_ValueMakeNull(interp, outValue);
    return JSI_OK;
}

static Jsi_OptionCustom jsi_OptSwitchNull = {
    .name="null", .parseProc=jsi_ValueToNull, .formatProc=jsi_NullToValue
};

#endif

typedef struct {
    Jsi_OptionInitVal init;
} jsi_IniValStruct;

Changes to src/jsiPstate.c.

240
241
242
243
244
245
246

247

248

249
250
251
252
253
254
255
256
    /* TODO: when do we free opcodes */
    jsi_PstateClear(ps);
    Jsi_Free(ps->lexer);
    if (ps->opcodes)
        jsi_FreeOpcodes(ps->opcodes);
    if (ps->hPtr)
        Jsi_HashEntryDelete(ps->hPtr);

    Jsi_HashDelete(ps->argsTbl);

    Jsi_HashDelete(ps->strTbl);

    Jsi_HashDelete(ps->fastVarTbl);
    if (ps->last_exception)
        Jsi_DecrRefCount(ps->interp, ps->last_exception);
    _JSI_MEMCLEAR(ps);
    Jsi_Free(ps);
}

#endif







>
|
>
|
>
|







240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    /* TODO: when do we free opcodes */
    jsi_PstateClear(ps);
    Jsi_Free(ps->lexer);
    if (ps->opcodes)
        jsi_FreeOpcodes(ps->opcodes);
    if (ps->hPtr)
        Jsi_HashEntryDelete(ps->hPtr);
    if (ps->argsTbl)
        Jsi_HashDelete(ps->argsTbl);
    if (ps->strTbl)
        Jsi_HashDelete(ps->strTbl);
    if (ps->fastVarTbl)
        Jsi_HashDelete(ps->fastVarTbl);
    if (ps->last_exception)
        Jsi_DecrRefCount(ps->interp, ps->last_exception);
    _JSI_MEMCLEAR(ps);
    Jsi_Free(ps);
}

#endif

Changes to src/jsiSqlite.c.

955
956
957
958
959
960
961

962
963
964
965
966
967
968
969
....
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
....
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
//  Jsi_Interp *interp = p->jdb->interp;

    if( p->pPreStmt ) {
        sqlite3_reset(p->pPreStmt->pStmt);
        dbReleaseStmt(p->jdb, p->pPreStmt, p->nocache);
        p->pPreStmt = 0;
    }

    Jsi_DSFree(p->dSql);
    dbReleaseColumnNames(p);
}

static void DbClose(sqlite3 *db) {
        sqlite3_close(db);
}

................................................................................
#endif
    const char *zSql = Jsi_ValueGetDString(interp, vSql, &eStr, 0);
    Jsi_Value *arg = Jsi_ValueArrayIndex(interp, args, 1);
    int cnt = 0;
    char **apColName = NULL;
    int *apColType = NULL, isopts = 0;
    DbEvalContext sEval = {};
    QueryOpts opts, *oEopt = NULL;
    opts = jdb->queryOpts;
    opts.callback = NULL;
    opts.width = NULL;
    Jsi_Value *callback = NULL, *width = NULL;
            
    if (jdb->echo && zSql)
        Jsi_LogInfo("SQL-QUERY: %s\n", zSql); 
................................................................................
    }
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    sEval.nocache = opts.nocache;
    if ((rc = dbEvalInit(interp, &sEval, jdb, zSql, &sStr, 0, 0)) != JSI_OK)
        goto bail;
    sEval.ret = *ret;
    oEopt = jdb->optPtr;
    jdb->optPtr = &opts;
    if (callback) {
        sEval.tocall = callback;
        if (opts.mode != _JSI_EF_ROWS) {
            Jsi_LogError("'mode' must be 'rows' with 'callback'");
            rc = JSI_ERROR;
            goto bail;







>
|







 







|







 







<







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
....
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
....
2553
2554
2555
2556
2557
2558
2559

2560
2561
2562
2563
2564
2565
2566
//  Jsi_Interp *interp = p->jdb->interp;

    if( p->pPreStmt ) {
        sqlite3_reset(p->pPreStmt->pStmt);
        dbReleaseStmt(p->jdb, p->pPreStmt, p->nocache);
        p->pPreStmt = 0;
    }
    if (p->dSql)
        Jsi_DSFree(p->dSql);
    dbReleaseColumnNames(p);
}

static void DbClose(sqlite3 *db) {
        sqlite3_close(db);
}

................................................................................
#endif
    const char *zSql = Jsi_ValueGetDString(interp, vSql, &eStr, 0);
    Jsi_Value *arg = Jsi_ValueArrayIndex(interp, args, 1);
    int cnt = 0;
    char **apColName = NULL;
    int *apColType = NULL, isopts = 0;
    DbEvalContext sEval = {};
    QueryOpts opts, *oEopt = jdb->optPtr;
    opts = jdb->queryOpts;
    opts.callback = NULL;
    opts.width = NULL;
    Jsi_Value *callback = NULL, *width = NULL;
            
    if (jdb->echo && zSql)
        Jsi_LogInfo("SQL-QUERY: %s\n", zSql); 
................................................................................
    }
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    sEval.nocache = opts.nocache;
    if ((rc = dbEvalInit(interp, &sEval, jdb, zSql, &sStr, 0, 0)) != JSI_OK)
        goto bail;
    sEval.ret = *ret;

    jdb->optPtr = &opts;
    if (callback) {
        sEval.tocall = callback;
        if (opts.mode != _JSI_EF_ROWS) {
            Jsi_LogError("'mode' must be 'rows' with 'callback'");
            rc = JSI_ERROR;
            goto bail;

Changes to src/jsiUtils.c.

123
124
125
126
127
128
129




130
131
132
133
134
135
136
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159


160
161
162
163
164
165

166
167
168
169
170
171
172
...
182
183
184
185
186
187
188






189
190
191
192
193

194










195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
    static char lastMsg[JSI_BUFSIZ/2] = "";
    static int lastCnt = 0;
    static Jsi_Interp *LastInterp = NULL;
    Jsi_Interp *lastInterp = LastInterp;
    const char *emsg = buf, *mt;
    int islog, line = 0, lofs = 0, noDups=0;
    bool isHelp = !Jsi_Strncmp(format, "...", 3);




    if (interp==NULL)
        interp = jsiIntData.mainInterp;
    LastInterp = interp;
    if (lastInterp != interp)
        noDups = 1;
    const char *curFile = jsi_GetCurFile(interp);
    /* Filter out try/catch (TODO: and non-syntax errors??). */
................................................................................
        else {
            vfprintf(stderr, format, va);
            fputc('\n', stderr);
        }
        va_end(va);
        return JSI_ERROR;
    }
        
    if (code == JSI_LOG_ERROR && (interp->framePtr->tryDepth - interp->framePtr->withDepth)>0 && interp->inParse<=0 
        && (!interp->tryList || !(interp->tryList->inCatch|interp->tryList->inFinal))) { 
        /* Should only do the first or traceback? */
        if (!interp->errMsgBuf[0]) {
            vsnprintf(interp->errMsgBuf, sizeof(interp->errMsgBuf), format, va);
            //interp->errMsgBuf[sizeof(interp->errMsgBuf)-1] = 0;
            interp->errFile = curFile;
            interp->errLine = (interp->curIp?interp->curIp->Line:0);
            emsg = interp->errMsgBuf;
        }
        goto done;
    }


    mt = (code <= JSI_LOG_PARSE ? jsi_LogCodes[code] : "");
    if (isHelp) mt = "help";
    assert((JSI_LOG_PARSE+2) == (sizeof(jsi_LogCodes)/sizeof(jsi_LogCodes[0])));
    if (!Jsi_Strchr(format,'\n')) term = "\n";
    if (code != JSI_LOG_INFO && interp && interp->lastPushStr && interp->lastPushStr[0]) {
        char *ss = interp->lastPushStr;

        char psbuf[JSI_BUFSIZ/6];
        if (Jsi_Strchr(ss,'%')) {
            char *s = ss, *sd = psbuf;
            int plen=0, llen = sizeof(psbuf)-2;
            while (*s && plen<llen) {
                if (*s == '%')
                    sd[plen++] = '%';
................................................................................
            snprintf(pbuf, sizeof(pbuf), "    (at or near \"%s\")\n", ss);
    }
    pbuf[sizeof(pbuf)-1] = 0;
    if (interp->inParse && interp->parseLine) {
        line = interp->parseLine->first_line;
        lofs = interp->parseLine->first_column;
    } else if (interp->curIp) {






        line = interp->curIp->Line;
        lofs = interp->curIp->Lofs;
        if (line<=0)
            line = interp->framePtr->line;
    }

    islog = (interp->parent && interp->debugOpts.msgCallback && code != JSI_LOG_BUG);










    if (interp && curFile && curFile[0] && Jsi_Strchr(curFile,'%')==0 && !islog) {
        if (!interp->subOpts.logColNums)
            snprintf(buf, sizeof(buf), "%s:%d: %s: %s%s%s",  curFile, line, mt,format, pterm, term);
        else
            snprintf(buf, sizeof(buf), "%s:%d.%d: %s: %s%s%s",  curFile, line, lofs, mt,format, pterm, term);
    } else {
        snprintf(buf, sizeof(buf), "%s: %s%s%s", mt, format, pterm, term);
    }

    buf[sizeof(buf)-1]=0;

    if (logHook)
        (*logHook)(buf, va);
    else if (interp->subOpts.logAllowDups)
        vfprintf(stderr, buf, va);
    else {







>
>
>
>







 







<












>
>




|
|
>







 







>
>
>
>
>
>
|
|
|
|
|
>

>
>
>
>
>
>
>
>
>
>


|

|

|

>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    static char lastMsg[JSI_BUFSIZ/2] = "";
    static int lastCnt = 0;
    static Jsi_Interp *LastInterp = NULL;
    Jsi_Interp *lastInterp = LastInterp;
    const char *emsg = buf, *mt;
    int islog, line = 0, lofs = 0, noDups=0;
    bool isHelp = !Jsi_Strncmp(format, "...", 3);
    Jsi_OptionSpec *oep = interp->parseMsgSpec;
    const char *pps = "";
    char *ss = interp->lastPushStr;

    if (interp==NULL)
        interp = jsiIntData.mainInterp;
    LastInterp = interp;
    if (lastInterp != interp)
        noDups = 1;
    const char *curFile = jsi_GetCurFile(interp);
    /* Filter out try/catch (TODO: and non-syntax errors??). */
................................................................................
        else {
            vfprintf(stderr, format, va);
            fputc('\n', stderr);
        }
        va_end(va);
        return JSI_ERROR;
    }

    if (code == JSI_LOG_ERROR && (interp->framePtr->tryDepth - interp->framePtr->withDepth)>0 && interp->inParse<=0 
        && (!interp->tryList || !(interp->tryList->inCatch|interp->tryList->inFinal))) { 
        /* Should only do the first or traceback? */
        if (!interp->errMsgBuf[0]) {
            vsnprintf(interp->errMsgBuf, sizeof(interp->errMsgBuf), format, va);
            //interp->errMsgBuf[sizeof(interp->errMsgBuf)-1] = 0;
            interp->errFile = curFile;
            interp->errLine = (interp->curIp?interp->curIp->Line:0);
            emsg = interp->errMsgBuf;
        }
        goto done;
    }
    if (code == JSI_LOG_ERROR)
        interp->logErrorCnt++;
    mt = (code <= JSI_LOG_PARSE ? jsi_LogCodes[code] : "");
    if (isHelp) mt = "help";
    assert((JSI_LOG_PARSE+2) == (sizeof(jsi_LogCodes)/sizeof(jsi_LogCodes[0])));
    if (!Jsi_Strchr(format,'\n')) term = "\n";
    if (jsi_IsStrictMode(interp) && interp->lastParseOpt)
        ss = (char*)Jsi_ValueToString(interp, interp->lastParseOpt, NULL);
    if (code != JSI_LOG_INFO && interp && ss && ss[0]) {
        char psbuf[JSI_BUFSIZ/6];
        if (Jsi_Strchr(ss,'%')) {
            char *s = ss, *sd = psbuf;
            int plen=0, llen = sizeof(psbuf)-2;
            while (*s && plen<llen) {
                if (*s == '%')
                    sd[plen++] = '%';
................................................................................
            snprintf(pbuf, sizeof(pbuf), "    (at or near \"%s\")\n", ss);
    }
    pbuf[sizeof(pbuf)-1] = 0;
    if (interp->inParse && interp->parseLine) {
        line = interp->parseLine->first_line;
        lofs = interp->parseLine->first_column;
    } else if (interp->curIp) {
        if (interp->callerErr && interp->framePtr && interp->framePtr->parent) {
            jsi_Frame *fptr = interp->framePtr->parent;
            line = fptr->line;
            lofs = 0;
            curFile = fptr->fileName;
        } else {
            line = interp->curIp->Line;
            lofs = interp->curIp->Lofs;
            if (line<=0)
                line = interp->framePtr->line;
        }
    }
    islog = (interp->parent && interp->debugOpts.msgCallback && code != JSI_LOG_BUG);
    Jsi_DString pStr;
    Jsi_DSInit(&pStr);
    if (oep) {
        if (oep->id != JSI_OPTION_CUSTOM || !oep->custom)
            pps = Jsi_DSPrintf(&pStr, "for option \"%s\": ", oep->name);
        else {
            Jsi_OptionCustom* cust = Jsi_OptionCustomBuiltin(oep->custom);
            pps = Jsi_DSPrintf(&pStr, "for %s option \"%s\": ", (cust?cust->name:""), oep->name);
        }
    }
    if (interp && curFile && curFile[0] && Jsi_Strchr(curFile,'%')==0 && !islog) {
        if (!interp->subOpts.logColNums)
            snprintf(buf, sizeof(buf), "%s:%d: %s: %s%s%s%s",  curFile, line, mt, pps, format, pterm, term);
        else
            snprintf(buf, sizeof(buf), "%s:%d.%d: %s: %s%s%s%s",  curFile, line, lofs, pps, mt,format, pterm, term);
    } else {
        snprintf(buf, sizeof(buf), "%s: %s%s%s%s", mt, pps, format, pterm, term);
    }
    Jsi_DSFree(&pStr);
    buf[sizeof(buf)-1]=0;

    if (logHook)
        (*logHook)(buf, va);
    else if (interp->subOpts.logAllowDups)
        vfprintf(stderr, buf, va);
    else {

Changes to tools/protos.jsi.

1
2
3
4
5
6
7
8
..
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
//JSI Command Prototypes: version 2.5.17
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 {};
................................................................................
Array.prototype.some = function(callback:function, this:object=void):boolean {};
Array.prototype.sort = function(options:function|object=void):array {};
Array.prototype.splice = function(start:number, howmany:number=void, ...):array {};
Array.prototype.unshift = function(...):number {};
var Boolean = function(cmd,args) {};
var CData = function(cmd,args) {};
CData.prototype.conf = function(options:object|string=void):any {};
CData.prototype.get = function(key:string|number|object|null, field:string=void):any {};
CData.prototype.incr = function(key:string|number|object|null, field:object|string, value:number):number {};
CData.prototype.info = function():object {};
CData.prototype.names = function():array {};
CData.prototype.set = function(key:string|number|object|null, field:object|string, value:any=void):any {};
CData.prototype.unset = function(key:string|number|object):any {};
var CEnum = function(cmd,args) {};
CEnum.prototype.conf = function(enum:string, options:object|string=void):any {};
................................................................................
System.prototype.isMain = function():boolean {};
System.prototype.isNaN = function(val):boolean {};
System.prototype.load = function(shlib:string):void {};
System.prototype.log = function(val, ...):void {};
System.prototype.noOp = function():any {};
System.prototype.parseFloat = function(val):number {};
System.prototype.parseInt = function(val:any, base:number=10):number {};
System.prototype.parseOpts = function(self:object, options:object, conf:object|null|undefined):any {};
System.prototype.printf = function(format:string, ...):void {};
System.prototype.provide = function(name:string|function=void, version:number|string=1.0):void {};
System.prototype.puts = function(val, ...):void {};
System.prototype.quote = function(val:string):string {};
System.prototype.require = function(name:string=void, version:number|string=1):number|array|object {};
System.prototype.runModule = function(cmd:string|function=void, conf:array=undefined):any {};
System.prototype.setInterval = function(callback:function, ms:number):number {};
................................................................................
var isMain = function():boolean {};
var isNaN = function(val):boolean {};
var load = function(shlib:string):void {};
var log = function(val, ...):void {};
var noOp = function():any {};
var parseFloat = function(val):number {};
var parseInt = function(val:any, base:number=10):number {};
var parseOpts = function(self:object, options:object, conf:object|null|undefined):any {};
var printf = function(format:string, ...):void {};
var provide = function(name:string|function=void, version:number|string=1.0):void {};
var puts = function(val, ...):void {};
var quote = function(val:string):string {};
var require = function(name:string=void, version:number|string=1):number|array|object {};
var runModule = function(cmd:string|function=void, conf:array=undefined):any {};
var setInterval = function(callback:function, ms:number):number {};
|







 







|







 







|







 







|







1
2
3
4
5
6
7
8
..
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
//JSI Command Prototypes: version 2.5.18
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 {};
................................................................................
Array.prototype.some = function(callback:function, this:object=void):boolean {};
Array.prototype.sort = function(options:function|object=void):array {};
Array.prototype.splice = function(start:number, howmany:number=void, ...):array {};
Array.prototype.unshift = function(...):number {};
var Boolean = function(cmd,args) {};
var CData = function(cmd,args) {};
CData.prototype.conf = function(options:object|string=void):any {};
CData.prototype.get = function(key:string|number|object=null, field:string=void):any {};
CData.prototype.incr = function(key:string|number|object|null, field:object|string, value:number):number {};
CData.prototype.info = function():object {};
CData.prototype.names = function():array {};
CData.prototype.set = function(key:string|number|object|null, field:object|string, value:any=void):any {};
CData.prototype.unset = function(key:string|number|object):any {};
var CEnum = function(cmd,args) {};
CEnum.prototype.conf = function(enum:string, options:object|string=void):any {};
................................................................................
System.prototype.isMain = function():boolean {};
System.prototype.isNaN = function(val):boolean {};
System.prototype.load = function(shlib:string):void {};
System.prototype.log = function(val, ...):void {};
System.prototype.noOp = function():any {};
System.prototype.parseFloat = function(val):number {};
System.prototype.parseInt = function(val:any, base:number=10):number {};
System.prototype.parseOpts = function(self:object|userobj, options:object, conf:object|null|undefined):any {};
System.prototype.printf = function(format:string, ...):void {};
System.prototype.provide = function(name:string|function=void, version:number|string=1.0):void {};
System.prototype.puts = function(val, ...):void {};
System.prototype.quote = function(val:string):string {};
System.prototype.require = function(name:string=void, version:number|string=1):number|array|object {};
System.prototype.runModule = function(cmd:string|function=void, conf:array=undefined):any {};
System.prototype.setInterval = function(callback:function, ms:number):number {};
................................................................................
var isMain = function():boolean {};
var isNaN = function(val):boolean {};
var load = function(shlib:string):void {};
var log = function(val, ...):void {};
var noOp = function():any {};
var parseFloat = function(val):number {};
var parseInt = function(val:any, base:number=10):number {};
var parseOpts = function(self:object|userobj, options:object, conf:object|null|undefined):any {};
var printf = function(format:string, ...):void {};
var provide = function(name:string|function=void, version:number|string=1.0):void {};
var puts = function(val, ...):void {};
var quote = function(val:string):string {};
var require = function(name:string=void, version:number|string=1):number|array|object {};
var runModule = function(cmd:string|function=void, conf:array=undefined):any {};
var setInterval = function(callback:function, ms:number):number {};

Changes to www/reference.wiki.

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
....
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
<a name="CData"></a>

<hr>


<h1>CData</h1>

<font color=red>Synopsis:new CData(options:string|object=void):userobj

</font><p>
<h2>Methods for "CData"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>CData</td><td>new CData(<a href='#new CDataOptions'>options</a>:string|object=void):userobj </td><td>Create a new struct or map/array of structs.</td></tr>
<tr><td>conf</td><td>conf(<a href='#CData.confOptions'>options</a>:object|string=void) </td><td>Configure options for c-data.</td></tr>
<tr><td>get</td><td>get(key:string|number|object|null, field:string=void) </td><td>Get struct/map/array value.</td></tr>
<tr><td>incr</td><td>incr(key:string|number|object|null, field:object|string, value:number):number </td><td>Increment a numeric field: returns the new value.</td></tr>
<tr><td>info</td><td>info():object </td><td>Return info for data.</td></tr>
<tr><td>names</td><td>names():array </td><td>Return keys for map.</td></tr>
<tr><td>set</td><td>set(key:string|number|object|null, field:object|string, value:any=void) </td><td>Set a struct/map/array value.</td></tr>
<tr><td>unset</td><td>unset(key:string|number|object) </td><td>Remove entry from map/array.</td></tr>
</table>

................................................................................
<tr><td>isMain</td><td>isMain():boolean </td><td>Return true if current script was the main script invoked from command-line.</td></tr>
<tr><td>isNaN</td><td>isNaN(val):boolean </td><td>Return true if not a number.</td></tr>
<tr><td>load</td><td>load(shlib:string):void </td><td>Load a shared executable and invoke its _Init call.</td></tr>
<tr><td>log</td><td>log(val, ...):void </td><td>Same as puts, but includes file:line.</td></tr>
<tr><td>noOp</td><td>noOp() </td><td>A No-Op. A zero overhead command call that is useful for debugging.</td></tr>
<tr><td>parseFloat</td><td>parseFloat(val):number </td><td>Convert string to a double.</td></tr>
<tr><td>parseInt</td><td>parseInt(val:any, base:number=10):number </td><td>Convert string to an integer.</td></tr>
<tr><td>parseOpts</td><td>parseOpts(self:object, options:object, conf:object|null|undefined) </td><td>Parse options.</td></tr>
<tr><td>printf</td><td>printf(format:string, ...):void </td><td>Formatted output to stdout.</td></tr>
<tr><td>provide</td><td>provide(name:string|function=void, version:number|string=1.0):void </td><td>Provide a package for use with require. Default is the file tail-rootname.</td></tr>
<tr><td>puts</td><td>puts(val, ...):void </td><td>Output one or more values to stdout. Each argument is quoted.  Use Interp.logOpts to control source line and/or timestamps output.</td></tr>
<tr><td>quote</td><td>quote(val:string):string </td><td>Return quoted string.</td></tr>
<tr><td>require</td><td>require(name:string=void, version:number|string=1):number|array|object </td><td>Load/query packages. With no arguments, returns the list of all loaded packages.
With one argument, loads the package (if necessary) and returns its version.
With two arguments, returns object containing: version, loadFile, func.







|





|

|







 







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
....
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
<a name="CData"></a>

<hr>


<h1>CData</h1>

<font color=red>Synopsis:new CData(options:string|object=void, inits:object=void):userobj

</font><p>
<h2>Methods for "CData"</h2>
<table border="1"class="cmdstbl table">
<tr><th>Method</th><th>Prototype</th><th>Description</th></tr>
<tr><td>CData</td><td>new CData(<a href='#new CDataOptions'>options</a>:string|object=void, inits:object=void):userobj </td><td>Create a new struct or map/array of structs.The 2nd arg is used for function option parsing and will report errors at the callers file:line</td></tr>
<tr><td>conf</td><td>conf(<a href='#CData.confOptions'>options</a>:object|string=void) </td><td>Configure options for c-data.</td></tr>
<tr><td>get</td><td>get(key:string|number|object=null, field:string=void) </td><td>Get struct/map/array value.</td></tr>
<tr><td>incr</td><td>incr(key:string|number|object|null, field:object|string, value:number):number </td><td>Increment a numeric field: returns the new value.</td></tr>
<tr><td>info</td><td>info():object </td><td>Return info for data.</td></tr>
<tr><td>names</td><td>names():array </td><td>Return keys for map.</td></tr>
<tr><td>set</td><td>set(key:string|number|object|null, field:object|string, value:any=void) </td><td>Set a struct/map/array value.</td></tr>
<tr><td>unset</td><td>unset(key:string|number|object) </td><td>Remove entry from map/array.</td></tr>
</table>

................................................................................
<tr><td>isMain</td><td>isMain():boolean </td><td>Return true if current script was the main script invoked from command-line.</td></tr>
<tr><td>isNaN</td><td>isNaN(val):boolean </td><td>Return true if not a number.</td></tr>
<tr><td>load</td><td>load(shlib:string):void </td><td>Load a shared executable and invoke its _Init call.</td></tr>
<tr><td>log</td><td>log(val, ...):void </td><td>Same as puts, but includes file:line.</td></tr>
<tr><td>noOp</td><td>noOp() </td><td>A No-Op. A zero overhead command call that is useful for debugging.</td></tr>
<tr><td>parseFloat</td><td>parseFloat(val):number </td><td>Convert string to a double.</td></tr>
<tr><td>parseInt</td><td>parseInt(val:any, base:number=10):number </td><td>Convert string to an integer.</td></tr>
<tr><td>parseOpts</td><td>parseOpts(self:object|userobj, options:object, conf:object|null|undefined) </td><td>Parse options.</td></tr>
<tr><td>printf</td><td>printf(format:string, ...):void </td><td>Formatted output to stdout.</td></tr>
<tr><td>provide</td><td>provide(name:string|function=void, version:number|string=1.0):void </td><td>Provide a package for use with require. Default is the file tail-rootname.</td></tr>
<tr><td>puts</td><td>puts(val, ...):void </td><td>Output one or more values to stdout. Each argument is quoted.  Use Interp.logOpts to control source line and/or timestamps output.</td></tr>
<tr><td>quote</td><td>quote(val:string):string </td><td>Return quoted string.</td></tr>
<tr><td>require</td><td>require(name:string=void, version:number|string=1):number|array|object </td><td>Load/query packages. With no arguments, returns the list of all loaded packages.
With one argument, loads the package (if necessary) and returns its version.
With two arguments, returns object containing: version, loadFile, func.