Example #1
0
static int _object_get_callback(Jsi_Tree *tree, Jsi_TreeEntry *hPtr, void *data)
{
    Jsi_Value *v;
    objwalker *ow = data;
    Jsi_DString *dStr = ow->dStr;
    int len;
    char *str;
    if ((hPtr->f.bits.dontenum))
        return JSI_OK;
    v = Jsi_TreeValueGet(hPtr);
    if ((ow->quote&JSI_OUTPUT_JSON) && v && v->vt == JSI_VT_UNDEF)
        return JSI_OK;
    str = Jsi_TreeKeyGet(hPtr);
    char *cp = Jsi_DSValue(dStr);
    len = Jsi_DSLength(dStr);
    if (len>=2 && cp[len-2] != '{')
        Jsi_DSAppend(dStr, ", ", NULL);
    if (((ow->quote&JSI_OUTPUT_JSON) == 0 || (ow->quote&JSI_JSON_STRICT) == 0) && IsAlnum(str) && !IsKeyword(tree->interp, str))
        Jsi_DSAppend(dStr, str, NULL);
    else
        /* JSON/spaces, etc requires quoting the name. */
        Jsi_DSAppend(dStr, "\"", str, "\"", NULL);
    Jsi_DSAppend(dStr, ":", NULL);
    ow->depth++;
    jsiValueGetString(tree->interp, v, dStr, ow);
    ow->depth--;
    return JSI_OK;
}
Example #2
0
void Jsi_DString_SelfTest() {
    {
        Jsi_DString d1 = {}, d2 = {"Here is"};
        Jsi_DSAppend(&d2 ," your score: ", NULL);
        Jsi_DSPrintf(&d2, " -> %d/%d", 99, 100);
        char *cp = Jsi_DSValue(&d2);
        puts(cp);     // "Here is your score: -> 99/100"
        Jsi_DSAppend(&d1, cp, NULL);
        Jsi_DSFree(&d1);  Jsi_DSFree(&d2);
    }
    {
        Jsi_DString d = {};;
        Jsi_DSPrintf(&d , "%0300d", 1); // Malloc
        Jsi_DSSetLength(&d, 0);
        Jsi_DSPrintf(&d , "%0300d", 1); // No-malloc
        Jsi_DSFree(&d);
        Jsi_DSPrintf(&d , "%0300d", 1); // Malloc
        Jsi_DSFree(&d);
    }
    {
        Jsi_DString d;
        Jsi_DSInit(&d);
        Jsi_DSAppend(&d , " some stuff: ", NULL);
        Jsi_DSFree(&d);
    }
    {
        JSI_DSTRING_VAR(dPtr,301);
        Jsi_DSPrintf(dPtr , "%0300d", 1); // No-malloc
        Jsi_DSSetLength(dPtr, 0);
        Jsi_DSPrintf(dPtr , "%0300d", 1); // No-malloc
        Jsi_DSFree(dPtr);
        Jsi_DSPrintf(dPtr , "%0400d", 1); // Malloc
        Jsi_DSFree(dPtr);
    }
}
Example #3
0
static int JsiCleanupChildren(Jsi_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId, Jsi_DString *dStr, Jsi_DString *cStr, int *code)
{
    struct WaitInfoTable *table = jsi_ExecCmdData(interp);
    int result = JSI_OK;
    int i, exitCode = 256;
    char buf[1000];
    Jsi_DString sStr;
    Jsi_DSInit(&sStr);
    for (i = 0; i < numPids; i++) {
        int waitStatus = 0;
        if (cStr) {
            if (i==0)
                Jsi_DSAppend(cStr, (Jsi_DSLength(cStr)>1?", ":""), "children: [", NULL);
            else
                Jsi_DSAppend(&sStr, ", ", NULL);
        }
        if (JsiWaitForProcess(table, pidPtr[i], &waitStatus) != JSI_BAD_PID) {
            //  if (JsiCheckWaitStatus(interp, pidPtr[i], waitStatus, dStr?&sStr:0) != JSI_OK) 
            //result = JSI_ERROR;  // TODO: we don't error out on non-zero return code. Find way to return it.
            int es = WEXITSTATUS(waitStatus);
            if (WIFEXITED(waitStatus)) {
                if (i==0)
                    exitCode = es;
                else if (es>exitCode)
                    exitCode = es;
            }
            if (cStr) {
                pidtype pid = pidPtr[i];
                if (WIFEXITED(waitStatus))
                    sprintf(buf, "{type:\"exit\", pid:%ld, exitCode:%d}", (long)pid, es);
                else 
                    sprintf(buf, "{type:\"%s\", pid:%ld, signal: %d}",
                        (WIFSIGNALED(waitStatus) ? "killed" : "suspended"), (long)pid, WTERMSIG(waitStatus));
                Jsi_DSAppend(&sStr, buf, NULL);
            }
        }
    }
    if (i>0 && cStr) {
        if (exitCode != 256)
            sprintf(buf, ", exitCode: %d", exitCode);
        Jsi_DSAppend(cStr, Jsi_DSValue(&sStr), "]", buf, NULL);
    }
    Jsi_DSFree(&sStr);
    Jsi_Free(pidPtr);

    /*
     * Read the standard error file.  If there's anything there,
     * then add the file's contents to the result
     * string.
     */
    if (errorId != JSI_BAD_FD) {
        JsiRewindFd(errorId);
        if (JsiAppendStreamToString(interp, errorId, dStr) != JSI_OK) {
            result = JSI_ERROR;
        }
    }
    *code = exitCode;
    return result;
}
Example #4
0
static char *get_inputline(int istty, char *prompt)
{
    char *res;
#ifdef HAVE_READLINE
    if (istty) {
        res = readline(prompt);
        if (res && *res) add_history(res);
        return res;
    }
#endif
    int done = 0;
    char bbuf[BUFSIZ];
    Jsi_DString dStr = {};
    if (istty)
        fputs(prompt, stdout);
    fflush(stdout);
    while (!done) { /* Read a line. */
        bbuf[0] = 0;
        if (fgets(bbuf, sizeof(bbuf), stdin) == NULL)
            return NULL;
        Jsi_DSAppend(&dStr, bbuf, NULL);
        if (strlen(bbuf) < (sizeof(bbuf)-1) || bbuf[sizeof(bbuf)-1] == '\n')
            break;
    }
    res = strdup(Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);
    return res;
}
Example #5
0
void jsi_UserObjToName(Jsi_Interp *interp, Jsi_UserObj *uobj, Jsi_DString *dStr)
{
    const char * uname = "userdata";
    char ubuf[50];
    Jsi_UserObjReg *reg = uobj->reg;
    uname = reg->name;
    sprintf(ubuf, "%d", uobj->idx);
    Jsi_DSAppend(dStr, "#", uname, "_", ubuf, NULL);
}
Example #6
0
static const char *jsi_TildePath(Jsi_Interp *interp, const char* path, Jsi_DString *dStr) {
    if (*path != '~')
        return path;
    const char *homedir = jsi_GetHomeDir(interp);
    if (!homedir)
        return path;
    Jsi_DSAppend(dStr, homedir, path[1] == '/' ? "" : "/", path+1, NULL);
    return Jsi_DSValue(dStr);
}
Example #7
0
/* Simple implementation of exec with system().  Returns return code.
 * The system() call *may* do command line redirection, etc.
 * The standard output is not available.
 * Can't redirect filehandles.
 */
