concat.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* Concatenate variable number of strings.
  2. Copyright (C) 1991-2022 Free Software Foundation, Inc.
  3. Written by Fred Fish @ Cygnus Support
  4. This file is part of the libiberty library.
  5. Libiberty is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. Libiberty is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with libiberty; see the file COPYING.LIB. If
  15. not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
  16. Boston, MA 02110-1301, USA. */
  17. /*
  18. @deftypefn Extension char* concat (const char *@var{s1}, const char *@var{s2}, @
  19. @dots{}, @code{NULL})
  20. Concatenate zero or more of strings and return the result in freshly
  21. @code{xmalloc}ed memory. The argument list is terminated by the first
  22. @code{NULL} pointer encountered. Pointers to empty strings are ignored.
  23. @end deftypefn
  24. */
  25. #ifdef HAVE_CONFIG_H
  26. #include "config.h"
  27. #endif
  28. #include "ansidecl.h"
  29. #include "libiberty.h"
  30. #include <sys/types.h> /* size_t */
  31. #include <stdarg.h>
  32. # if HAVE_STRING_H
  33. # include <string.h>
  34. # else
  35. # if HAVE_STRINGS_H
  36. # include <strings.h>
  37. # endif
  38. # endif
  39. #if HAVE_STDLIB_H
  40. #include <stdlib.h>
  41. #endif
  42. static inline unsigned long vconcat_length (const char *, va_list);
  43. static inline unsigned long
  44. vconcat_length (const char *first, va_list args)
  45. {
  46. unsigned long length = 0;
  47. const char *arg;
  48. for (arg = first; arg ; arg = va_arg (args, const char *))
  49. length += strlen (arg);
  50. return length;
  51. }
  52. static inline char *
  53. vconcat_copy (char *dst, const char *first, va_list args)
  54. {
  55. char *end = dst;
  56. const char *arg;
  57. for (arg = first; arg ; arg = va_arg (args, const char *))
  58. {
  59. unsigned long length = strlen (arg);
  60. memcpy (end, arg, length);
  61. end += length;
  62. }
  63. *end = '\000';
  64. return dst;
  65. }
  66. /* @undocumented concat_length */
  67. unsigned long
  68. concat_length (const char *first, ...)
  69. {
  70. unsigned long length;
  71. va_list args;
  72. va_start (args, first);
  73. length = vconcat_length (first, args);
  74. va_end (args);
  75. return length;
  76. }
  77. /* @undocumented concat_copy */
  78. char *
  79. concat_copy (char *dst, const char *first, ...)
  80. {
  81. char *save_dst;
  82. va_list args;
  83. va_start (args, first);
  84. vconcat_copy (dst, first, args);
  85. save_dst = dst; /* With K&R C, dst goes out of scope here. */
  86. va_end (args);
  87. return save_dst;
  88. }
  89. #ifdef __cplusplus
  90. extern "C" {
  91. #endif /* __cplusplus */
  92. char *libiberty_concat_ptr;
  93. #ifdef __cplusplus
  94. }
  95. #endif /* __cplusplus */
  96. /* @undocumented concat_copy2 */
  97. char *
  98. concat_copy2 (const char *first, ...)
  99. {
  100. va_list args;
  101. va_start (args, first);
  102. vconcat_copy (libiberty_concat_ptr, first, args);
  103. va_end (args);
  104. return libiberty_concat_ptr;
  105. }
  106. char *
  107. concat (const char *first, ...)
  108. {
  109. char *newstr;
  110. va_list args;
  111. /* First compute the size of the result and get sufficient memory. */
  112. va_start (args, first);
  113. newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
  114. va_end (args);
  115. /* Now copy the individual pieces to the result string. */
  116. va_start (args, first);
  117. vconcat_copy (newstr, first, args);
  118. va_end (args);
  119. return newstr;
  120. }
  121. /*
  122. @deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @
  123. @dots{}, @code{NULL})
  124. Same as @code{concat}, except that if @var{optr} is not @code{NULL} it
  125. is freed after the string is created. This is intended to be useful
  126. when you're extending an existing string or building up a string in a
  127. loop:
  128. @example
  129. str = reconcat (str, "pre-", str, NULL);
  130. @end example
  131. @end deftypefn
  132. */
  133. char *
  134. reconcat (char *optr, const char *first, ...)
  135. {
  136. char *newstr;
  137. va_list args;
  138. /* First compute the size of the result and get sufficient memory. */
  139. va_start (args, first);
  140. newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
  141. va_end (args);
  142. /* Now copy the individual pieces to the result string. */
  143. va_start (args, first);
  144. vconcat_copy (newstr, first, args);
  145. if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C. */
  146. free (optr);
  147. va_end (args);
  148. return newstr;
  149. }
  150. #ifdef MAIN
  151. #define NULLP (char *)0
  152. /* Simple little test driver. */
  153. #include <stdio.h>
  154. int
  155. main (void)
  156. {
  157. printf ("\"\" = \"%s\"\n", concat (NULLP));
  158. printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
  159. printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
  160. printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
  161. printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
  162. printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
  163. printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
  164. return 0;
  165. }
  166. #endif