⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jim.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
    pc->tstart = ++pc->p; pc->len--;
    pc->tline = pc->linenr;
    while (1) {
        if (*pc->p == '\\' && pc->len >= 2) {
            pc->p++; pc->len--;
            if (*pc->p == '\n')
                pc->linenr++;
        } else if (*pc->p == '{') {
            level++;
        } else if (pc->len == 0 || *pc->p == '}') {
            level--;
            if (pc->len == 0 || level == 0) {
                pc->tend = pc->p-1;
                if (pc->len != 0) {
                    pc->p++; pc->len--;
                }
                pc->tt = JIM_TT_STR;
                return JIM_OK;
            }
        } else if (*pc->p == '\n') {
            pc->linenr++;
        }
        pc->p++; pc->len--;
    }
    return JIM_OK; /* unreached */
}

int JimParseStr(struct JimParserCtx *pc)
{
    int newword = (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
            pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR);
    if (newword && *pc->p == '{') {
        return JimParseBrace(pc);
    } else if (newword && *pc->p == '"') {
        pc->state = JIM_PS_QUOTE;
        pc->p++; pc->len--;
    }
    pc->tstart = pc->p;
    pc->tline = pc->linenr;
    while (1) {
        if (pc->len == 0) {
            pc->tend = pc->p-1;
            pc->tt = JIM_TT_ESC;
            return JIM_OK;
        }
        switch(*pc->p) {
        case '\\':
            if (pc->state == JIM_PS_DEF &&
                *(pc->p+1) == '\n') {
                pc->tend = pc->p-1;
                pc->tt = JIM_TT_ESC;
                return JIM_OK;
            }
            if (pc->len >= 2) {
                pc->p++; pc->len--;
            }
            break;
        case '$':
        case '[':
            pc->tend = pc->p-1;
            pc->tt = JIM_TT_ESC;
            return JIM_OK;
        case ' ':
        case '\t':
        case '\n':
        case '\r':
        case ';':
            if (pc->state == JIM_PS_DEF) {
                pc->tend = pc->p-1;
                pc->tt = JIM_TT_ESC;
                return JIM_OK;
            } else if (*pc->p == '\n') {
                pc->linenr++;
            }
            break;
        case '"':
            if (pc->state == JIM_PS_QUOTE) {
                pc->tend = pc->p-1;
                pc->tt = JIM_TT_ESC;
                pc->p++; pc->len--;
                pc->state = JIM_PS_DEF;
                return JIM_OK;
            }
            break;
        }
        pc->p++; pc->len--;
    }
    return JIM_OK; /* unreached */
}

int JimParseComment(struct JimParserCtx *pc)
{
    while (*pc->p) {
        if (*pc->p == '\n') {
            pc->linenr++;
            if (*(pc->p-1) != '\\') {
                pc->p++; pc->len--;
                return JIM_OK;
            }
        }
        pc->p++; pc->len--;
    }
    return JIM_OK;
}

/* xdigitval and odigitval are helper functions for JimParserGetToken() */
static int xdigitval(int c)
{
    if (c >= '0' && c <= '9') return c-'0';
    if (c >= 'a' && c <= 'f') return c-'a'+10;
    if (c >= 'A' && c <= 'F') return c-'A'+10;
    return -1;
}

static int odigitval(int c)
{
    if (c >= '0' && c <= '7') return c-'0';
    return -1;
}

/* Perform Tcl escape substitution of 's', storing the result
 * string into 'dest'. The escaped string is guaranteed to
 * be the same length or shorted than the source string.
 * Slen is the length of the string at 's', if it's -1 the string
 * length will be calculated by the function.
 *
 * The function returns the length of the resulting string. */
