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

📄 jim.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:

/* ----------------------- StringCopy Hash Table Type ------------------------*/

static unsigned int JimStringCopyHTHashFunction(const void *key)
{
    return Jim_GenHashFunction(key, strlen(key));
}

static const void *JimStringCopyHTKeyDup(void *privdata, const void *key)
{
    int len = strlen(key);
    char *copy = Jim_Alloc(len+1);
    JIM_NOTUSED(privdata);

    memcpy(copy, key, len);
    copy[len] = '\0';
    return copy;
}

static void *JimStringKeyValCopyHTValDup(void *privdata, const void *val)
{
    int len = strlen(val);
    char *copy = Jim_Alloc(len+1);
    JIM_NOTUSED(privdata);

    memcpy(copy, val, len);
    copy[len] = '\0';
    return copy;
}

static int JimStringCopyHTKeyCompare(void *privdata, const void *key1,
        const void *key2)
{
    JIM_NOTUSED(privdata);

    return strcmp(key1, key2) == 0;
}

static void JimStringCopyHTKeyDestructor(void *privdata, const void *key)
{
    JIM_NOTUSED(privdata);

    Jim_Free((void*)key); /* ATTENTION: const cast */
}

static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val)
{
    JIM_NOTUSED(privdata);

    Jim_Free((void*)val); /* ATTENTION: const cast */
}

static Jim_HashTableType JimStringCopyHashTableType = {
    JimStringCopyHTHashFunction,        /* hash function */
    JimStringCopyHTKeyDup,              /* key dup */
    NULL,                               /* val dup */
    JimStringCopyHTKeyCompare,          /* key compare */
    JimStringCopyHTKeyDestructor,       /* key destructor */
    NULL                                /* val destructor */
};

/* This is like StringCopy but does not auto-duplicate the key.
 * It's used for intepreter's shared strings. */
static Jim_HashTableType JimSharedStringsHashTableType = {
    JimStringCopyHTHashFunction,        /* hash function */
    NULL,                               /* key dup */
    NULL,                               /* val dup */
    JimStringCopyHTKeyCompare,          /* key compare */
    JimStringCopyHTKeyDestructor,       /* key destructor */
    NULL                                /* val destructor */
};

/* This is like StringCopy but also automatically handle dynamic
 * allocated C strings as values. */
static Jim_HashTableType JimStringKeyValCopyHashTableType = {
    JimStringCopyHTHashFunction,        /* hash function */
    JimStringCopyHTKeyDup,              /* key dup */
    JimStringKeyValCopyHTValDup,        /* val dup */
    JimStringCopyHTKeyCompare,          /* key compare */
    JimStringCopyHTKeyDestructor,       /* key destructor */
    JimStringKeyValCopyHTValDestructor, /* val destructor */
};

typedef struct AssocDataValue {
    Jim_InterpDeleteProc *delProc;
    void *data;
} AssocDataValue;

static void JimAssocDataHashTableValueDestructor(void *privdata, void *data)
{
    AssocDataValue *assocPtr = (AssocDataValue *)data;
    if (assocPtr->delProc != NULL)
        assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data);
    Jim_Free(data);
}

static Jim_HashTableType JimAssocDataHashTableType = {
    JimStringCopyHTHashFunction,         /* hash function */
    JimStringCopyHTKeyDup,               /* key dup */
    NULL,                                /* val dup */
    JimStringCopyHTKeyCompare,           /* key compare */
    JimStringCopyHTKeyDestructor,        /* key destructor */
    JimAssocDataHashTableValueDestructor /* val destructor */
};

/* -----------------------------------------------------------------------------
 * Stack - This is a simple generic stack implementation. It is used for
 * example in the 'expr' expression compiler.
 * ---------------------------------------------------------------------------*/
void Jim_InitStack(Jim_Stack *stack)
{
    stack->len = 0;
    stack->maxlen = 0;
    stack->vector = NULL;
}

void Jim_FreeStack(Jim_Stack *stack)
{
    Jim_Free(stack->vector);
}

int Jim_StackLen(Jim_Stack *stack)
{
    return stack->len;
}

