1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11
12 #include <dx/dx.h>
13 #include <fcntl.h>
14 #include "internals.h"
15
16 #if defined(HAVE_UNISTD_H)
17 #include <unistd.h>
18 #endif
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #if defined(HAVE_SYS_ERRNO_H)
25 #include <sys/errno.h>
26 #endif
27
28 #if defined(HAVE_ERRNO_H)
29 #include <errno.h>
30 #endif
31
32 #if defined(HAVE_IO_H)
33 #include <io.h>
34 #endif
35
36 /*
37 * DXMessage system state.
38 */
39
40 static struct state { /* message system state */
41
42 int error_exit; /* 2=exit, 1=print, 0=nothing, on error */
43 int trace; /* enable/disable messages */
44 int enabled[256]; /* enabled debug classes */
45
46 int nmessages; /* number of messages */
47 int alloc; /* allocate size of messages array */
48 char **messages; /* the messages */
49 char *buf; /* the buffer for the messages */
50 int translate; /* use the messages file if available */
51
52 } *state;
53
54
55 Error
_dxf_initmessages(void)56 _dxf_initmessages(void)
57 {
58 char *file, *s, name[100];
59 int fd, mno, size;
60
61 if (state)
62 return OK;
63
64 #if pgcc
65 atexit(DXqflush);
66 #endif
67
68 /* initialize state vector */
69 state = (struct state *) DXAllocateZero(sizeof(struct state));
70 if (!state)
71 return ERROR;
72 state->error_exit = 1;
73 state->trace = 1;
74 state->translate = 1;
75 #ifdef DEBUGGED /* Turn this off for production code, it confuses users */
76 DXEnableDebug("M", 1);
77 #endif
78 if (!_dxf_initmemqueue())
79 return ERROR;
80
81 /* read and parse message file */
82 file = getenv("DXMESSAGES");
83 if (file)
84 sprintf(name, "%s", file);
85 else {
86 char *root = getenv("DXEXECROOT");
87 if (!root) root = getenv("DXROOT");
88 if (!root) root = "/usr/local/dx";
89 sprintf(name, "%s/lib/messages", root);
90 }
91 fd = open(name, O_RDONLY);
92 if (fd<0) {
93 DXWarning("message file %s could not be opened", name);
94 state->translate = 0;
95 return OK;
96 }
97 size = lseek(fd, 0, 2);
98 lseek(fd, 0, 0);
99 state->buf = DXAllocate(size+1);
100 if (!state->buf)
101 return ERROR;
102 if (read(fd, state->buf, size) < size) {
103 DXWarning("message file %s could not be read", name);
104 state->translate = 0;
105 close(fd);
106 return OK;
107 }
108 close(fd);
109 state->buf[size] = '\0';
110 s = state->buf;
111 while (*s!='#' && *s)
112 s++;
113 while (*s) {
114 *s = '\0';
115 s++;
116 mno = atoi(s);
117 if (mno >= state->alloc) {
118 int n = 2*mno + 1;
119 char **m = (char **) DXReAllocate((Pointer)state->messages,
120 n * sizeof(char*));
121 if (!m)
122 return ERROR;
123 state->messages = m;
124 state->alloc = n;
125 }
126 while ('0'<=*s && *s<='9')
127 s++;
128 while (*s==' ' || *s=='\t' || *s=='\n')
129 s++;
130 state->messages[mno] = s;
131 if (mno > state->nmessages)
132 state->nmessages = mno;
133 while (*s!='#' && *s) {
134 if (*s=='\n')
135 *s = ' ';
136 s++;
137 }
138 }
139 return OK;
140 }
141
142 static char *
translate(char * s,int * messfile)143 translate(char *s, int *messfile)
144 {
145 int i;
146 if (!state || !s || *s!='#' || !state->translate) {
147 *messfile = 0;
148 return s;
149 }
150 i = atoi(s+1);
151 if (0<=i && i<=state->nmessages && state->messages[i]) {
152 *messfile = 1;
153 return state->messages[i];
154 } else {
155 *messfile = 0;
156 return s;
157 }
158 }
159
160
161 static void
aqmessage(char * who,char * message,...)162 aqmessage(char *who, char *message, ...)
163 {
164 va_list arg;
165 va_start(arg,message);
166 DXqmessage(who, message, arg);
167 va_end(arg);
168 }
169
170
171
172 /*
173 * Error handling.
174 */
175
176 static ErrorCode _ErrorCode = ERROR_NONE;
177 static char _ErrorMessage[2000] = "";
178
179 void
DXSetErrorExit(int t)180 DXSetErrorExit(int t)
181 {
182 if (!state && !DXinitdx())
183 return;
184 state->error_exit = t;
185 }
186
DXGetErrorExit()187 int DXGetErrorExit()
188 {
189 if(state)
190 return(state->error_exit);
191 else return(0);
192 }
193
194 /* mark the messages which don't come from the messages file, so we
195 * can eventually get them all out of the code. debug version only.
196 */
197 #define TAG "(!file) "
198 #define TAGLEN 8
199
200 Error
DXSetError(ErrorCode code,char * message,...)201 DXSetError(ErrorCode code, char *message, ...)
202 {
203 va_list arg;
204 int usedmessfile;
205 int offset = 0;
206
207 message = translate(message, &usedmessfile);
208
209 /* error code */
210 _ErrorCode = code;
211
212 /* message */
213 #if DEBUGGED
214 if (!usedmessfile) {
215 strcpy(_ErrorMessage, TAG);
216 offset = TAGLEN;
217 }
218 #endif
219 va_start(arg,message);
220 vsprintf(_ErrorMessage+offset, message, arg);
221 va_end(arg);
222
223 /* action */
224 if (!state || state->error_exit == 1)
225 DXPrintError(NULL);
226 else if (state->error_exit >= 2)
227 DXErrorExit(NULL);
228
229 return ERROR;
230 }
231
232
233 Error
DXAddMessage(char * message,...)234 DXAddMessage(char *message, ...)
235 {
236 char buf[2000];
237 va_list arg;
238 int usedmessfile;
239
240 message = translate(message, &usedmessfile);
241
242 /* message */
243 va_start(arg,message);
244 vsprintf(buf, message, arg);
245 va_end(arg);
246 strcat(_ErrorMessage, " / ");
247 strcat(_ErrorMessage, buf);
248
249 /* action */
250 if (!state || state->error_exit)
251 DXMessage(" (%s)", buf);
252
253 return ERROR;
254 }
255
256
257 ErrorCode
DXGetError(void)258 DXGetError(void)
259 {
260 return _ErrorCode;
261 }
262
263
264 char *
DXGetErrorMessage(void)265 DXGetErrorMessage(void)
266 {
267 return _ErrorMessage;
268 }
269
270
271 void
DXResetError(void)272 DXResetError(void)
273 {
274 #if !defined(HAVE__ERRNO)
275 errno = 0;
276 #endif
277 _ErrorCode = ERROR_NONE;
278 _ErrorMessage[0] = 0;
279 }
280
281
282 void
DXPrintError(char * s)283 DXPrintError(char *s)
284 {
285 char *msg, *errnomsg;
286 static int been_here = 0;
287 static char *messages[(int)ERROR_MAX];
288
289 if (!been_here) {
290 messages[(int)ERROR_NONE] = "Error code not set";
291 messages[(int)ERROR_INTERNAL] = "Internal error";
292 messages[(int)ERROR_UNEXPECTED] = "Unexpected error";
293 messages[(int)ERROR_ASSERTION] = "Assertion failed";
294 messages[(int)ERROR_NOT_IMPLEMENTED] = "Operation not implemented";
295 messages[(int)ERROR_NO_MEMORY] = "Out of memory";
296 messages[(int)ERROR_BAD_CLASS] = "Bad class";
297 messages[(int)ERROR_BAD_TYPE] = "Bad type";
298 messages[(int)ERROR_NO_CAMERA] = "No camera";
299 messages[(int)ERROR_MISSING_DATA] = "Missing data";
300 messages[(int)ERROR_DATA_INVALID] = "Invalid data";
301 messages[(int)ERROR_BAD_PARAMETER] = "Bad parameter";
302 been_here = 1;
303 }
304
305 if ((int)_ErrorCode<0
306 || (int)_ErrorCode>=ERROR_MAX
307 || !messages[(int)_ErrorCode])
308 msg = "Bad error code";
309 else
310 msg = messages[(int)_ErrorCode];
311
312 /* print error message */
313 if (_ErrorCode==ERROR_NONE && errno) {
314 errnomsg = (char *) strerror(errno); /* sys_errlist[errno]; */
315 if (s)
316 aqmessage("ERROR", "%s: %s", s, errnomsg);
317 else
318 aqmessage("ERROR", "%s", errnomsg);
319 } else {
320 if (s)
321 aqmessage("ERROR", "%s: %s: %s", s, msg, _ErrorMessage);
322 else
323 aqmessage("ERROR", "%s: %s", msg, _ErrorMessage);
324 }
325 }
326
327 void
DXErrorExit(char * s)328 DXErrorExit(char *s)
329 {
330 DXPrintError(s);
331 exit(DXGetError());
332 }
333
334
335 /*
336 * DXMessage, DXWarning, DXUIMessage
337 */
338 #if 0
339 void
340 _dxfTraceMessage(int t)
341 {
342 if (!state && !DXinitdx())
343 return;
344 state->trace = t;
345 }
346 #endif
347
348 #define LARGE 2000
349 #define SAFE 1000
350 static char long_buf[LARGE];
351 static int long_n = 0;
352 static int long_message = 0;
353
354
355 void
DXBeginLongMessage(void)356 DXBeginLongMessage(void)
357 {
358 long_message = 1;
359 }
360
361
362 void
DXEndLongMessage(void)363 DXEndLongMessage(void)
364 {
365 if (long_n > 0)
366 aqmessage("*", "%s", long_buf);
367 long_n = 0;
368 long_message = 0;
369 }
370
371
372 void
DXMessage(char * message,...)373 DXMessage(char *message, ...)
374 {
375 char *p;
376 va_list arg;
377 int usedmessfile;
378
379 if (state && !state->trace)
380 return;
381 message = translate(message, &usedmessfile);
382
383 if (long_message) {
384 va_start(arg,message);
385 vsprintf(long_buf+long_n, message, arg);
386 va_end(arg);
387 for (p=long_buf+long_n; *p; ) {
388 if (*p=='\n') {
389 *p = '\0';
390 aqmessage("*", "%s", long_buf);
391 strcpy(long_buf, p+1);
392 p = long_buf;
393 }
394 else
395 p++;
396 }
397 long_n = p-long_buf;
398 if (long_n > SAFE) {
399 *p = '\0';
400 aqmessage("*", "%s", long_buf);
401 long_n = 0;
402 }
403 } else {
404 va_start(arg,message);
405 DXqmessage(NULL, message, arg);
406 va_end(arg);
407 }
408 }
409
410
411 void
DXWarning(char * message,...)412 DXWarning(char *message, ...)
413 {
414 va_list arg;
415 int usedmessfile;
416
417 message = translate(message, &usedmessfile);
418 va_start(arg,message);
419 DXqmessage("WARNING", message, arg);
420 va_end(arg);
421 }
422
423
424 void
DXUIMessage(char * who,char * message,...)425 DXUIMessage(char *who, char *message, ...)
426 {
427 va_list arg;
428 int usedmessfile;
429
430 message = translate(message, &usedmessfile);
431 if (state && !state->trace)
432 return;
433 va_start(arg,message);
434 DXqmessage(who, message, arg);
435 va_end(arg);
436 }
437
438
439 void
DXExpandMessage(int enable)440 DXExpandMessage(int enable)
441 {
442 state->translate = enable;
443 }
444
445 /*
446 * DXDebug mechanism
447 */
448
449 void
DXEnableDebug(char * classes,int enable)450 DXEnableDebug(char *classes, int enable)
451 {
452 int i;
453 if (!state && !DXinitdx())
454 return;
455 if (!classes)
456 for (i=0; i<256; i++)
457 state->enabled[i] = enable;
458 else
459 for (i=0; classes[i]; i++)
460 state->enabled[(unsigned char)classes[i]] = enable;
461 }
462
463
464 void
DXDebug(char * classes,char * message,...)465 DXDebug(char *classes, char *message, ...)
466 {
467 int i;
468 int usedmessfile;
469
470 if (!state && !DXinitdx())
471 return;
472 message = translate(message, &usedmessfile);
473 for (i=0; classes[i]; i++) {
474 if (!state || state->enabled[(unsigned char)classes[i]]) {
475 va_list arg;
476 va_start(arg,message);
477 DXqmessage(NULL, message, arg);
478 va_end(arg);
479 return;
480 }
481 }
482 }
483
484 int
DXQueryDebug(char * classes)485 DXQueryDebug(char *classes)
486 {
487 int c, i;
488 if (!state && !DXinitdx())
489 return 0;
490 for (i=0; (c=classes[i])!=0; i++)
491 if (state->enabled[c])
492 return 1;
493 return 0;
494 }
495