define MAXSTRING and use vsnprintf to preven overflows
[mesa.git] / src / mesa / main / imports.c
1 /* $Id: imports.c,v 1.17 2002/08/01 15:10:23 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * Imports are services which the device driver or window system or
30 * operating system provides to the core renderer. The core renderer (Mesa)
31 * will call these functions in order to do memory allocation, simple I/O,
32 * etc.
33 *
34 * Some drivers will want to override/replace this file with something
35 * specialized, but most Mesa drivers will be able to call
36 *_mesa_init_default_imports() and go with what's here.
37 *
38 * Eventually, I'd like to move most of the stuff in glheader.h and mem.[ch]
39 * into imports.[ch]. Then we'll really have one, single place where
40 * all OS-related dependencies are isolated.
41 */
42
43
44 #include "glheader.h"
45 #include "mtypes.h"
46 #include "context.h"
47 #include "imports.h"
48 #include "mem.h"
49
50 #define MAXSTRING 4000 /* for vsnprintf() */
51
52
53 static void *
54 _mesa_Malloc(__GLcontext *gc, size_t size)
55 {
56 return MALLOC(size);
57 }
58
59 static void *
60 _mesa_Calloc(__GLcontext *gc, size_t numElem, size_t elemSize)
61 {
62 return CALLOC(numElem * elemSize);
63 }
64
65 static void *
66 _mesa_Realloc(__GLcontext *gc, void *oldAddr, size_t newSize)
67 {
68 return realloc(oldAddr, newSize);
69 }
70
71 static void
72 _mesa_Free(__GLcontext *gc, void *addr)
73 {
74 FREE(addr);
75 }
76
77
78 /* Must be before '#undef getenv' for inclusion in XFree86.
79 */
80 static char * CAPI
81 _mesa_getenv(__GLcontext *gc, const char *var)
82 {
83 (void) gc;
84 /* Whacko XFree86 macro:
85 */
86 #ifdef getenv
87 #undef getenv
88 #endif
89 return getenv(var);
90 }
91
92
93 static void
94 warning(__GLcontext *gc, char *str)
95 {
96 GLboolean debug;
97 #ifdef DEBUG
98 debug = GL_TRUE;
99 #else
100 if (_mesa_getenv(gc , "MESA_DEBUG"))
101 debug = GL_TRUE;
102 else
103 debug = GL_FALSE;
104 #endif
105 if (debug) {
106 fprintf(stderr, "Mesa warning: %s\n", str);
107 }
108 }
109
110
111 void
112 _mesa_fatal(__GLcontext *gc, char *str)
113 {
114 (void) gc;
115 fprintf(stderr, "%s\n", str);
116 abort();
117 }
118
119
120 static int CAPI
121 _mesa_atoi(__GLcontext *gc, const char *str)
122 {
123 (void) gc;
124 return atoi(str);
125 }
126
127
128 int CAPI
129 _mesa_sprintf(__GLcontext *gc, char *str, const char *fmt, ...)
130 {
131 int r;
132 va_list args;
133 va_start( args, fmt );
134 r = vsprintf( str, fmt, args );
135 va_end( args );
136 return r;
137 }
138
139
140 static void * CAPI
141 _mesa_fopen(__GLcontext *gc, const char *path, const char *mode)
142 {
143 return fopen(path, mode);
144 }
145
146
147 static int CAPI
148 _mesa_fclose(__GLcontext *gc, void *stream)
149 {
150 return fclose((FILE *) stream);
151 }
152
153
154 static int CAPI
155 _mesa_fprintf(__GLcontext *gc, void *stream, const char *fmt, ...)
156 {
157 int r;
158 va_list args;
159 va_start( args, fmt );
160 r = vfprintf( (FILE *) stream, fmt, args );
161 va_end( args );
162 return r;
163 }
164
165
166 /* XXX this really is driver-specific and can't be here */
167 static __GLdrawablePrivate *
168 _mesa_GetDrawablePrivate(__GLcontext *gc)
169 {
170 return NULL;
171 }
172
173
174
175 void
176 _mesa_warning(__GLcontext *gc, const char *fmtString, ...)
177 {
178 char str[MAXSTRING];
179 va_list args;
180 va_start( args, fmtString );
181 (void) vsnprintf( str, MAXSTRING, fmtString, args );
182 va_end( args );
183 warning(gc, str);
184 }
185
186
187 /*
188 * This function is called when the Mesa user has stumbled into a code
189 * path which may not be implemented fully or correctly.
190 */
191 void
192 _mesa_problem( const GLcontext *ctx, const char *s )
193 {
194 if (ctx) {
195 ctx->imports.fprintf((GLcontext *) ctx, stderr, "Mesa implementation error: %s\n", s);
196 #ifdef XF86DRI
197 ctx->imports.fprintf((GLcontext *) ctx, stderr, "Please report to the DRI bug database at dri.sourceforge.net\n");
198 #else
199 ctx->imports.fprintf((GLcontext *) ctx, stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
200 #endif
201 }
202 else {
203 /* what can we do if we don't have a context???? */
204 fprintf( stderr, "Mesa implementation error: %s\n", s );
205 #ifdef XF86DRI
206 fprintf( stderr, "Please report to the DRI bug database at dri.sourceforge.net\n");
207 #else
208 fprintf( stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
209 #endif
210 }
211 }
212
213
214 /*
215 * If in debug mode, print error message to stdout.
216 * Also, record the error code by calling _mesa_record_error().
217 * Input: ctx - the GL context
218 * error - the error value
219 * fmtString - printf-style format string, followed by optional args
220 */
221 void
222 _mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
223 {
224 const char *debugEnv;
225 GLboolean debug;
226
227 debugEnv = _mesa_getenv(ctx, "MESA_DEBUG");
228
229 #ifdef DEBUG
230 if (debugEnv && strstr(debugEnv, "silent"))
231 debug = GL_FALSE;
232 else
233 debug = GL_TRUE;
234 #else
235 if (debugEnv)
236 debug = GL_TRUE;
237 else
238 debug = GL_FALSE;
239 #endif
240
241 if (debug) {
242 va_list args;
243 char where[MAXSTRING];
244 const char *errstr;
245
246 va_start( args, fmtString );
247 vsnprintf( where, MAXSTRING, fmtString, args );
248 va_end( args );
249
250 switch (error) {
251 case GL_NO_ERROR:
252 errstr = "GL_NO_ERROR";
253 break;
254 case GL_INVALID_VALUE:
255 errstr = "GL_INVALID_VALUE";
256 break;
257 case GL_INVALID_ENUM:
258 errstr = "GL_INVALID_ENUM";
259 break;
260 case GL_INVALID_OPERATION:
261 errstr = "GL_INVALID_OPERATION";
262 break;
263 case GL_STACK_OVERFLOW:
264 errstr = "GL_STACK_OVERFLOW";
265 break;
266 case GL_STACK_UNDERFLOW:
267 errstr = "GL_STACK_UNDERFLOW";
268 break;
269 case GL_OUT_OF_MEMORY:
270 errstr = "GL_OUT_OF_MEMORY";
271 break;
272 case GL_TABLE_TOO_LARGE:
273 errstr = "GL_TABLE_TOO_LARGE";
274 break;
275 default:
276 errstr = "unknown";
277 break;
278 }
279 _mesa_debug(ctx, "Mesa user error: %s in %s\n", errstr, where);
280 }
281
282 _mesa_record_error(ctx, error);
283 }
284
285
286 /*
287 * Call this to report debug information. Uses stderr.
288 */
289 void
290 _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
291 {
292 char s[MAXSTRING];
293 va_list args;
294 va_start(args, fmtString);
295 vsnprintf(s, MAXSTRING, fmtString, args);
296 if (ctx)
297 (void) ctx->imports.fprintf( (__GLcontext *) ctx, stderr, s );
298 else
299 fprintf( stderr, s );
300 va_end(args);
301 }
302
303
304 /*
305 * A wrapper for printf. Uses stdout.
306 */
307 void
308 _mesa_printf( const GLcontext *ctx, const char *fmtString, ... )
309 {
310 char s[MAXSTRING];
311 va_list args;
312 va_start( args, fmtString );
313 vsnprintf(s, MAXSTRING, fmtString, args);
314 if (ctx)
315 (void) ctx->imports.fprintf( (__GLcontext *) ctx, stdout, s );
316 else
317 printf( s );
318 va_end( args );
319 }
320
321
322 /*
323 * Initialize a __GLimports object to point to the functions in
324 * this file. This is to be called from device drivers.
325 * Input: imports - the object to init
326 * driverCtx - pointer to device driver-specific data
327 */
328 void
329 _mesa_init_default_imports(__GLimports *imports, void *driverCtx)
330 {
331 imports->malloc = _mesa_Malloc;
332 imports->calloc = _mesa_Calloc;
333 imports->realloc = _mesa_Realloc;
334 imports->free = _mesa_Free;
335 imports->warning = warning;
336 imports->fatal = _mesa_fatal;
337 imports->getenv = _mesa_getenv;
338 imports->atoi = _mesa_atoi;
339 imports->sprintf = _mesa_sprintf;
340 imports->fopen = _mesa_fopen;
341 imports->fclose = _mesa_fclose;
342 imports->fprintf = _mesa_fprintf;
343 imports->getDrawablePrivate = _mesa_GetDrawablePrivate;
344 imports->other = driverCtx;
345 }