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