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

📄 jim.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Jim - A small embeddable Tcl interpreter
 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
 * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
 *
 * $Id: jim.c,v 1.170 2006/11/06 21:48:57 antirez Exp $
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * A copy of the license is also included in the source distribution
 * of Jim, as a TXT file name called LICENSE.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define __JIM_CORE__
#define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */

#include <pkgconf/athttpd.h>

#ifndef JIM_ANSIC
#define JIM_DYNLIB      /* Dynamic library support for UNIX and WIN32 */
#endif /* JIM_ANSIC */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <assert.h>
#include <errno.h>
#include <time.h>

/* Include the platform dependent libraries for
 * dynamic loading of libraries. */
#ifdef JIM_DYNLIB
#if defined(_WIN32) || defined(WIN32)
#ifndef WIN32
#define WIN32 1
#endif
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if _MSC_VER >= 1000
#pragma warning(disable:4146)
#endif /* _MSC_VER */
#else
#include <dlfcn.h>
#endif /* WIN32 */
#endif /* JIM_DYNLIB */

#include <cyg/athttpd/jim.h>

#ifdef HAVE_BACKTRACE
#include <execinfo.h>
#endif

/* -----------------------------------------------------------------------------
 * Global variables
 * ---------------------------------------------------------------------------*/

/* A shared empty string for the objects string representation.
 * Jim_InvalidateStringRep knows about it and don't try to free. */
static char *JimEmptyStringRep = (char*) "";

/* -----------------------------------------------------------------------------
 * Required prototypes of not exported functions
 * ---------------------------------------------------------------------------*/
static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf);
static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags);
static void JimRegisterCoreApi(Jim_Interp *interp);

static Jim_HashTableType JimVariablesHashTableType;

/* -----------------------------------------------------------------------------
 * Utility functions
 * ---------------------------------------------------------------------------*/

/*
 * Convert a string to a jim_wide INTEGER.
 * This function originates from BSD.
 *
 * Ignores `locale' stuff.  Assumes that the upper and lower case
 * alphabets and digits are each contiguous.
 */
#ifdef HAVE_LONG_LONG
#define JimIsAscii(c) (((c) & ~0x7f) == 0)
static jim_wide JimStrtoll(const char *nptr, char **endptr, register int base)
{
    register const char *s;
    register unsigned jim_wide acc;
    register unsigned char c;
    register unsigned jim_wide qbase, cutoff;
    register int neg, any, cutlim;

    /*
     * Skip white space and pick up leading +/- sign if any.
     * If base is 0, allow 0x for hex and 0 for octal, else
     * assume decimal; if base is already 16, allow 0x.
     */
    s = nptr;
    do {
        c = *s++;
    } while (isspace(c));
    if (c == '-') {
        neg = 1;
        c = *s++;
    } else {
        neg = 0;
        if (c == '+')
            c = *s++;
    }
    if ((base == 0 || base == 16) &&
        c == '0' && (*s == 'x' || *s == 'X')) {
        c = s[1];
        s += 2;
        base = 16;
    }
    if (base == 0)
        base = c == '0' ? 8 : 10;

    /*
     * Compute the cutoff value between legal numbers and illegal
     * numbers.  That is the largest legal value, divided by the
     * base.  An input number that is greater than this value, if
     * followed by a legal input character, is too big.  One that
     * is equal to this value may be valid or not; the limit
     * between valid and invalid numbers is then based on the last
     * digit.  For instance, if the range for quads is
     * [-9223372036854775808..9223372036854775807] and the input base
     * is 10, cutoff will be set to 922337203685477580 and cutlim to
     * either 7 (neg==0) or 8 (neg==1), meaning that if we have
     * accumulated a value > 922337203685477580, or equal but the
     * next digit is > 7 (or 8), the number is too big, and we will
     * return a range error.
     *
     * Set any if any `digits' consumed; make it negative to indicate
     * overflow.
     */
    qbase = (unsigned)base;
    cutoff = neg ? (unsigned jim_wide)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
        : LLONG_MAX;
    cutlim = (int)(cutoff % qbase);
    cutoff /= qbase;
    for (acc = 0, any = 0;; c = *s++) {
        if (!JimIsAscii(c))
            break;
        if (isdigit(c))
            c -= '0';
        else if (isalpha(c))
            c -= isupper(c) ? 'A' - 10 : 'a' - 10;
        else
            break;
        if (c >= base)
            break;
        if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
            any = -1;
        else {
            any = 1;
            acc *= qbase;
            acc += c;
        }
    }
    if (any < 0) {
        acc = neg ? LLONG_MIN : LLONG_MAX;
        errno = ERANGE;
    } else if (neg)
        acc = -acc;
    if (endptr != 0)
        *endptr = (char *)(any ? s - 1 : nptr);
    return (acc);
}
#endif

/* Glob-style pattern matching. */
static int JimStringMatch(const char *pattern, int patternLen,
        const char *string, int stringLen, int nocase)
{
    while(patternLen) {
        switch(pattern[0]) {
        case '*':
            while (pattern[1] == '*') {
                pattern++;
                patternLen--;
            }
            if (patternLen == 1)
                return 1; /* match */
            while(stringLen) {
                if (JimStringMatch(pattern+1, patternLen-1,
                            string, stringLen, nocase))
                    return 1; /* match */
                string++;
                stringLen--;
            }
            return 0; /* no match */
            break;
        case '?':
            if (stringLen == 0)
                return 0; /* no match */
            string++;
            stringLen--;
            break;
        case '[':
        {
            int not, match;

            pattern++;
            patternLen--;
            not = pattern[0] == '^';
            if (not) {
                pattern++;
                patternLen--;
            }
            match = 0;
            while(1) {
                if (pattern[0] == '\\') {
                    pattern++;
                    patternLen--;
                    if (pattern[0] == string[0])
                        match = 1;
                } else if (pattern[0] == ']') {
                    break;
                } else if (patternLen == 0) {
                    pattern--;
                    patternLen++;
                    break;
                } else if (pattern[1] == '-' && patternLen >= 3) {
                    int start = pattern[0];
                    int end = pattern[2];
                    int c = string[0];
                    if (start > end) {
                        int t = start;
                        start = end;
                        end = t;
                    }
                    if (nocase) {
                        start = tolower(start);
                        end = tolower(end);
                        c = tolower(c);
                    }
                    pattern += 2;
                    patternLen -= 2;
                    if (c >= start && c <= end)
                        match = 1;
                } else {
                    if (!nocase) {
                        if (pattern[0] == string[0])
                            match = 1;
                    } else {
                        if (tolower((int)pattern[0]) == tolower((int)string[0]))
                            match = 1;
                    }
                }
                pattern++;
                patternLen--;
            }
            if (not)
                match = !match;
            if (!match)
                return 0; /* no match */
            string++;
            stringLen--;
            break;
        }
        case '\\':
            if (patternLen >= 2) {
                pattern++;
                patternLen--;
            }
            /* fall through */
        default:
            if (!nocase) {
                if (pattern[0] != string[0])
                    return 0; /* no match */
            } else {
                if (tolower((int)pattern[0]) != tolower((int)string[0]))
                    return 0; /* no match */
            }
            string++;
            stringLen--;
            break;
        }
        pattern++;
        patternLen--;
        if (stringLen == 0) {
            while(*pattern == '*') {
                pattern++;
                patternLen--;
            }
            break;
        }
    }
    if (patternLen == 0 && stringLen == 0)
        return 1;
    return 0;
}

int JimStringCompare(const char *s1, int l1, const char *s2, int l2,
        int nocase)
{
    unsigned char *u1 = (unsigned char*) s1, *u2 = (unsigned char*) s2;

    if (nocase == 0) {
        while(l1 && l2) {
            if (*u1 != *u2)
                return (int)*u1-*u2;
            u1++; u2++; l1--; l2--;
        }
        if (!l1 && !l2) return 0;
        return l1-l2;
    } else {
        while(l1 && l2) {
            if (tolower((int)*u1) != tolower((int)*u2))
                return tolower((int)*u1)-tolower((int)*u2);
            u1++; u2++; l1--; l2--;
        }
        if (!l1 && !l2) return 0;
        return l1-l2;
    }
}

/* Search 's1' inside 's2', starting to search from char 'index' of 's2'.
 * The index of the first occurrence of s1 in s2 is returned. 
 * If s1 is not found inside s2, -1 is returned. */
int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int index)
{
    int i;

    if (!l1 || !l2 || l1 > l2) return -1;
    if (index < 0) index = 0;
    s2 += index;
    for (i = index; i <= l2-l1; i++) {
        if (memcmp(s2, s1, l1) == 0)
            return i;
        s2++;
    }
    return -1;
}

int Jim_WideToString(char *buf, jim_wide wideValue)
{
    const char *fmt = "%" JIM_WIDE_MODIFIER;
    return sprintf(buf, fmt, wideValue);
}

int Jim_StringToWide(const char *str, jim_wide *widePtr, int base)
{
    char *endptr;

#ifdef HAVE_LONG_LONG
    *widePtr = JimStrtoll(str, &endptr, base);
#else
    *widePtr = strtol(str, &endptr, base);
#endif
    if (str[0] == '\0')
        return JIM_ERR;
    if (endptr[0] != '\0') {
        while(*endptr) {
            if (!isspace((int)*endptr))
                return JIM_ERR;
            endptr++;
        }
    }
    return JIM_OK;
}

int Jim_StringToIndex(const char *str, int *intPtr)
{
    char *endptr;

    *intPtr = strtol(str, &endptr, 10);
    if (str[0] == '\0')
        return JIM_ERR;
    if (endptr[0] != '\0') {
        while(*endptr) {
            if (!isspace((int)*endptr))
                return JIM_ERR;
            endptr++;
        }
    }
    return JIM_OK;
}

/* The string representation of references has two features in order
 * to make the GC faster. The first is that every reference starts
 * with a non common character '~', in order to make the string matching
 * fater. The second is that the reference string rep his 32 characters
 * in length, this allows to avoid to check every object with a string
 * repr < 32, and usually there are many of this objects. */

#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN)

static int JimFormatReference(char *buf, Jim_Reference *refPtr, jim_wide id)
{
    const char *fmt = "<reference.<%s>.%020" JIM_WIDE_MODIFIER ">";
    sprintf(buf, fmt, refPtr->tag, id);
    return JIM_REFERENCE_SPACE;
}

int Jim_DoubleToString(char *buf, double doubleValue)
{
    char *s;
    int len;

    len = sprintf(buf, "%.17g", doubleValue);
    s = buf;
    while(*s) {
        if (*s == '.') return len;
        s++;
    }
    /* Add a final ".0" if it's a number. But not
     * for NaN or InF */
    if (isdigit((int)buf[0])
        || ((buf[0] == '-' || buf[0] == '+')
            && isdigit((int)buf[1]))) {
        s[0] = '.';
        s[1] = '0';
        s[2] = '\0';
        return len+2;
    }
    return len;
}

int Jim_StringToDouble(const char *str, double *doublePtr)
{
    char *endptr;

⌨️ 快捷键说明

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