void Jim_StackPush(Jim_Stack *stack, void *element) {
    int neededLen = stack->len+1;
    if (neededLen > stack->maxlen) {
        stack->maxlen = neededLen*2;
        stack->vector = Jim_Realloc(stack->vector, sizeof(void*)*stack->maxlen);
    }
    stack->vector[stack->len] = element;
    stack->len++;
}

void *Jim_StackPop(Jim_Stack *stack)
{
    if (stack->len == 0) return NULL;
    stack->len--;
    return stack->vector[stack->len];
}

void *Jim_StackPeek(Jim_Stack *stack)
{
    if (stack->len == 0) return NULL;
    return stack->vector[stack->len-1];
}

void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr))
{
    int i;

    for (i = 0; i < stack->len; i++)
        freeFunc(stack->vector[i]);
}

/* -----------------------------------------------------------------------------
 * Parser
 * ---------------------------------------------------------------------------*/

/* Token types */
#define JIM_TT_NONE -1        /* No token returned */
#define JIM_TT_STR 0        /* simple string */
#define JIM_TT_ESC 1        /* string that needs escape chars conversion */
#define JIM_TT_VAR 2        /* var substitution */
#define JIM_TT_DICTSUGAR 3    /* Syntax sugar for [dict get], $foo(bar) */
#define JIM_TT_CMD 4        /* command substitution */
#define JIM_TT_SEP 5        /* word separator */
#define JIM_TT_EOL 6        /* line separator */

/* Additional token types needed for expressions */
#define JIM_TT_SUBEXPR_START 7
#define JIM_TT_SUBEXPR_END 8
#define JIM_TT_EXPR_NUMBER 9
#define JIM_TT_EXPR_OPERATOR 10

/* Parser states */
#define JIM_PS_DEF 0        /* Default state */
#define JIM_PS_QUOTE 1        /* Inside "" */

/* Parser context structure. The same context is used both to parse
 * Tcl scripts and lists. */
struct JimParserCtx {
    const char *prg;     /* Program text */
    const char *p;       /* Pointer to the point of the program we are parsing */
    int len;             /* Left length of 'prg' */
    int linenr;          /* Current line number */
    const char *tstart;
    const char *tend;    /* Returned token is at tstart-tend in 'prg'. */
    int tline;           /* Line number of the returned token */
    int tt;              /* Token type */
    int eof;             /* Non zero if EOF condition is true. */
    int state;           /* Parser state */
    int comment;         /* Non zero if the next chars may be a comment. */
};

#define JimParserEof(c) ((c)->eof)
#define JimParserTstart(c) ((c)->tstart)
#define JimParserTend(c) ((c)->tend)
#define JimParserTtype(c) ((c)->tt)
#define JimParserTline(c) ((c)->tline)

static int JimParseScript(struct JimParserCtx *pc);
static int JimParseSep(struct JimParserCtx *pc);
static int JimParseEol(struct JimParserCtx *pc);
static int JimParseCmd(struct JimParserCtx *pc);
static int JimParseVar(struct JimParserCtx *pc);
static int JimParseBrace(struct JimParserCtx *pc);
static int JimParseStr(struct JimParserCtx *pc);
static int JimParseComment(struct JimParserCtx *pc);
static char *JimParserGetToken(struct JimParserCtx *pc,
        int *lenPtr, int *typePtr, int *linePtr);

/* Initialize a parser context.
 * 'prg' is a pointer to the program text, linenr is the line
 * number of the first line contained in the program. */
void JimParserInit(struct JimParserCtx *pc, const char *prg, 
        int len, int linenr)
{
    pc->prg = prg;
    pc->p = prg;
    pc->len = len;
    pc->tstart = NULL;
    pc->tend = NULL;
    pc->tline = 0;
    pc->tt = JIM_TT_NONE;
    pc->eof = 0;
    pc->state = JIM_PS_DEF;
    pc->linenr = linenr;
    pc->comment = 1;
}

