expandVars through glob and wordexp

This commit is contained in:
Vítor Santos Costa 2015-11-05 16:47:52 +00:00
parent e3a56234e4
commit 77d57b90d4
1 changed files with 224 additions and 6 deletions

View File

@ -372,7 +372,7 @@ yapExpandVars (const char *source, char *result)
}
static char *
expandVars(const char *pattern, char *expanded, int maxlen)
expandVars(const char *pattern, char *expanded, int maxlent)
{
return yapExpandVars(pattern, expanded);
@ -448,7 +448,6 @@ PrologPath(const char *Y, char *X) {
#if _WIN32
#define HAVE_BASENAME 1
#define HAVE_REALPATH 1
#define HAVE_WORDEXP 1
#endif
static bool ChDir(const char *path) {
@ -462,6 +461,7 @@ static bool ChDir(const char *path) {
}
if (Yap_isAsset(qpath) ) {
AAssetManager* mgr = Yap_assetManager;
const char *ptr = qpath+8;
AAssetDir* d;
if (ptr[0] == '/')
@ -591,6 +591,222 @@ Yap_AbsoluteFile(const char *spec, char *tmp)
return rc;
}
#define EXPAND_FILENAME_DEFS() \
PAR("parameter_expansion", isatom, EXPAND_FILENAME_PARAMETER_EXPANSION), \
PAR("commands", boolean, EXPAND_FILENAME_COMMANDS), \
PAR(NULL, ok, EXPAND_FILENAME_END)
#define PAR(x, y, z) z
typedef enum expand_filename_enum_choices {
EXPAND_FILENAME_DEFS()
} expand_filename_enum_choices_t;
#undef PAR
#define PAR(x, y, z) \
{ x, y, z }
static const param_t expand_filename_defs[] = {EXPAND_FILENAME_DEFS()};
#undef PAR
static Term
do_expand_file_name(Term t1, Term opts USES_REGS)
{
xarg *args;
expand_filename_enum_choices_t i;
bool use_glob = false;
char **ss = NULL;
char *tmp = NULL;
const char *spec;
char *tmpe = NULL;
size_t j, pathcount;
int flags = 0;
#if HAVE_WORDEXP
wordexp_t wresult;
#endif
#if HAVE_GLOB
glob_t gresult;
#endif
if (IsVarTerm(t1)) {
Yap_Error(INSTANTIATION_ERROR, t1, NULL);
return TermNil;
} else if (IsAtomTerm(t1)) {
spec = AtomTermName( t1 );
} else if (IsStringTerm(t1)) {
spec = StringOfTerm( t1 );
} else {
Yap_Error(TYPE_ERROR_ATOM, t1, NULL);
return TermNil;
}
args = Yap_ArgListToVector(opts, expand_filename_defs, EXPAND_FILENAME_END);
if (args == NULL) {
return TermNil;
}
for (i = 0; i < EXPAND_FILENAME_END; i++) {
if (args[i].used) {
Term t = args[i].tvalue;
switch (i) {
case EXPAND_FILENAME_PARAMETER_EXPANSION:
if (t == TermProlog) {
use_glob = true;
tmpe = malloc(YAP_FILENAME_MAX+1);
if (tmpe == NULL) {
return TermNil;
}
tmpe = expandVars( spec, tmpe, YAP_FILENAME_MAX);
#ifdef GLOB_BRACE
flags = GLOB_BRACE;
#endif
spec = tmpe;
} else if (t == TermTrue) {
use_glob = false;
} else if (t == TermFalse) {
use_glob = true;
}
break;
case EXPAND_FILENAME_COMMANDS:
if (!use_glob) {
if (t == TermFalse) {
flags = WRDE_NOCMD;
}
}
case EXPAND_FILENAME_END:
break;
}
}
}
#if _WIN32 || defined(__MINGW32__)
char u[YAP_FILENAME_MAX+1];
// first pass, remove Unix style stuff
if (unix2win(spec, u, YAP_FILENAME_MAX) == NULL)
return NULL;
spec = (const char *)u;
#endif
if (tmp == NULL) {
tmp = malloc(YAP_FILENAME_MAX+1);
if (tmp == NULL) {
return TermNil;
}
}
#if ( __WIN32 || __MINGW32__ )
DWORD retval=0;
// notice that the file does not need to exist
if (ini == NULL) {
ini = malloc(strlen(w)+1);
}
retval = ExpandEnvironmentStrings(pattern,
expanded,
maxlen);
if (retval == 0)
{
Yap_WinError("Generating a full path name for a file" );
return NULL;
}
return expanded;
#elif HAVE_WORDEXP || HAVE_GLOB
/* Expand the string for the program to run. */
if (use_glob) {
#if HAVE_GLOB
switch (glob (spec, flags, NULL, &gresult))
{
case 0: /* Successful. */
ss = gresult.gl_pathv;
pathcount = gresult.gl_pathc;
break;
case GLOB_NOMATCH:
globfree(&gresult);
return Yap_unify_constant(TermNil, ARG2);
case GLOB_ABORTED:
PlIOError(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "glob aborted: %sn", strerror(errno));
globfree (&gresult);
return TermNil;
case GLOB_NOSPACE:
Yap_Error(RESOURCE_ERROR_HEAP, ARG1, "glob ran out of space: %sn", strerror(errno));
globfree (&gresult);
return TermNil;
/* If the error was WRDE_NOSPACE,
then perhaps part of the result was allocated. */
default: /* Some other error. */
return TermNil;
}
#endif
} else {
#if HAVE_WORDEXP
int rc;
switch ((rc = wordexp (spec, &wresult, flags)))
{
case 0: /* Successful. */
ss = wresult.we_wordv;
pathcount = wresult.we_wordc;
break;
case WRDE_NOSPACE:
/* If the error was WRDE_NOSPACE,
then perhaps part of the result was allocated. */
Yap_Error(RESOURCE_ERROR_HEAP, ARG1, "wordexp ran out of space: %s", strerror(errno));
wordfree (&wresult);
return TermNil;
default: /* Some other error. */
PlIOError(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1, "wordexp failed: %s", strerror(errno));
wordfree (&wresult);
return TermNil;
}
#endif
}
Term tf = TermNil;
for (j = 0; j < pathcount; j++) {
const char *s = ss[pathcount-(j+1)];
#if HAVE_REALPATH
s = myrealpath(s, tmp);
#endif
if (!exists(s))
continue;
Atom a = Yap_LookupAtom(s);
tf = MkPairTerm(MkAtomTerm( a ),tf);
}
#else
// just use basic
if (expanded == NULL) {
expanded = malloc(strlen(pattern)+1);
}
strcpy(expanded, pattern);
#endif
if (tmp)
free( tmp );
if (tmpe)
free( tmpe );
#if HAVE_GLOB
if (use_glob)
globfree( &gresult );
#endif
#if HAVE_WORDEXP
if (!use_glob)
wordfree( &wresult );
#endif
return tf;
}
static Int
expand_file_name( USES_REGS1)
{
Term tf = do_expand_file_name( Deref(ARG1), TermNil PASS_REGS);
return
Yap_unify( tf, ARG2);
}
static Int
expand_file_name3( USES_REGS1)
{
Term tf = do_expand_file_name( Deref(ARG1), Deref(ARG2) PASS_REGS);
return
Yap_unify( tf, ARG3 );
}
/*
static char *canoniseFileName( char *path) {
#if HAVE_REALPATH && HAVE_BASENAME
@ -1132,7 +1348,7 @@ Yap_InitPageSize(void)
}
static Int
p_true_file_name ( USES_REGS1 )
true_file_name ( USES_REGS1 )
{
Term t = Deref(ARG1);
@ -1144,7 +1360,7 @@ Yap_InitPageSize(void)
Yap_Error(TYPE_ERROR_ATOM,t,"argument to true_file_name");
return FALSE;
}
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, NULL, LOCAL_FileNameBuf, true, YAP_PL, false, false))
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, NULL, LOCAL_FileNameBuf, false, YAP_PL, false, false))
return FALSE;
return Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)));
}
@ -1168,7 +1384,7 @@ Yap_InitPageSize(void)
}
static Int
p_true_file_name3 ( USES_REGS1 )
true_file_name3 ( USES_REGS1 )
{
Term t = Deref(ARG1), t2 = Deref(ARG2);
char *root = NULL;
@ -1188,7 +1404,7 @@ Yap_InitPageSize(void)
}
root = RepAtom(AtomOfTerm(t2))->StrOfAE;
}
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, root, LOCAL_FileNameBuf, true, YAP_PL, false, false))
if (!Yap_trueFileName (RepAtom(AtomOfTerm(t))->StrOfAE, NULL, root, LOCAL_FileNameBuf, false, YAP_PL, false, false))
return FALSE;
return Yap_unify(ARG3, MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf)));
}
@ -1957,6 +2173,8 @@ Yap_InitPageSize(void)
Yap_InitCPred ("$ld_path", 1, p_ld_path, SafePredFlag);
Yap_InitCPred ("$address_bits", 1, p_address_bits, SafePredFlag);
Yap_InitCPred ("$expand_file_name", 2, p_expand_file_name, SyncPredFlag);
Yap_InitCPred ("expand_file_name", 3, expand_file_name3, SyncPredFlag);
Yap_InitCPred ("expand_file_name", 2, expand_file_name, SyncPredFlag);
Yap_InitCPred ("working_directory", 2,working_directory, SyncPredFlag);
Yap_InitCPred ("prolog_to_os_filename", 2, prolog_to_os_filename, SyncPredFlag);
Yap_InitCPred ("prolog_to_os_filename", 2, prolog_to_os_filename, SyncPredFlag);