Changeset: 4464c60a81d5 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4464c60a81d5 Modified Files: MonetDB5/src/mal/mal_import.mx MonetDB5/src/mal/mal_linker.mx Branch: default Log Message:
Add the ability to include directories (transplanted from daba5234988c72ed2e02a583b15de59895b7901b) diffs (297 lines): diff -r 8990c4a0fa19 -r 4464c60a81d5 MonetDB5/src/mal/mal_import.mx --- a/MonetDB5/src/mal/mal_import.mx Thu May 13 16:49:39 2010 +0200 +++ b/MonetDB5/src/mal/mal_import.mx Wed May 12 16:22:44 2010 +0200 @@ -34,7 +34,6 @@ #include "mal_utils.h" mal_export void slash_2_dir_sep(str fname); -mal_export stream *openSourceFile(str fname); @- The import context is located. If the module already exists, we should silently skip parsing the file. This is handled at the parser level. @@ -62,23 +61,22 @@ *s = DIR_SEP; } -stream * -openSourceFile(str fname) +static str +malResolveFile(str fname) +{ + char path[PATHLENGTH]; + + snprintf(path, PATHLENGTH, "%s", fname); + slash_2_dir_sep(path); + return MSP_locate_script(path); +} + +static stream * +malOpenSource(str file) { stream *fd = NULL; - char path[PATHLENGTH]; - str fullname; - - snprintf(path,PATHLENGTH,"%s",fname); - slash_2_dir_sep(path); - fullname = MSP_locate_script(path); - - if (fullname) { - fd = open_rastream(fullname); - GDKfree(fullname); - } else { - fd = open_rastream(path); - } + if (file) + fd = open_rastream(file); return fd; } @@ -97,14 +95,14 @@ { stream *fd; - fd = openSourceFile(name); + fd = malOpenSource(name); if (stream_errnr(fd) == OPEN_ERROR) { stream_destroy(fd); throw(MAL, "malInclude", "could not open file: %s", name); } *fdin = bstream_create(fd, 128 * BLOCK); - if( bstream_next(*fdin) < 0) - stream_printf(c->fdout,"!WARNING: could not read %s\n",name); + if (bstream_next(*fdin) < 0) + stream_printf(c->fdout, "!WARNING: could not read %s\n", name); return MAL_SUCCEED; } @@ -175,6 +173,8 @@ malInclude(Client c, str name, int listing) { str s= MAL_SUCCEED; + str filename; + str p; bstream *oldfdin = c->fdin; int oldyycur = c->yycur; @@ -189,16 +189,30 @@ Module oldnspace = c->nspace; Symbol oldprg = c->curprg; - c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = 0; c->listing = listing; - c->bak = NULL; c->fdin = NULL; - c->srcFile = name; - if ((s = malLoadScript(c, name, &c->fdin)) == 0) - parseMAL(c,c->curprg); + + if ((filename = malResolveFile(name)) != NULL) { + name = filename; + while ((p = strchr(filename, PATH_SEP)) != NULL) { + *p = '\0'; + c->srcFile = filename; + c->yycur = 0; + c->bak = NULL; + if ((s = malLoadScript(c, filename, &c->fdin)) == 0) + parseMAL(c, c->curprg); + filename = p + 1; + } + c->srcFile = filename; + c->yycur = 0; + c->bak = NULL; + if ((s = malLoadScript(c, filename, &c->fdin)) == 0) + parseMAL(c, c->curprg); + GDKfree(name); + } @:restoreClient()@ return s; @@ -229,24 +243,55 @@ @:restoreState@ stream *fd; str msg= MAL_SUCCEED; + str p; + str filename; - c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = 0; c->listing = listing; - c->bak = NULL; c->fdin = NULL; - c->srcFile= fname; - fd = openSourceFile(fname); + + filename = malResolveFile(fname); + if (filename == NULL) { + stream_printf(c->fdout, "#WARNING: could not open file: %s\n", fname); + @:restoreClient3()@ + @:restoreClient()@ + return msg; + } + + fname = filename; + while ((p = strchr(filename, PATH_SEP)) != NULL) { + *p = '\0'; + fd = malOpenSource(filename); + if (stream_errnr(fd) == OPEN_ERROR) { + stream_destroy(fd); + stream_printf(c->fdout, "#WARNING: could not open file: %s\n", + filename); + } else { + c->srcFile = filename; + c->yycur = 0; + c->bak = NULL; + MSinitClientPrg(c, "user", "main"); /* re-initialize context */ + MCpushClientInput(c, bstream_create(fd, 128 * BLOCK), c->listing, ""); + msg = runScenario(c); + } + filename = p + 1; + } + fd = malOpenSource(filename); if (stream_errnr(fd) == OPEN_ERROR) { stream_destroy(fd); - stream_printf(c->fdout, "#WARNING: could not open file: %s\n", fname); + stream_printf(c->fdout, "#WARNING: could not open file: %s\n", + filename); } else { - MSinitClientPrg(c,"user","main"); /* re-initialize context */ - MCpushClientInput(c, bstream_create(fd, 128 * BLOCK),c->listing,""); + c->srcFile = filename; + c->yycur = 0; + c->bak = NULL; + MSinitClientPrg(c, "user", "main"); /* re-initialize context */ + MCpushClientInput(c, bstream_create(fd, 128 * BLOCK), c->listing, ""); msg = runScenario(c); } + GDKfree(fname); @:restoreClient3()@ @:restoreClient()@ diff -r 8990c4a0fa19 -r 4464c60a81d5 MonetDB5/src/mal/mal_linker.mx --- a/MonetDB5/src/mal/mal_linker.mx Thu May 13 16:49:39 2010 +0200 +++ b/MonetDB5/src/mal/mal_linker.mx Wed May 12 16:22:44 2010 +0200 @@ -59,6 +59,9 @@ #define RTLD_NOW_REPORT_ERROR 8 #endif +#include <sys/types.h> /* opendir */ +#include <dirent.h> /* opendir */ + /* #define DEBUG_MAL_LINKER */ #define MONET64 1 mal_export MALfcn getAddress(str filename, str modnme, str fcnname,int silent); @@ -71,7 +74,7 @@ mal_export int isLoaded(str modulename); #endif @- -The MAL module should be compiled with -rdynamic and -ldl. +The MAL module should be compiled with -rdynamic and -ldl (Linux). This enables loading the routines and finding out the address of a particular routine. The mapping from MAL module.function() identifier to an address is @@ -83,7 +86,7 @@ the current directory. Note, however, that the libraries are reference counted. Although we -do;t close them until end of session it seems prudent to maintain +don't close them until end of session it seems prudent to maintain the consistency of this counter. @c @@ -320,8 +323,14 @@ The plausible locations of the modules can be designated by an environment variable. @c +static int +cmpstr(const void *p1, const void *p2) +{ + return strcmp(*(char* const*)p1, *(char* const*)p2); +} + static char * -locate_file(const char *basename, const char *ext) +locate_file(const char *basename, const char *ext, const bit recurse) { char *mod_path = GDKgetenv("monet_mod_path"); char *fullname; @@ -342,6 +351,7 @@ size_t i; char *p; int fd; + DIR *rdir; if ((p = strchr(mod_path, PATH_SEP)) != NULL) { i = p - mod_path; @@ -361,6 +371,44 @@ strncpy(fullname, mod_path, i); fullname[i] = DIR_SEP; strcpy(fullname + i + 1, basename); + /* see if this is a directory, if so, recurse */ + if (recurse == 1 && (rdir = opendir(fullname)) != NULL) { + struct dirent *e; + str strs[48]; /* hardwired limit */ + int lasts = 0; + int c; + /* list *ext, sort, return */ + while ((e = readdir(rdir)) != NULL) { + if (strcmp(e->d_name, "..") == 0 || strcmp(e->d_name, ".") == 0) + continue; + if (strcmp(e->d_name + strlen(e->d_name) - strlen(ext), ext) == 0) { + strs[lasts] = GDKmalloc(strlen(fullname) + + sizeof(DIR_SEP) + strlen(e->d_name) + 1); + sprintf(strs[lasts], "%s%c%s", + fullname, DIR_SEP, GDKstrdup(e->d_name)); + lasts++; + } + if (lasts >= 48) + break; + } + (void)closedir(rdir); + if (lasts > 0) { + /* assure that an ordering such as 10_first, 20_second works */ + qsort(strs, lasts, sizeof(char *), cmpstr); + i = 0; + for (c = 0; c < lasts; c++) + i += strlen(strs[c]) + 1; /* PATH_SEP or \0 */ + fullname = GDKrealloc(fullname, i); + i = 0; + for (c = 0; c < lasts; c++) { + strcpy(fullname + i, strs[c]); + i += strlen(strs[c]); + fullname[i++] = PATH_SEP; + } + fullname[i - 1] = '\0'; + return fullname; + } + } strcat(fullname + i + 1, ext); if ((fd = open(fullname, O_RDONLY)) >= 0) { close(fd); @@ -379,11 +427,7 @@ char * MSP_locate_script(const char *filename) { - char *f; - f= locate_file(filename, MAL_EXT); - if ( f == NULL) - f= locate_file(filename, SQL_EXT); - return f; + return locate_file(filename, MAL_EXT, 1); } char * @@ -395,7 +439,7 @@ strcpy(lib_name, SO_PREFIX); strcpy(lib_name + strlen(SO_PREFIX), filename); - fullname = locate_file(lib_name, SO_EXT); + fullname = locate_file(lib_name, SO_EXT, 0); #ifdef _AIX fullname = GDKrealloc(fullname, strlen(fullname) + strlen(lib_name) + 5); strcat(fullname, "("); _______________________________________________ Checkin-list mailing list Checkin-list@monetdb.org http://mail.monetdb.org/mailman/listinfo/checkin-list