#include "gettext.h"
#define _(msgid) gettext (msgid)
-#include <libpspp/debug-print.h>
-
/* PORTME: Everything in this file is system dependent. */
#ifdef unix
\f
/* Functions for performing operations on filenames. */
-/* Substitutes $variables as defined by GETENV into INPUT and returns
- a copy of the resultant string. Supports $var and ${var} syntaxes;
- $$ substitutes as $. */
-char *
-fn_interp_vars (const char *input, const char *(*getenv) (const char *))
+
+/* Substitutes $variables as defined by GETENV into TARGET.
+ TARGET must be a string containing the text for which substitution
+ is required.
+ Supports $var and ${var} syntaxes;
+ $$ substitutes as $.
+*/
+void
+fn_interp_vars (struct string *target,
+ const char *(*getenv) (const char *))
{
- struct string output;
+ char *input ;
+ char *s ;
+
+ assert (target);
- if (NULL == strchr (input, '$'))
- return xstrdup (input);
+ input = xmalloc(ds_length(target) + 1);
+ s = input;
- ds_init (&output, strlen (input));
+ strcpy(input, ds_c_str(target));
+
+ if (NULL == strchr (ds_c_str(target), '$'))
+ goto done;
+
+ ds_clear(target);
for (;;)
- switch (*input)
- {
- case '\0':
- return ds_c_str (&output);
+ {
+ switch (*s)
+ {
+ case '\0':
+ goto done ;
- case '$':
- input++;
-
- if (*input == '$')
- {
- ds_putc (&output, '$');
- input++;
- }
- else
- {
- int stop;
- int start;
- const char *value;
-
- start = ds_length (&output);
-
- if (*input == '(')
- {
- stop = ')';
- input++;
- }
- else if (*input == '{')
- {
- stop = '}';
- input++;
- }
- else
- stop = 0;
-
- while (*input && *input != stop
- && (stop || isalpha ((unsigned char) *input)))
- ds_putc (&output, *input++);
+ case '$':
+ s++;
+
+ if (*s == '$')
+ {
+ ds_putc (target, '$');
+ s++;
+ }
+ else
+ {
+ int stop;
+ int start;
+ const char *value;
+
+ start = ds_length (target);
+
+ if (*s == '(')
+ {
+ stop = ')';
+ s++;
+ }
+ else if (*s == '{')
+ {
+ stop = '}';
+ s++;
+ }
+ else
+ stop = 0;
+
+ while (*s && *s != stop
+ && (stop || isalpha ((unsigned char) *s)))
+ {
+ ds_putc (target, *s++);
+ }
- value = getenv (ds_c_str (&output) + start);
- ds_truncate (&output, start);
- ds_puts (&output, value);
+ value = getenv (ds_c_str (target) + start);
+ ds_truncate (target, start);
+ ds_puts (target, value);
+
+ if (stop && *s == stop)
+ s++;
+ }
+ break;
- if (stop && *input == stop)
- input++;
- }
+ default:
+ ds_putc (target, *s++);
+ }
+ }
- default:
- ds_putc (&output, *input++);
- }
+ done:
+ free(input);
+ return;
}
#ifdef unix
char *
fn_tilde_expand (const char *input)
{
- const char *ip;
- struct string output;
-
- if (NULL == strchr (input, '~'))
- return xstrdup (input);
- ds_init (&output, strlen (input));
-
- ip = input;
-
- for (ip = input; *ip; )
- if (*ip != '~' || (ip != input && ip[-1] != PATH_DELIMITER))
- ds_putc (&output, *ip++);
- else
- {
- static const char stop_set[3] = {DIR_SEPARATOR, PATH_DELIMITER, 0};
- const char *cp;
-
- ip++;
-
- cp = ip + strcspn (ip, stop_set);
-
- if (cp > ip)
- {
- struct passwd *pwd;
- char username[9];
-
- strncpy (username, ip, cp - ip + 1);
- username[8] = 0;
- pwd = getpwnam (username);
-
- if (!pwd || !pwd->pw_dir)
- ds_putc (&output, *ip++);
- else
- ds_puts (&output, pwd->pw_dir);
- }
- else
- {
- const char *home = fn_getenv ("HOME");
- if (!home)
- ds_putc (&output, *ip++);
- else
- ds_puts (&output, home);
- }
-
- ip = cp;
- }
-
+ struct string output = DS_INITIALIZER;
+ if (input[0] == '~')
+ {
+ const char *home = NULL;
+ const char *remainder = NULL;
+ if (input[1] == '/' || input[1] == '\0')
+ {
+ home = fn_getenv ("HOME");
+ remainder = input + 1;
+ }
+ else
+ {
+ struct string user_name = DS_INITIALIZER;
+ struct passwd *pwd;
+
+ ds_assign_buffer (&user_name, input + 1, strcspn (input + 1, "/"));
+ pwd = getpwnam (ds_c_str (&user_name));
+ if (pwd != NULL && pwd->pw_dir[0] != '\0')
+ {
+ home = pwd->pw_dir;
+ remainder = input + 1 + ds_length (&user_name);
+ }
+ ds_destroy (&user_name);
+ }
+
+ if (home != NULL)
+ {
+ ds_puts (&output, home);
+ if (*remainder != '\0')
+ ds_puts (&output, remainder);
+ }
+ }
+ if (ds_is_empty (&output))
+ ds_puts (&output, input);
return ds_c_str (&output);
}
#else /* !unix */
Returns the malloc'd full name of the first file found, or NULL if
none is found.
- If PREPEND is non-NULL, then it is prepended to each filename;
- i.e., it looks like PREPEND/PATH_COMPONENT/NAME. This is not done
+ If PREFIX is non-NULL, then it is prefixed to each filename;
+ i.e., it looks like PREFIX/PATH_COMPONENT/NAME. This is not done
with absolute directories in the path. */
-#if defined (unix) || defined (__MSDOS__) || defined (__WIN32__)
char *
-fn_search_path (const char *basename, const char *path, const char *prepend)
+fn_search_path (const char *base_name, const char *path_, const char *prefix)
{
- char *subst_path;
- struct string filename;
- const char *bp;
+ struct string path;
+ struct string dir = DS_INITIALIZER;
+ struct string file = DS_INITIALIZER;
+ size_t save_idx = 0;
- if (fn_absolute_p (basename))
- return fn_tilde_expand (basename);
-
- {
- char *temp = fn_interp_vars (path, fn_getenv);
- bp = subst_path = fn_tilde_expand (temp);
- free (temp);
- }
+ if (fn_is_absolute (base_name))
+ return fn_tilde_expand (base_name);
- msg (VM (4), _("Searching for `%s'..."), basename);
- ds_init (&filename, 64);
+ /* Interpolate environment variables. */
+ ds_create (&path, path_);
+ fn_interp_vars (&path, fn_getenv);
- for (;;)
+ verbose_msg (2, _("searching for \"%s\" in path \"%s\""),
+ base_name, ds_c_str (&path));
+ while (ds_separate (&path, &dir, PATH_DELIMITER_STRING, &save_idx))
{
- const char *ep;
- if (0 == *bp)
- {
- msg (VM (4), _("Search unsuccessful!"));
- ds_destroy (&filename);
- free (subst_path);
- return NULL;
- }
-
- for (ep = bp; *ep && *ep != PATH_DELIMITER; ep++)
- ;
-
- /* Paste together PREPEND/PATH/BASENAME. */
- ds_clear (&filename);
- if (prepend && !fn_absolute_p (bp))
+ /* Do tilde expansion. */
+ if (ds_first (&dir) == '~')
+ {
+ char *tmp_str = fn_tilde_expand (ds_c_str (&dir));
+ ds_assign_c_str (&dir, tmp_str);
+ free (tmp_str);
+ }
+
+ /* Construct file name. */
+ ds_clear (&file);
+ if (prefix != NULL && !fn_is_absolute (ds_c_str (&dir)))
{
- ds_puts (&filename, prepend);
- ds_putc (&filename, DIR_SEPARATOR);
- }
- ds_concat (&filename, bp, ep - bp);
- if (ep - bp
- && ds_c_str (&filename)[ds_length (&filename) - 1] != DIR_SEPARATOR)
- ds_putc (&filename, DIR_SEPARATOR);
- ds_puts (&filename, basename);
-
- msg (VM (5), " - %s", ds_c_str (&filename));
- if (fn_exists_p (ds_c_str (&filename)))
- {
- msg (VM (4), _("Found `%s'."), ds_c_str (&filename));
- free (subst_path);
- return ds_c_str (&filename);
+ ds_puts (&file, prefix);
+ ds_putc (&file, DIR_SEPARATOR);
}
+ ds_puts (&file, ds_c_str (&dir));
+ if (ds_length (&dir) && ds_last (&file) != DIR_SEPARATOR)
+ ds_putc (&file, DIR_SEPARATOR);
+ ds_puts (&file, base_name);
- if (0 == *ep)
+ /* Check whether file exists. */
+ if (fn_exists (ds_c_str (&file)))
{
- msg (VM (4), _("Search unsuccessful!"));
- free (subst_path);
- ds_destroy (&filename);
- return NULL;
+ verbose_msg (2, _("...found \"%s\""), ds_c_str (&file));
+ ds_destroy (&path);
+ ds_destroy (&dir);
+ return ds_c_str (&file);
}
- bp = ep + 1;
- }
-}
-#else /* not unix, msdog, lose32 */
-char *
-fn_search_path (const char *basename, const char *path, const char *prepend)
-{
- size_t size = strlen (path) + 1 + strlen (basename) + 1;
- char *string;
- char *cp;
-
- if (prepend)
- size += strlen (prepend) + 1;
- string = xmalloc (size);
-
- cp = string;
- if (prepend)
- {
- cp = stpcpy (cp, prepend);
- *cp++ = DIR_SEPARATOR;
}
- cp = stpcpy (cp, path);
- *cp++ = DIR_SEPARATOR;
- strcpy (cp, basename);
-
- return string;
-}
-#endif /* not unix, msdog, lose32 */
-
-/* Prepends directory DIR to filename FILE and returns a malloc()'d
- copy of it. */
-char *
-fn_prepend_dir (const char *file, const char *dir)
-{
- char *temp;
- char *cp;
-
- if (fn_absolute_p (file))
- return xstrdup (file);
- temp = xmalloc (strlen (file) + 1 + strlen (dir) + 1);
- cp = stpcpy (temp, dir);
- if (cp != temp && cp[-1] != DIR_SEPARATOR)
- *cp++ = DIR_SEPARATOR;
- cp = stpcpy (cp, file);
-
- return temp;
+ /* Failure. */
+ verbose_msg (2, _("...not found"));
+ ds_destroy (&path);
+ ds_destroy (&dir);
+ ds_destroy (&file);
+ return NULL;
}
/* fn_normalize(): This very OS-dependent routine canonicalizes
char *fn1, *fn2, *dest;
int maxlen;
- if (fn_special_p (filename))
+ if (fn_is_special (filename))
return xstrdup (filename);
fn1 = fn_tilde_expand (filename);
/* Returns the directory part of FILENAME, as a malloc()'d
string. */
char *
-fn_dirname (const char *filename)
+fn_dir_name (const char *filename)
{
const char *p;
char *s;
return s;
}
-/* Returns the basename part of FILENAME as a malloc()'d string. */
-#if 0
-char *
-fn_basename (const char *filename)
-{
- /* Not used, not implemented. */
- abort ();
-}
-#endif
-
/* Returns the extension part of FILENAME as a malloc()'d string.
If FILENAME does not have an extension, returns an empty
string. */
int size = 2;
char *buffer = xmalloc (size);
if ( buffer)
- {
- buffer[0]='.';
- buffer[1]='\0';
- }
+ {
+ buffer[0]='.';
+ buffer[1]='\0';
+ }
return buffer;
/* Returns nonzero iff NAME specifies an absolute filename. */
int
-fn_absolute_p (const char *name)
+fn_is_absolute (const char *name)
{
#ifdef unix
if (name[0] == '/'
/* Returns 1 if the filename specified is a virtual file that doesn't
really exist on disk, 0 if it's a real filename. */
int
-fn_special_p (const char *filename)
+fn_is_special (const char *filename)
{
if (!strcmp (filename, "-") || !strcmp (filename, "stdin")
|| !strcmp (filename, "stdout") || !strcmp (filename, "stderr")
/* Returns nonzero if file with name NAME exists. */
int
-fn_exists_p (const char *name)
+fn_exists (const char *name)
{
#ifdef unix
struct stat temp;
else
return fclose (f);
}
-\f
-/* More extensive file handling. */
-
-/* File open routine that extends fn_open(). Opens or reopens a
- file according to the contents of file_ext F. Returns nonzero on
- success. If 0 is returned, errno is set to a sensible value. */
-int
-fn_open_ext (struct file_ext *f)
-{
- char *p;
-
- p = strstr (f->filename, "%d");
- if (p)
- {
- char *s = local_alloc (strlen (f->filename)
- + INT_STRLEN_BOUND (int) - 1);
- char *cp;
-
- memcpy (s, f->filename, p - f->filename);
- cp = spprintf (&s[p - f->filename], "%d", *f->sequence_no);
- strcpy (cp, &p[2]);
-
- if (f->file)
- {
- int error = 0;
-
- if (f->preclose)
- if (f->preclose (f) == 0)
- error = errno;
-
- if (EOF == fn_close (f->filename, f->file) || error)
- {
- f->file = NULL;
- local_free (s);
-
- if (error)
- errno = error;
-
- return 0;
- }
-
- f->file = NULL;
- }
-
- f->file = fn_open (s, f->mode);
- local_free (s);
-
- if (f->file && f->postopen)
- if (f->postopen (f) == 0)
- {
- int error = errno;
- fn_close (f->filename, f->file);
- errno = error;
-
- return 0;
- }
-
- return (f->file != NULL);
- }
- else if (f->file)
- return 1;
- else
- {
- f->file = fn_open (f->filename, f->mode);
-
- if (f->file && f->postopen)
- if (f->postopen (f) == 0)
- {
- int error = errno;
- fn_close (f->filename, f->file);
- errno = error;
-
- return 0;
- }
-
- return (f->file != NULL);
- }
-}
-
-/* Properly closes the file associated with file_ext F, if any.
- Return nonzero on success. If zero is returned, errno is set to a
- sensible value. */
-int
-fn_close_ext (struct file_ext *f)
-{
- if (f->file)
- {
- int error = 0;
-
- if (f->preclose)
- if (f->preclose (f) == 0)
- error = errno;
-
- if (EOF == fn_close (f->filename, f->file) || error)
- {
- f->file = NULL;
-
- if (error)
- errno = error;
-
- return 0;
- }
-
- f->file = NULL;
- }
- return 1;
-}
#ifdef unix
/* A file's identity. */
struct file_identity
- {
- dev_t device; /* Device number. */
- ino_t inode; /* Inode number. */
- };
+{
+ dev_t device; /* Device number. */
+ ino_t inode; /* Inode number. */
+};
/* Returns a pointer to a dynamically allocated structure whose
value can be used to tell whether two files are actually the
#else /* not unix */
/* A file's identity. */
struct file_identity
- {
- char *normalized_filename; /* File's normalized name. */
- };
+{
+ char *normalized_filename; /* File's normalized name. */
+};
/* Returns a pointer to a dynamically allocated structure whose
value can be used to tell whether two files are actually the