• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* vasprintf and asprintf with out-of-memory checking.
2   Copyright (C) 1999, 2002-2004, 2006, 2007 Free Software Foundation, Inc.
3
4   This program is free software: you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 3 of the License, or
7   (at your option) any later version.
8
9   This program 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
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17#include <config.h>
18
19/* Specification.  */
20#include "xvasprintf.h"
21
22#include <errno.h>
23#include <limits.h>
24#include <string.h>
25#include <stdio.h>
26
27#include "xalloc.h"
28
29/* Checked size_t computations.  */
30#include "xsize.h"
31
32/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
33#ifndef EOVERFLOW
34# define EOVERFLOW E2BIG
35#endif
36
37static inline char *
38xstrcat (size_t argcount, va_list args)
39{
40  char *result;
41  va_list ap;
42  size_t totalsize;
43  size_t i;
44  char *p;
45
46  /* Determine the total size.  */
47  totalsize = 0;
48  va_copy (ap, args);
49  for (i = argcount; i > 0; i--)
50    {
51      const char *next = va_arg (ap, const char *);
52      totalsize = xsum (totalsize, strlen (next));
53    }
54  va_end (ap);
55
56  /* Test for overflow in the summing pass above or in (totalsize + 1) below.
57     Also, don't return a string longer than INT_MAX, for consistency with
58     vasprintf().  */
59  if (totalsize == SIZE_MAX || totalsize > INT_MAX)
60    {
61      errno = EOVERFLOW;
62      return NULL;
63    }
64
65  /* Allocate and fill the result string.  */
66  result = XNMALLOC (totalsize + 1, char);
67  p = result;
68  for (i = argcount; i > 0; i--)
69    {
70      const char *next = va_arg (args, const char *);
71      size_t len = strlen (next);
72      memcpy (p, next, len);
73      p += len;
74    }
75  *p = '\0';
76
77  return result;
78}
79
80char *
81xvasprintf (const char *format, va_list args)
82{
83  char *result;
84
85  /* Recognize the special case format = "%s...%s".  It is a frequently used
86     idiom for string concatenation and needs to be fast.  We don't want to
87     have a separate function xstrcat() for this purpose.  */
88  {
89    size_t argcount = 0;
90    const char *f;
91
92    for (f = format;;)
93      {
94	if (*f == '\0')
95	  /* Recognized the special case of string concatenation.  */
96	  return xstrcat (argcount, args);
97	if (*f != '%')
98	  break;
99	f++;
100	if (*f != 's')
101	  break;
102	f++;
103	argcount++;
104      }
105  }
106
107  if (vasprintf (&result, format, args) < 0)
108    {
109      if (errno == ENOMEM)
110	xalloc_die ();
111      return NULL;
112    }
113
114  return result;
115}
116