Beispiel #1
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);
    }
}
Beispiel #2
0
char *
Jsi_DSSet(Jsi_DString *dsPtr, const char *str)
{
    Jsi_DSSetLength(dsPtr, 0);
    if (str)
        Jsi_DSAppendLen(dsPtr, str, -1);
    return Jsi_DSValue(dsPtr);
}
Beispiel #3
0
static void Jsi_RemoveTrailingNewline(Jsi_DString *dStr)
{
    char *s = Jsi_DSValue(dStr);
    int len = strlen(s);

    if (len > 0 && s[len - 1] == '\n') {
        s[len-1] = 0;
        Jsi_DSSetLength(dStr, len-1);
    }
}
Beispiel #4
0
/*
 * Returns the strdup of the string value and resets the DString in the same way as Jsi_DSFree.
 * This just avoids the user having to do an extra malloc/free when the DString was already malloced.
 * It is the responsibility of the caller to free the returned value.
 * RETURNS: previous string value malloced.
 */
char*  Jsi_DSFreeDup(Jsi_DString *dsPtr)
{
    char *cp;
    if (DSNotInit(dsPtr))
        InitStr(dsPtr);
    if (dsPtr->staticSpace == dsPtr->str) {
        cp = Jsi_Strdup(dsPtr->str);
        Jsi_DSSetLength(dsPtr, 0);
        return cp;
    }
    cp = dsPtr->str;
    dsPtr->str = dsPtr->staticSpace;
    dsPtr->staticSpace[0] = 0;
    dsPtr->spaceAvl = dsPtr->staticSize;
    dsPtr->len = 0;
    dsPtr->str = NULL;
    return cp;
}
Beispiel #5
0
/*
 * Format output and append to the end of dsPtr.
 * RETURNS: The string starting at the first appended character.
 */
