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