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, sizeof(char), 1, 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
00195 if (!item_head) item_head = info_ptr;
00196 info_ptr->next = NULL;
00197 if (item_tail) item_tail->next = info_ptr;
00198 item_tail = info_ptr;
00199
00200 if (++curr_items == max_items) {
00201
00202 pst_debug_write();
00203 info_ptr = NULL;
00204 }
00205 }
00206
00207
00208 void pst_debug_hexdump(char *x, size_t y, int cols, int delta) {
00209 struct pst_debug_item *temp;
00210 if (!debug_fp) return;
00211 info_ptr = temp_list;
00212 if (info_ptr) temp_list = info_ptr->next;
00213 temp = info_ptr;
00214 pst_debug_write();
00215 info_ptr = temp;
00216 pst_debug_write_hex(info_ptr, x, y, cols);
00217 free(info_ptr->function);
00218 free(info_ptr->file);
00219 free(info_ptr);
00220 info_ptr = NULL;
00221 }
00222
00223
00224 void pst_debug_func(const char *function) {
00225 func_ptr = xmalloc (sizeof(struct pst_debug_func));
00226 func_ptr->name = xmalloc(strlen(function)+1);
00227 strcpy(func_ptr->name, function);
00228 func_ptr->next = func_head;
00229 func_head = func_ptr;
00230 }
00231
00232
00233 void pst_debug_func_ret() {
00234
00235 func_ptr = func_head;
00236 if (func_head) {
00237 func_head = func_head->next;
00238 free(func_ptr->name);
00239 free(func_ptr);
00240 } else {
00241 DIE(("function list is empty!\n"));
00242 }
00243 }
00244
00245
00246 void pst_debug_close(void) {
00247 pst_debug_write();
00248 while (func_head) {
00249 func_ptr = func_head;
00250 func_head = func_head->next;
00251 free(func_ptr->name);
00252 free(func_ptr);
00253 }
00254 if (debug_fp) fclose(debug_fp);
00255 debug_fp = NULL;
00256 }
00257
00258
00259 void pst_debug_write() {
00260 size_t size, ptr, funcname, filename, text, end;
00261 char *buf = NULL, rec_type;
00262 if (!debug_fp) return;
00263 off_t index_pos = ftello(debug_fp);
00264 off_t file_pos = index_pos;
00265
00266
00267 int index_size = ((curr_items+2) * sizeof(off_t));
00268 off_t *index;
00269 int index_ptr = 0;
00270 struct pst_debug_file_rec_m mfile_rec;
00271 struct pst_debug_file_rec_l lfile_rec;
00272
00273 if (curr_items == 0) return;
00274
00275 index = (off_t*)xmalloc(index_size);
00276 memset(index, 0, index_size);
00277 file_pos += index_size;
00278
00279
00280 pst_debug_fwrite(index, index_size, 1, debug_fp);
00281 index[index_ptr++] = curr_items;
00282
00283 item_ptr = item_head;
00284 while (item_ptr) {
00285 file_pos = ftello(debug_fp);
00286 index[index_ptr++] = file_pos;
00287 size = strlen(item_ptr->function) +
00288 strlen(item_ptr->file) +
00289 strlen(item_ptr->text) + 3;
00290 if (buf) free(buf);
00291 buf = xmalloc(size+1);
00292 ptr = 0;
00293 funcname=ptr;
00294 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->function)+1;
00295 filename=ptr;
00296 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->file)+1;
00297 text=ptr;
00298 ptr += sprintf(&(buf[ptr]), "%s", item_ptr->text)+1;
00299 end=ptr;
00300 if (end > USHRT_MAX) {
00301 rec_type = 'L';
00302 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00303 lfile_rec.type = item_ptr->type;
00304 lfile_rec.line = item_ptr->line;
00305 lfile_rec.funcname = funcname;
00306 lfile_rec.filename = filename;
00307 lfile_rec.text = text;
00308 lfile_rec.end = end;
00309 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00310 } else {
00311 rec_type = 'M';
00312 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00313 mfile_rec.type = item_ptr->type;
00314 mfile_rec.line = item_ptr->line;
00315 mfile_rec.funcname = funcname;
00316 mfile_rec.filename = filename;
00317 mfile_rec.text = text;
00318 mfile_rec.end = end;
00319 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00320 }
00321 pst_debug_fwrite(buf, ptr, 1, debug_fp);
00322 if (buf) free(buf); buf = NULL;
00323 item_head = item_ptr->next;
00324 free(item_ptr->function);
00325 free(item_ptr->file);
00326 free(item_ptr->text);
00327 free(item_ptr);
00328 item_ptr = item_head;
00329 }
00330 curr_items = 0;
00331 index[index_ptr] = ftello(debug_fp);
00332
00333
00334 fseeko(debug_fp, index_pos, SEEK_SET);
00335 pst_debug_fwrite(index, index_size, 1, debug_fp);
00336 fseeko(debug_fp, 0, SEEK_END);
00337 item_ptr = item_head = item_tail = NULL;
00338 free(index);
00339 if (buf) free(buf);
00340 }
00341
00342
00343 void pst_debug_write_msg(struct pst_debug_item *item, const char *fmt, va_list *ap, int size) {
00344 struct pst_debug_file_rec_l lfile_rec;
00345 struct pst_debug_file_rec_m mfile_rec;
00346 unsigned char rec_type;
00347 int index_size = 3 * sizeof(off_t);
00348 off_t index[3];
00349 off_t index_pos, file_pos;
00350 char zero = '\0';
00351 unsigned int end;
00352 if (!debug_fp) return;
00353 index[0] = 1;
00354 index[1] = 0;
00355 index[2] = 0;
00356 index_pos = ftello(debug_fp);
00357 pst_debug_fwrite(index, index_size, 1, debug_fp);
00358
00359 index[1] = ftello(debug_fp);
00360
00361 if (size > USHRT_MAX) {
00362 rec_type = 'L';
00363 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00364 lfile_rec.type = item->type;
00365 lfile_rec.line = item->line;
00366 lfile_rec.funcname = 0;
00367 lfile_rec.filename = strlen(item->function)+1;
00368 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
00369 lfile_rec.end = 0;
00370 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00371 } else {
00372 rec_type = 'M';
00373 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00374 mfile_rec.type = item->type;
00375 mfile_rec.line = item->line;
00376 mfile_rec.funcname = 0;
00377 mfile_rec.filename = strlen(item->function)+1;
00378 mfile_rec.text = mfile_rec.filename+strlen(item->file)+1;
00379 mfile_rec.end = 0;
00380 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00381 }
00382 file_pos = ftello(debug_fp);
00383 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
00384 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
00385 vfprintf(debug_fp, fmt, *ap);
00386 pst_debug_fwrite(&zero, 1, 1, debug_fp);
00387
00388 end = (unsigned int) (ftello(debug_fp) - file_pos);
00389
00390 index[2] = ftello(debug_fp);
00391 fseeko(debug_fp, index_pos, SEEK_SET);
00392 pst_debug_fwrite(index, index_size, 1, debug_fp);
00393 if (size > USHRT_MAX) {
00394 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00395 lfile_rec.end = end;
00396 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00397 } else {
00398 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00399 mfile_rec.end = end;
00400 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp);
00401 }
00402 fseeko(debug_fp, 0, SEEK_END);
00403 }
00404
00405
00406 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col) {
00407 struct pst_debug_file_rec_l lfile_rec;
00408 unsigned char rec_type;
00409 int index_size = 3 * sizeof(off_t);
00410 off_t index_pos, file_pos, index[3];
00411 char zero='\0';
00412 if (!debug_fp) return;
00413 index[0] = 1;
00414 index[1] = 0;
00415 index[2] = 0;
00416 index_pos = ftello(debug_fp);
00417 pst_debug_fwrite(index, index_size, 1, debug_fp);
00418 index[1] = ftello(debug_fp);
00419
00420
00421 rec_type = 'L';
00422 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00423 lfile_rec.funcname = 0;
00424 lfile_rec.filename = strlen(item->function)+1;
00425 lfile_rec.text = lfile_rec.filename+strlen(item->file)+1;
00426 lfile_rec.end = 0;
00427 lfile_rec.line = item->line;
00428 lfile_rec.type = item->type;
00429 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00430
00431 file_pos = ftello(debug_fp);
00432 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp);
00433 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp);
00434
00435 pst_debug_hexdumper(debug_fp, buf, size, col, 0);
00436 pst_debug_fwrite(&zero, 1, 1, debug_fp);
00437 lfile_rec.end = ftello(debug_fp) - file_pos;
00438
00439 index[2] = ftello(debug_fp);
00440 fseeko(debug_fp, index_pos, SEEK_SET);
00441 pst_debug_fwrite(index, index_size, 1, debug_fp);
00442 pst_debug_fwrite(&rec_type, sizeof(char), 1, debug_fp);
00443 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp);
00444 fseeko(debug_fp, 0, SEEK_END);
00445 }
00446
00447
00448 void *xmalloc(size_t size) {
00449 void *mem = malloc(size);
00450 if (!mem) {
00451 fprintf(stderr, "xMalloc: Out Of memory [req: %ld]\n", (long)size);
00452 exit(1);
00453 }
00454 return mem;
00455 }
00456