| Ilya Zakharevich on Thu, 19 Jan 2006 05:45:25 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| [PATCH 2.2.11+] Support for packages: require() |
This is the second path of "package" support in GP/PARI (installing
functionality via loaded library written in GP). This patch enables
new gp function require() documented in the first chunk.
--- ./src/functions/programming/require-ppre Wed Jan 18 20:01:44 2006
+++ ./src/functions/programming/require Wed Jan 18 20:07:58 2006
@@ -0,0 +1,9 @@
+Function: require
+Class: highlevel
+Section: programming
+C-Name: gp_require_file
+Prototype: vs
+Help: require(name): find file with given 'name' and extension .gp
+ on GP load path and load it. Keeps hash of required 'name's; if the
+ 'name' is already loaded, does nothing. '::' in 'name' is replaced by '/'.
+
--- ./src/headers/paridecl.h-ppre Tue Nov 15 10:01:50 2005
+++ ./src/headers/paridecl.h Wed Jan 18 19:43:12 2006
@@ -929,6 +929,7 @@ GEN gp_read_file(char *s);
GEN gp_read_stream(FILE *f);
GEN gp_readvec_file(char *s);
GEN gp_readvec_stream(FILE *f);
+void gp_require_file(char *s);
void killallfiles(int check);
int killfile(pariFILE *f);
void matbrute(GEN g, char format, long dec);
--- ./src/language/es.c-ppre Wed Jan 18 17:47:24 2006
+++ ./src/language/es.c Wed Jan 18 20:22:36 2006
@@ -186,6 +186,8 @@ init_filtre(filtre_t *F, Buffer *buf)
/** INPUT METHODS **/
/** **/
/********************************************************************/
+static void switchin2(const char *name0, int on_path);
+
/* create */
Buffer *
new_buffer(void)
@@ -233,11 +235,11 @@ gp_read_stream(FILE *fi)
delete_buffer(b); return x;
}
-GEN
-gp_read_file(char *s)
+static GEN
+gp_read_file2(char *s, int on_path)
{
GEN x = gnil;
- switchin(s);
+ switchin2(s, on_path);
if (file_is_binary(infile))
x = readbin(s,infile);
else {
@@ -253,6 +255,12 @@ gp_read_file(char *s)
}
GEN
+gp_read_file(char *s)
+{
+ return gp_read_file2(s, 0);
+}
+
+GEN
gp_readvec_stream(FILE *fi)
{
pari_sp ltop = avma;
@@ -3128,8 +3136,8 @@ try_name(char *name)
}
/* If name = "", re-read last file */
-void
-switchin(const char *name0)
+static void
+switchin2(const char *name0, int on_path)
{
char *s, *name;
@@ -3143,8 +3151,10 @@ switchin(const char *name0)
name = pari_strdup(name0);
}
/* if name contains '/', don't use dir_list */
- s=name; while (*s && *s != '/' && *s != '\\') s++;
- if (*s) { if (try_name(name)) return; }
+ s=name;
+ if (!on_path)
+ while (*s && *s != '/' && *s != '\\') s++;
+ if (!on_path && *s) { if (try_name(name)) return; }
else
{
char **tmp = GP_DATA->path->dirs;
@@ -3158,6 +3168,12 @@ switchin(const char *name0)
err(openfiler,"input",name0);
}
+void
+switchin(const char *name0)
+{
+ switchin2(name0, 0);
+}
+
static int is_magic_ok(FILE *f);
void
@@ -3645,3 +3661,40 @@ pari_unique_filename(char *s)
}
return buf;
}
+
+void
+gp_require_file(char *name)
+{
+ char buf[1024], *s = name, *t = buf;
+ entree *ep;
+ GEN res;
+
+ if (!is_identifier(name))
+ err(talker, "required name (%s) is not an identifier", name);
+ if (strlen(name) >= sizeof(buf) - 2)
+ err(talker, "required name (%s) too long", name);
+ sprintf(buf, "%s::", name);
+ ep = is_entry(buf);
+ if (ep) {
+ if (EpVALENCE(ep) != EpVAR)
+ err(talker, "panic: corrupted hash of loaded packages");
+ if (signe(ep->value))
+ return; /* loaded already */
+ }
+
+ while (*s) {
+ if (s[0] == ':' && s[1] == ':') {
+ *t++ = '/';
+ s += 2;
+ } else *t++ = *s++;
+ }
+ *t = 0;
+ res = gp_read_file2(buf, 1); /* on path */
+ if (gsigne(res) == 0)
+ err(talker, "required file (%s) did not return true", name);
+ sprintf(buf, "%s::", name);
+ ep = fetch_named_var(buf); /* Create value */
+ changevalue(ep, gen_1);
+ return;
+}
+