jcs ratpoison hax
1/* Ratpoison.
2 * Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca>
3 *
4 * This file is part of ratpoison.
5 *
6 * ratpoison is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * ratpoison is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this software; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307 USA
20 */
21
22#include "ratpoison.h"
23
24#include <ctype.h>
25
26void
27fatal (const char *msg)
28{
29 fprintf (stderr, "ratpoison: %s", msg);
30 abort ();
31}
32
33void *
34xmalloc (size_t size)
35{
36 void *value;
37
38 value = malloc (size);
39 if (value == NULL)
40 fatal ("Virtual memory exhausted");
41 return value;
42}
43
44void *
45xrealloc (void *ptr, size_t size)
46{
47 void *value;
48
49 value = realloc (ptr, size);
50 if (value == NULL)
51 fatal ("Virtual memory exhausted");
52 return value;
53}
54
55char *
56xstrdup (const char *s)
57{
58 char *value;
59 value = strdup (s);
60 if (value == NULL)
61 fatal ("Virtual memory exhausted");
62 return value;
63}
64
65/* Return a new string based on fmt. */
66char *
67xvsprintf (char *fmt, va_list ap)
68{
69 int size, nchars;
70 char *buffer;
71 va_list ap_copy;
72
73 /* A reasonable starting value. */
74 size = strlen (fmt) + 1;
75 buffer = xmalloc (size);
76
77 while (1)
78 {
79#if defined(va_copy)
80 va_copy (ap_copy, ap);
81#elif defined(__va_copy)
82 __va_copy (ap_copy, ap);
83#else
84 /* If there is no copy macro then this MAY work. On some systems
85 this could fail because va_list is a pointer so assigning one
86 to the other as below wouldn't make a copy of the data, but
87 just the pointer to the data. */
88 ap_copy = ap;
89#endif
90 nchars = vsnprintf (buffer, size, fmt, ap_copy);
91#if defined(va_copy) || defined(__va_copy)
92 va_end (ap_copy);
93#endif
94
95 if (nchars > -1 && nchars < size)
96 return buffer;
97 else if (nchars > -1)
98 size = nchars + 1;
99 /* c99 says -1 is an error other than truncation,
100 * which thus will not go away with a larger buffer.
101 * To support older system but not making errors fatal
102 * (ratpoison will abort when trying to get too much memory otherwise),
103 * try to increase a bit but not too much: */
104 else if (size < MAX_LEGACY_SNPRINTF_SIZE)
105 size *= 2;
106 else
107 {
108 free(buffer);
109 break;
110 }
111
112 /* Resize the buffer and try again. */
113 buffer = xrealloc (buffer, size);
114 }
115
116 return xstrdup("<FAILURE>");
117}
118
119/* Return a new string based on fmt. */
120char *
121xsprintf (char *fmt, ...)
122{
123 char *buffer;
124 va_list ap;
125
126 va_start (ap, fmt);
127 buffer = xvsprintf (fmt, ap);
128 va_end (ap);
129
130 return buffer;
131}
132
133/* strtok but do it for whitespace and be locale compliant. */
134char *
135strtok_ws (char *s)
136{
137 char *nonws;
138 static char *last = NULL;
139
140 if (s != NULL)
141 last = s;
142 else if (last == NULL)
143 {
144 PRINT_ERROR (("strtok_ws() called but not initalized, this is a *BUG*\n"));
145 abort();
146 }
147
148 /* skip to first non-whitespace char. */
149 while (*last && isspace ((unsigned char)*last))
150 last++;
151
152 /* If we reached the end of the string here then there is no more
153 data. */
154 if (*last == '\0')
155 return NULL;
156
157 /* Now skip to the end of the data. */
158 nonws = last;
159 while (*last && !isspace ((unsigned char)*last))
160 last++;
161 if (*last)
162 {
163 *last = '\0';
164 last++;
165 }
166 return nonws;
167}