Paul Batchelorimported lil3a2b0615 years agoHistory
3526 lines · 102.1 KB · C
RawDownload
/* * LIL - Little Interpreted Language * Copyright (C) 2010-2013 Kostas Michalopoulos * * This software is provided 'as-is', without any express or implied * warranty.  In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not *    claim that you wrote the original software. If you use this software *    in a product, an acknowledgment in the product documentation would be *    appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be *    misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * Kostas Michalopoulos <badsector@runtimelegend.com> */ #define __LIL_C_FILE__#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <math.h>#include "lil.h" /* Enable pools for reusing values, lists and environments. This will use more memory and * will rely on the runtime/OS to free the pools once the program ends, but will cause * considerably less memory fragmentation and improve the script execution performance. *//*#define LIL_ENABLE_POOLS*/ /* Enable limiting recursive calls to lil_parse - this can be used to avoid call stack * overflows and is also useful when running through an automated fuzzer like AFL *//*#define LIL_ENABLE_RECLIMIT 10000*/ /* Visual C++ does not have atoll (Pelles C does and thinks it is fully MSVC compatible) */#if defined(_MSC_VER) && !defined(__POCC__)#define atoll _atoi64/* disable warning about unsafe standard C calls */#pragma warning(disable:4996)/* disable float/int conversion warnings */#pragma warning(disable:4244)#endif #define ERROR_NOERROR 0#define ERROR_DEFAULT 1#define ERROR_FIXHEAD 2 #define CALLBACKS 8#define MAX_CATCHER_DEPTH 16384#define HASHMAP_CELLS 256#define HASHMAP_CELLMASK 0xFF /* note: static lil_xxx functions might become public later */ struct hashentry_t{    char* k;    void* v;}; struct hashcell_t{    struct hashentry_t* e;    size_t c;}; typedef struct _hashmap_t{    struct hashcell_t cell[HASHMAP_CELLS];} hashmap_t; struct _lil_value_t{    size_t l;#ifdef LIL_ENABLE_POOLS    size_t c;#endif    char* d;}; struct _lil_var_t{    char* n;    char* w;    struct _lil_env_t* env;    lil_value_t v;}; struct _lil_env_t{    struct _lil_env_t* parent;    lil_func_t func;    lil_value_t catcher_for;    lil_var_t* var;    size_t vars;    hashmap_t varmap;    lil_value_t retval;    int retval_set;    int breakrun;}; struct _lil_list_t{    lil_value_t* v;    size_t c;    size_t cap;}; struct _lil_func_t{    char* name;    lil_value_t code;    lil_list_t argnames;    lil_func_proc_t proc;}; struct _lil_t{    const char* code; /* need save on parse */    const char* rootcode;    size_t clen; /* need save on parse */    size_t head; /* need save on parse */    int ignoreeol;    lil_func_t* cmd;    size_t cmds;    size_t syscmds;    hashmap_t cmdmap;    char* catcher;    int in_catcher;    char* dollarprefix;    lil_env_t env;    lil_env_t rootenv;    lil_env_t downenv;    lil_value_t empty;    int error;    size_t err_head;    char* err_msg;    lil_callback_proc_t callback[CALLBACKS];    size_t parse_depth;    void* data;    char* embed;    size_t embedlen;}; typedef struct _expreval_t{    const char* code;    size_t len, head;    lilint_t ival;    double dval;    int type;    int error;} expreval_t; static lil_value_t next_word(lil_t lil);static void register_stdcmds(lil_t lil); #ifdef LIL_ENABLE_POOLSstatic lil_value_t* pool;static int poolsize, poolcap;static lil_list_t* listpool;static size_t listpoolsize, listpoolcap;static lil_env_t* envpool;static size_t envpoolsize, envpoolcap;#endif static char* strclone(const char* s){    size_t len = strlen(s) + 1;    char* ns = malloc(len);    if (!ns) return NULL;    memcpy(ns, s, len);    return ns;} static unsigned long hm_hash(const char* key){    unsigned long hash = 5381;    int c;    while ((c = *key++)) hash = ((hash << 5) + hash) + c;    return hash;} static void hm_init(hashmap_t* hm){    memset(hm, 0, sizeof(hashmap_t));} static void hm_destroy(hashmap_t* hm){    size_t i, j;    for (i=0; i<HASHMAP_CELLS; i++) {        for (j=0; j<hm->cell[i].c; j++)            free(hm->cell[i].e[j].k);        free(hm->cell[i].e);    }} static void hm_put(hashmap_t* hm, const char* key, void* value){    struct hashcell_t* cell = hm->cell + (hm_hash(key) & HASHMAP_CELLMASK);    size_t i;    for (i=0; i<cell->c; i++)        if (!strcmp(key, cell->e[i].k)) {            cell->e[i].v = value;            return;        }    cell->e = realloc(cell->e, sizeof(struct hashentry_t)*(cell->c + 1));    cell->e[cell->c].k = strclone(key);    cell->e[cell->c].v = value;    cell->c++;} static void* hm_get(hashmap_t* hm, const char* key){    struct hashcell_t* cell = hm->cell + (hm_hash(key) & HASHMAP_CELLMASK);    size_t i;    for (i = 0; i<cell->c; i++)        if (!strcmp(key, cell->e[i].k))            return cell->e[i].v;    return NULL;} static int hm_has(hashmap_t* hm, const char* key){    struct hashcell_t* cell = hm->cell + (hm_hash(key) & HASHMAP_CELLMASK);    size_t i;    for (i = 0; i < cell->c; i++)        if (!strcmp(key, cell->e[i].k))            return 1;    return 0;} #ifdef LIL_ENABLE_POOLSstatic lil_value_t alloc_from_pool(void){    if (poolsize > 0) {        poolsize--;        return pool[poolsize];    } else {        lil_value_t val = calloc(1, sizeof(struct _lil_value_t));        return val;    }} static void release_to_pool(lil_value_t val){    if (poolsize == poolcap) {        poolcap = poolcap ? (poolcap + poolcap / 2) : 64;        pool = realloc(pool, sizeof(lil_value_t)*poolcap);    }    pool[poolsize++] = val;} static void ensure_capacity(lil_value_t val, size_t cap){    if (val->c < cap) {        val->c = cap + 128;        val->d = realloc(val->d, val->c);    }}#endif static lil_value_t alloc_value_len(const char* str, size_t len){#ifdef LIL_ENABLE_POOLS    lil_value_t val = alloc_from_pool();#else    lil_value_t val = calloc(1, sizeof(struct _lil_value_t));#endif    if (!val) return NULL;    if (str) {        val->l = len;#ifdef LIL_ENABLE_POOLS        ensure_capacity(val, len + 1);#else        val->d = malloc(len + 1);        if (!val->d) {            free(val);            return NULL;        }#endif        memcpy(val->d, str, len);        val->d[len] = 0;    } else {        val->l = 0;#ifdef LIL_ENABLE_POOLS        ensure_capacity(val, 1);        val->d[0] = '\0';#else        val->d = NULL;#endif    }    return val;} static lil_value_t alloc_value(const char* str){    return alloc_value_len(str, str ? strlen(str) : 0);} lil_value_t lil_clone_value(lil_value_t src){    lil_value_t val;    if (!src) return NULL;#ifdef LIL_ENABLE_POOLS    val = alloc_from_pool();#else    val = calloc(1, sizeof(struct _lil_value_t));#endif    if (!val) return NULL;    val->l = src->l;    if (src->l) {#ifdef LIL_ENABLE_POOLS        ensure_capacity(val, val->l + 1);#else        val->d = malloc(val->l + 1);        if (!val->d) {            free(val);            return NULL;        }#endif        memcpy(val->d, src->d, val->l + 1);    } else {#ifdef LIL_ENABLE_POOLS        ensure_capacity(val, 1);        val->d[0] = '\0';#else        val->d = NULL;#endif    }    return val;} int lil_append_char(lil_value_t val, char ch){#ifdef LIL_ENABLE_POOLS    ensure_capacity(val, val->l + 2);    val->d[val->l++] = ch;    val->d[val->l] = '\0';#else    char* new = realloc(val->d, val->l + 2);    if (!new) return 0;    new[val->l++] = ch;    new[val->l] = 0;    val->d = new;#endif    return 1;} int lil_append_string_len(lil_value_t val, const char* s, size_t len){#ifndef LIL_ENABLE_POOLS    char* new;#endif    if (!s || !s[0]) return 1;#ifdef LIL_ENABLE_POOLS    ensure_capacity(val, val->l + len + 1);    memcpy(val->d + val->l, s, len + 1);#else    new = realloc(val->d, val->l + len + 1);    if (!new) return 0;    memcpy(new + val->l, s, len + 1);    val->d = new;#endif    val->l += len;    return 1;} int lil_append_string(lil_value_t val, const char* s){    return lil_append_string_len(val, s, strlen(s));} int lil_append_val(lil_value_t val, lil_value_t v){#ifndef LIL_ENABLE_POOLS    char* new;#endif    if (!v || !v->l) return 1;#ifdef LIL_ENABLE_POOLS    ensure_capacity(val, val->l + v->l + 1);    memcpy(val->d + val->l, v->d, v->l + 1);#else    new = realloc(val->d, val->l + v->l + 1);    if (!new) return 0;    memcpy(new + val->l, v->d, v->l + 1);    val->d = new;#endif    val->l += v->l;    return 1;} void lil_free_value(lil_value_t val){    if (!val) return;#ifdef LIL_ENABLE_POOLS    release_to_pool(val);#else    free(val->d);    free(val);#endif} lil_list_t lil_alloc_list(void){    lil_list_t list;#ifdef LIL_ENABLE_POOLS    if (listpoolsize > 0)        return listpool[--listpoolsize];#endif    list = calloc(1, sizeof(struct _lil_list_t));    list->v = NULL;    return list;} void lil_free_list(lil_list_t list){    size_t i;    if (!list) return;    for (i = 0; i<list->c; i++) lil_free_value(list->v[i]);#ifdef LIL_ENABLE_POOLS    list->c = 0;    if (listpoolsize == listpoolcap) {        listpoolcap = listpoolcap ? (listpoolcap + listpoolcap / 2) : 32;        listpool = realloc(listpool, sizeof(lil_list_t)*listpoolcap);    }    listpool[listpoolsize++] = list;#else    free(list->v);    free(list);#endif} void lil_list_append(lil_list_t list, lil_value_t val){    if (list->c == list->cap) {        size_t cap = list->cap ? (list->cap + list->cap / 2) : 32;        lil_value_t* nv = realloc(list->v, sizeof(lil_value_t)*cap);        if (!nv) return;        list->cap = cap;        list->v = nv;    }    list->v[list->c++] = val;} size_t lil_list_size(lil_list_t list){    return list->c;} lil_value_t lil_list_get(lil_list_t list, size_t index){    return index >= list->c ? NULL : list->v[index];} static int needs_escape(const char* str){    size_t i;    if (!str || !str[0]) return 1;    for (i=0; str[i]; i++)        if (ispunct(str[i]) || isspace(str[i])) return 1;    return 0;} lil_value_t lil_list_to_value(lil_list_t list, int do_escape){    lil_value_t val = alloc_value(NULL);    size_t i, j;    for (i=0; i<list->c; i++) {        int escape = do_escape ? needs_escape(lil_to_string(list->v[i])) : 0;        if (i) lil_append_char(val, ' ');        if (escape) {            lil_append_char(val, '{');            for (j=0; j < list->v[i]->l; j++) {                if (list->v[i]->d[j] == '{')                    lil_append_string(val, "}\"\\o\"{");                else if (list->v[i]->d[j] == '}')                    lil_append_string(val, "}\"\\c\"{");                else lil_append_char(val, list->v[i]->d[j]);            }            lil_append_char(val, '}');        } else lil_append_val(val, list->v[i]);    }    return val;} lil_env_t lil_alloc_env(lil_env_t parent){    lil_env_t env;#ifdef LIL_ENABLE_POOLS    if (envpoolsize > 0) {        size_t i, j;        env = envpool[--envpoolsize];

Lines 1–500 of 3526.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t