X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Ffile-name.c;h=57dfe08d0bc3f17d1fce15e5e03a7f47aa856df9;hb=cf63d499efd5e6ca3a7dcc6386b3b87bd31bfda9;hp=dd512c033680fa03c7e612b1e33a84642753f6ea;hpb=3f2ed1c5fe6dc692ca00bb18a15e41617fa2d37d;p=pspp-builds.git diff --git a/src/data/file-name.c b/src/data/file-name.c index dd512c03..57dfe08d 100644 --- a/src/data/file-name.c +++ b/src/data/file-name.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. - Written by Ben Pfaff . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -18,19 +17,25 @@ 02110-1301, USA. */ #include -#include + #include "file-name.h" -#include -#include + #include #include -#include +#include +#include + #include "intprops.h" +#include "minmax.h" +#include "settings.h" +#include "xreadlink.h" + +#include +#include #include #include -#include "settings.h" +#include #include -#include "xreadlink.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -68,90 +73,49 @@ fn_init (void) /* Functions for performing operations on file names. */ -/* 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 $. -*/ +/* Substitutes $variables in SRC, putting the result in DST, + properly handling the case where SRC is a substring of DST. + Variables are as defined by GETENV. Supports $var and ${var} + syntaxes; $$ substitutes as $. */ void -fn_interp_vars (struct string *target, - const char *(*getenv) (const char *)) +fn_interp_vars (struct substring src, const char *(*getenv) (const char *), + struct string *dst_) { - char *input ; - char *s ; - - assert (target); - - input = xmalloc(ds_length(target) + 1); - s = input; - - strcpy(input, ds_c_str(target)); - - if (NULL == strchr (ds_c_str(target), '$')) - goto done; - - ds_clear(target); - - for (;;) - { - switch (*s) - { - case '\0': - goto done ; - - 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 (target) + start); - ds_truncate (target, start); - ds_puts (target, value); - - if (stop && *s == stop) - s++; - } - break; - - default: - ds_putc (target, *s++); - } - } - - done: - free(input); - return; + struct string dst = DS_EMPTY_INITIALIZER; + int c; + + while ((c = ss_get_char (&src)) != EOF) + if (c != '$') + ds_put_char (&dst, c); + else + { + if (ss_match_char (&src, '$') || ss_is_empty (src)) + ds_put_char (&dst, '$'); + else + { + struct substring var_name; + size_t start; + const char *value; + + if (ss_match_char (&src, '(')) + ss_get_until (&src, ')', &var_name); + else if (ss_match_char (&src, '{')) + ss_get_until (&src, '}', &var_name); + else + ss_get_chars (&src, MIN (1, ss_span (src, ss_cstr (CC_ALNUM))), + &var_name); + + start = ds_length (&dst); + ds_put_substring (&dst, var_name); + value = getenv (ds_cstr (&dst) + start); + ds_truncate (&dst, start); + + ds_put_cstr (&dst, value); + } + } + + ds_swap (&dst, dst_); + ds_destroy (&dst); } #ifdef unix @@ -160,7 +124,7 @@ fn_interp_vars (struct string *target, char * fn_tilde_expand (const char *input) { - struct string output = DS_INITIALIZER; + struct string output = DS_EMPTY_INITIALIZER; if (input[0] == '~') { const char *home = NULL; @@ -172,14 +136,16 @@ fn_tilde_expand (const char *input) } else { - struct string user_name = DS_INITIALIZER; + struct string user_name = DS_EMPTY_INITIALIZER; struct passwd *pwd; - ds_assign_buffer (&user_name, input + 1, strcspn (input + 1, "/")); - pwd = getpwnam (ds_c_str (&user_name)); + ds_assign_substring (&user_name, + ss_buffer (input + 1, + strcspn (input + 1, "/"))); + pwd = getpwnam (ds_cstr (&user_name)); if (pwd != NULL && pwd->pw_dir[0] != '\0') { - home = pwd->pw_dir; + home = xstrdup (pwd->pw_dir); remainder = input + 1 + ds_length (&user_name); } ds_destroy (&user_name); @@ -187,14 +153,14 @@ fn_tilde_expand (const char *input) if (home != NULL) { - ds_puts (&output, home); + ds_put_cstr (&output, home); if (*remainder != '\0') - ds_puts (&output, remainder); + ds_put_cstr (&output, remainder); } } if (ds_is_empty (&output)) - ds_puts (&output, input); - return ds_c_str (&output); + ds_put_cstr (&output, input); + return ds_cstr (&output); } #else /* !unix */ char * @@ -208,64 +174,57 @@ fn_tilde_expand (const char *input) given by PATH, which is tilde- and environment-interpolated. Directories in PATH are delimited by ':'. Returns the malloc'd full name of the first file found, or NULL if none is - found. - - If PREFIX is non-NULL, then it is prefixed to each file name; - i.e., it looks like PREFIX/PATH_COMPONENT/NAME. This is not - done with absolute directories in the path. */ + found. */ char * -fn_search_path (const char *base_name, const char *path_, const char *prefix) +fn_search_path (const char *base_name, const char *path_) { struct string path; - struct string dir = DS_INITIALIZER; - struct string file = DS_INITIALIZER; + struct substring dir_; + struct string file = DS_EMPTY_INITIALIZER; size_t save_idx = 0; if (fn_is_absolute (base_name)) return fn_tilde_expand (base_name); /* Interpolate environment variables. */ - ds_create (&path, path_); - fn_interp_vars (&path, fn_getenv); + ds_init_cstr (&path, path_); + fn_interp_vars (ds_ss (&path), fn_getenv, &path); verbose_msg (2, _("searching for \"%s\" in path \"%s\""), - base_name, ds_c_str (&path)); - while (ds_separate (&path, &dir, ":", &save_idx)) + base_name, ds_cstr (&path)); + while (ds_separate (&path, ss_cstr (":"), &save_idx, &dir_)) { + struct string dir; + /* Do tilde expansion. */ + ds_init_substring (&dir, dir_); if (ds_first (&dir) == '~') { - char *tmp_str = fn_tilde_expand (ds_c_str (&dir)); - ds_assign_c_str (&dir, tmp_str); + char *tmp_str = fn_tilde_expand (ds_cstr (&dir)); + ds_assign_cstr (&dir, tmp_str); free (tmp_str); } /* Construct file name. */ ds_clear (&file); - if (prefix != NULL && !fn_is_absolute (ds_c_str (&dir))) - { - ds_puts (&file, prefix); - ds_putc (&file, '/'); - } - ds_puts (&file, ds_c_str (&dir)); - if (ds_length (&dir) && ds_last (&file) != '/') - ds_putc (&file, '/'); - ds_puts (&file, base_name); + ds_put_cstr (&file, ds_cstr (&dir)); + if (!ds_is_empty (&file) && ds_last (&file) != '/') + ds_put_char (&file, '/'); + ds_put_cstr (&file, base_name); + ds_destroy (&dir); /* Check whether file exists. */ - if (fn_exists (ds_c_str (&file))) + if (fn_exists (ds_cstr (&file))) { - verbose_msg (2, _("...found \"%s\""), ds_c_str (&file)); + verbose_msg (2, _("...found \"%s\""), ds_cstr (&file)); ds_destroy (&path); - ds_destroy (&dir); - return ds_c_str (&file); + return ds_cstr (&file); } } /* Failure. */ verbose_msg (2, _("...not found")); ds_destroy (&path); - ds_destroy (&dir); ds_destroy (&file); return NULL; } @@ -524,8 +483,8 @@ fn_get_cwd (void) /* Find out information about files. */ -/* Returns nonzero iff NAME specifies an absolute file name. */ -int +/* Returns true iff NAME specifies an absolute file name. */ +bool fn_is_absolute (const char *name) { #ifdef unix @@ -533,21 +492,21 @@ fn_is_absolute (const char *name) || !strncmp (name, "./", 2) || !strncmp (name, "../", 3) || name[0] == '~') - return 1; + return true; #elif defined (__MSDOS__) if (name[0] == '\\' || !strncmp (name, ".\\", 2) || !strncmp (name, "..\\", 3) || (name[0] && name[1] == ':')) - return 1; + return true; #endif - return 0; + return false; } -/* Returns 1 if FILE_NAME is a virtual file that doesn't - really exist on disk, 0 if it's a real file name. */ -int +/* Returns true if FILE_NAME is a virtual file that doesn't + really exist on disk, false if it's a real file name. */ +bool fn_is_special (const char *file_name) { if (!strcmp (file_name, "-") || !strcmp (file_name, "stdin") @@ -557,13 +516,13 @@ fn_is_special (const char *file_name) || (*file_name && file_name[strlen (file_name) - 1] == '|') #endif ) - return 1; + return true; - return 0; + return false; } -/* Returns nonzero if file with name NAME exists. */ -int +/* Returns true if file with name NAME exists. */ +bool fn_exists (const char *name) { #ifdef unix @@ -573,9 +532,9 @@ fn_exists (const char *name) #else FILE *f = fopen (name, "r"); if (!f) - return 0; + return false; fclose (f); - return 1; + return true; #endif }