int Jsi_SysExecCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_DString *rStr)
{
    int i, j, len, rc = 0;
    Jsi_DString dStr, eStr;
    len = Jsi_ValueGetLength(interp, args);
    Jsi_DSInit(rStr);
    if (len<=0)
        return 0;
    Jsi_DSInit(&dStr);
#ifdef __WIN32
    Jsi_DSAppendLen(&dStr, "\"", 1);
#endif
    for (i=0; i<len; i++) {
        Jsi_Value *v = Jsi_ValueArrayIndex(interp, args, i);
        const char *arg = Jsi_ValueGetDString(interp, v, &eStr, 0);
        if (i>1)
        Jsi_DSAppendLen(&dStr, " ", 1);
        if (strpbrk(arg, "\\\" ") == NULL) {
            Jsi_DSAppend(&dStr, arg, NULL);
        } else {
            Jsi_DSAppendLen(&dStr, "\"", 1);
            for (j = 0; j < len; j++) {
                if (arg[j] == '\\' || arg[j] == '"') {
                    Jsi_DSAppendLen(&dStr, "\\", 1);
                }
                Jsi_DSAppendLen(&dStr, &arg[j], 1);
            }
            Jsi_DSAppendLen(&dStr, "\"", 1);
        }
        Jsi_DSFree(&eStr);

    }
#ifdef __WIN32
    Jsi_DSAppendLen(&dStr, "\"", 1);
#endif
    rc = system(Jsi_DSValue(&dStr));
    Jsi_DSFree(&dStr);
    return rc;
}
Example #8
0
/* Collect and execute code from stdin.  The first byte of flags are passed to Jsi_ValueGetDString(). */
int Jsi_Interactive(Jsi_Interp* interp, int flags) {
    int rc = 0, done = 0, len, quote = (flags & 0xff), istty = 1;
    char *prompt = "# ", *buf;
    Jsi_DString dStr;
    Jsi_DSInit(&dStr);
#ifndef __WIN32
    istty = isatty(fileno(stdin));
#else
    istty = _isatty(_fileno(stdin));
#endif
#ifdef HAVE_READLINE
    Jsi_DString dHist = {};
    char *hist = NULL;
    if(interp->noreadline == 0 && !interp->parent)
    {
        hist = Jsi_NormalPath(interp, "~/.jsish_history", &dHist);
        if (hist)
            read_history(hist);
    }
#endif
    interp->level++;
    while (done==0 && interp->exited==0) {
        buf = get_inputline(istty, prompt);
        if (buf) {
          Jsi_DSAppend(&dStr, buf, NULL);
          free(buf);
        } else {
          done = 1;
        }
        len = Jsi_DSLength(&dStr);
        if (done && len == 0)
            break;
        buf = Jsi_DSValue(&dStr);
        if (done == 0 && (!balanced(buf))) {
            prompt = "> ";
            if (len<5)
                break;
            continue;
        }
        prompt = "# ";
        while ((len = Jsi_Strlen(buf))>0 && (isspace(buf[len-1])))
            buf[len-1] = 0;
        if (buf[0] == 0)
            continue;
        /* Convenience: add semicolon to "var" statements (required by parser). */
        if (strncmp(buf,"var ", 4) == 0 && strchr(buf, '\n')==NULL && strchr(buf, ';')==NULL)
            strcat(buf, ";");
        rc = Jsi_EvalString(interp, buf, JSI_EVAL_RETURN);
        if (interp->exited)
            break;
        if (rc == 0) {
             if (interp->ret.vt != JSI_VT_UNDEF || interp->noUndef==0) {
                Jsi_DString eStr = {};
                fputs(Jsi_ValueGetDString(interp,&interp->ret, &eStr, quote), stdout);
                Jsi_DSFree(&eStr);
                fputs("\n", stdout);
             }
        } else if (!interp->exited) {
            fputs("ERROR\n", stderr);
        }
        Jsi_DSSetLength(&dStr, 0);
        len = 0;
    }
    interp->level--;
#ifdef HAVE_READLINE
    if (hist) {
        stifle_history(100);
        write_history(hist);
    }
    Jsi_DSFree(&dHist);
#endif
    Jsi_DSFree(&dStr);
    if (interp->exited && interp->level <= 0)
    {
        rc = interp->exitCode;
        Jsi_InterpDelete(interp);
    }
    return rc;
}
Example #9
0
/* Format value into dStr.  Toplevel caller does init/free. */
static void jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
{
    char buf[100], *str;
    if (owPtr->depth > interp->maxDepth) {
        Jsi_LogError("recursive ToString");
        return;
    }
    int quote = owPtr->quote;
    int isjson = owPtr->quote&JSI_OUTPUT_JSON;
    double num;
    switch(v->vt) {
        case JSI_VT_UNDEF:
            Jsi_DSAppend(dStr, "undefined", NULL);
            return;
        case JSI_VT_NULL:
            Jsi_DSAppend(dStr, "null", NULL);
            return;
        case JSI_VT_VARIABLE:
            Jsi_DSAppend(dStr, "variable", NULL);
            return;
        case JSI_VT_BOOL:
            Jsi_DSAppend(dStr, (v->d.val ? "true":"false"), NULL);
            return;
        case JSI_VT_NUMBER:
            num = v->d.num;
outnum:
            if (jsi_is_integer(num)) {
                sprintf(buf, "%d", (int)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (jsi_is_wide(num)) {
                sprintf(buf, "%Ld", (Jsi_Wide)num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (jsi_ieee_isnormal(num)) {
                sprintf(buf, "%" JSI_NUMGFMT, num);
                Jsi_DSAppend(dStr, buf, NULL);
            } else if (jsi_ieee_isnan(num)) {
                Jsi_DSAppend(dStr, "NaN", NULL);
            } else {
                int s = jsi_ieee_infinity(num);
                if (s > 0) Jsi_DSAppend(dStr, "+Infinity", NULL);
                else if (s < 0) Jsi_DSAppend(dStr, "-Infinity", NULL);
                else Jsi_LogBug("Ieee function problem");
            }
            return;
        case JSI_VT_STRING:
            str = v->d.s.str;
outstr:
            if (!quote) {
                Jsi_DSAppend(dStr, str, NULL);
                return;
            }
            Jsi_DSAppend(dStr,"\"", NULL);
            while (*str) {
                if ((*str == '\'' && (!(isjson))) || *str == '\"' ||
                    (*str == '\n' && (!(owPtr->quote&JSI_OUTPUT_NEWLINES))) || *str == '\r' || *str == '\t' || *str == '\f' || *str == '\b'  ) {
                    char pcp[2];
                    *pcp = *str;
                    pcp[1] = 0;
                    Jsi_DSAppendLen(dStr,"\\", 1);
                    switch (*str) {
                        case '\r': *pcp = 'r'; break;
                        case '\n': *pcp = 'n'; break;
                        case '\t': *pcp = 't'; break;
                        case '\f': *pcp = 'f'; break;
                        case '\b': *pcp = 'b'; break;
                    }
                    Jsi_DSAppendLen(dStr,pcp, 1);
                } else if (!isprint(*str))
                    /* TODO: encode */
                    if (isjson) {
                        char ubuf[10];
                        sprintf(ubuf, "\\u00%.02x", (unsigned char)*str);
                        Jsi_DSAppend(dStr,ubuf, NULL);
                        //Jsi_DSAppendLen(dStr,".", 1);
                    } else
                        Jsi_DSAppendLen(dStr,str, 1);
                    
                else
                    Jsi_DSAppendLen(dStr,str, 1);
                str++;
            }
            Jsi_DSAppend(dStr,"\"", NULL);
            return;
        case JSI_VT_OBJECT: {
            Jsi_Obj *o = v->d.obj;
            switch(o->ot) {
                case JSI_OT_BOOL:
                    Jsi_DSAppend(dStr, (o->d.val ? "true":"false"), NULL);
                    return;
                case JSI_OT_NUMBER:
                    num = o->d.num;
                    goto outnum;
                    return;
                case JSI_OT_STRING:
                    str = o->d.s.str;
                    goto outstr;
                    return;
                case JSI_OT_FUNCTION: {
                    Jsi_FuncObjToString(interp, o, dStr);
                    return;
                }
                case JSI_OT_REGEXP:
                    Jsi_DSAppend(dStr, o->d.robj->pattern, NULL);
                    return;
                case JSI_OT_USEROBJ: 
                    jsi_UserObjToName(interp, o->d.uobj, dStr);
                    return;
                case JSI_OT_ITER:
                    Jsi_DSAppend(dStr, "*ITER*", NULL);
                    return;
            }
                        
            if (o->isArray)
            {
                Jsi_Value *nv;
                int i, len = o->arrCnt;
                
                if (!o->arr)
                    len = Jsi_ValueGetLength(interp, v);
                Jsi_DSAppend(dStr,"[ ", NULL);
                for (i = 0; i < len; ++i) {
                    nv = Jsi_ValueArrayIndex(interp, v, i);
                    if (i) Jsi_DSAppend(dStr,", ", NULL);
                    if (nv) jsiValueGetString(interp, nv, dStr, owPtr);
                    else Jsi_DSAppend(dStr, "undefined", NULL);
                }
                Jsi_DSAppend(dStr," ]", NULL);
            } else {
                Jsi_DSAppend(dStr,"{ ", NULL);
                owPtr->depth++;
                Jsi_TreeWalk(o->tree, _object_get_callback, owPtr, 0);
                owPtr->depth--;
                Jsi_DSAppend(dStr," }", NULL);
            }
            return;
        }
        default:
            Jsi_LogBug("Unexpected value type: %d\n", v->vt);
    }
}
Example #10
0
/*
 * The main exec command
 */
int jsi_execCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_DString *dStr, Jsi_DString *cStr, int *code)
{
    fdtype outputId;               /* File id for output pipe.  -1
                                 * means command overrode. */
    fdtype errorId;                /* File id for temporary file
                                 * containing error output. */
    pidtype *pidPtr;
    int numPids, result, argc;
    
    argc = Jsi_ValueGetLength(interp, args);
    /*
     * See if the command is to be run in background;  if so, create
     * the command, detach it, and return.
     */

    if (argc > 1 && Jsi_Strcmp(Jsi_ValueArrayIndexToStr(interp, args, argc-1, NULL), "&") == 0) {
        int i;

        argc--;
        numPids = JsiCreatePipeline(interp, args, argc, &pidPtr, NULL, NULL, NULL);
        if (numPids < 0) {
            return JSI_ERROR;
        }
        if (cStr) {
            /* The return value is a list of the pids */
            Jsi_DSAppend(cStr,(Jsi_DSLength(cStr)>1?", ":""), "pids : [", NULL);
            for (i = 0; i < numPids; i++) {
                char ibuf[100];
                sprintf(ibuf, "%s%ld", (i?",":""), (long)pidPtr[i]);
                Jsi_DSAppend(cStr, ibuf, NULL);
            }
            Jsi_DSAppend(cStr, "]", NULL);
        }
        JsiDetachPids(interp, numPids, pidPtr);
        Jsi_Free(pidPtr);
        return JSI_OK;
    }
    /*
     * Create the command's pipeline.
     */
    numPids =
        JsiCreatePipeline(interp, args, argc, &pidPtr, NULL, &outputId, &errorId);

    if (numPids < 0) {
        return JSI_ERROR;
    }

    /*
     * Read the child's output (if any) and put it into the result.
     */

    result = JSI_OK;
    if (outputId != JSI_BAD_FD) {
        result = JsiAppendStreamToString(interp, outputId, dStr);
        if (result != JSI_OK && cStr)
            Jsi_DSAppend(cStr, (Jsi_DSLength(cStr)>1?", ":""), "errstr: \"error reading from output pipe\"", NULL);
    }

    if (JsiCleanupChildren(interp, numPids, pidPtr, errorId, dStr, cStr, code) != JSI_OK) {
        result = JSI_ERROR;
    }
    return result;
}
Example #11
0
int main(int argc, char **argv)
{
    int rc = JSI_OK, jsFound = 0;
    Jsi_Interp* interp = Jsi_InterpCreate(NULL, argc, argv, 0);
    Jsi_InterpOnDelete(interp, &InterpDelete);

#ifndef NO_JAZ
    /* Mount zip at end of executable */
    Jsi_Value *v = Jsi_Executable(interp);
    const char *exeFile = Jsi_ValueString(interp, v, NULL);
    if (argc != 2 || Jsi_Strcmp(argv[1], "--nozvfs")) {
        rc = Jsi_ExecZip(interp, exeFile, JSI_ZVFS_DIR, &jsFound);
        if (rc >= 0) {
            if (!jsFound) {
#if (!defined(JSI_OMIT_FILESYS)) && (!defined(JSI_OMIT_ZVFS))
                fprintf(stderr, "warning: no main.jsi or jsiIndex.jsi\n");
#endif
            }
            if (deleted)
                exit(exitCode);
            else if (rc != JSI_OK) {
                fprintf(stderr, "Error\n");
                exit(1);
            }
        }
    }
#endif

#ifdef USER_EXTENSION
    extern int USER_EXTENSION(Jsi_Interp *interp);
    if (USER_EXTENSION (interp) != JSI_OK) {
        fprintf(stderr, "extension load failed");
        exit(1);
    }
#endif
    Jsi_ShiftArgs(interp);
    if (argc == 1) {
        rc = Jsi_Interactive(interp, JSI_OUTPUT_QUOTE|JSI_OUTPUT_NEWLINES);
    } else {
        if (argc == 2 && (Jsi_Strcmp(argv[1], "--help")==0 || Jsi_Strcmp(argv[1], "-h" )==0)) {
            puts("usage: jsi ?--help | -e SCRIPT | FILE arg arg ...?");
            exit(0);
        }
        if (argc == 2 && (Jsi_Strcmp(argv[1], "--version")==0 || Jsi_Strcmp(argv[1], "-v" )==0)) {
            char str[200] = "\n";
            Jsi_Channel chan = Jsi_Open(interp, Jsi_ValueNewStringKey(interp, "/zvfs/lib/sourceid.txt"), "r");
            if (chan)
                Jsi_Read(chan, str, sizeof(str));
            printf("%d.%d.%d (%" JSI_NUMGFMT ") %s", JSI_VERSION_MAJOR, JSI_VERSION_MINOR, JSI_VERSION_RELEASE, Jsi_Version(), str);
            exit(0);
        }
        if (argc > 2 && (Jsi_Strcmp(argv[1], "--invoke")==0 || Jsi_Strcmp(argv[1], "-i" )==0)) {
            Jsi_DString dStr = {};
            Jsi_DSAppend(&dStr, "jsi_invokeCmd(\"", argv[2], "\",console.args.slice(1));", NULL);
            rc = Jsi_EvalString(interp, Jsi_DSValue(&dStr), JSI_EVAL_NOSKIPBANG);
            Jsi_DSFree(&dStr);
        }
        else if (argc == 3 && (Jsi_Strcmp(argv[1], "--eval")==0 || Jsi_Strcmp(argv[1], "-e" )==0))
            rc = Jsi_EvalString(interp, argv[2], JSI_EVAL_NOSKIPBANG);
        else {
            Jsi_Value *vf = NULL;
            const char *ext = strrchr(argv[1], '.');
            /* Support running "main.jsi" from a zip file. */
            if (ext && (strcmp(ext,".zip")==0 ||strcmp(ext,".jsz")==0 ) ) {
                rc = Jsi_ExecZip(interp, argv[1], NULL, &jsFound);
                if (rc<0) {
                    fprintf(stderr, "zip mount failed\n");
                    exit(1);
                }
                if (!(jsFound&JSI_ZIP_MAIN)) {
                    fprintf(stderr, "main.jsi not found\n");
                    exit(1);
                }
            } else {
                if (argc>1)
                    vf = Jsi_ValueNewStringKey(interp, argv[1]);
                rc = Jsi_EvalFile(interp, vf, JSI_EVAL_ARGV0|JSI_EVAL_INDEX);
            }
        }
        if (deleted)
            exit(exitCode);
        if (rc == 0) {
            /* Skip output from an ending semicolon which evaluates to undefined */
            Jsi_Value *ret = Jsi_ReturnValue(interp);
            if (!Jsi_ValueIsType(interp, ret, JSI_VT_UNDEF)) {
                Jsi_DString dStr = {};
                fputs(Jsi_ValueGetDString(interp, ret, &dStr, 0), stdout);
                Jsi_DSFree(&dStr);
                fputs("\n", stdout);
            }
        } else
            fputs("ERROR\n", stderr);

    }
    if (!deleted)
        Jsi_InterpDelete(interp);
    return rc;
}