| 1 | greg | 2.2 | #ifndef lint | 
| 2 |  |  | static const char RCSid[] = "$Id$"; | 
| 3 |  |  | #endif | 
| 4 | greg | 2.1 | /* | 
| 5 |  |  | *  dmessage.c | 
| 6 |  |  | *  panlib | 
| 7 |  |  | * | 
| 8 |  |  | *  Debug message reporting routines. | 
| 9 |  |  | * | 
| 10 |  |  | *  Created by gward on Thu May 10 2001. | 
| 11 |  |  | *  Copyright (c) 2001 Anyhere Software. All rights reserved. | 
| 12 |  |  | * | 
| 13 |  |  | */ | 
| 14 |  |  |  | 
| 15 |  |  | #include <stdio.h> | 
| 16 |  |  | #include <stdlib.h> | 
| 17 |  |  | #include <string.h> | 
| 18 |  |  | #include <errno.h> | 
| 19 |  |  | #include "dmessage.h" | 
| 20 |  |  |  | 
| 21 |  |  | #define DM_NCLASSES     DMCnerr         /* number of message classes */ | 
| 22 |  |  | #define DM_MOSTFLAGS    (DMFrecord|DMFlog|DMFstderr|DMFalert) | 
| 23 |  |  |  | 
| 24 |  |  | char                    dmessage_buf[DM_BUF_LEN]; | 
| 25 |  |  | const char *            dmessage_class_name[DM_NCLASSES+1] = { | 
| 26 |  |  | "assert", | 
| 27 |  |  | "memory", | 
| 28 |  |  | "system", | 
| 29 |  |  | "parameter", | 
| 30 |  |  | "resource", | 
| 31 |  |  | "data", | 
| 32 |  |  | "input", | 
| 33 |  |  | "warning", | 
| 34 |  |  | "info", | 
| 35 |  |  | "trace", | 
| 36 |  |  | "none" | 
| 37 |  |  | }; | 
| 38 |  |  | int                     dmessage_class_flags[DM_NCLASSES+1] = { | 
| 39 |  |  | DM_MOSTFLAGS|DMFabort, | 
| 40 |  |  | DM_MOSTFLAGS|DMFexit, | 
| 41 |  |  | DM_MOSTFLAGS, | 
| 42 |  |  | DM_MOSTFLAGS, | 
| 43 |  |  | DM_MOSTFLAGS, | 
| 44 |  |  | DM_MOSTFLAGS, | 
| 45 |  |  | DM_MOSTFLAGS, | 
| 46 |  |  | DMFrecord|DMFlog|DMFstderr, | 
| 47 |  |  | DMFrecord|DMFlog, | 
| 48 |  |  | DMFrecord, | 
| 49 |  |  | 0 | 
| 50 |  |  | }; | 
| 51 |  |  | int                     dmessage_class_done[DM_NCLASSES]; | 
| 52 |  |  | const char *            dmessage_file[DM_NCLASSES]; | 
| 53 |  |  | int                     dmessage_line[DM_NCLASSES]; | 
| 54 |  |  | const char *            dmessage_record[DM_NCLASSES+1]; | 
| 55 |  |  | DMsgClass               dmessage_last_class = DMCnerr; | 
| 56 |  |  | FILE *                  dmessage_logfp = NULL; | 
| 57 |  |  | int                     (*dmessage_call)(DMsgClass cls, const char *msg, | 
| 58 |  |  | const char *file, int line) = NULL; | 
| 59 |  |  | int                     (*dmessage_alert)(const char *msg) = NULL; | 
| 60 |  |  | void                    (*dmessage_exit)(int status) = exit; | 
| 61 |  |  | void                    (*dmessage_abort)() = abort; | 
| 62 |  |  |  | 
| 63 |  |  | #define DM_MAX_RECORD   128 | 
| 64 |  |  |  | 
| 65 |  |  | static char             dmessage_mine[DM_NCLASSES][DM_MAX_RECORD]; | 
| 66 |  |  |  | 
| 67 |  |  | /* Report/record message, aborting program if cls is DMCassert */ | 
| 68 |  |  | int | 
| 69 |  |  | dmessage(DMsgClass cls, const char *msg, const char *file, int line) | 
| 70 |  |  | { | 
| 71 |  |  | int             todo; | 
| 72 |  |  | const char      *cp; | 
| 73 |  |  | if ((cls < 0) | (cls >= DMCnerr)) | 
| 74 |  |  | return 0; | 
| 75 |  |  | todo = dmessage_class_flags[cls]; | 
| 76 |  |  | if (msg == NULL || !*msg) | 
| 77 |  |  | msg = "(missing message)"; | 
| 78 |  |  | if (file != NULL && ((cp = strrchr(file, '/')) != NULL || | 
| 79 |  |  | (cp = strrchr(file, '\\')) != NULL)) | 
| 80 |  |  | file = cp+1;                            /* use tail */ | 
| 81 |  |  | dmessage_file[cls] = file;                      /* remember call */ | 
| 82 |  |  | dmessage_line[cls] = line; | 
| 83 |  |  | dmessage_class_done[cls] = todo; | 
| 84 |  |  | if (cls < dmessage_last_class)                  /* mark class */ | 
| 85 |  |  | dmessage_last_class = cls; | 
| 86 |  |  | if (dmessage_call != NULL)                      /* notify callback */ | 
| 87 |  |  | todo &= ~(*dmessage_call)(cls, msg, file, line); | 
| 88 |  |  | if (todo & DMFrecord) {                         /* save message */ | 
| 89 |  |  | if (msg != dmessage_buf && strlen(msg) >= DM_MAX_RECORD) { | 
| 90 |  |  | dmessage_record[cls] = msg; | 
| 91 |  |  | } else { | 
| 92 |  |  | strncpy(dmessage_mine[cls], msg, DM_MAX_RECORD-1); | 
| 93 |  |  | dmessage_record[cls] = dmessage_mine[cls]; | 
| 94 |  |  | } | 
| 95 |  |  | todo &= ~DMFrecord; | 
| 96 |  |  | } | 
| 97 |  |  | if (todo & DMFstderr) {                         /* send to stderr */ | 
| 98 |  |  | if (file != NULL) | 
| 99 |  |  | fprintf(stderr, "%s@%d>%s: %s", file, line, | 
| 100 |  |  | dmessage_class_name[cls], msg); | 
| 101 |  |  | else | 
| 102 |  |  | fprintf(stderr, "%s: %s", | 
| 103 |  |  | dmessage_class_name[cls], msg); | 
| 104 |  |  | if ((cls == DMCsystem) | (cls == DMCresource) && errno) { | 
| 105 |  |  | fputs(": ", stderr); | 
| 106 |  |  | perror(NULL); | 
| 107 |  |  | } else | 
| 108 |  |  | fputc('\n', stderr); | 
| 109 |  |  | if (fflush(stderr) != EOF) { | 
| 110 |  |  | todo &= ~DMFstderr; | 
| 111 |  |  | if (dmessage_logfp == stderr) | 
| 112 |  |  | todo &= ~DMFlog; | 
| 113 |  |  | } | 
| 114 |  |  | } | 
| 115 |  |  | if (todo & DMFlog && dmessage_logfp != NULL) {  /* log to file */ | 
| 116 |  |  | if (file != NULL) | 
| 117 |  |  | fprintf(dmessage_logfp, "%s@%d>%s: %s\n", file, line, | 
| 118 |  |  | dmessage_class_name[cls], msg); | 
| 119 |  |  | else | 
| 120 |  |  | fprintf(dmessage_logfp, "%s: %s\n", | 
| 121 |  |  | dmessage_class_name[cls], msg); | 
| 122 |  |  | if (fflush(dmessage_logfp) != EOF) | 
| 123 |  |  | todo &= ~DMFlog; | 
| 124 |  |  | } | 
| 125 |  |  | if (todo & DMFalert && dmessage_alert != NULL)  /* alert user */ | 
| 126 |  |  | if ((*dmessage_alert)(msg)) | 
| 127 |  |  | todo &= ~DMFalert; | 
| 128 |  |  |  | 
| 129 |  |  | if (todo & DMFabort && dmessage_abort != NULL) {/* abort */ | 
| 130 |  |  | (*dmessage_abort)(); | 
| 131 |  |  | todo &= ~DMFabort; | 
| 132 |  |  | } | 
| 133 |  |  | if (todo & DMFexit && dmessage_exit != NULL) {  /* exit */ | 
| 134 |  |  | (*dmessage_exit)(1); | 
| 135 |  |  | todo &= ~DMFexit; | 
| 136 |  |  | } | 
| 137 |  |  | /* say what was done */ | 
| 138 |  |  | return dmessage_class_done[cls] = (dmessage_class_flags[cls] & ~todo); | 
| 139 |  |  | } |