int JimParseScript(struct JimParserCtx *pc)
{
    while(1) { /* the while is used to reiterate with continue if needed */
        if (!pc->len) {
            pc->tstart = pc->p;
            pc->tend = pc->p-1;
            pc->tline = pc->linenr;
            pc->tt = JIM_TT_EOL;
            pc->eof = 1;
            return JIM_OK;
        }
        switch(*(pc->p)) {
        case '\\':
            if (*(pc->p+1) == '\n')
                return JimParseSep(pc);
            else {
                pc->comment = 0;
                return JimParseStr(pc);
            }
            break;
        case ' ':
        case '\t':
        case '\r':
            if (pc->state == JIM_PS_DEF)
                return JimParseSep(pc);
            else {
                pc->comment = 0;
                return JimParseStr(pc);
            }
            break;
        case '\n':
        case ';':
            pc->comment = 1;
            if (pc->state == JIM_PS_DEF)
                return JimParseEol(pc);
            else
                return JimParseStr(pc);
            break;
        case '[':
            pc->comment = 0;
            return JimParseCmd(pc);
            break;
        case '$':
            pc->comment = 0;
            if (JimParseVar(pc) == JIM_ERR) {
                pc->tstart = pc->tend = pc->p++; pc->len--;
                pc->tline = pc->linenr;
                pc->tt = JIM_TT_STR;
                return JIM_OK;
            } else
                return JIM_OK;
            break;
        case '#':
            if (pc->comment) {
                JimParseComment(pc);
                continue;
            } else {
                return JimParseStr(pc);
            }
        default:
            pc->comment = 0;
            return JimParseStr(pc);
            break;
        }
        return JIM_OK;
    }
}

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

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

/* Todo. Don't stop if ']' appears inside {} or quoted.
 * Also should handle the case of puts [string length "]"] */
int JimParseCmd(struct JimParserCtx *pc)
{
    int level = 1;
    int blevel = 0;

    pc->tstart = ++pc->p; pc->len--;
    pc->tline = pc->linenr;
    while (1) {
        if (pc->len == 0) {
            break;
        } else if (*pc->p == '[' && blevel == 0) {
            level++;
        } else if (*pc->p == ']' && blevel == 0) {
            level--;
            if (!level) break;
        } else if (*pc->p == '\\') {
            pc->p++; pc->len--;
        } else if (*pc->p == '{') {
            blevel++;
        } else if (*pc->p == '}') {
            if (blevel != 0)
                blevel--;
        } else if (*pc->p == '\n')
            pc->linenr++;
        pc->p++; pc->len--;
    }
    pc->tend = pc->p-1;
    pc->tt = JIM_TT_CMD;
    if (*pc->p == ']') {
        pc->p++; pc->len--;
    }
    return JIM_OK;
}

int JimParseVar(struct JimParserCtx *pc)
{
    int brace = 0, stop = 0, ttype = JIM_TT_VAR;

    pc->tstart = ++pc->p; pc->len--; /* skip the $ */
    pc->tline = pc->linenr;
    if (*pc->p == '{') {
        pc->tstart = ++pc->p; pc->len--;
        brace = 1;
    }
    if (brace) {
        while (!stop) {
            if (*pc->p == '}' || pc->len == 0) {
                stop = 1;
                if (pc->len == 0)
                    continue;
            }
            else if (*pc->p == '\n')
                pc->linenr++;
            pc->p++; pc->len--;
        }
        if (pc->len == 0)
            pc->tend = pc->p-1;
        else
            pc->tend = pc->p-2;
    } else {
        while (!stop) {
            if (!((*pc->p >= 'a' && *pc->p <= 'z') ||
                (*pc->p >= 'A' && *pc->p <= 'Z') ||
                (*pc->p >= '0' && *pc->p <= '9') || *pc->p == '_'))
                stop = 1;
            else {
                pc->p++; pc->len--;
            }
        }
        /* Parse [dict get] syntax sugar. */
        if (*pc->p == '(') {
            while (*pc->p != ')' && pc->len) {
                pc->p++; pc->len--;
                if (*pc->p == '\\' && pc->len >= 2) {
                    pc->p += 2; pc->len -= 2;
                }
            }
            if (*pc->p != '\0') {
                pc->p++; pc->len--;
            }
            ttype = JIM_TT_DICTSUGAR;
        }
        pc->tend = pc->p-1;
    }
    /* Check if we parsed just the '$' character.
     * That's not a variable so an error is returned
     * to tell the state machine to consider this '$' just
     * a string. */
    if (pc->tstart == pc->p) {
        pc->p--; pc->len++;
        return JIM_ERR;
    }
    pc->tt = ttype;
    return JIM_OK;
}

int JimParseBrace(struct JimParserCtx *pc)
{
    int level = 1;

⌨️ 快捷键说明

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