00001
00002 #include "define.h"
00003
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <stdarg.h>
00007 #include <ctype.h>
00008 #include <string.h>
00009 #include <limits.h>
00010 #include <stdint.h>
00011 #include <inttypes.h>
00012
00013 struct pst_debug_item {
00014 int type;
00015 char * function;
00016 unsigned int line;
00017 char * file;
00018 char * text;
00019 struct pst_debug_item *next;
00020 } *item_head=NULL, *item_tail=NULL, *item_ptr=NULL, *info_ptr=NULL, *temp_list=NULL;
00021
00022
00023 struct pst_debug_func {
00024 char * name;
00025 struct pst_debug_func *next;
00026 } *func_head=NULL, *func_ptr=NULL;
00027
00028
00029 void pst_debug_write_msg(struct pst_debug_item *item, const char *fmt, va_list *ap, int size);
00030 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col);
00031 void * xmalloc(size_t size);
00032
00033 size_t pst_debug_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream) {
00034 return fwrite(ptr, size, nitems, stream);
00035 }
00036
00037
00038
00039
00040
00041 #define MAX_MESSAGE_SIZE 4096
00042
00043 void pst_debug(const char *fmt, ...) {
00044 va_list ap;
00045 va_start(ap,fmt);
00046 vfprintf(stderr, fmt, ap);
00047 va_end(ap);
00048 }
00049
00050
00051 #define NUM_COL 30
00052 void pst_debug_hexdumper(FILE *out, char *buf, size_t size, int col, int delta) {
00053 size_t off = 0, toff;
00054 int count = 0;
00055
00056 if (!out) return;
00057 if (col == -1) col = NUM_COL;
00058 fprintf(out, "\n");
00059 while (off < size) {
00060 fprintf(out, "%06"PRIx64"\t:", (uint64_t)(off+delta));
00061 toff = off;
00062 while (count < col && off < size) {
00063 fprintf(out, "%02hhx ", (unsigned char)buf[off]);
00064 off++; count++;
00065 }
00066 off = toff;
00067 while (count < col) {
00068
00069 fprintf(out, " ");
00070 count++;
00071 }
00072 count = 0;
00073 fprintf(out, ":");
00074 while (count < col && off < size) {
00075 fprintf(out, "%c", isgraph(buf[off])?buf[off]:'.');
00076 off++; count ++;
00077 }
00078
00079 fprintf(out, "\n");
00080 count=0;
00081 }
00082
00083 fprintf(out, "\n");
00084 }
00085
00086
00087 FILE *debug_fp = NULL;
00088 unsigned int max_items=DEBUG_MAX_ITEMS, curr_items=0;
00089
00090
00091 void pst_debug_init(const char* fname) {
00092 unsigned char version = DEBUG_VERSION;
00093 item_head = item_tail = NULL;
00094 curr_items = 0;
00095 if (debug_fp) pst_debug_close();
00096 if (!fname) return;
00097 if ((debug_fp = fopen(fname, "wb")) == NULL) {
00098 fprintf(stderr, "Opening of file %s failed\n", fname);
00099 exit(1);
00100 }
00101 pst_debug_fwrite(&version, 1, sizeof(char), debug_fp);
00102 }
00103
00104
00105
00106
00107 void pst_debug_msg_info(int line, const char* file, int type) {
00108 char *x;
00109 if (!debug_fp) return;
00110 info_ptr = (struct pst_debug_item*) xmalloc(sizeof(struct pst_debug_item));
00111 info_ptr->type = type;
00112 info_ptr->line = line;
00113 x = (func_head==NULL?"No Function":func_head->name);
00114 info_ptr->function = (char*) xmalloc(strlen(x)+1);
00115 strcpy(info_ptr->function, x);
00116
00117 info_ptr->file = (char*) xmalloc(strlen(file)+1);
00118 strcpy(info_ptr->file, file);
00119
00120
00121 info_ptr->next = temp_list;
00122 temp_list = info_ptr;
00123 }
00124
00125
00126 void pst_debug_msg_text(const char* fmt, ...) {
00127 va_list ap;
00128 int f, g;
00129 char x[2];
00130 #ifdef _WIN32
00131 char *buf = NULL;
00132 #endif
00133 struct pst_debug_item *temp;
00134 if (!debug_fp) return;
00135
00136 info_ptr = temp_list;
00137 if (info_ptr)
00138 temp_list = info_ptr->next;
00139 else {
00140 fprintf(stderr, "NULL info_ptr. ERROR!!\n");
00141 exit(-2);
00142 }
00143
00144 #ifdef _WIN32
00145
00146 g = 2000;
00147 f = -1;
00148 while (f < 0) {
00149 buf = realloc(buf, g+1);
00150 va_start(ap, fmt);
00151 f = vsnprintf(buf, g, fmt, ap);
00152 va_end(ap);
00153 g += g/2;
00154 }
00155 free(buf);
00156 #else
00157
00158
00159 va_start(ap, fmt);
00160 f = vsnprintf(x, 1, fmt, ap);
00161 va_end(ap);
00162 #endif
00163
00164 if (f > 0 && f < MAX_MESSAGE_SIZE) {
00165 info_ptr->text = (char*) xmalloc(f+1);
00166 va_start(ap, fmt);
00167 if ((g = vsnprintf(info_ptr->text, f, fmt, ap)) == -1) {
00168 fprintf(stderr, "_debug_msg: Dying! vsnprintf returned -1 for format \"%s\"\n", fmt);
00169 exit(-2);
00170 }
00171 va_end(ap);
00172 info_ptr->text[g] = '\0';
00173 if (f != g) {
00174 fprintf(stderr, "_debug_msg: f != g\n");
00175 }
00176 } else if (f > 0) {
00177 f += strlen(info_ptr->file)+strlen(info_ptr->function);
00178 temp = info_ptr;
00179 pst_debug_write();
00180 info_ptr = temp;
00181 va_start(ap, fmt);
00182 pst_debug_write_msg(info_ptr, fmt, &ap, f);
00183 va_end(ap);
00184 free(info_ptr->function);
00185 free(info_ptr->file);
00186 free(info_ptr);
00187 info_ptr = NULL;
00188 return;
00189 } else {
00190 fprintf(stderr, "_debug_msg: error getting requested size of debug message\n");
00191 info_ptr->text = "ERROR Saving\n";
00192 }
00193
00194 if (!item_head)
00195 item_head = info_ptr;
00196
00197 info_ptr->next = NULL;
00198 if (item_tail) item_tail->next = info_ptr;
00199 item_tail = info_ptr;
00200
00201 if (++curr_items == max_items) {
00202
00203 pst_debug_write();
00204 info_ptr = NULL;
00205 }
00206 }
00207
00208
00209 void pst_debug_hexdump(char *x, size_t y, int cols, int delta) {
00210 struct pst_debug_item *temp;
00211 if (!debug_fp) return;
00212 info_ptr = temp_list;
00213 if (info_ptr) temp_list = info_ptr->next;
00214 temp = info_ptr;
00215 pst_debug_write();
00216 info_ptr = temp;
00217 pst_debug_write_hex(info_ptr, x, y, cols);
00218 free(info_ptr->function);
00219 free(info_ptr->file);
00220 free(info_ptr);
00221 info_ptr = NULL;
00222 }
00223
00224
00225 void pst_debug_func(const char *function) {
00226 func_ptr = xmalloc (sizeof(struct pst_debug_func));
00227 func_ptr->name = xmalloc(strlen(function)+1);
00228 strcpy(func_ptr->name, function);
00229 func_ptr->next = func_head;
00230 func_head = func_ptr;
00231 }
00232
00233
00234 void pst_debug_func_ret() {
00235
00236 func_ptr = func_head;
00237 if (func_head) {
00238 func_head = func_head->next;
00239 free(func_ptr->name);
00240 free(func_ptr);
00241 } else {
00242 DIE(("function list is empty!\n"));
00243 }
00244 }
00245
00246
00247 void pst_debug_close(void) {
00248 pst_debug_write();
00249 while (func_head) {
00250 func_ptr = func_head;
00251 func_head = func_head->next;
00252 free(func_ptr->name);
00253 free(func_ptr);
00254 }
00255 if (debug_fp) fclose(debug_fp);
00256 debug_fp = NULL;
00257 }
00258
00259
00260 void pst_debug_write() {
00261 size_t size, ptr, funcname, filename, text, end;
00262 char *buf = NULL, rec_type;
00263 if (!debug_fp) return;
00264 off_t index_pos = ftello(debug_fp);
00265 off_t file_pos = index_pos;
00266
00267
00268 int index_size = ((curr_items+2) * sizeof(off_t));
00269 off_t *index;
00270 int index_ptr = 0;
00271 struct pst_debug_file_rec_m mfile_rec;
00272 struct pst_debug_file_rec_l lfile_rec;
00273
00274 if (curr_items == 0) return;
00275
00276 index = (off_t*)xmalloc(index_size);
00277 memset(index, 0, index_size);
00278 file_pos += index_size;
00279
00280
00281 pst_debug_fwrite(index, index_size, 1, debug_fp);
00282 index[index_ptr++] = curr_items;
00283
00284 item_ptr = item_head;
00285 while (item_ptr) {
00286 file_pos = ftello(debug_fp);
00287 index[index_ptr++] = file_pos;
00288 size = strlen(item_ptr->function) +
00289 strlen(item_ptr->file) +
00290 strlen(item_ptr->text) + 3;
00291 if (buf) free(buf);
00292 buf = xmalloc(size+1);
00293 ptr = 0;
00294 funcname=ptr;
00295 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->function)+1;
00296 filename=ptr;
00297 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->file)+1;
00298 text=ptr;
00299 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->text)+1;
00300 end=ptr;
00301 if (end > USHRT_MAX) {
00302 rec_type = 'L';
00303 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00304 lfile_rec.type = item_ptr->type;
00305 lfile_rec.line = item_ptr->line;
00306 lfile_rec.funcname = funcname;
00307 lfile_rec.filename = filename;
00308 lfile_rec.text = text;
00309 lfile_rec.end = end;
00310 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00311 } else {
00312 rec_type = 'M';
00313 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00314 mfile_rec.type = item_ptr->type;
00315 mfile_rec.line = item_ptr->line;
00316 mfile_rec.funcname = funcname;
00317 mfile_rec.filename = filename;
00318 mfile_rec.text = text;
00319 mfile_rec.end = end;
00320 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00321 }
00322 pst_debug_fwrite(buf, 1, ptr, debug_fp);
00323 if (buf) free(buf); buf = NULL;
00324 item_head = item_ptr->next;
00325 free(item_ptr->function);
00326 free(item_ptr->file);
00327 free(item_ptr->text);
00328 free(item_ptr);
00329 item_ptr = item_head;
00330 }
00331 curr_items = 0;
00332 index[index_ptr] = ftello(debug_fp);
00333
00334
00335 fseeko(debug_fp, index_pos, SEEK_SET);
00336 pst_debug_fwrite(index, index_size, 1, debug_fp);
00337 fseeko(debug_fp, 0, SEEK_END);
00338 item_ptr = item_head = item_tail = NULL;
00339 free(index);
00340 if (buf) free(buf);
00341 }
00342
00343
00344 void pst_debug_write_msg(struct pst_debug_item *item, const char *fmt, va_list *ap, int size) {
00345 struct pst_debug_file_rec_l lfile_rec;
00346 struct pst_debug_file_rec_m mfile_rec;
00347 unsigned char rec_type;
00348 int index_size = 3 * sizeof(off_t);
00349 off_t index[3];
00350 off_t index_pos, file_pos;
00351 char zero='\0';
00352 unsigned int end;
00353 if (!debug_fp) return;
00354 index[0] = 1;
00355 index_pos = ftello(debug_fp);
00356 pst_debug_fwrite(index, index_size, 1, debug_fp);
00357
00358 index[1] = ftello(debug_fp);
00359
00360 if (size > USHRT_MAX) {
00361 rec_type = 'L';
00362 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00363 lfile_rec.type = item->type;
00364 lfile_rec.line = item->line;
00365 lfile_rec.funcname = 0;
00366 lfile_rec.filename = strlen(item->function)+1;
00367 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
00368 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00369 } else {
00370 rec_type = 'M';
00371 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00372 mfile_rec.type = item->type;
00373 mfile_rec.line = item->line;
00374 mfile_rec.funcname = 0;
00375 mfile_rec.filename = strlen(item->function)+1;
00376 mfile_rec.text = mfile_rec.filename+strlen(item->file)+1;
00377 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00378 }
00379 file_pos = ftello(debug_fp);
00380 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
00381 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
00382 vfprintf(debug_fp, fmt, *ap);
00383 pst_debug_fwrite(&zero, 1, 1, debug_fp);
00384
00385 end = (unsigned int) (ftello(debug_fp) - file_pos);
00386
00387 index[2] = ftello(debug_fp);
00388 fseeko(debug_fp, index_pos, SEEK_SET);
00389 pst_debug_fwrite(index, index_size, 1, debug_fp);
00390 if (size > USHRT_MAX) {
00391 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00392 lfile_rec.end = end;
00393 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00394 } else {
00395 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00396 mfile_rec.end = end;
00397 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00398 }
00399 fseeko(debug_fp, 0, SEEK_END);
00400 }
00401
00402
00403 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col) {
00404 struct pst_debug_file_rec_l lfile_rec;
00405 unsigned char rec_type;
00406 int index_size = 3 * sizeof(off_t);
00407 off_t index_pos, file_pos, index[3];
00408 char zero='\0';
00409 if (!debug_fp) return;
00410 index[0] = 1;
00411 index[1] = 0;
00412 index[2] = 0;
00413 index_pos = ftello(debug_fp);
00414 pst_debug_fwrite(index, index_size, 1, debug_fp);
00415 index[1] = ftello(debug_fp);
00416
00417
00418 rec_type = 'L';
00419 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00420 lfile_rec.funcname = 0;
00421 lfile_rec.filename = strlen(item->function)+1;
00422 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
00423 lfile_rec.end = 0;
00424 lfile_rec.line = item->line;
00425 lfile_rec.type = item->type;
00426 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00427
00428 file_pos = ftello(debug_fp);
00429 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
00430 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
00431
00432 pst_debug_hexdumper(debug_fp, buf, size, col, 0);
00433 pst_debug_fwrite(&zero, 1, 1, debug_fp);
00434 lfile_rec.end = ftello(debug_fp) - file_pos;
00435
00436 index[2] = ftello(debug_fp);
00437 fseeko(debug_fp, index_pos, SEEK_SET);
00438 pst_debug_fwrite(index, index_size, 1, debug_fp);
00439 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp);
00440 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00441 fseeko(debug_fp, 0, SEEK_END);
00442 }
00443
00444
00445 void *xmalloc(size_t size) {
00446 void *mem = malloc(size);
00447 if (!mem) {
00448 fprintf(stderr, "xMalloc: Out Of memory [req: %ld]\n", (long)size);
00449 exit(1);
00450 }
00451 return mem;
00452 }
00453