char *
Jsi_DSPrintf(Jsi_DString *dsPtr, const char *fmt, ...)
{
    va_list argList;
#ifndef JSI_PRINTF_BUFSIZ
#define JSI_PRINTF_BUFSIZ BUFSIZ
#endif
    char buf[JSI_PRINTF_BUFSIZ], *bPtr = buf;
    int n, bsiz = sizeof(buf), needAppend = 1;
    if (DSNotInit(dsPtr))
        InitStr(dsPtr);
    int len = dsPtr->len;
    char *send = dsPtr->str + len;
    uint avail = (dsPtr->spaceAvl - len);
    if (avail >= sizeof(buf)) { /* Format directly into string. */
        bPtr = dsPtr->str+len;
        bsiz = avail;
        needAppend = 0;
    }
    va_start(argList, fmt);
    n = vsnprintf(bPtr, bsiz, fmt, argList);
    if (n<0 || (n+len)>JSI_MAX_ALLOC_BUF) {
        LogError("vsnprintf error: rc=%d, len=%d", n, len);
        va_end(argList);
        return send;
    }
    if (n >= bsiz) {
        int m = len+n+1;
        if (Jsi_DSSetLength(dsPtr, m) < m) {
            va_start(argList, fmt);
            return send;
        }
        m = vsnprintf(dsPtr->str+len, len+1, fmt, argList);
        if (m != n) {
            LogError("len mismatch: %d != %d",  m, n);
            va_end(argList);
            return send;
        }
    } else if (needAppend) {
        Jsi_DSAppendLen(dsPtr, buf, n);
    }
    va_end(argList);
    return send;
}
Beispiel #6
0
/* 
 * Append length bytes to the string. If length is less than 0,
 * the value of strlen is used.  If required, the DString is realloced to
 * be large enough to contain bytes, plus an extra null byte that is added to the end.
 * RETURNS: The string starting at the first appended character.
*/
char *Jsi_DSAppendLen(Jsi_DString *dsPtr, const char *string, int length)
{
    if (DSNotInit(dsPtr))
        InitStr(dsPtr);        
    int len = dsPtr->len;
    if (string) {
        if (length < 0)
            length = strlen(string);
        int nsiz = length + len+1;
    
        if (nsiz >= dsPtr->spaceAvl) {
            if (nsiz < dsPtr->spaceAvl*2)
                nsiz = dsPtr->spaceAvl*2;
            if (Jsi_DSSetLength(dsPtr, nsiz) < nsiz)
                return Jsi_DSValue(dsPtr);
        }
        char * dst = dsPtr->str + dsPtr->len;
        memcpy(dst, string, length);
        dst[length] = 0;
        dsPtr->len += length;
    }
    return dsPtr->str+len;
}
Beispiel #7
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;
}
Beispiel #8
0
/* Lookup a name, eg.  "a[b].c  a.b.c  a[b][c]  a.b[c]  a["b"].c  a[1].c  */
Jsi_Value *Jsi_NameLookup(Jsi_Interp *interp, const char *name)
{
    int cnt = 0, len, isq;
    char *nam = (char*)name, *cp, *cp2, *ocp, *kstr;
    Jsi_Value *v = NULL, tv = VALINIT, nv = VALINIT, key = VALINIT;
    Jsi_DString dStr = {};
    cp2 = strchr(nam,'[');
    cp = strchr(nam, '.');
    if (cp2 && (cp==0 || cp2<cp))
        cp = cp2;
    if (!cp)
        return Jsi_VarLookup(interp, nam);
    Jsi_DSSetLength(&dStr, 0);
    Jsi_DSAppendLen(&dStr, nam, cp-nam);
    v = Jsi_VarLookup(interp, Jsi_DSValue(&dStr));
    if (!v)
        goto bail;
    while (cnt++ < 1000) {
        ocp = cp;
        nam = cp+1;
        isq = 0;
        if (*cp == '[') {
            cp = FindEndB(cp+1); /* handle [] in strings. */
            if (!cp) goto bail;
            len = cp-nam;
            cp++;
            if (len>=2 && ((nam[0] == '\"' && nam[len-1] == '\"') || (nam[0] == '\'' && nam[len-1] == '\''))) {
                nam += 1;
                len -= 2;
                isq = 1;
            }
        } else if (*cp == '.') {
            cp2 = strchr(nam,'[');
            cp = strchr(nam, '.');
            if (cp2 && (cp==0 || cp2<cp))
                cp = cp2;
            len = (cp ? cp-nam : strlen(nam));
        } else {
            goto bail;
        }
        Jsi_DSSetLength(&dStr, 0);
        Jsi_DSAppendLen(&dStr, nam, len);
        kstr = Jsi_DSValue(&dStr);
        if (*ocp == '[' && isq == 0 && isdigit(kstr[0]) && Jsi_ValueIsArray(interp, v)) {
            int nn;
            if (Jsi_GetInt(interp, kstr, &nn, 0) != JSI_OK)
                goto bail;
            v = Jsi_ValueArrayIndex(interp, v, nn);
            if (!v)
                goto bail;
        } else if (*ocp == '[' && isq == 0) {
            Jsi_Value *kv = Jsi_VarLookup(interp, kstr);
            if (!kv)
                goto bail;
            jsi_ValueSubscriptLen(interp, v, kv, &nv, 1);
            goto keyon;
        } else {
            Jsi_ValueMakeStringKey(interp, &key, kstr); 
            jsi_ValueSubscriptLen(interp, v, &key, &nv, 1);
keyon:
            if (nv.vt == JSI_VT_UNDEF)
                goto bail;
            else {
                tv = nv;
                v = &tv;
            }
        }
        if (cp == 0 || *cp == 0) break;
    }
    //Jsi_ValueReset(interp, &ret);
    Jsi_DSFree(&dStr);
    if (v && v == &tv) {
        v = Jsi_ValueNew(interp);
        *v = tv;
    }
    return v;
bail:
    Jsi_DSFree(&dStr);
    return NULL;
}