1706f2543Smrg/**
2706f2543Smrg * @file
3706f2543Smrg *
4706f2543Smrg * @section DESCRIPTION
5706f2543Smrg *
6706f2543Smrg * These functions provide a portable implementation of the common (but not
7706f2543Smrg * yet universal) asprintf & vasprintf routines to allocate a buffer big
8706f2543Smrg * enough to sprintf the arguments to.  The XNF variants terminate the server
9706f2543Smrg * if the allocation fails.
10706f2543Smrg */
11706f2543Smrg/*
12706f2543Smrg * Copyright (c) 2004 Alexander Gottwald
13706f2543Smrg *
14706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
15706f2543Smrg * copy of this software and associated documentation files (the "Software"),
16706f2543Smrg * to deal in the Software without restriction, including without limitation
17706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
19706f2543Smrg * Software is furnished to do so, subject to the following conditions:
20706f2543Smrg *
21706f2543Smrg * The above copyright notice and this permission notice shall be included in
22706f2543Smrg * all copies or substantial portions of the Software.
23706f2543Smrg *
24706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
28706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30706f2543Smrg * DEALINGS IN THE SOFTWARE.
31706f2543Smrg *
32706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright
33706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale,
34706f2543Smrg * use or other dealings in this Software without prior written authorization.
35706f2543Smrg */
36706f2543Smrg/*
37706f2543Smrg * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
38706f2543Smrg *
39706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
40706f2543Smrg * copy of this software and associated documentation files (the "Software"),
41706f2543Smrg * to deal in the Software without restriction, including without limitation
42706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
43706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
44706f2543Smrg * Software is furnished to do so, subject to the following conditions:
45706f2543Smrg *
46706f2543Smrg * The above copyright notice and this permission notice (including the next
47706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the
48706f2543Smrg * Software.
49706f2543Smrg *
50706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
53706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
55706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56706f2543Smrg * DEALINGS IN THE SOFTWARE.
57706f2543Smrg */
58706f2543Smrg
59706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
60706f2543Smrg#include <dix-config.h>
61706f2543Smrg#endif
62706f2543Smrg
63706f2543Smrg#include <X11/Xos.h>
64706f2543Smrg#include "os.h"
65706f2543Smrg#include <stdarg.h>
66706f2543Smrg#include <stdio.h>
67706f2543Smrg
68706f2543Smrg#ifdef asprintf
69706f2543Smrg# undef asprintf
70706f2543Smrg#endif
71706f2543Smrg#ifdef vasprintf
72706f2543Smrg# undef vasprintf
73706f2543Smrg#endif
74706f2543Smrg
75706f2543Smrg#ifndef va_copy
76706f2543Smrg# ifdef __va_copy
77706f2543Smrg#  define va_copy __va_copy
78706f2543Smrg# else
79706f2543Smrg#  error "no working va_copy was found"
80706f2543Smrg# endif
81706f2543Smrg#endif
82706f2543Smrg
83706f2543Smrg/**
84706f2543Smrg * Varargs sprintf that allocates a string buffer the right size for
85706f2543Smrg * the pattern & data provided and prints the requested data to it.
86706f2543Smrg *
87706f2543Smrg * @param ret     Pointer to which the newly allocated buffer is written
88706f2543Smrg *                (contents undefined on error)
89706f2543Smrg * @param format  printf style format string
90706f2543Smrg * @param va      variable argument list
91706f2543Smrg * @return        size of allocated buffer, or -1 on error.
92706f2543Smrg */
93706f2543Smrgint
94706f2543SmrgXvasprintf(char **ret, const char * _X_RESTRICT_KYWD format, va_list va)
95706f2543Smrg{
96706f2543Smrg#ifdef HAVE_VASPRINTF
97706f2543Smrg    return vasprintf(ret, format, va);
98706f2543Smrg#else
99706f2543Smrg    int size;
100706f2543Smrg    va_list va2;
101706f2543Smrg
102706f2543Smrg    va_copy(va2, va);
103706f2543Smrg    size = vsnprintf(NULL, 0, format, va2);
104706f2543Smrg    va_end(va2);
105706f2543Smrg
106706f2543Smrg    *ret = malloc(size + 1);
107706f2543Smrg    if (*ret == NULL)
108706f2543Smrg        return -1;
109706f2543Smrg
110706f2543Smrg    vsnprintf(*ret, size + 1, format, va);
111706f2543Smrg    (*ret)[size] = 0;
112706f2543Smrg    return size;
113706f2543Smrg#endif
114706f2543Smrg}
115706f2543Smrg
116706f2543Smrg#ifndef HAVE_VASPRINTF
117706f2543Smrg# define vasprintf Xvasprintf
118706f2543Smrg#endif
119706f2543Smrg
120706f2543Smrg/**
121706f2543Smrg * sprintf that allocates a string buffer the right size for
122706f2543Smrg * the pattern & data provided and prints the requested data to it.
123706f2543Smrg *
124706f2543Smrg * @param ret     Pointer to which the newly allocated buffer is written
125706f2543Smrg *                (contents undefined on error)
126706f2543Smrg * @param format  printf style format string
127706f2543Smrg * @param ...     arguments for specified format
128706f2543Smrg * @return        size of allocated buffer, or -1 on error.
129706f2543Smrg */
130706f2543Smrgint
131706f2543SmrgXasprintf(char ** ret, const char * _X_RESTRICT_KYWD format, ...)
132706f2543Smrg{
133706f2543Smrg    int size;
134706f2543Smrg    va_list va;
135706f2543Smrg    va_start(va, format);
136706f2543Smrg    size = vasprintf(ret, format, va);
137706f2543Smrg    va_end(va);
138706f2543Smrg    return size;
139706f2543Smrg}
140706f2543Smrg
141706f2543Smrg/**
142706f2543Smrg * Varargs sprintf that allocates a string buffer the right size for
143706f2543Smrg * the pattern & data provided and prints the requested data to it.
144706f2543Smrg * On failure, issues a FatalError message and aborts the server.
145706f2543Smrg *
146706f2543Smrg * @param ret     Pointer to which the newly allocated buffer is written
147706f2543Smrg *                (contents undefined on error)
148706f2543Smrg * @param format  printf style format string
149706f2543Smrg * @param va      variable argument list
150706f2543Smrg * @return        size of allocated buffer
151706f2543Smrg */
152706f2543Smrgint
153706f2543SmrgXNFvasprintf(char **ret, const char * _X_RESTRICT_KYWD format, va_list va)
154706f2543Smrg{
155706f2543Smrg    int size = vasprintf(ret, format, va);
156706f2543Smrg    if ((size == -1) || (*ret == NULL)) {
157706f2543Smrg	Error("XNFvasprintf");
158706f2543Smrg	FatalError("XNFvasprintf failed");
159706f2543Smrg    }
160706f2543Smrg    return size;
161706f2543Smrg}
162706f2543Smrg
163706f2543Smrg/**
164706f2543Smrg * sprintf that allocates a string buffer the right size for
165706f2543Smrg * the pattern & data provided and prints the requested data to it.
166706f2543Smrg * On failure, issues a FatalError message and aborts the server.
167706f2543Smrg *
168706f2543Smrg * @param ret     Pointer to which the newly allocated buffer is written
169706f2543Smrg *                (contents undefined on error)
170706f2543Smrg * @param format  printf style format string
171706f2543Smrg * @param ...     arguments for specified format
172706f2543Smrg * @return        size of allocated buffer
173706f2543Smrg */
174706f2543Smrgint
175706f2543SmrgXNFasprintf(char ** ret, const char * _X_RESTRICT_KYWD format, ...)
176706f2543Smrg{
177706f2543Smrg    int size;
178706f2543Smrg    va_list va;
179706f2543Smrg    va_start(va, format);
180706f2543Smrg    size = XNFvasprintf(ret, format, va);
181706f2543Smrg    va_end(va);
182706f2543Smrg    return size;
183706f2543Smrg}
184706f2543Smrg
185706f2543Smrg/* Old api, now deprecated, may be removed in the future */
186706f2543Smrgchar *
187706f2543SmrgXvprintf(const char *format, va_list va)
188706f2543Smrg{
189706f2543Smrg    char *ret;
190706f2543Smrg
191706f2543Smrg    if (vasprintf(&ret, format, va) == -1)
192706f2543Smrg	ret = NULL;
193706f2543Smrg
194706f2543Smrg    return ret;
195706f2543Smrg}
196706f2543Smrg
197706f2543Smrgchar *Xprintf(const char *format, ...)
198706f2543Smrg{
199706f2543Smrg    char *ret;
200706f2543Smrg    va_list va;
201706f2543Smrg    va_start(va, format);
202706f2543Smrg    if (vasprintf(&ret, format, va) == -1)
203706f2543Smrg	ret = NULL;
204706f2543Smrg    va_end(va);
205706f2543Smrg    return ret;
206706f2543Smrg}
207706f2543Smrg
208706f2543Smrgchar *
209706f2543SmrgXNFvprintf(const char *format, va_list va)
210706f2543Smrg{
211706f2543Smrg    char *ret;
212706f2543Smrg
213706f2543Smrg    XNFvasprintf(&ret, format, va);
214706f2543Smrg
215706f2543Smrg    return ret;
216706f2543Smrg}
217706f2543Smrg
218706f2543Smrgchar *XNFprintf(const char *format, ...)
219706f2543Smrg{
220706f2543Smrg    char *ret;
221706f2543Smrg    va_list va;
222706f2543Smrg    va_start(va, format);
223706f2543Smrg    XNFvasprintf(&ret, format, va);
224706f2543Smrg    va_end(va);
225706f2543Smrg    return ret;
226706f2543Smrg}
227