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