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;
+}
+