source: web/old/remctl-2.14/util/concat.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 2.6 KB
Line 
1/*
2 * Concatenate strings with dynamic memory allocation.
3 *
4 * Usage:
5 *
6 *      string = concat(string1, string2, ..., (char *) 0);
7 *      path = concatpath(base, name);
8 *
9 * Dynamically allocates (using xmalloc) sufficient memory to hold all of the
10 * strings given and then concatenates them together into that allocated
11 * memory, returning a pointer to it.  Caller is responsible for freeing.
12 * Assumes xmalloc is available.  The last argument must be a null pointer (to
13 * a char *, if you actually find a platform where it matters).
14 *
15 * concatpath is similar, except that it only takes two arguments.  If the
16 * second argument begins with / or ./, a copy of it is returned; otherwise,
17 * the first argument, a slash, and the second argument are concatenated
18 * together and returned.  This is useful for building file names where names
19 * that aren't fully qualified are qualified with some particular directory.
20 *
21 * Written by Russ Allbery <rra@stanford.edu>
22 * This work is hereby placed in the public domain by its author.
23 */
24
25#include <config.h>
26#include <portable/system.h>
27
28#include <util/util.h>
29
30/* Abbreviation for cleaner code. */
31#define VA_NEXT(var, type)      ((var) = (type) va_arg(args, type))
32
33
34/*
35 * Concatenate all of the arguments into a newly allocated string.  ANSI C
36 * requires at least one named parameter, but it's not treated any different
37 * than the rest.
38 */
39char *
40concat(const char *first, ...)
41{
42    va_list args;
43    char *result, *p;
44    const char *string;
45    size_t length = 0;
46
47    /* Find the total memory required. */
48    va_start(args, first);
49    for (string = first; string != NULL; VA_NEXT(string, const char *))
50        length += strlen(string);
51    va_end(args);
52    length++;
53
54    /*
55     * Create the string.  Doing the copy ourselves avoids useless string
56     * traversals of result, if using strcat, or string, if using strlen to
57     * increment a pointer into result, at the cost of losing the native
58     * optimization of strcat if any.
59     */
60    result = xmalloc(length);
61    p = result;
62    va_start(args, first);
63    for (string = first; string != NULL; VA_NEXT(string, const char *))
64        while (*string != '\0')
65            *p++ = *string++;
66    va_end(args);
67    *p = '\0';
68
69    return result;
70}
71
72
73/*
74 * Concatenate name with base, unless name begins with / or ./.  Return the
75 * new string in newly allocated memory.
76 */
77char *
78concatpath(const char *base, const char *name)
79{
80    if (name[0] == '/' || (name[0] == '.' && name[1] == '/'))
81        return xstrdup(name);
82    else
83        return concat(base != NULL ? base : ".", "/", name, (char *) 0);
84}
Note: See TracBrowser for help on using the repository browser.