aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--STYLE13
-rw-r--r--TODO13
-rw-r--r--jim-aio.c6
-rw-r--r--jim-posix.c6
-rw-r--r--jim-sdl.c7
-rw-r--r--jim-win32.c6
-rw-r--r--jim-win32com.c6
-rw-r--r--jim.c140
-rw-r--r--jim.h21
10 files changed, 201 insertions, 21 deletions
diff --git a/ChangeLog b/ChangeLog
index fb49983..eaf11bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/STYLE b/STYLE
index 99b02d1..906d744 100644
--- a/STYLE
+++ b/STYLE
@@ -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.
diff --git a/TODO b/TODO
index 6198020..a0d33ce 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/jim-aio.c b/jim-aio.c
index dfcf035..a8b06ae 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -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);
diff --git a/jim-sdl.c b/jim-sdl.c
index 50240e0..25b59d6 100644
--- a/jim-sdl.c
+++ b/jim-sdl.c
@@ -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,
diff --git a/jim.c b/jim.c
index 24c2255..68076a2 100644
--- a/jim.c
+++ b/jim.c
@@ -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];
diff --git a/jim.h b/jim.h
index 2ed1b26..0c8a8d0 100644
--- a/jim.h
+++ b/jim.h
@@ -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 */