aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Makefile35
-rw-r--r--TODO15
-rw-r--r--jim.c250
-rw-r--r--jim.h5
5 files changed, 272 insertions, 39 deletions
diff --git a/ChangeLog b/ChangeLog
index eaf11bb..24e9062 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-03-31 14:20 antirez
+
+ * ChangeLog, STYLE, TODO, jim-aio.c, jim-posix.c, jim-sdl.c,
+ jim-win32.c, jim-win32com.c, jim.c, jim.h: Implemented the C API
+ "background" for the packages system of Jim.
+
2005-03-29 18:50 antirez
* ChangeLog, jim.c, test.tcl: [info args] added
diff --git a/Makefile b/Makefile
index 32ae949..b5d3c65 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,7 @@
.SUFFIXES:
.SUFFIXES: .c .so .xo .o .dll
+.PHONY: jim-aio-1.0.so
SHELL = /bin/sh
RM = rm -f
@@ -32,11 +33,17 @@ LIBS = -ldl
stopit:
@echo "Use:"
- @echo "make jim - to build the Jim interpreter"
- @echo "make extensions - to build the aio,posix and sdl extensions"
- @echo "make posix - to build only the posix extension"
- @echo "make aio - to build only the ANSI I/O extension"
- @echo "make sdl - to build only the SDL extension"
+ @echo "make jim - to build the Jim interpreter"
+ @echo "---"
+ @echo "make aio - to build only the ANSI I/O extension"
+ @echo "---"
+ @echo "make unix-ext - to build the AIO, POSIX and SDL extensions"
+ @echo "make posix - to build only the POSIX extension"
+ @echo "make sdl - to build only the SDL extension"
+ @echo "---"
+ @echo "make win32-ext - to build the WIN32 and WIN32COM extensions"
+ @echo "make win32 - to build only the WIN32 extension"
+ @echo "make win32com - to build only the WIN32COM extension"
all: $(DEFAULT_BUILD)
@@ -69,11 +76,19 @@ jim-sdl.so: jim-sdl.xo
jim: $(JIM_OBJECTS)
$(CC) $(LDFLAGS) -o jim $(JIM_OBJECTS) $(LIBS)
-posix: jim-posix.so
-aio: jim-aio.so
-sdl: jim-sdl.so
-win32: jim-win32.dll jim-win32com.dll
-extensions: posix aio sdl
+posix: jim-posix-1.0.so
+aio: jim-aio-1.0.so
+sdl: jim-sdl-1.0.so
+win32: jim-win32-1.0.dll
+win32com: jim-win32com-1.0.dll
+unix-extensions: posix aio sdl
+win32-extensions: win32 win32com
+
+jim-posix-1.0.so: jim-posix.xo
+jim-aio-1.0.so: jim-aio.xo
+jim-sdl-1.0.so: jim-sdl.xo
+jim-win32-1.0.dll: jim-win32.o
+jim-win32com-1.0.dll: jim-win32com.o
clean:
$(RM) *.o *.so *.dll *.xo core .depend .*.swp gmon.out $(PROGRAMS)
diff --git a/TODO b/TODO
index a0d33ce..429c04b 100644
--- a/TODO
+++ b/TODO
@@ -34,17 +34,30 @@ EXTENSIONS
- Regexp extension
- OOP system
+- Event loop
+- Files
+- Sockets
+- Tuplespace extension (http://wiki.tcl.tk/3947) (using sqlite as backend)
SPEED OPTIMIZATIONS
- Find a way to avoid interpolation/reparsing in "foo($bar)" tokens.
See the "sieve" and "ary" bench performances, result of this problem.
(to compare with sieve_dict is also useful.)
-- Many other possible things, including better literal sharing.
+- Experiment with better ways to do literal sharing.
+- Organize the 'script' object so that a single data structure is
+ used for a full command, and interpolation is done using an
+ 'interpolation token type' like JIM_TT_VAR and so on.
+ This way there is no need to run the array if integer objects
+ with the command structure. Also should help for better cache usage.
- Generate .c from Jim programs, as calls to the Jim API to avoid
the performance penality of Jim_EvalObj() overhead. In the future
try to generate the calls like a JIT emitting assembler from
Jim directly.
+- Jim_GetDouble() should check if the object type is an integer into
+ a range that a double can represent without any loss, and directly
+ return the double value converting the integer one instead to pass
+ for the string repr.
IMPLEMENTATION ISSUES
diff --git a/jim.c b/jim.c
index 68076a2..c411ebb 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.138 2005/03/31 12:20:21 antirez Exp $
+ * $Id: jim.c,v 1.139 2005/04/02 07:44:24 antirez Exp $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -7341,37 +7341,52 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
/* -----------------------------------------------------------------------------
* Packages handling
* ---------------------------------------------------------------------------*/
+
+#define JIM_PKG_ANY_VERSION -1
+
/* 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;
+ char *copy;
+ jim_wide major, minor;
+ char *majorStr, *minorStr, *p;
- p = buf;
- while (*v) {
- if (!isdigit(*v)) continue;
- *p++ = *v++;
+ if (v[0] == '\0') {
+ *intPtr = JIM_PKG_ANY_VERSION;
+ return JIM_OK;
}
+
+ copy = Jim_StrDup(v);
+ p = strchr(copy, '.');
+ if (p == NULL) goto badfmt;
*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;
+ majorStr = copy;
+ minorStr = p+1;
+
+ if (Jim_StringToWide(majorStr, &major, 10) != JIM_OK ||
+ Jim_StringToWide(minorStr, &minor, 10) != JIM_OK)
+ goto badfmt;
+ *intPtr = major*100+minor;
+ Jim_Free(copy);
return JIM_OK;
+
+badfmt:
+ Jim_Free(copy);
+ if (flags & JIM_ERRMSG) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp),
+ "invalid package version '", v, "'", NULL);
+ }
+ return JIM_ERR;
}
#define JIM_MATCHVER_EXACT (1<<JIM_PRIV_FLAG_SHIFT)
static int JimPackageMatchVersion(int needed, int actual, int flags)
{
+ if (needed == JIM_PKG_ANY_VERSION) return 1;
if (flags & JIM_MATCHVER_EXACT) {
return needed == actual;
} else {
@@ -7395,13 +7410,156 @@ int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver,
return JIM_OK;
}
-const char *Jim_PackageRequire(Jim_Interp *interp, char *name, char *ver, int flags)
+#ifndef JIM_ANSIC
+#ifndef WIN32
+
+#include <sys/types.h>
+#include <dirent.h>
+
+static char *JimFindBestPackage(Jim_Interp *interp, char **prefixes,
+ int prefixc, const char *pkgName, int pkgVer, int flags)
+{
+ int bestVer = -1, i;
+ int pkgNameLen = strlen(pkgName);
+ char *bestPackage = NULL;
+ struct dirent *de;
+
+ for (i = 0; i < prefixc; i++) {
+ DIR *dir;
+ char buf[JIM_LIBPATH_LEN];
+ int prefixLen;
+
+ if (prefixes[i] == NULL) continue;
+ strncpy(buf, prefixes[i], JIM_LIBPATH_LEN);
+ buf[JIM_LIBPATH_LEN-1] = '\0';
+ prefixLen = strlen(buf);
+ if (prefixLen && buf[prefixLen-1] == '/')
+ buf[prefixLen-1] = '\0';
+
+ if ((dir = opendir(buf)) == NULL) continue;
+ while ((de = readdir(dir)) != NULL) {
+ char *fileName = de->d_name;
+ int fileNameLen = strlen(fileName);
+
+ if (strncmp(fileName, "jim-", 4) == 0 &&
+ strncmp(fileName+4, pkgName, pkgNameLen) == 0 &&
+ *(fileName+4+pkgNameLen) == '-' &&
+ fileNameLen > 4 && /* note that this is not really useful */
+ (strncmp(fileName+fileNameLen-4, ".tcl", 4) == 0 ||
+ strncmp(fileName+fileNameLen-4, ".dll", 4) == 0 ||
+ strncmp(fileName+fileNameLen-3, ".so", 3) == 0))
+ {
+ char ver[6]; /* xx.yy<nulterm> */
+ char *p = strrchr(fileName, '.');
+ int verLen, fileVer;
+
+ verLen = p - (fileName+4+pkgNameLen+1);
+ if (verLen < 3 || verLen > 5) continue;
+ memcpy(ver, fileName+4+pkgNameLen+1, verLen);
+ ver[verLen] = '\0';
+ if (JimPackageVersionToInt(interp, ver, &fileVer, JIM_NONE)
+ != JIM_OK) continue;
+ if (JimPackageMatchVersion(pkgVer, fileVer, flags) &&
+ (bestVer == -1 || bestVer < fileVer))
+ {
+ bestVer = fileVer;
+ Jim_Free(bestPackage);
+ bestPackage = Jim_Alloc(strlen(buf)+strlen(fileName)+2);
+ sprintf(bestPackage, "%s/%s", buf, fileName);
+ }
+ }
+ }
+ closedir(dir);
+ }
+ return bestPackage;
+}
+
+#else /* WIN32 */
+
+static char *JimFindBestPackage(char **prefixes, int prefixc,
+ const char *name, int ver)
+{
+ JIM_NOTUSED(prefixes);
+ JIM_NOTUSED(prefixc);
+ JIM_NOTUSED(name);
+ JIM_NOTUSED(ver);
+ return NULL;
+}
+
+#endif /* WIN32 */
+#endif /* JIM_ANSIC */
+
+/* Search for a suitable package under every dir specified by jim_libpath
+ * and load it if possible. If a suitable package was loaded with success
+ * JIM_OK is returned, otherwise JIM_ERR is returned. */
+static int JimLoadPackage(Jim_Interp *interp, const char *name, int ver,
+ int flags)
+{
+ Jim_Obj *libPathObjPtr;
+ char **prefixes, *best;
+ int prefixc, i, retCode = JIM_OK;
+
+ libPathObjPtr = Jim_GetGlobalVariableStr(interp, "jim_libpath", JIM_NONE);
+ if (libPathObjPtr == NULL) {
+ prefixc = 0;
+ libPathObjPtr = NULL;
+ } else {
+ Jim_IncrRefCount(libPathObjPtr);
+ Jim_ListLength(interp, libPathObjPtr, &prefixc);
+ }
+
+ prefixes = malloc(sizeof(char*)*prefixc);
+ for (i = 0; i < prefixc; i++) {
+ Jim_Obj *prefixObjPtr;
+ if (Jim_ListIndex(interp, libPathObjPtr, i,
+ &prefixObjPtr, JIM_NONE) != JIM_OK)
+ {
+ prefixes[i] = NULL;
+ continue;
+ }
+ prefixes[i] = Jim_StrDup(Jim_GetString(prefixObjPtr, NULL));
+ }
+ /* Scan every directory to find the "best" package. */
+ best = JimFindBestPackage(interp, prefixes, prefixc, name, ver, flags);
+ if (best != NULL) {
+ char *p = strrchr(best, '.');
+ /* Try to load/source it */
+ if (p && strcmp(p, ".tcl") == 0) {
+ retCode = Jim_EvalFile(interp, best);
+ } else {
+ retCode = Jim_LoadLibrary(interp, best);
+ }
+ } else {
+ retCode = JIM_ERR;
+ }
+ Jim_Free(best);
+ for (i = 0; i < prefixc; i++)
+ Jim_Free(prefixes[i]);
+ Jim_Free(prefixes);
+ if (libPathObjPtr)
+ Jim_DecrRefCount(interp, libPathObjPtr);
+ return retCode;
+}
+
+const char *Jim_PackageRequire(Jim_Interp *interp, const char *name,
+ const char *ver, int flags)
{
Jim_HashEntry *he;
+ int requiredVer;
+ if (JimPackageVersionToInt(interp, ver, &requiredVer, JIM_ERRMSG) != JIM_OK)
+ return NULL;
he = Jim_FindHashEntry(&interp->packages, name);
if (he == NULL) {
- /* TODO: try to load the given extension. */
+ /* Try to load the package. */
+ if (JimLoadPackage(interp, name, requiredVer, flags) == JIM_OK) {
+ he = Jim_FindHashEntry(&interp->packages, name);
+ if (he == NULL) {
+ return "?";
+ }
+ return he->val;
+ }
+ /* No way... return an error. */
if (flags & JIM_ERRMSG) {
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
Jim_AppendStrings(interp, Jim_GetResult(interp),
@@ -7409,10 +7567,8 @@ const char *Jim_PackageRequire(Jim_Interp *interp, char *name, char *ver, int fl
}
return NULL;
} else {
- int requiredVer, actualVer;
- if (JimPackageVersionToInt(interp, ver, &requiredVer, JIM_ERRMSG)
- != JIM_OK ||
- JimPackageVersionToInt(interp, he->key, &actualVer, JIM_ERRMSG)
+ int actualVer;
+ if (JimPackageVersionToInt(interp, he->val, &actualVer, JIM_ERRMSG)
!= JIM_OK)
{
return NULL;
@@ -7422,10 +7578,10 @@ const char *Jim_PackageRequire(Jim_Interp *interp, char *name, char *ver, int fl
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
Jim_AppendStrings(interp, Jim_GetResult(interp),
"Package '", name, "' already loaded, but with version ",
- he->key, NULL);
+ he->val, NULL);
return NULL;
}
- return he->key;
+ return he->val;
}
}
@@ -11043,6 +11199,47 @@ static int Jim_RandCoreCommand(Jim_Interp *interp, int argc,
}
}
+/* [package] */
+static int Jim_PackageCoreCommand(Jim_Interp *interp, int argc,
+ Jim_Obj *const *argv)
+{
+ int option;
+ const char *options[] = {
+ "require", NULL
+ };
+ enum {OPT_REQUIRE};
+
+ if (argc < 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?");
+ return JIM_ERR;
+ }
+ if (Jim_GetEnum(interp, argv[1], options, &option, "option",
+ JIM_ERRMSG) != JIM_OK)
+ return JIM_ERR;
+
+ if (option == OPT_REQUIRE) {
+ int exact = 0;
+ const char *ver;
+
+ if (Jim_CompareStringImmediate(interp, argv[2], "-exact")) {
+ exact = 1;
+ argv++;
+ argc--;
+ }
+ if (argc != 3 && argc != 4) {
+ Jim_WrongNumArgs(interp, 2, argv, "?-exact? package ?version?");
+ return JIM_ERR;
+ }
+ ver = Jim_PackageRequire(interp, Jim_GetString(argv[2], NULL),
+ argc == 4 ? Jim_GetString(argv[3], NULL) : "",
+ JIM_ERRMSG);
+ if (ver == NULL)
+ return JIM_ERR;
+ Jim_SetResultString(interp, ver, -1);
+ }
+ return JIM_OK;
+}
+
static struct {
const char *name;
Jim_CmdProc cmdProc;
@@ -11106,6 +11303,7 @@ static struct {
{"range", Jim_RangeCoreCommand},
{"scope", Jim_ScopeCoreCommand},
{"rand", Jim_RandCoreCommand},
+ {"package", Jim_PackageCoreCommand},
{NULL, NULL},
};
@@ -11174,7 +11372,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.138 2005/03/31 12:20:21 antirez Exp $\n");
+ printf("CVS ID: $Id: jim.c,v 1.139 2005/04/02 07:44:24 antirez Exp $\n");
Jim_SetVariableStrWithStr(interp, "jim_interactive", "1");
while (1) {
char buf[1024];
diff --git a/jim.h b/jim.h
index 0c8a8d0..012aa84 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.65 2005/03/31 12:20:21 antirez Exp $
+ * $Id: jim.h,v 1.66 2005/04/02 07:44:24 antirez Exp $
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -747,7 +747,8 @@ JIM_STATIC int JIM_API(Jim_RegisterApi) (Jim_Interp *interp,
/* 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);
+JIM_STATIC const char * JIM_API(Jim_PackageRequire) (Jim_Interp *interp,
+ const char *name, const char *ver, int flags);
/* error messages */
JIM_STATIC void JIM_API(Jim_PrintErrorMessage) (Jim_Interp *interp);