add oversampler
This commit is contained in:
834
oversampling/WDL/eel2/eelscript.h
Normal file
834
oversampling/WDL/eel2/eelscript.h
Normal file
@@ -0,0 +1,834 @@
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../wdltypes.h"
|
||||
#include "../ptrlist.h"
|
||||
#include "../wdlstring.h"
|
||||
#include "../assocarray.h"
|
||||
#include "../queue.h"
|
||||
#include "../mutex.h"
|
||||
#include "../win32_utf8.h"
|
||||
#include "ns-eel.h"
|
||||
|
||||
|
||||
#ifndef EELSCRIPT_MAX_FILE_HANDLES
|
||||
#define EELSCRIPT_MAX_FILE_HANDLES 512
|
||||
#endif
|
||||
#ifndef EELSCRIPT_FILE_HANDLE_INDEX_BASE
|
||||
#define EELSCRIPT_FILE_HANDLE_INDEX_BASE 1000000
|
||||
#endif
|
||||
#ifndef EEL_STRING_MAXUSERSTRING_LENGTH_HINT
|
||||
#define EEL_STRING_MAXUSERSTRING_LENGTH_HINT (1<<16) // 64KB per string max
|
||||
#endif
|
||||
#ifndef EEL_STRING_MAX_USER_STRINGS
|
||||
#define EEL_STRING_MAX_USER_STRINGS 32768
|
||||
#endif
|
||||
#ifndef EEL_STRING_LITERAL_BASE
|
||||
#define EEL_STRING_LITERAL_BASE 2000000
|
||||
#endif
|
||||
#ifndef EELSCRIPT_LICE_MAX_IMAGES
|
||||
#define EELSCRIPT_LICE_MAX_IMAGES 1024
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_LICE_MAX_FONTS
|
||||
#define EELSCRIPT_LICE_MAX_FONTS 128
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NET_MAXCON
|
||||
#define EELSCRIPT_NET_MAXCON 4096
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_LICE_CLASSNAME
|
||||
#define EELSCRIPT_LICE_CLASSNAME "eelscript_gfx"
|
||||
#endif
|
||||
|
||||
|
||||
// #define EELSCRIPT_NO_NET
|
||||
// #define EELSCRIPT_NO_LICE
|
||||
// #define EELSCRIPT_NO_FILE
|
||||
// #define EELSCRIPT_NO_FFT
|
||||
// #define EELSCRIPT_NO_MDCT
|
||||
// #define EELSCRIPT_NO_EVAL
|
||||
|
||||
class eel_string_context_state;
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
class eel_net_state;
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
class eel_lice_state;
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
#include "eel_pproc.h"
|
||||
#endif
|
||||
|
||||
class eelScriptInst {
|
||||
public:
|
||||
|
||||
static int init();
|
||||
|
||||
eelScriptInst();
|
||||
virtual ~eelScriptInst();
|
||||
|
||||
NSEEL_CODEHANDLE compile_code(const char *code, const char **err);
|
||||
int runcode(const char *code, int showerr, const char *showerrfn, bool canfree, bool ignoreEndOfInputChk, bool doExec);
|
||||
int loadfile(const char *fn, const char *callerfn, bool allowstdin);
|
||||
|
||||
NSEEL_VMCTX m_vm;
|
||||
|
||||
WDL_PtrList<void> m_code_freelist;
|
||||
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
FILE *m_handles[EELSCRIPT_MAX_FILE_HANDLES];
|
||||
virtual EEL_F OpenFile(const char *fn, const char *mode)
|
||||
{
|
||||
if (!*fn || !*mode) return 0.0;
|
||||
#ifndef EELSCRIPT_NO_STDIO
|
||||
if (!strcmp(fn,"stdin")) return 1;
|
||||
if (!strcmp(fn,"stdout")) return 2;
|
||||
if (!strcmp(fn,"stderr")) return 3;
|
||||
#endif
|
||||
|
||||
WDL_FastString fnstr(fn);
|
||||
if (!translateFilename(&fnstr,mode)) return 0.0;
|
||||
|
||||
int x;
|
||||
for (x=0;x<EELSCRIPT_MAX_FILE_HANDLES && m_handles[x];x++);
|
||||
if (x>= EELSCRIPT_MAX_FILE_HANDLES) return 0.0;
|
||||
|
||||
FILE *fp = fopenUTF8(fnstr.Get(),mode);
|
||||
if (!fp) return 0.0;
|
||||
m_handles[x]=fp;
|
||||
return x + EELSCRIPT_FILE_HANDLE_INDEX_BASE;
|
||||
}
|
||||
virtual EEL_F CloseFile(int fp_idx)
|
||||
{
|
||||
fp_idx-=EELSCRIPT_FILE_HANDLE_INDEX_BASE;
|
||||
if (fp_idx>=0 && fp_idx<EELSCRIPT_MAX_FILE_HANDLES && m_handles[fp_idx])
|
||||
{
|
||||
fclose(m_handles[fp_idx]);
|
||||
m_handles[fp_idx]=0;
|
||||
return 0.0;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
virtual FILE *GetFileFP(int fp_idx)
|
||||
{
|
||||
#ifndef EELSCRIPT_NO_STDIO
|
||||
if (fp_idx==1) return stdin;
|
||||
if (fp_idx==2) return stdout;
|
||||
if (fp_idx==3) return stderr;
|
||||
#endif
|
||||
fp_idx-=EELSCRIPT_FILE_HANDLE_INDEX_BASE;
|
||||
if (fp_idx>=0 && fp_idx<EELSCRIPT_MAX_FILE_HANDLES) return m_handles[fp_idx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
virtual bool translateFilename(WDL_FastString *fs, const char *mode) { return true; }
|
||||
|
||||
virtual bool GetFilenameForParameter(EEL_F idx, WDL_FastString *fs, int iswrite);
|
||||
|
||||
eel_string_context_state *m_string_context;
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
eel_net_state *m_net_state;
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
eel_lice_state *m_gfx_state;
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
struct evalCacheEnt {
|
||||
char *str;
|
||||
NSEEL_CODEHANDLE ch;
|
||||
};
|
||||
int m_eval_depth;
|
||||
WDL_TypedBuf<evalCacheEnt> m_eval_cache;
|
||||
virtual char *evalCacheGet(const char *str, NSEEL_CODEHANDLE *ch);
|
||||
virtual void evalCacheDispose(char *key, NSEEL_CODEHANDLE ch);
|
||||
WDL_Queue m_defer_eval, m_atexit_eval;
|
||||
void runCodeQ(WDL_Queue *q, const char *fname);
|
||||
void runAtExitCode()
|
||||
{
|
||||
runCodeQ(&m_atexit_eval,"atexit");
|
||||
m_atexit_eval.Clear(); // make sure nothing gets added in atexit(), in case the user called runAtExitCode before destroying
|
||||
}
|
||||
#endif
|
||||
virtual bool run_deferred(); // requires eval support to be useful
|
||||
virtual bool has_deferred();
|
||||
|
||||
|
||||
WDL_StringKeyedArray<bool> m_loaded_fnlist; // imported file list (to avoid repeats)
|
||||
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
EEL2_PreProcessor m_preproc;
|
||||
#endif
|
||||
};
|
||||
|
||||
//#define EEL_STRINGS_MUTABLE_LITERALS
|
||||
//#define EEL_STRING_WANT_MUTEX
|
||||
|
||||
|
||||
#define EEL_STRING_GET_CONTEXT_POINTER(opaque) (((eelScriptInst *)opaque)->m_string_context)
|
||||
#ifndef EEL_STRING_STDOUT_WRITE
|
||||
#ifndef EELSCRIPT_NO_STDIO
|
||||
#define EEL_STRING_STDOUT_WRITE(x,len) { fwrite(x,len,1,stdout); fflush(stdout); }
|
||||
#endif
|
||||
#endif
|
||||
#include "eel_strings.h"
|
||||
|
||||
#include "eel_misc.h"
|
||||
|
||||
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
#define EEL_FILE_OPEN(fn,mode) ((eelScriptInst*)opaque)->OpenFile(fn,mode)
|
||||
#define EEL_FILE_GETFP(fp) ((eelScriptInst*)opaque)->GetFileFP(fp)
|
||||
#define EEL_FILE_CLOSE(fpindex) ((eelScriptInst*)opaque)->CloseFile(fpindex)
|
||||
|
||||
#include "eel_files.h"
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_FFT
|
||||
#include "eel_fft.h"
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_MDCT
|
||||
#include "eel_mdct.h"
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
#define EEL_NET_GET_CONTEXT(opaque) (((eelScriptInst *)opaque)->m_net_state)
|
||||
#include "eel_net.h"
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
#ifndef EEL_LICE_WANT_STANDALONE
|
||||
#define EEL_LICE_WANT_STANDALONE
|
||||
#endif
|
||||
#ifndef EELSCRIPT_LICE_NOUPDATE
|
||||
#define EEL_LICE_WANT_STANDALONE_UPDATE // gfx_update() which runs message pump and updates screen etc
|
||||
#endif
|
||||
|
||||
#define EEL_LICE_GET_FILENAME_FOR_STRING(idx, fs, p) (((eelScriptInst*)opaque)->GetFilenameForParameter(idx,fs,p))
|
||||
#define EEL_LICE_GET_CONTEXT(opaque) ((opaque) ? (((eelScriptInst *)opaque)->m_gfx_state) : NULL)
|
||||
#include "eel_lice.h"
|
||||
#endif
|
||||
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
#define EEL_EVAL_GET_CACHED(str, ch) ((eelScriptInst *)opaque)->evalCacheGet(str,&(ch))
|
||||
#define EEL_EVAL_SET_CACHED(str, ch) ((eelScriptInst *)opaque)->evalCacheDispose(str,ch)
|
||||
#define EEL_EVAL_GET_VMCTX(opaque) (((eelScriptInst *)opaque)->m_vm)
|
||||
#define EEL_EVAL_SCOPE_ENTER (((eelScriptInst *)opaque)->m_eval_depth < 3 ? \
|
||||
++((eelScriptInst *)opaque)->m_eval_depth : 0)
|
||||
#define EEL_EVAL_SCOPE_LEAVE ((eelScriptInst *)opaque)->m_eval_depth--;
|
||||
#include "eel_eval.h"
|
||||
|
||||
static EEL_F NSEEL_CGEN_CALL _eel_defer(void *opaque, EEL_F *s)
|
||||
{
|
||||
EEL_STRING_MUTEXLOCK_SCOPE
|
||||
const char *str=EEL_STRING_GET_FOR_INDEX(*s,NULL);
|
||||
if (str && *str && *s >= EEL_STRING_MAX_USER_STRINGS) // don't allow defer(0) etc
|
||||
{
|
||||
eelScriptInst *inst = (eelScriptInst *)opaque;
|
||||
if (inst->m_defer_eval.Available() < EEL_STRING_MAXUSERSTRING_LENGTH_HINT)
|
||||
{
|
||||
inst->m_defer_eval.Add(str,strlen(str)+1);
|
||||
return 1.0;
|
||||
}
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
EEL_STRING_DEBUGOUT("defer(): too much defer() code already added, ignoring");
|
||||
#endif
|
||||
}
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
else if (!str)
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("defer(): invalid string identifier specified %f",*s);
|
||||
}
|
||||
else if (*s < EEL_STRING_MAX_USER_STRINGS)
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("defer(): user string identifier %f specified but not allowed",*s);
|
||||
}
|
||||
#endif
|
||||
return 0.0;
|
||||
}
|
||||
static EEL_F NSEEL_CGEN_CALL _eel_atexit(void *opaque, EEL_F *s)
|
||||
{
|
||||
EEL_STRING_MUTEXLOCK_SCOPE
|
||||
const char *str=EEL_STRING_GET_FOR_INDEX(*s,NULL);
|
||||
if (str && *str && *s >= EEL_STRING_MAX_USER_STRINGS) // don't allow atexit(0) etc
|
||||
{
|
||||
eelScriptInst *inst = (eelScriptInst *)opaque;
|
||||
if (inst->m_atexit_eval.Available() < EEL_STRING_MAXUSERSTRING_LENGTH_HINT)
|
||||
{
|
||||
inst->m_atexit_eval.Add(str,strlen(str)+1);
|
||||
return 1.0;
|
||||
}
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
EEL_STRING_DEBUGOUT("atexit(): too much atexit() code already added, ignoring");
|
||||
#endif
|
||||
}
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
else if (!str)
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("atexit(): invalid string identifier specified %f",*s);
|
||||
}
|
||||
else if (*s < EEL_STRING_MAX_USER_STRINGS)
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("atexit(): user string identifier %f specified but not allowed",*s);
|
||||
}
|
||||
#endif
|
||||
return 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define opaque ((void *)this)
|
||||
|
||||
eelScriptInst::eelScriptInst() : m_loaded_fnlist(false)
|
||||
{
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
memset(m_handles,0,sizeof(m_handles));
|
||||
#endif
|
||||
m_vm = NSEEL_VM_alloc();
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
if (!m_vm) EEL_STRING_DEBUGOUT("NSEEL_VM_alloc(): failed");
|
||||
#endif
|
||||
NSEEL_VM_SetCustomFuncThis(m_vm,this);
|
||||
#ifdef NSEEL_ADDFUNC_DESTINATION
|
||||
NSEEL_VM_SetFunctionTable(m_vm,NSEEL_ADDFUNC_DESTINATION);
|
||||
#endif
|
||||
|
||||
m_string_context = new eel_string_context_state;
|
||||
eel_string_initvm(m_vm);
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
m_net_state = new eel_net_state(EELSCRIPT_NET_MAXCON,NULL);
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
m_gfx_state = new eel_lice_state(m_vm,this,EELSCRIPT_LICE_MAX_IMAGES,EELSCRIPT_LICE_MAX_FONTS);
|
||||
|
||||
m_gfx_state->resetVarsToStock();
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
m_eval_depth=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
eelScriptInst::~eelScriptInst()
|
||||
{
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
if (m_atexit_eval.GetSize()>0) runAtExitCode();
|
||||
#endif
|
||||
int x;
|
||||
m_code_freelist.Empty((void (*)(void *))NSEEL_code_free);
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
for (x=0;x<m_eval_cache.GetSize();x++)
|
||||
{
|
||||
free(m_eval_cache.Get()[x].str);
|
||||
NSEEL_code_free(m_eval_cache.Get()[x].ch);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_vm) NSEEL_VM_free(m_vm);
|
||||
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
for (x=0;x<EELSCRIPT_MAX_FILE_HANDLES;x++)
|
||||
{
|
||||
if (m_handles[x]) fclose(m_handles[x]);
|
||||
m_handles[x]=0;
|
||||
}
|
||||
#endif
|
||||
delete m_string_context;
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
delete m_net_state;
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
delete m_gfx_state;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool eelScriptInst::GetFilenameForParameter(EEL_F idx, WDL_FastString *fs, int iswrite)
|
||||
{
|
||||
const char *fmt = EEL_STRING_GET_FOR_INDEX(idx,NULL);
|
||||
if (!fmt) return false;
|
||||
fs->Set(fmt);
|
||||
return translateFilename(fs,iswrite?"w":"r");
|
||||
}
|
||||
|
||||
NSEEL_CODEHANDLE eelScriptInst::compile_code(const char *code, const char **err)
|
||||
{
|
||||
if (!m_vm)
|
||||
{
|
||||
*err = "EEL VM not initialized";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
WDL_FastString str;
|
||||
if (strstr(code,EEL2_PREPROCESS_OPEN_TOKEN))
|
||||
{
|
||||
const char *pperr = m_preproc.preprocess(code,&str);
|
||||
if (pperr)
|
||||
{
|
||||
*err = pperr;
|
||||
return NULL;
|
||||
}
|
||||
code = str.Get();
|
||||
}
|
||||
else
|
||||
m_preproc.clear_line_info();
|
||||
#endif
|
||||
|
||||
NSEEL_CODEHANDLE ch = NSEEL_code_compile_ex(m_vm, code, 0, NSEEL_CODE_COMPILE_FLAG_COMMONFUNCS);
|
||||
if (ch)
|
||||
{
|
||||
m_string_context->update_named_vars(m_vm);
|
||||
m_code_freelist.Add((void*)ch);
|
||||
return ch;
|
||||
}
|
||||
*err = NSEEL_code_getcodeerror(m_vm);
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
if (*err) *err = m_preproc.translate_error_line(*err);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int eelScriptInst::runcode(const char *codeptr, int showerr, const char *showerrfn, bool canfree, bool ignoreEndOfInputChk, bool doExec)
|
||||
{
|
||||
if (m_vm)
|
||||
{
|
||||
const char *err = NULL;
|
||||
NSEEL_CODEHANDLE code = NULL;
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
WDL_FastString str;
|
||||
if (strstr(codeptr,EEL2_PREPROCESS_OPEN_TOKEN))
|
||||
{
|
||||
err = m_preproc.preprocess(codeptr,&str);
|
||||
if (err) goto on_preproc_error;
|
||||
codeptr = str.Get();
|
||||
}
|
||||
else
|
||||
m_preproc.clear_line_info();
|
||||
#endif
|
||||
|
||||
code = NSEEL_code_compile_ex(m_vm,codeptr,0,canfree ? 0 : NSEEL_CODE_COMPILE_FLAG_COMMONFUNCS);
|
||||
if (code) m_string_context->update_named_vars(m_vm);
|
||||
|
||||
if (!code && (err=NSEEL_code_getcodeerror(m_vm)))
|
||||
{
|
||||
if (!ignoreEndOfInputChk && (NSEEL_code_geterror_flag(m_vm)&1)) return 1;
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
err = m_preproc.translate_error_line(err);
|
||||
on_preproc_error:
|
||||
#endif
|
||||
if (showerr)
|
||||
{
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
if (showerr==2)
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("Warning: %s:%s",WDL_get_filepart(showerrfn),err);
|
||||
}
|
||||
else
|
||||
{
|
||||
EEL_STRING_DEBUGOUT("%s:%s",WDL_get_filepart(showerrfn),err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (code)
|
||||
{
|
||||
#ifdef EELSCRIPT_DO_DISASSEMBLE
|
||||
codeHandleType *p = (codeHandleType*)code;
|
||||
|
||||
char buf[512];
|
||||
buf[0]=0;
|
||||
#ifdef _WIN32
|
||||
GetTempPath(sizeof(buf)-64,buf);
|
||||
lstrcatn(buf,"jsfx-out",sizeof(buf));
|
||||
#else
|
||||
lstrcpyn_safe(buf,"/tmp/jsfx-out",sizeof(buf));
|
||||
#endif
|
||||
FILE *fp = fopenUTF8(buf,"wb");
|
||||
if (fp)
|
||||
{
|
||||
fwrite(p->code,1,p->code_size,fp);
|
||||
fclose(fp);
|
||||
char buf2[2048];
|
||||
#ifdef _WIN32
|
||||
snprintf(buf2,sizeof(buf2),"disasm \"%s\"",buf);
|
||||
#else
|
||||
#ifdef __aarch64__
|
||||
snprintf(buf2,sizeof(buf2), "objdump -D -b binary -maarch64 \"%s\"",buf);
|
||||
#elif defined(__arm__)
|
||||
snprintf(buf2,sizeof(buf2), "objdump -D -b binary -m arm \"%s\"",buf);
|
||||
#elif defined(__LP64__)
|
||||
#ifdef __APPLE__
|
||||
snprintf(buf2,sizeof(buf2),"distorm3 --b64 \"%s\"",buf);
|
||||
#else
|
||||
snprintf(buf2,sizeof(buf2),"objdump -D -b binary -m i386:x86-64 \"%s\"",buf);
|
||||
#endif
|
||||
#else
|
||||
snprintf(buf2,sizeof(buf2),"distorm3 --b32 \"%s\"",buf);
|
||||
#endif
|
||||
#endif
|
||||
system(buf2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (doExec) NSEEL_code_execute(code);
|
||||
if (canfree) NSEEL_code_free(code);
|
||||
else m_code_freelist.Add((void*)code);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
FILE *eelscript_resolvePath(WDL_FastString &usefn, const char *fn, const char *callerfn)
|
||||
{
|
||||
// resolve path relative to current
|
||||
int x;
|
||||
bool had_abs=false;
|
||||
for (x=0;x<2; x ++)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!x && ((fn[0] == '\\' && fn[1] == '\\') || (fn[0] && fn[1] == ':')))
|
||||
#else
|
||||
if (!x && fn[0] == '/')
|
||||
#endif
|
||||
{
|
||||
usefn.Set(fn);
|
||||
had_abs=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *fnu = fn;
|
||||
if (x)
|
||||
{
|
||||
while (*fnu) fnu++;
|
||||
while (fnu >= fn && *fnu != '\\' && *fnu != '/') fnu--;
|
||||
if (fnu < fn) break;
|
||||
fnu++;
|
||||
}
|
||||
|
||||
usefn.Set(callerfn);
|
||||
int l=usefn.GetLength();
|
||||
while (l > 0 && usefn.Get()[l-1] != '\\' && usefn.Get()[l-1] != '/') l--;
|
||||
if (l > 0)
|
||||
{
|
||||
usefn.SetLen(l);
|
||||
usefn.Append(fnu);
|
||||
}
|
||||
else
|
||||
{
|
||||
usefn.Set(fnu);
|
||||
}
|
||||
int last_slash_pos=-1;
|
||||
for (l = 0; l < usefn.GetLength(); l ++)
|
||||
{
|
||||
if (usefn.Get()[l] == '/' || usefn.Get()[l] == '\\')
|
||||
{
|
||||
if (usefn.Get()[l+1] == '.' && usefn.Get()[l+2] == '.' &&
|
||||
(usefn.Get()[l+3] == '/' || usefn.Get()[l+3] == '\\'))
|
||||
{
|
||||
if (last_slash_pos >= 0)
|
||||
usefn.DeleteSub(last_slash_pos, l+3-last_slash_pos);
|
||||
else
|
||||
usefn.DeleteSub(0,l+3+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_slash_pos=l;
|
||||
}
|
||||
}
|
||||
// take currentfn, remove filename part, add fnu
|
||||
}
|
||||
}
|
||||
|
||||
FILE *fp = fopenUTF8(usefn.Get(),"r");
|
||||
if (fp) return fp;
|
||||
}
|
||||
if (had_abs) usefn.Set(fn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int eelScriptInst::loadfile(const char *fn, const char *callerfn, bool allowstdin)
|
||||
{
|
||||
WDL_FastString usefn;
|
||||
FILE *fp = NULL;
|
||||
if (!strcmp(fn,"-"))
|
||||
{
|
||||
if (callerfn)
|
||||
{
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
EEL_STRING_DEBUGOUT("@import: can't import \"-\" (stdin)");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if (allowstdin)
|
||||
{
|
||||
fp = stdin;
|
||||
fn = "(stdin)";
|
||||
}
|
||||
}
|
||||
else if (!callerfn)
|
||||
{
|
||||
fp = fopenUTF8(fn,"r");
|
||||
if (fp) m_loaded_fnlist.Insert(fn,true);
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = eelscript_resolvePath(usefn,fn,callerfn);
|
||||
if (fp)
|
||||
{
|
||||
if (m_loaded_fnlist.Get(usefn.Get()))
|
||||
{
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
m_loaded_fnlist.Insert(usefn.Get(),true);
|
||||
fn = usefn.Get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
if (callerfn)
|
||||
EEL_STRING_DEBUGOUT("Warning: @import could not open '%s'",fn);
|
||||
else
|
||||
EEL_STRING_DEBUGOUT("Error opening %s",fn);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
WDL_FastString incpath(fn);
|
||||
incpath.remove_filepart();
|
||||
m_preproc.m_include_paths.Add(incpath.Get());
|
||||
#endif
|
||||
|
||||
WDL_FastString code;
|
||||
char line[4096];
|
||||
for (;;)
|
||||
{
|
||||
line[0]=0;
|
||||
fgets(line,sizeof(line),fp);
|
||||
if (!line[0]) break;
|
||||
if (!strnicmp(line,"@import",7) && isspace((unsigned char)line[7]))
|
||||
{
|
||||
char *p=line+7;
|
||||
while (isspace((unsigned char)*p)) p++;
|
||||
|
||||
char *ep=p;
|
||||
while (*ep) ep++;
|
||||
while (ep>p && isspace((unsigned char)ep[-1])) ep--;
|
||||
*ep=0;
|
||||
|
||||
if (*p) loadfile(p,fn,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
code.Append(line);
|
||||
}
|
||||
}
|
||||
if (fp != stdin) fclose(fp);
|
||||
|
||||
int rv = runcode(code.Get(),callerfn ? 2 : 1, fn,false,true,!callerfn);
|
||||
|
||||
#ifndef EELSCRIPT_NO_PREPROC
|
||||
m_preproc.m_include_paths.Delete(m_preproc.m_include_paths.GetSize()-1);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *eelScriptInst::evalCacheGet(const char *str, NSEEL_CODEHANDLE *ch)
|
||||
{
|
||||
// should mutex protect if multiple threads access this eelScriptInst context
|
||||
int x=m_eval_cache.GetSize();
|
||||
while (--x >= 0)
|
||||
{
|
||||
char *ret;
|
||||
if (!strcmp(ret=m_eval_cache.Get()[x].str, str))
|
||||
{
|
||||
*ch = m_eval_cache.Get()[x].ch;
|
||||
m_eval_cache.Delete(x);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void eelScriptInst::evalCacheDispose(char *key, NSEEL_CODEHANDLE ch)
|
||||
{
|
||||
// should mutex protect if multiple threads access this eelScriptInst context
|
||||
evalCacheEnt ecc;
|
||||
ecc.str= key;
|
||||
ecc.ch = ch;
|
||||
if (m_eval_cache.GetSize() > 1024)
|
||||
{
|
||||
NSEEL_code_free(m_eval_cache.Get()->ch);
|
||||
free(m_eval_cache.Get()->str);
|
||||
m_eval_cache.Delete(0);
|
||||
}
|
||||
m_eval_cache.Add(ecc);
|
||||
}
|
||||
|
||||
int eelScriptInst::init()
|
||||
{
|
||||
EEL_string_register();
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
EEL_file_register();
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_FFT
|
||||
EEL_fft_register();
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_MDCT
|
||||
EEL_mdct_register();
|
||||
#endif
|
||||
EEL_misc_register();
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
EEL_eval_register();
|
||||
NSEEL_addfunc_retval("defer",1,NSEEL_PProc_THIS,&_eel_defer);
|
||||
NSEEL_addfunc_retval("runloop", 1, NSEEL_PProc_THIS, &_eel_defer);
|
||||
NSEEL_addfunc_retval("atexit",1,NSEEL_PProc_THIS,&_eel_atexit);
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
EEL_tcp_register();
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
eel_lice_register();
|
||||
#ifdef _WIN32
|
||||
eel_lice_register_standalone(GetModuleHandle(NULL),EELSCRIPT_LICE_CLASSNAME,NULL,NULL);
|
||||
#else
|
||||
eel_lice_register_standalone(NULL,EELSCRIPT_LICE_CLASSNAME,NULL,NULL);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool eelScriptInst::has_deferred()
|
||||
{
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
return m_defer_eval.Available() && m_vm;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
void eelScriptInst::runCodeQ(WDL_Queue *q, const char *callername)
|
||||
{
|
||||
const int endptr = q->Available();
|
||||
int offs = 0;
|
||||
while (offs < endptr)
|
||||
{
|
||||
if (q->Available() < endptr) break; // should never happen, but safety first!
|
||||
|
||||
const char *ptr = (const char *)q->Get() + offs;
|
||||
offs += strlen(ptr)+1;
|
||||
|
||||
NSEEL_CODEHANDLE ch=NULL;
|
||||
char *sv=evalCacheGet(ptr,&ch);
|
||||
|
||||
if (!sv) sv=strdup(ptr);
|
||||
if (!ch) ch=NSEEL_code_compile(m_vm,sv,0);
|
||||
if (!ch)
|
||||
{
|
||||
free(sv);
|
||||
#ifdef EEL_STRING_DEBUGOUT
|
||||
const char *err = NSEEL_code_getcodeerror(m_vm);
|
||||
if (err) EEL_STRING_DEBUGOUT("%s: error in code: %s",callername,err);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
NSEEL_code_execute(ch);
|
||||
evalCacheDispose(sv,ch);
|
||||
}
|
||||
}
|
||||
q->Advance(endptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool eelScriptInst::run_deferred()
|
||||
{
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
if (!m_defer_eval.Available()||!m_vm) return false;
|
||||
|
||||
runCodeQ(&m_defer_eval,"defer");
|
||||
m_defer_eval.Compact();
|
||||
return m_defer_eval.Available()>0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EEL_WANT_DOCUMENTATION
|
||||
#include "ns-eel-func-ref.h"
|
||||
|
||||
void EELScript_GenerateFunctionList(WDL_PtrList<const char> *fs)
|
||||
{
|
||||
const char *p = nseel_builtin_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
p = eel_strings_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
p = eel_misc_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#ifndef EELSCRIPT_NO_EVAL
|
||||
fs->Add("atexit\t\"code\"\t"
|
||||
#ifndef EELSCRIPT_HELP_NO_DEFER_DESC
|
||||
"Adds code to be executed when the script finishes."
|
||||
#endif
|
||||
);
|
||||
fs->Add("defer\t\"code\"\t"
|
||||
#ifndef EELSCRIPT_HELP_NO_DEFER_DESC
|
||||
"Adds code which will be executed some small amount of time after the current code finishes. Identical to runloop()"
|
||||
#endif
|
||||
);
|
||||
fs->Add("runloop\t\"code\"\t"
|
||||
#ifndef EELSCRIPT_HELP_NO_DEFER_DESC
|
||||
"Adds code which will be executed some small amount of time after the current code finishes. Identical to defer()"
|
||||
#endif
|
||||
);
|
||||
|
||||
p = eel_eval_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_NET
|
||||
p = eel_net_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_FFT
|
||||
p = eel_fft_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_FILE
|
||||
p = eel_file_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_MDCT
|
||||
p = eel_mdct_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
#ifndef EELSCRIPT_NO_LICE
|
||||
p = eel_lice_function_reference;
|
||||
while (*p) { fs->Add(p); p += strlen(p) + 1; }
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#undef opaque
|
||||
Reference in New Issue
Block a user