diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | STYLE | 13 | ||||
-rw-r--r-- | TODO | 13 | ||||
-rw-r--r-- | jim-aio.c | 6 | ||||
-rw-r--r-- | jim-posix.c | 6 | ||||
-rw-r--r-- | jim-sdl.c | 7 | ||||
-rw-r--r-- | jim-win32.c | 6 | ||||
-rw-r--r-- | jim-win32com.c | 6 | ||||
-rw-r--r-- | jim.c | 140 | ||||
-rw-r--r-- | jim.h | 21 |
10 files changed, 201 insertions, 21 deletions
@@ -1,3 +1,7 @@ +2005-03-29 18:50 antirez + + * ChangeLog, jim.c, test.tcl: [info args] added + 2005-03-29 16:17 antirez * ChangeLog, jim.c: Fixed [range] for the case of unique element @@ -28,7 +28,7 @@ Another example is: JimNotExportedFunction() Not exported functions that are not general, like functions -implementing hashtables or jim objects methods can be named +implementing hashtables or Jim objects methods can be named in any prefix as long as capitalization rules are followed, like in: @@ -47,10 +47,19 @@ lowcase: thisIsALogVarName +---- +GOTO +---- + +Goto is allowed every time it makes the code cleaner, like in complex +functions that need to handle exceptions, there is often an "err" label +at the end of the function where allocated resources are freed before to exit +with an error. Goto is also used in order to excape multiple nexted loops. + ---------- C FEATURES ---------- Only C89 ANSI C is allowed. C99 features can't be used currently. - +GCC extensions are not allowed. @@ -23,6 +23,13 @@ OTHER COMMANDS NOT IN TCL BUT THAT SHOULD BE IN JIM - Set commands: [lunion], [lintersect], and [ldifference] +EXTENSIONS LOADING + +- Avoid that the same extension can be loaded multiple times inside the + same interpreter. The extension should return its name on initialization + together with the version so that Jim_InitExtension will fail if the + extension with the same name is already loaded. + EXTENSIONS - Regexp extension @@ -43,6 +50,12 @@ IMPLEMENTATION ISSUES - Objects lazy free. - Rewrite all the commands accepting a set of options to use Jim_GetEnum(). +- Every time an extension is loaded Jim should put the dlopen() (or win32 + equivalent) handle in a list inside the interpreter structure. When + the interpreter is freed all this handles should be closed with dlclose(). +- *AssocData() function should allow to specify a delProc C function like + in the Tcl API. When the interpreter is destroied all the delProc functions + should be called to free the memory before to free the interpreter. ERROR MESSAGES @@ -1,7 +1,7 @@ /* Jim - ANSI I/O extension * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> * - * $Id: jim-aio.c,v 1.6 2005/03/16 16:28:34 antirez Exp $ + * $Id: jim-aio.c,v 1.7 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -265,7 +265,9 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, int Jim_OnLoad(Jim_Interp *interp) { - Jim_InitExtension(interp, "1.0"); + Jim_InitExtension(interp); + if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; Jim_CreateCommand(interp, "aio.open", JimAioOpenCommand, NULL, NULL); return JIM_OK; } diff --git a/jim-posix.c b/jim-posix.c index feba435..0af0729 100644 --- a/jim-posix.c +++ b/jim-posix.c @@ -1,7 +1,7 @@ /* Jim - POSIX extension * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> * - * $Id: jim-posix.c,v 1.11 2005/03/05 12:22:35 antirez Exp $ + * $Id: jim-posix.c,v 1.12 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -123,7 +123,9 @@ static int Jim_PosixSethostnameCommand(Jim_Interp *interp, int argc, int Jim_OnLoad(Jim_Interp *interp) { - Jim_InitExtension(interp, "1.0"); + Jim_InitExtension(interp); + if (Jim_PackageProvide(interp, "posix", "1.0", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); Jim_CreateCommand(interp, "os.sleep", Jim_PosixSleepCommand, NULL, NULL); Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL); @@ -1,7 +1,7 @@ /* Jim - SDL extension * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> * - * $Id: jim-sdl.c,v 1.2 2005/03/26 14:12:32 antirez Exp $ + * $Id: jim-sdl.c,v 1.3 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -224,8 +224,9 @@ static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, int Jim_OnLoad(Jim_Interp *interp) { - Jim_InitExtension(interp, "1.0"); - + Jim_InitExtension(interp); + if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; if (SDL_Init(SDL_INIT_VIDEO) < 0) { JimSdlSetError(interp); return JIM_ERR; diff --git a/jim-win32.c b/jim-win32.c index d44b6a6..0331af7 100644 --- a/jim-win32.c +++ b/jim-win32.c @@ -2,7 +2,7 @@ * * Copyright (C) 2005 Pat Thoyts <patthoyts@users.sourceforge.net> * - * $Id: jim-win32.c,v 1.18 2005/03/14 16:36:11 patthoyts Exp $ + * $Id: jim-win32.c,v 1.19 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -688,7 +688,9 @@ Win32_FreeLibrary(Jim_Interp *interp, int objc, Jim_Obj *const *objv) int Jim_OnLoad(Jim_Interp *interp) { - Jim_InitExtension(interp, "1.0"); + Jim_InitExtension(interp); + if (Jim_PackageProvide(interp, "win32", "1.0", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; #define CMD(name) \ Jim_CreateCommand(interp, "win32." #name , Win32_ ## name , NULL, NULL) diff --git a/jim-win32com.c b/jim-win32com.c index db5dade..c1ff2ca 100644 --- a/jim-win32com.c +++ b/jim-win32com.c @@ -2,7 +2,7 @@ * * Windows COM extension. * - * $Id: jim-win32com.c,v 1.16 2005/03/05 12:22:35 antirez Exp $ + * $Id: jim-win32com.c,v 1.17 2005/03/31 12:20:21 antirez Exp $ * * Example: * load jim-win32com @@ -595,7 +595,9 @@ __declspec(dllexport) int Jim_OnLoad(Jim_Interp *interp) { HRESULT hr; - Jim_InitExtension(interp, "1.0"); + Jim_InitExtension(interp); + if (Jim_PackageProvide(interp, "win32com", "1.0", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; hr = CoInitialize(0); if (FAILED(hr)) { Jim_SetResult(interp, @@ -2,7 +2,7 @@ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> * - * $Id: jim.c,v 1.137 2005/03/29 16:50:22 antirez Exp $ + * $Id: jim.c,v 1.138 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -860,6 +860,17 @@ static const void *JimStringCopyHTKeyDup(void *privdata, const void *key) 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) { @@ -875,6 +886,13 @@ static void JimStringCopyHTKeyDestructor(void *privdata, const void *key) 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 */ @@ -895,6 +913,17 @@ static Jim_HashTableType JimSharedStringsHashTableType = { 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; @@ -2075,7 +2104,8 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, resObjPtr = Jim_NewStringObj(interp, "", 0); while (fmtLen) { const char *p = fmt; - char spec[2]; + char spec[2], c; + jim_wide wideValue; while (*fmt != '%' && fmtLen) { fmt++; fmtLen--; @@ -2099,6 +2129,14 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, Jim_AppendObj(interp, resObjPtr, objv[0]); objv++; break; + case 'c': + if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) { + Jim_FreeNewObj(interp, resObjPtr); + return NULL; + } + c = (char) wideValue; + Jim_AppendString(interp, resObjPtr, &c, 1); + break; case '%': Jim_AppendString(interp, resObjPtr, "%" , 1); break; @@ -3953,6 +3991,7 @@ Jim_Interp *Jim_CreateInterp(void) NULL); Jim_InitHashTable(&i->stub, &JimStringCopyHashTableType, NULL); Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); + Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL); i->framePtr = i->topFramePtr = JimCreateCallFrame(i); i->emptyObj = Jim_NewEmptyStringObj(i); i->result = i->emptyObj; @@ -3996,6 +4035,7 @@ void Jim_FreeInterp(Jim_Interp *i) Jim_FreeHashTable(&i->references); Jim_FreeHashTable(&i->stub); Jim_FreeHashTable(&i->assocData); + Jim_FreeHashTable(&i->packages); Jim_Free(i->prngState); /* Free the call frames list */ while(cf) { @@ -7277,6 +7317,7 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) dlclose(handle); goto err; } + Jim_SetEmptyResult(interp); if (libPathObjPtr != NULL) Jim_DecrRefCount(interp, libPathObjPtr); return JIM_OK; @@ -7298,6 +7339,97 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) #endif/* JIM_DYNLIB */ /* ----------------------------------------------------------------------------- + * Packages handling + * ---------------------------------------------------------------------------*/ +/* Convert a string of the type "1.2" into an integer. + * MAJOR.MINOR is converted as MAJOR*100+MINOR, so "1.2" is converted + * to the integer with value 102 */ +static int JimPackageVersionToInt(Jim_Interp *interp, const char *v, + int *intPtr, int flags) +{ + char *buf = Jim_Alloc(strlen(v)+1), *p; + jim_wide wideValue; + + p = buf; + while (*v) { + if (!isdigit(*v)) continue; + *p++ = *v++; + } + *p = '\0'; + if (Jim_StringToWide(buf, &wideValue, 10) != JIM_OK) { + Jim_Free(buf); + if (flags & JIM_ERRMSG) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "invalid package version '", v, "'", NULL); + } + return JIM_ERR; + } + *intPtr = wideValue; + return JIM_OK; +} + +#define JIM_MATCHVER_EXACT (1<<JIM_PRIV_FLAG_SHIFT) +static int JimPackageMatchVersion(int needed, int actual, int flags) +{ + if (flags & JIM_MATCHVER_EXACT) { + return needed == actual; + } else { + return needed/100 == actual/100 && (needed <= actual); + } +} + +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, + int flags) +{ + /* If the package was already provided returns an error. */ + if (Jim_FindHashEntry(&interp->packages, name) != NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "package '", name, "' was already provided", NULL); + } + return JIM_ERR; + } + Jim_AddHashEntry(&interp->packages, name, (char*) ver); + return JIM_OK; +} + +const char *Jim_PackageRequire(Jim_Interp *interp, char *name, char *ver, int flags) +{ + Jim_HashEntry *he; + + he = Jim_FindHashEntry(&interp->packages, name); + if (he == NULL) { + /* TODO: try to load the given extension. */ + if (flags & JIM_ERRMSG) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "Can't find package '", name, "'", NULL); + } + return NULL; + } else { + int requiredVer, actualVer; + if (JimPackageVersionToInt(interp, ver, &requiredVer, JIM_ERRMSG) + != JIM_OK || + JimPackageVersionToInt(interp, he->key, &actualVer, JIM_ERRMSG) + != JIM_OK) + { + return NULL; + } + /* Check if version matches. */ + if (JimPackageMatchVersion(requiredVer, actualVer, flags) == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "Package '", name, "' already loaded, but with version ", + he->key, NULL); + return NULL; + } + return he->key; + } +} + +/* ----------------------------------------------------------------------------- * Eval * ---------------------------------------------------------------------------*/ #define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */ @@ -8182,6 +8314,8 @@ void JimRegisterCoreApi(Jim_Interp *interp) JIM_REGISTER_API(DeleteAssocData); JIM_REGISTER_API(GetEnum); JIM_REGISTER_API(ScriptIsComplete); + JIM_REGISTER_API(PackageRequire); + JIM_REGISTER_API(PackageProvide); } /* ----------------------------------------------------------------------------- @@ -11040,7 +11174,7 @@ int Jim_InteractivePrompt(Jim_Interp *interp) printf("Welcome to Jim version %d.%d, " "Copyright (c) 2005 Salvatore Sanfilippo\n", JIM_VERSION / 100, JIM_VERSION % 100); - printf("CVS ID: $Id: jim.c,v 1.137 2005/03/29 16:50:22 antirez Exp $\n"); + printf("CVS ID: $Id: jim.c,v 1.138 2005/03/31 12:20:21 antirez Exp $\n"); Jim_SetVariableStrWithStr(interp, "jim_interactive", "1"); while (1) { char buf[1024]; @@ -2,7 +2,7 @@ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> * - * $Id: jim.h,v 1.64 2005/03/29 13:38:04 antirez Exp $ + * $Id: jim.h,v 1.65 2005/03/31 12:20:21 antirez Exp $ * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -358,6 +358,11 @@ typedef struct Jim_ObjType { #define JIM_TYPE_NONE 0 /* No flags */ #define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */ +/* Starting from 1 << 20 flags are reserved for private uses of + * different calls. This way the same 'flags' argument may be used + * to pass both global flags and private flags. */ +#define JIM_PRIV_FLAG_SHIFT 20 + /* ----------------------------------------------------------------------------- * Call frame, vars, commands structures * ---------------------------------------------------------------------------*/ @@ -459,6 +464,7 @@ typedef struct Jim_Interp { struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ struct Jim_HashTable assocData; /* per-interp storage for use by packages */ Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ + struct Jim_HashTable packages; /* Provided packages hash table */ } Jim_Interp; /* Currently provided as macro that performs the increment. @@ -738,6 +744,11 @@ JIM_STATIC int JIM_API(Jim_GetApi) (Jim_Interp *interp, const char *funcname, JIM_STATIC int JIM_API(Jim_RegisterApi) (Jim_Interp *interp, const char *funcname, void *funcptr); +/* Packages C API */ +JIM_STATIC int JIM_API(Jim_PackageProvide) (Jim_Interp *interp, + const char *name, const char *ver, int flags); +JIM_STATIC const char * JIM_API(Jim_PackageRequire) (Jim_Interp *interp, char *name, char *ver, int flags); + /* error messages */ JIM_STATIC void JIM_API(Jim_PrintErrorMessage) (Jim_Interp *interp); @@ -753,7 +764,7 @@ JIM_STATIC void JIM_API(Jim_Panic) (const char *fmt, ...); Jim_GetApi(interp, "Jim_" #name, &Jim_ ## name) /* This must be included "inline" inside the extension */ -static void Jim_InitExtension(Jim_Interp *interp, const char *version) +static void Jim_InitExtension(Jim_Interp *interp) { Jim_GetApi = interp->getApiFuncPtr; @@ -855,15 +866,15 @@ static void Jim_InitExtension(Jim_Interp *interp, const char *version) JIM_GET_API(DeleteAssocData); JIM_GET_API(GetEnum); JIM_GET_API(ScriptIsComplete); - - Jim_SetResultString(interp, version, -1); + JIM_GET_API(PackageProvide); + JIM_GET_API(PackageRequire); } #ifdef JIM_EMBEDDED Jim_Interp *ExportedJimCreateInterp(void); static void Jim_InitEmbedded(void) { Jim_Interp *i = ExportedJimCreateInterp(); - Jim_InitExtension(i, ""); + Jim_InitExtension(i); Jim_FreeInterp(i); } #endif /* JIM_EMBEDDED */ |