static int JimEscape(char *dest, const char *s, int slen)
{
    char *p = dest;
    int i, len;
    
    if (slen == -1)
        slen = strlen(s);

    for (i = 0; i < slen; i++) {
        switch(s[i]) {
        case '\\':
            switch(s[i+1]) {
            case 'a': *p++ = 0x7; i++; break;
            case 'b': *p++ = 0x8; i++; break;
            case 'f': *p++ = 0xc; i++; break;
            case 'n': *p++ = 0xa; i++; break;
            case 'r': *p++ = 0xd; i++; break;
            case 't': *p++ = 0x9; i++; break;
            case 'v': *p++ = 0xb; i++; break;
            case '\0': *p++ = '\\'; i++; break;
            case '\n': *p++ = ' '; i++; break;
            default:
                  if (s[i+1] == 'x') {
                    int val = 0;
                    int c = xdigitval(s[i+2]);
                    if (c == -1) {
                        *p++ = 'x';
                        i++;
                        break;
                    }
                    val = c;
                    c = xdigitval(s[i+3]);
                    if (c == -1) {
                        *p++ = val;
                        i += 2;
                        break;
                    }
                    val = (val*16)+c;
                    *p++ = val;
                    i += 3;
                    break;
                  } else if (s[i+1] >= '0' && s[i+1] <= '7')
                  {
                    int val = 0;
                    int c = odigitval(s[i+1]);
                    val = c;
                    c = odigitval(s[i+2]);
                    if (c == -1) {
                        *p++ = val;
                        i ++;
                        break;
                    }
                    val = (val*8)+c;
                    c = odigitval(s[i+3]);
                    if (c == -1) {
                        *p++ = val;
                        i += 2;
                        break;
                    }
                    val = (val*8)+c;
                    *p++ = val;
                    i += 3;
                  } else {
                    *p++ = s[i+1];
                    i++;
                  }
                  break;
            }
            break;
        default:
            *p++ = s[i];
            break;
        }
    }
    len = p-dest;
    *p++ = '\0';
    return len;
}

/* Returns a dynamically allocated copy of the current token in the
 * parser context. The function perform conversion of escapes if
 * the token is of type JIM_TT_ESC.
 *
 * Note that after the conversion, tokens that are grouped with
 * braces in the source code, are always recognizable from the
 * identical string obtained in a different way from the type.
 *
 * For exmple the string:
 *
 * {expand}$a
 * 
 * will return as first token "expand", of type JIM_TT_STR
 *
 * While the string:
 *
 * expand$a
 *
 * will return as first token "expand", of type JIM_TT_ESC
 */
char *JimParserGetToken(struct JimParserCtx *pc,
        int *lenPtr, int *typePtr, int *linePtr)
{
    const char *start, *end;
    char *token;
    int len;

    start = JimParserTstart(pc);
    end = JimParserTend(pc);
    if (start > end) {
        if (lenPtr) *lenPtr = 0;
        if (typePtr) *typePtr = JimParserTtype(pc);
        if (linePtr) *linePtr = JimParserTline(pc);
        token = Jim_Alloc(1);
        token[0] = '\0';
        return token;
    }
    len = (end-start)+1;
    token = Jim_Alloc(len+1);
    if (JimParserTtype(pc) != JIM_TT_ESC) {
        /* No escape conversion needed? Just copy it. */
        memcpy(token, start, len);
        token[len] = '\0';
    } else {
        /* Else convert the escape chars. */
        len = JimEscape(token, start, len);
    }
    if (lenPtr) *lenPtr = len;
    if (typePtr) *typePtr = JimParserTtype(pc);
    if (linePtr) *linePtr = JimParserTline(pc);
    return token;
}

/* The following functin is not really part of the parsing engine of Jim,
 * but it somewhat related. Given an string and its length, it tries
 * to guess if the script is complete or there are instead " " or { }
 * open and not completed. This is useful for interactive shells
 * implementation and for [info complete].
 *
 * If 'stateCharPtr' != NULL, the function stores ' ' on complete script,
 * '{' on scripts incomplete missing one or more '}' to be balanced.
 * '"' on scripts incomplete missing a '"' char.
 *
 * If the script is complete, 1 is returned, otherwise 0. */
