fix bug where environment was wrongly dropped, loosing type variable information
[hiphop-php.git] / hphp / neo / neo_err.c
blob26d00825cf5d303397fe6ec0501c92930b658764
1 /*
2 * Copyright 2001-2004 Brandon Long
3 * All Rights Reserved.
5 * ClearSilver Templating System
7 * This code is made available under the terms of the ClearSilver License.
8 * http://www.clearsilver.net/license.hdf
12 #include "cs_config.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <errno.h>
18 #include <string.h>
20 #include "neo_misc.h"
21 #include "neo_err.h"
22 #include "ulist.h"
23 #include "ulocks.h"
25 int NERR_PASS = -1;
26 int NERR_ASSERT = 0;
27 int NERR_NOT_FOUND = 0;
28 int NERR_DUPLICATE = 0;
29 int NERR_NOMEM = 0;
30 int NERR_PARSE = 0;
31 int NERR_OUTOFRANGE = 0;
32 int NERR_SYSTEM = 0;
33 int NERR_IO = 0;
34 int NERR_LOCK = 0;
35 int NERR_DB = 0;
36 int NERR_EXISTS = 0;
37 int NERR_MAX_RECURSION = 0;
39 static ULIST *Errors = NULL;
40 static int Inited = 0;
41 #ifdef HAVE_PTHREADS
42 /* In multi-threaded environments, we have to init thread safely */
43 static pthread_mutex_t InitLock = PTHREAD_MUTEX_INITIALIZER;
44 #endif
47 static NEOERR *_err_alloc(void)
49 NEOERR *err = (NEOERR *)calloc (1, sizeof (NEOERR));
50 if (err == NULL)
52 ne_warn ("INTERNAL ERROR: Unable to allocate memory for NEOERR");
53 return INTERNAL_ERR;
55 return err;
58 NEOERR *nerr_raisef (const char *func, const char *file, int lineno, int error,
59 const char *fmt, ...)
61 NEOERR *err;
62 va_list ap;
64 err = _err_alloc();
65 if (err == INTERNAL_ERR)
66 return err;
68 va_start(ap, fmt);
69 vsnprintf (err->desc, sizeof(err->desc), fmt, ap);
70 va_end(ap);
72 err->error = error;
73 err->func = func;
74 err->file = file;
75 err->lineno = lineno;
77 return err;
80 NEOERR *nerr_raise_errnof (const char *func, const char *file, int lineno,
81 int error, const char *fmt, ...)
83 NEOERR *err;
84 va_list ap;
85 int l;
87 err = _err_alloc();
88 if (err == INTERNAL_ERR)
89 return err;
91 va_start(ap, fmt);
92 vsnprintf (err->desc, sizeof(err->desc), fmt, ap);
93 va_end(ap);
95 l = strlen(err->desc);
96 snprintf (err->desc + l, sizeof(err->desc)-l, ": [%d] %s", errno,
97 strerror (errno));
99 err->error = error;
100 err->func = func;
101 err->file = file;
102 err->lineno = lineno;
104 return err;
107 NEOERR *nerr_passf (const char *func, const char *file, int lineno, NEOERR *err)
109 NEOERR *nerr;
111 if (err == STATUS_OK)
112 return err;
114 nerr = _err_alloc();
115 if (nerr == INTERNAL_ERR)
116 return err;
118 nerr->error = NERR_PASS;
119 nerr->func = func;
120 nerr->file = file;
121 nerr->lineno = lineno;
122 nerr->next = err;
124 return nerr;
127 NEOERR *nerr_pass_ctxf (const char *func, const char *file, int lineno,
128 NEOERR *err, const char *fmt, ...)
130 NEOERR *nerr;
131 va_list ap;
133 if (err == STATUS_OK)
134 return err;
136 nerr = _err_alloc();
137 if (nerr == INTERNAL_ERR)
138 return err;
140 va_start(ap, fmt);
141 vsnprintf (nerr->desc, sizeof(nerr->desc), fmt, ap);
142 va_end(ap);
144 nerr->error = NERR_PASS;
145 nerr->func = func;
146 nerr->file = file;
147 nerr->lineno = lineno;
148 nerr->next = err;
150 return nerr;
153 /* In the future, we'll allow someone to register an error handler */
154 void nerr_log_error (NEOERR *err)
156 NEOERR *more;
157 char buf[1024];
158 char *err_name;
160 if (err == STATUS_OK)
161 return;
163 if (err == INTERNAL_ERR)
165 ne_warn ("Internal error");
166 return;
169 more = err;
170 fprintf (stderr, "Traceback (innermost last):\n");
171 while (more && more != INTERNAL_ERR)
173 err = more;
174 more = err->next;
175 if (err->error != NERR_PASS)
177 NEOERR *r;
178 if (err->error == 0)
180 err_name = buf;
181 snprintf (buf, sizeof (buf), "Unknown Error");
183 else
185 r = uListGet (Errors, err->error - 1, (void **)&err_name);
186 if (r != STATUS_OK)
188 err_name = buf;
189 snprintf (buf, sizeof (buf), "Error %d", err->error);
193 fprintf (stderr, " File \"%s\", line %d, in %s()\n%s: %s\n", err->file,
194 err->lineno, err->func, err_name, err->desc);
196 else
198 fprintf (stderr, " File \"%s\", line %d, in %s()\n", err->file,
199 err->lineno, err->func);
200 if (err->desc[0])
202 fprintf (stderr, " %s\n", err->desc);
208 void nerr_error_string (NEOERR *err, NEOSTRING *str)
210 NEOERR *more;
211 char buf[1024];
212 char *err_name;
214 if (err == STATUS_OK)
215 return;
217 if (err == INTERNAL_ERR)
219 string_append (str, "Internal error");
220 return;
223 more = err;
224 while (more && more != INTERNAL_ERR)
226 err = more;
227 more = err->next;
228 if (err->error != NERR_PASS)
230 NEOERR *r;
231 if (err->error == 0)
233 err_name = buf;
234 snprintf (buf, sizeof (buf), "Unknown Error");
236 else
238 r = uListGet (Errors, err->error - 1, (void **)&err_name);
239 if (r != STATUS_OK)
241 err_name = buf;
242 snprintf (buf, sizeof (buf), "Error %d", err->error);
246 string_appendf(str, "%s: %s", err_name, err->desc);
247 return;
252 NEOERR *nerr_register (int *val, const char *name)
254 NEOERR *err;
256 err = uListAppend (Errors, (void *) name);
257 if (err != STATUS_OK) return nerr_pass(err);
259 *val = uListLength(Errors);
260 return STATUS_OK;
263 NEOERR *nerr_init (void)
265 NEOERR *err;
267 if (Inited == 0)
269 #ifdef HAVE_PTHREADS
270 /* In threaded environments, we have to mutex lock to do this init, but
271 * we don't want to use a mutex every time to check that it was Inited.
272 * So, we only lock if our first test of Inited was false */
273 err = mLock(&InitLock);
274 if (err != STATUS_OK) return nerr_pass(err);
275 if (Inited == 0) {
276 #endif
277 err = uListInit (&Errors, 10, 0);
278 if (err != STATUS_OK) return nerr_pass(err);
280 err = nerr_register (&NERR_PASS, "InternalPass");
281 if (err != STATUS_OK) return nerr_pass(err);
282 err = nerr_register (&NERR_ASSERT, "AssertError");
283 if (err != STATUS_OK) return nerr_pass(err);
284 err = nerr_register (&NERR_NOT_FOUND, "NotFoundError");
285 if (err != STATUS_OK) return nerr_pass(err);
286 err = nerr_register (&NERR_DUPLICATE, "DuplicateError");
287 if (err != STATUS_OK) return nerr_pass(err);
288 err = nerr_register (&NERR_NOMEM, "MemoryError");
289 if (err != STATUS_OK) return nerr_pass(err);
290 err = nerr_register (&NERR_PARSE, "ParseError");
291 if (err != STATUS_OK) return nerr_pass(err);
292 err = nerr_register (&NERR_OUTOFRANGE, "RangeError");
293 if (err != STATUS_OK) return nerr_pass(err);
294 err = nerr_register (&NERR_SYSTEM, "SystemError");
295 if (err != STATUS_OK) return nerr_pass(err);
296 err = nerr_register (&NERR_IO, "IOError");
297 if (err != STATUS_OK) return nerr_pass(err);
298 err = nerr_register (&NERR_LOCK, "LockError");
299 if (err != STATUS_OK) return nerr_pass(err);
300 err = nerr_register (&NERR_DB, "DBError");
301 if (err != STATUS_OK) return nerr_pass(err);
302 err = nerr_register (&NERR_EXISTS, "ExistsError");
303 if (err != STATUS_OK) return nerr_pass(err);
304 err = nerr_register (&NERR_MAX_RECURSION, "MaxRecursionError");
305 if (err != STATUS_OK) return nerr_pass(err);
307 Inited = 1;
308 #ifdef HAVE_PTHREADS
310 err = mUnlock(&InitLock);
311 if (err != STATUS_OK) return nerr_pass(err);
312 #endif
314 return STATUS_OK;