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