X-Git-Url: http://git.tuebingen.mpg.de/?p=adu.git;a=blobdiff_plain;f=string.c;h=e5670f8c66e932f1a617301d0fe6fe7b793fa795;hp=07dd8459cda272666a4714941549d68bec1cc9b9;hb=c77e8ad08e743b3922c58f40cc7b1a063d291d69;hpb=fe0e88be156f2eba1dfd93e9d00f74bfba3a5c1e diff --git a/string.c b/string.c index 07dd845..e5670f8 100644 --- a/string.c +++ b/string.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Andre Noll + * Copyright (C) 2004-2008 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -123,10 +123,28 @@ __must_check __malloc char *adu_strdup(const char *s) */ __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...) { - char *msg; + char *p; + int n; + size_t size = 100; - VSPRINTF(fmt, msg); - return msg; + p = adu_malloc(size); + while (1) { + va_list ap; + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf(p, size, fmt, ap); + va_end(ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + break; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + p = adu_realloc(p, size); + } + return p; } /** @@ -138,7 +156,7 @@ __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...) * Append \p b to \p a. * * \return If \a a is \p NULL, return a pointer to a copy of \a b, i.e. - * para_strcat(NULL, b) is equivalent to para_strdup(b). If \a b is \p NULL, + * adu_strcat(NULL, b) is equivalent to adu_strdup(b). If \a b is \p NULL, * return \a a without making a copy of \a a. Otherwise, construct the * concatenation \a c, free \a a (but not \a b) and return \a c. * @@ -196,20 +214,20 @@ __must_check int atoi64(const char *str, int64_t *result) } /** - * Split string and return pointers to its parts. + * Split a string and return pointers to its parts. * * \param args The string to be split. * \param argv_ptr Pointer to the list of substrings. * \param delim Delimiter. * * This function modifies \a args by replacing each occurance of \a delim by - * zero. A \p NULL-terminated array of pointers to char* is allocated dynamically + * zero. A \p NULL terminated array of pointers to char* is allocated dynamically * and these pointers are initialized to point to the broken-up substrings * within \a args. A pointer to this array is returned via \a argv_ptr. * * \return The number of substrings found in \a args. */ -__must_check unsigned split_args(char *args, char *** const argv_ptr, const char *delim) +unsigned split_args(char *args, char *** const argv_ptr, const char *delim) { char *p = args; char **argv; @@ -245,10 +263,11 @@ __must_check unsigned split_args(char *args, char *** const argv_ptr, const char return n; } -enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2, LSF_QUOTE = 4}; static int get_next_word(const char *line, char **word) { + enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2, + LSF_QUOTE = 4}; const char *in; char *out; int ret, state = 0; @@ -320,6 +339,11 @@ out: return ret; } +/** + * Free an array of words created by create_argv(). + * + * \param argv A pointer previously obtained by \ref create_argv(). + */ void free_argv(char **argv) { int i; @@ -330,6 +354,16 @@ void free_argv(char **argv) } /** + * Split a line into words which are separated by whitespace. + * + * In contrast to gengetopt's string parser, double quotes, backslash-escaped + * characters and special characters like \p \\n are honored. The result + * contains pointers to copies of the words contained in \a line and has to be + * freed by using \ref free_argv(). + * + * \param line The line to be split. + * \param result The array of words is returned here. + * * \return Number of words in \a line, negative on errors. */ int create_argv(const char *line, char ***result) @@ -357,3 +391,35 @@ err: free(argv); return ret; } + +char *absolute_path(const char *path) +{ + char *cwd, *ap; + long int path_max; + + if (!path || !path[0]) + return NULL; + if (path[0] == '/') + return adu_strdup(path); + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + /* + * The result of pathconf(3) may be huge and unsuitable for mallocing + * memory. OTOH pathconf(3) may return -1 to signify that PATH_MAX is + * not bounded. + */ + path_max = pathconf(name, _PC_PATH_MAX); + if (path_max <= 0 || path_max >= 4096) + path_max = 4096; +#endif + cwd = adu_malloc(path_max); + if (!getcwd(cwd, path_max)) { + free(cwd); + return NULL; + } + ap = make_message("%s/%s", cwd, path); + free(cwd); + return ap; +}