source: libcf/trunk/src/cf_debug.c@ 12

Last change on this file since 12 was 12, checked in by cheese, 11 years ago

#1 implement logging module

File size: 4.7 KB
Line 
1/**
2 * cf_debug.c
3 */
4#include "cf_debug.h"
5#include "cf_local.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <ctype.h>
10#include <stdarg.h>
11#include <string.h>
12
13#ifdef _WIN32
14# include <io.h>
15#else
16# include <unistd.h>
17#endif
18
19#define IS_READABLE_CHAR(__c) (' ' <= __c && __c <= '~')
20
21#define CHECK_INVALID_CTX(__ctx) \
22 if (__ctx == NULL) \
23 return CF_ERROR_DEBUG_INVALID_CTX
24
25#define GET_CTX_OSTREAM(__ctx) \
26 ((((CF_DEBUG_CTX *)__ctx)->fp == NULL) \
27 ? stderr \
28 : ((CF_DEBUG_CTX *)__ctx)->fp)
29
30typedef struct __cf_debug_callstack__
31{
32 char file[NAME_LENGTH + 1];
33 char func[NAME_LENGTH + 1];
34 int line;
35
36 struct __cf_debug_callstack__ * caller;
37} S_CF_DEBUG_CALLSTACK, CF_DEBUG_CALLSTACK;
38
39/* implementation of CF_Debug_Ctx */
40typedef struct __cf_debug_ctx__
41{
42 char file[NAME_LENGTH + 1];
43 char func[NAME_LENGTH + 1];
44 int line;
45
46 FILE * fp;
47
48 CF_DEBUG_CALLSTACK callstack;
49} S_CF_DEBUG_CTX, CF_DEBUG_CTX;
50
51void
52CF_Debug_Local_Print (CF_DEBUG_CTX * ctx,
53 const char * fmt,
54 va_list valist)
55{
56 fprintf (GET_CTX_OSTREAM (ctx), "[DEBUG][%s %s(%d)] ",
57 ctx->file,
58 ctx->func,
59 ctx->line);
60 vfprintf (GET_CTX_OSTREAM (ctx), fmt, valist);
61}
62
63CF_Debug_Ctx
64CF_Debug_CreateCtx (void)
65{
66 CF_DEBUG_CTX * ctx = NULL;
67
68 ctx = (CF_DEBUG_CTX *) calloc (sizeof (CF_DEBUG_CTX), 1);
69
70 return (CF_Debug_Ctx) ctx;
71}
72
73int
74CF_Debug_DestroyCtx (CF_Debug_Ctx ctx)
75{
76 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
77 CF_DEBUG_CALLSTACK * pop = NULL;
78 CF_DEBUG_CALLSTACK * next = NULL;
79
80 CHECK_INVALID_CTX (ctx);
81
82 if (context->fp != NULL)
83 fclose (context->fp);
84
85 for (pop = next = context->callstack.caller ; pop ; pop = next)
86 {
87 next = next->caller;
88 free (pop);
89 }
90
91 free (context);
92
93 return CF_OK;
94}
95
96int
97CF_Debug_SetOutputFD (CF_Debug_Ctx ctx,
98 int fd)
99{
100 int result = 0;
101 int dupfd = 0;
102
103 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
104 FILE * fp = NULL;
105
106 CHECK_INVALID_CTX (ctx);
107
108 TRY
109 {
110 dupfd = dup (fd);
111 if (dupfd < 0)
112 {
113 result = -1;
114 TRY_BREAK;
115 }
116
117 fp = fdopen (dupfd, "a+");
118 if (fp == NULL)
119 {
120 close (dupfd);
121 result = -2;
122 TRY_BREAK;
123 }
124
125 context->fp = fp;
126 }
127 CATCH_IF (result < 0)
128 {
129 return CF_ERROR_DEBUG_SET_OUTPUT_FD;
130 }
131
132 return CF_OK;
133}
134
135int
136CF_Debug_Trace (CF_Debug_Ctx ctx,
137 const char * fmt, ...)
138{
139 va_list valist;
140
141 CHECK_INVALID_CTX (ctx);
142
143 va_start (valist, fmt);
144 CF_Debug_Local_Print ((CF_DEBUG_CTX *) ctx, fmt, valist);
145 va_end (valist);
146
147 return CF_OK;
148}
149
150int
151CF_Debug_TraceBin (CF_Debug_Ctx ctx,
152 const unsigned char * bin,
153 const int len,
154 const char * fmt, ...)
155{
156 int i, j;
157 va_list valist;
158 FILE * fp = GET_CTX_OSTREAM (ctx);
159
160 CHECK_INVALID_CTX (ctx);
161
162 va_start (valist, fmt);
163 CF_Debug_Local_Print ((CF_DEBUG_CTX *) ctx, fmt, valist);
164
165 for (i = 0 ; i < len ; i += 16)
166 {
167 fprintf (fp, "[DEBUG][%s %s(%d)] ", __FILE__, __func__, __LINE__);
168 fprintf (fp, "%06x : ", i);
169
170 for (j = 0 ; j < 16 ; j++)
171 {
172 if (i+j < len)
173 fprintf (fp, "%02x ", bin[i+j]);
174 else
175 fprintf (fp, " ");
176 }
177 fprintf (fp, " ");
178
179 for (j = 0 ; j < 16 ; j++)
180 {
181 if (i+j < len)
182 fprintf (fp, "%c", IS_READABLE_CHAR(bin[i+j]) ? bin[i+j] : '.');
183 }
184 fprintf (fp, "\n");
185 }
186
187 return CF_OK;
188}
189
190int
191CF_Debug_CallStackPush (CF_Debug_Ctx ctx,
192 const char * file,
193 const char * func,
194 const int line)
195{
196 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
197 CF_DEBUG_CALLSTACK * push = NULL;
198
199 CHECK_INVALID_CTX (ctx);
200
201 push = (CF_DEBUG_CALLSTACK *) calloc (sizeof (CF_DEBUG_CALLSTACK), 1);
202 if (push == NULL)
203 return CF_ERROR_DEBUG_PUSH_CALLSTACK;
204
205 /* push to callstack */
206 sprintf (push->file, "%s", file);
207 sprintf (push->func, "%s", func);
208 push->line = line;
209 push->caller = context->callstack.caller;
210 context->callstack.caller = push;
211
212 /* set current context */
213 sprintf (context->file, "%s", file);
214 sprintf (context->func, "%s", func);
215 context->line = line;
216
217 return CF_OK;
218}
219
220int
221CF_Debug_CallStackPop (CF_Debug_Ctx ctx,
222 CF_Debug_CallStack * callstack)
223{
224 CF_DEBUG_CTX * context = (CF_DEBUG_CTX *) ctx;
225 CF_DEBUG_CALLSTACK * pop = NULL;
226
227 CHECK_INVALID_CTX (ctx);
228
229 pop = context->callstack.caller;
230 if (pop == NULL)
231 return CF_ERROR_DEBUG_POP_CALLSTACK;
232
233 if (callstack != NULL)
234 {
235 sprintf (callstack->function, "%s", pop->func);
236 callstack->line = pop->line;
237 }
238
239 memset (context->file, 0x00, sizeof (context->file));
240 memset (context->func, 0x00, sizeof (context->func));
241 context->line = 0;
242
243 /* restore current context */
244 if (pop->caller != NULL)
245 {
246 sprintf (context->file, "%s", pop->caller->file);
247 sprintf (context->func, "%s", pop->caller->func);
248 context->line = pop->caller->line;
249 context->callstack.caller = pop->caller;
250 }
251
252 free (pop);
253
254 return CF_OK;
255}
Note: See TracBrowser for help on using the repository browser.