int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
{
    int level = 0;
    int state = ' ';

    while(len) {
        switch (*s) {
            case '\\':
                if (len > 1)
                    s++;
                break;
            case '"':
                if (state == ' ') {
                    state = '"';
                } else if (state == '"') {
                    state = ' ';
                }
                break;
            case '{':
                if (state == '{') {
                    level++;
                } else if (state == ' ') {
                    state = '{';
                    level++;
                }
                break;
            case '}':
                if (state == '{') {
                    level--;
                    if (level == 0)
                        state = ' ';
                }
                break;
        }
        s++;
        len--;
    }
    if (stateCharPtr)
        *stateCharPtr = state;
    return state == ' ';
}

/* -----------------------------------------------------------------------------
 * Tcl Lists parsing
 * ---------------------------------------------------------------------------*/
static int JimParseListSep(struct JimParserCtx *pc);
static int JimParseListStr(struct JimParserCtx *pc);

int JimParseList(struct JimParserCtx *pc)
{
    if (pc->len == 0) {
        pc->tstart = pc->tend = pc->p;
        pc->tline = pc->linenr;
        pc->tt = JIM_TT_EOL;
        pc->eof = 1;
        return JIM_OK;
    }
    switch(*pc->p) {
    case ' ':
    case '\n':
    case '\t':
    case '\r':
        if (pc->state == JIM_PS_DEF)
            return JimParseListSep(pc);
        else
            return JimParseListStr(pc);
        break;
    default:
        return JimParseListStr(pc);
        break;
    }
    return JIM_OK;
}

int JimParseListSep(struct JimParserCtx *pc)
{
    pc->tstart = pc->p;
    pc->tline = pc->linenr;
    while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == '\n')
    {
        pc->p++; pc->len--;
    }
    pc->tend = pc->p-1;
    pc->tt = JIM_TT_SEP;
    return JIM_OK;
}

int JimParseListStr(struct JimParserCtx *pc)
{
    int newword = (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL ||
            pc->tt == JIM_TT_NONE);
    if (newword && *pc->p == '{') {
        return JimParseBrace(pc);
    } else if (newword && *pc->p == '"') {
        pc->state = JIM_PS_QUOTE;
        pc->p++; pc->len--;
    }
    pc->tstart = pc->p;
    pc->tline = pc->linenr;
    while (1) {
        if (pc->len == 0) {
            pc->tend = pc->p-1;
            pc->tt = JIM_TT_ESC;
            return JIM_OK;
        }
        switch(*pc->p) {
        case '\\':
            pc->p++; pc->len--;
            break;
        case ' ':
        case '\t':
        case '\n':
        case '\r':
            if (pc->state == JIM_PS_DEF) {
                pc->tend = pc->p-1;
                pc->tt = JIM_TT_ESC;
                return JIM_OK;
            } else if (*pc->p == '\n') {
                pc->linenr++;
            }
            break;
        case '"':
            if (pc->state == JIM_PS_QUOTE) {
                pc->tend = pc->p-1;
                pc->tt = JIM_TT_ESC;
                pc->p++; pc->len--;
                pc->state = JIM_PS_DEF;
                return JIM_OK;
            }
            break;
        }
        pc->p++; pc->len--;
    }
    return JIM_OK; /* unreached */
}

/* -----------------------------------------------------------------------------
 * Jim_Obj related functions
 * ---------------------------------------------------------------------------*/

/* Return a new initialized object. */
Jim_Obj *Jim_NewObj(Jim_Interp *interp)
{
    Jim_Obj *objPtr;

    /* -- Check if there are objects in the free list -- */
    if (interp->freeList != NULL) {
        /* -- Unlink the object from the free list -- */
        objPtr = interp->freeList;
        interp->freeList = objPtr->nextObjPtr;
    } else {
        /* -- No ready to use objects: allocate a new one -- */
        objPtr = Jim_Alloc(sizeof(*objPtr));
    }

    /* Object is returned with refCount of 0. Every
     * kind of GC implemented should take care to don't try
     * to scan objects with refCount == 0. */
    objPtr->refCount = 0;
    /* All the other fields are left not initialized to save time.
     * The caller will probably want set they to the right
     * value anyway. */

    /* -- Put the object into the live list -- */
    objPtr->prevObjPtr = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -