Beispiel #1
0
static ekRegex * ekRegexCreate(ekContext * E, ekValue * subject, ekValue * pattern, ekValue * options)
{
    ekS32 regexFlags = 0;
    const char * regexError;
    ekS32 regexErrorOffset;
    ekRegex * regex = calloc(1, sizeof(ekRegex));

    regex->subject = subject;
    regex->offset = 0;
    regex->global = ekFalse;

    if (options) {
        const char * c = ekValueSafeStr(options);
        for (; *c; c++) {
            switch (*c) {
                case 'x': regexFlags |= PCRE_EXTENDED;  break;
                case 'i': regexFlags |= PCRE_CASELESS;  break;
                case 's': regexFlags |= PCRE_DOTALL;    break;
                case 'm': regexFlags |= PCRE_MULTILINE; break;

                case 'g': regex->global = ekTrue;       break;
            }
        }
    }

    regex->regex = pcre_compile(ekValueSafeStr(pattern), regexFlags, &regexError, &regexErrorOffset, NULL);
    if (!regex->regex) {
        // Regex compilation errors are fatal for now. I think this is good.
        ekContextSetError(E, EVE_RUNTIME, "regex compilation error: %s", regexError);
        ekRegexDestroy(E, regex);
        regex = NULL;
    }
    return regex;
}
Beispiel #2
0
static ekU32 fileSize(struct ekContext *E, ekU32 argCount)
{
    ekValue *ret = ekValueNullPtr;
    ekValue *filenameValue;
    ekFile *file;
    struct stat s;

    if(!ekContextGetArgs(E, argCount, "s", &filenameValue))
    {
        return ekContextArgsFailure(E, argCount, "file.size(path)");
    }

    if(stat(ekValueSafeStr(file->filename), &s) != -1)
    {
        if(S_ISDIR(s.st_mode))
        {
            return ekContextArgsFailure(E, 0, "file.size() does not work on directories");
        }
        else
        {
            ret = ekValueCreateInt(E, s.st_size);
        }
    }

    ekValueRemoveRefNote(E, filenameValue, "fileSize doesnt need filename anymore");
    ekContextReturn(E, ret);
}
Beispiel #3
0
static ekU32 fileWrite(struct ekContext *E, ekU32 argCount)
{
    ekValue *thisValue;
    ekValue *ret = ekValueNullPtr;
    ekValue *dataValue = NULL;
    ekFile *file;

    if(!ekContextGetArgs(E, argCount, "*Fs", &thisValue, &dataValue))
    {
        return ekContextArgsFailure(E, argCount, "file.write([string] data)");
    }

    file = (ekFile *)thisValue->ptrVal;

    if((file->state != EFS_WRITE) && (file->state != EFS_APPEND))
    {
        switchState(E, file, EFS_WRITE);
    }
    if(file->handle)
    {
        const char *data = ekValueSafeStr(dataValue);
        int len = strlen(data);
        int bytesWritten = fwrite(data, 1, len, file->handle);
        if(bytesWritten == len)
        {
            ret = ekValueCreateInt(E, 1);
        }
    }
    ekValueRemoveRefNote(E, thisValue, "fileWrite no longer needs thisValue");
    ekContextReturn(E, ret); // will be true if we successfully wrote
}
Beispiel #4
0
static ekU32 fileLs(struct ekContext *E, ekU32 argCount)
{
    ekValue *filenameValue = NULL;
    ekValue *arrayValue = NULL;

    if(!ekContextGetArgs(E, argCount, "s", &filenameValue))
    {
        return ekContextArgsFailure(E, argCount, "file.ls(dirpath)");
    }

    arrayValue = ekValueCreateArray(E);

#ifdef USE_DIRENT
    {
        DIR *dir = opendir(ekValueSafeStr(filenameValue));
        if(dir)
        {
            struct dirent *entry;
            while((entry = readdir(dir)) != NULL)
            {
                if(strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
                {
                    ekValueArrayPush(E, arrayValue, ekValueCreateString(E, entry->d_name));
                }
            }
            closedir(dir);
        }
    }
#endif

    ekValueRemoveRefNote(E, filenameValue, "fileExists doesnt need filename anymore");
    ekContextReturn(E, arrayValue);
}
Beispiel #5
0
static ekValue *absolutePath(struct ekContext *E, ekValue *path)
{
    char temppath[MAX_PATH_LENGTH];
    realpath(ekValueSafeStr(path), temppath);
    ekValueRemoveRefNote(E, path, "absolutePath doesn't need relative path anymore");
    return ekValueCreateString(E, temppath);
}
Beispiel #6
0
static void fileFuncDump(struct ekContext *E, ekDumpParams *params, struct ekValue *p)
{
    ekFile *file = (ekFile *)p->ptrVal;
    ekStringConcat(E, &params->output, "{ ");
    ekStringConcat(E, &params->output, "FILE: ");
    ekStringConcat(E, &params->output, ekValueSafeStr(file->filename));
    ekStringConcat(E, &params->output, " }");
}
Beispiel #7
0
static ekBool ekRegexMatchNext(ekContext * E, ekRegex * regex, ekValue * matches)
{
    // Why PCRE didn't make this an array of small structs is baffling to me;
    // it would have led to much more obvious, self-documenting code.
    ekS32 regexVectors[EUREKA_MAX_REGEX_VECTORS];
    ekS32 len = strlen(ekValueSafeStr(regex->subject));
    ekS32 err = pcre_exec(regex->regex, 0, ekValueSafeStr(regex->subject), len, regex->offset, 0, regexVectors, EUREKA_MAX_REGEX_VECTORS);
    if (err > 0) {
        ekS32 i;
        ekAssert(matches->type == EVT_ARRAY);
        for (i = 0; i < err; ++i) {
            ekS32 index = i * 2;
            ekValue * match = ekValueDonateString(E, ekSubstrdup(E, ekValueSafeStr(regex->subject), regexVectors[index], regexVectors[index + 1]));
            ekArrayPush(E, &matches->arrayVal, match);
        }
        regex->offset = regexVectors[1];
        return ekTrue;
    }
    return ekFalse;
}
Beispiel #8
0
static int isDir(struct ekContext *E, ekValue *filenameValue)
{
    struct stat s;
    if(stat(ekValueSafeStr(filenameValue), &s) != -1)
    {
        if(S_ISDIR(s.st_mode))
        {
            return 1;
        }
    }
    return 0;
}
Beispiel #9
0
static ekU32 fileOpenInternal(struct ekContext *E, ekValue *fileValue, ekValue *modesValue)
{
    ekValue *ret = ekValueNullPtr;
    ekFile *file = (ekFile *)fileValue->ptrVal;
    if(isDir(E, file->filename))
    {
        return ekContextArgsFailure(E, 0, "file.open() does not work on directories");
    }

    {
        const char *c;
        const char *modes = "r";
        int state = EFS_READ;
        if(modesValue)
        {
            modes = ekValueSafeStr(modesValue);
        }
        for(c = modes; *c; ++c)
        {
            switch(*c)
            {
                case 'r':
                    state = EFS_READ;
                    break;
                case 'w':
                    state = EFS_WRITE;
                    break;
                case 'a':
                    state = EFS_APPEND;
                    break;
            };
        }

        switchState(E, file, state);
        if(file->handle)
        {
            ret = fileValue;
        }
        else
        {
            ekValueRemoveRefNote(E, fileValue, "fileOpen failed, so forget about fileValue");
        }
    }

    ekContextReturn(E, ret);
}
Beispiel #10
0
static ekU32 fileExists(struct ekContext *E, ekU32 argCount)
{
    ekValue *filenameValue = NULL;
    struct stat s;
    int exists = 0;

    if(!ekContextGetArgs(E, argCount, "s", &filenameValue))
    {
        return ekContextArgsFailure(E, argCount, "file.exists(path)");
    }

    if(stat(ekValueSafeStr(filenameValue), &s) != -1)
    {
        exists = 1;
    }

    ekValueRemoveRefNote(E, filenameValue, "fileExists doesnt need filename anymore");
    ekContextReturnInt(E, exists);
}
Beispiel #11
0
static int switchState(struct ekContext *E, ekFile *file, int newState)
{
    const char *mode = NULL;
    if(file->state == newState)
    {
        return 0;
    }
    if(file->permanent)
    {
        ekContextSetError(E, EVE_RUNTIME, "attempting to change file state on a permanent file: file.%s", ekValueSafeStr(file->filename));
        return 0; // never change the state on a permanent file!
    }
    if(file->handle)
    {
        fclose(file->handle);
        file->handle = NULL;
    }
    switch(newState)
    {
        case EFS_CLOSED:
            // do nothing, we already closed it
            break;

        case EFS_READ:
            mode = "rb";
            break;

        case EFS_WRITE:
            mode = "wb";
            break;

        case EFS_APPEND:
            mode = "ab";
            break;
    }
    if(mode)
    {
        file->handle = fopen(ekValueSafeStr(file->filename), mode);
    }
    file->state = newState;
    return 1;
}
Beispiel #12
0
struct ekValue *ekValueTypeGetIntrinsic(struct ekContext *E, ekU32 type, struct ekValue *index, ekBool lvalue)
{
    ekMap *map = E->types[type]->intrinsics;
    if(map && index && (index->type == EVT_STRING))
    {
        ekMapEntry *mapEntry = ekMapGetS(E, map, ekValueSafeStr(index), ekFalse);
        if(mapEntry && mapEntry->valuePtr)
        {
            if(lvalue)
            {
                ekContextSetError(E, EVE_RUNTIME, "cannot use intrinsic %s function as an lvalue", ekValueTypeName(E, type));
            }
            else
            {
                return ekValueCreateCFunction(E, mapEntry->valuePtr);
            }
        }
    }
    return NULL;
}
Beispiel #13
0
static ekS32 ekRegexSub(ekContext * E, ekRegex * regex, ekValue * replace, ekString * output)
{
    const char * subject = ekValueSafeStr(regex->subject);
    ekS32 len = strlen(subject);
    ekS32 count = 0;
    ekS32 regexVectors[EUREKA_MAX_REGEX_VECTORS];
    ekS32 err;
    while ((err = pcre_exec(regex->regex, 0, subject, len, regex->offset, 0, regexVectors, EUREKA_MAX_REGEX_VECTORS)) > 0) {
        ekStringConcatLen(E, output, &subject[regex->offset], regexVectors[0] - regex->offset);
        ekStringConcatStr(E, output, &replace->stringVal);
        regex->offset = regexVectors[1];
        ++count;

        if (!regex->global)
            break;
    }
    if (regex->offset < len) {
        ekStringConcatLen(E, output, &subject[regex->offset], len - regex->offset);
    }
    return count;
}