Mercurial > libpst
comparison src/debug.c @ 75:987aa872294e stable-0-6-11
Use ftello/fseeko to properly handle large files.
Document and properly use datasize field in b5 blocks.
Fix some MSVC compile issues and collect MSVC dependencies into one place.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 03 Jun 2008 12:00:58 -0700 |
parents | 3cb02cb1e6cd |
children | 56fa05fd5271 |
comparison
equal
deleted
inserted
replaced
74:6f82d13e9300 | 75:987aa872294e |
---|---|
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <ctype.h> | 7 #include <ctype.h> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <limits.h> | 9 #include <limits.h> |
10 | |
11 #ifdef _WIN32 | |
12 # define vsnprintf _vsnprintf | |
13 #endif | |
14 | 10 |
15 struct pst_debug_item { | 11 struct pst_debug_item { |
16 int type; | 12 int type; |
17 char * function; | 13 char * function; |
18 unsigned int line; | 14 unsigned int line; |
127 | 123 |
128 void pst_debug_msg_text(const char* fmt, ...) { | 124 void pst_debug_msg_text(const char* fmt, ...) { |
129 va_list ap; | 125 va_list ap; |
130 int f, g; | 126 int f, g; |
131 char x[2]; | 127 char x[2]; |
128 char *buf = NULL; | |
132 struct pst_debug_item *temp; | 129 struct pst_debug_item *temp; |
133 if (!debug_fp) return; // no file | 130 if (!debug_fp) return; // no file |
134 va_start(ap, fmt); | |
135 // get the record off of the temp_list | 131 // get the record off of the temp_list |
136 info_ptr = temp_list; | 132 info_ptr = temp_list; |
137 if (info_ptr) | 133 if (info_ptr) |
138 temp_list = info_ptr->next; | 134 temp_list = info_ptr->next; |
139 else { | 135 else { |
140 fprintf(stderr, "NULL info_ptr. ERROR!!\n"); | 136 fprintf(stderr, "NULL info_ptr. ERROR!!\n"); |
141 exit(-2); | 137 exit(-2); |
142 } | 138 } |
143 // according to glibc 2.1, this should return the req. number of bytes for | 139 |
144 // the string | 140 #ifdef _WIN32 |
145 #ifdef _WIN32 | 141 // vsnprintf trick doesn't work on msvc. |
146 // vsnprintf trick doesn't work. must use function called _vscprintf | 142 g = 2000; |
147 // cannot find much documentation about this on internet or anywhere. | 143 f = -1; |
148 // I assume it isn't a standard function, but only in VisualC++ | 144 while (f < 0) { |
149 f = _vscprintf(fmt, ap); | 145 buf = realloc(buf, g+1); |
150 #else | 146 va_start(ap, fmt); |
151 f = vsnprintf(x, 1, fmt, ap); | 147 f = vsnprintf(buf, g, fmt, ap); |
152 #endif | 148 va_end(ap); |
153 va_end(ap); // must be called after vsnprintf() | 149 g += g/2; |
150 } | |
151 free(buf); | |
152 #else | |
153 // according to glibc 2.1, this should return the req. number of bytes for | |
154 // the string | |
155 va_start(ap, fmt); | |
156 f = vsnprintf(x, 1, fmt, ap); | |
157 va_end(ap); | |
158 #endif | |
154 | 159 |
155 if (f > 0 && f < MAX_MESSAGE_SIZE) { | 160 if (f > 0 && f < MAX_MESSAGE_SIZE) { |
156 info_ptr->text = (char*) xmalloc(f+1); | 161 info_ptr->text = (char*) xmalloc(f+1); |
157 va_start(ap, fmt); | 162 va_start(ap, fmt); |
158 if ((g = vsnprintf(info_ptr->text, f, fmt, ap)) == -1) { | 163 if ((g = vsnprintf(info_ptr->text, f, fmt, ap)) == -1) { |
159 fprintf(stderr, "_debug_msg: Dieing! vsnprintf returned -1 for format \"%s\"\n", fmt); | 164 fprintf(stderr, "_debug_msg: Dying! vsnprintf returned -1 for format \"%s\"\n", fmt); |
160 exit(-2); | 165 exit(-2); |
161 } | 166 } |
162 va_end(ap); | 167 va_end(ap); |
163 info_ptr->text[g] = '\0'; | 168 info_ptr->text[g] = '\0'; |
164 if (f != g) { | 169 if (f != g) { |
250 | 255 |
251 void pst_debug_write() { | 256 void pst_debug_write() { |
252 size_t size, ptr, funcname, filename, text, end; | 257 size_t size, ptr, funcname, filename, text, end; |
253 char *buf = NULL, rec_type; | 258 char *buf = NULL, rec_type; |
254 if (!debug_fp) return; // no file | 259 if (!debug_fp) return; // no file |
255 off_t index_pos = ftell(debug_fp); | 260 off_t index_pos = ftello(debug_fp); |
256 off_t file_pos = index_pos; | 261 off_t file_pos = index_pos; |
257 // add 2. One for the pointer to the next index, | 262 // add 2. One for the pointer to the next index, |
258 // one for the count of this index | 263 // one for the count of this index |
259 int index_size = ((curr_items+2) * sizeof(off_t)); | 264 int index_size = ((curr_items+2) * sizeof(off_t)); |
260 off_t *index; | 265 off_t *index; |
272 pst_debug_fwrite(index, index_size, 1, debug_fp); | 277 pst_debug_fwrite(index, index_size, 1, debug_fp); |
273 index[index_ptr++] = curr_items; | 278 index[index_ptr++] = curr_items; |
274 | 279 |
275 item_ptr = item_head; | 280 item_ptr = item_head; |
276 while (item_ptr) { | 281 while (item_ptr) { |
277 file_pos = ftell(debug_fp); | 282 file_pos = ftello(debug_fp); |
278 index[index_ptr++] = file_pos; | 283 index[index_ptr++] = file_pos; |
279 size = strlen(item_ptr->function) + | 284 size = strlen(item_ptr->function) + |
280 strlen(item_ptr->file) + | 285 strlen(item_ptr->file) + |
281 strlen(item_ptr->text) + 3; //for the three \0s | 286 strlen(item_ptr->text) + 3; //for the three \0s |
282 if (buf) free(buf); | 287 if (buf) free(buf); |
318 free(item_ptr->text); | 323 free(item_ptr->text); |
319 free(item_ptr); | 324 free(item_ptr); |
320 item_ptr = item_head; | 325 item_ptr = item_head; |
321 } | 326 } |
322 curr_items = 0; | 327 curr_items = 0; |
323 index[index_ptr] = ftell(debug_fp); | 328 index[index_ptr] = ftello(debug_fp); |
324 | 329 |
325 // we should now have a complete index | 330 // we should now have a complete index |
326 fseek(debug_fp, index_pos, SEEK_SET); | 331 fseeko(debug_fp, index_pos, SEEK_SET); |
327 pst_debug_fwrite(index, index_size, 1, debug_fp); | 332 pst_debug_fwrite(index, index_size, 1, debug_fp); |
328 fseek(debug_fp, 0, SEEK_END); | 333 fseeko(debug_fp, 0, SEEK_END); |
329 item_ptr = item_head = item_tail = NULL; | 334 item_ptr = item_head = item_tail = NULL; |
330 free(index); | 335 free(index); |
331 if (buf) free(buf); | 336 if (buf) free(buf); |
332 } | 337 } |
333 | 338 |
341 off_t index_pos, file_pos; | 346 off_t index_pos, file_pos; |
342 char zero='\0'; | 347 char zero='\0'; |
343 unsigned int end; | 348 unsigned int end; |
344 if (!debug_fp) return; // no file | 349 if (!debug_fp) return; // no file |
345 index[0] = 1; //only one item in this index | 350 index[0] = 1; //only one item in this index |
346 index_pos = ftell(debug_fp); | 351 index_pos = ftello(debug_fp); |
347 pst_debug_fwrite(index, index_size, 1, debug_fp); | 352 pst_debug_fwrite(index, index_size, 1, debug_fp); |
348 | 353 |
349 index[1] = ftell(debug_fp); | 354 index[1] = ftello(debug_fp); |
350 | 355 |
351 if (size > USHRT_MAX) { // bigger than can be stored in a short | 356 if (size > USHRT_MAX) { // bigger than can be stored in a short |
352 rec_type = 'L'; | 357 rec_type = 'L'; |
353 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); | 358 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); |
354 lfile_rec.type = item->type; | 359 lfile_rec.type = item->type; |
365 mfile_rec.funcname = 0; | 370 mfile_rec.funcname = 0; |
366 mfile_rec.filename = strlen(item->function)+1; | 371 mfile_rec.filename = strlen(item->function)+1; |
367 mfile_rec.text = mfile_rec.filename+strlen(item->file)+1; | 372 mfile_rec.text = mfile_rec.filename+strlen(item->file)+1; |
368 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp); | 373 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp); |
369 } | 374 } |
370 file_pos = ftell(debug_fp); | 375 file_pos = ftello(debug_fp); |
371 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp); | 376 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp); |
372 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp); | 377 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp); |
373 vfprintf(debug_fp, fmt, *ap); | 378 vfprintf(debug_fp, fmt, *ap); |
374 pst_debug_fwrite(&zero, 1, 1, debug_fp); | 379 pst_debug_fwrite(&zero, 1, 1, debug_fp); |
375 | 380 |
376 end = ftell(debug_fp)-file_pos; | 381 end = (unsigned int) (ftello(debug_fp) - file_pos); |
377 | 382 |
378 index[2] = ftell(debug_fp); | 383 index[2] = ftello(debug_fp); |
379 fseek(debug_fp, index_pos, SEEK_SET); | 384 fseeko(debug_fp, index_pos, SEEK_SET); |
380 pst_debug_fwrite(index, index_size, 1, debug_fp); | 385 pst_debug_fwrite(index, index_size, 1, debug_fp); |
381 if (size > USHRT_MAX) { | 386 if (size > USHRT_MAX) { |
382 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); | 387 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); |
383 lfile_rec.end = end; | 388 lfile_rec.end = end; |
384 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); | 389 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); |
385 } else { | 390 } else { |
386 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); | 391 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); |
387 mfile_rec.end = end; | 392 mfile_rec.end = end; |
388 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp); | 393 pst_debug_fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp); |
389 } | 394 } |
390 fseek(debug_fp, 0, SEEK_END); | 395 fseeko(debug_fp, 0, SEEK_END); |
391 } | 396 } |
392 | 397 |
393 | 398 |
394 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col) { | 399 void pst_debug_write_hex(struct pst_debug_item *item, char *buf, size_t size, int col) { |
395 struct pst_debug_file_rec_l lfile_rec; | 400 struct pst_debug_file_rec_l lfile_rec; |
399 char zero='\0'; | 404 char zero='\0'; |
400 if (!debug_fp) return; // no file | 405 if (!debug_fp) return; // no file |
401 index[0] = 1; // only one item in this index run | 406 index[0] = 1; // only one item in this index run |
402 index[1] = 0; // valgrind, avoid writing uninitialized data | 407 index[1] = 0; // valgrind, avoid writing uninitialized data |
403 index[2] = 0; // "" | 408 index[2] = 0; // "" |
404 index_pos = ftell(debug_fp); | 409 index_pos = ftello(debug_fp); |
405 pst_debug_fwrite(index, index_size, 1, debug_fp); | 410 pst_debug_fwrite(index, index_size, 1, debug_fp); |
406 index[1] = ftell(debug_fp); | 411 index[1] = ftello(debug_fp); |
407 | 412 |
408 // always use the long | 413 // always use the long |
409 rec_type = 'L'; | 414 rec_type = 'L'; |
410 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); | 415 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); |
411 lfile_rec.funcname = 0; | 416 lfile_rec.funcname = 0; |
414 lfile_rec.end = 0; // valgrind, avoid writing uninitialized data | 419 lfile_rec.end = 0; // valgrind, avoid writing uninitialized data |
415 lfile_rec.line = item->line; | 420 lfile_rec.line = item->line; |
416 lfile_rec.type = item->type; | 421 lfile_rec.type = item->type; |
417 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); | 422 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); |
418 | 423 |
419 file_pos = ftell(debug_fp); | 424 file_pos = ftello(debug_fp); |
420 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp); | 425 pst_debug_fwrite(item->function, strlen(item->function)+1, 1, debug_fp); |
421 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp); | 426 pst_debug_fwrite(item->file, strlen(item->file)+1, 1, debug_fp); |
422 | 427 |
423 pst_debug_hexdumper(debug_fp, buf, size, col, 0); | 428 pst_debug_hexdumper(debug_fp, buf, size, col, 0); |
424 pst_debug_fwrite(&zero, 1, 1, debug_fp); | 429 pst_debug_fwrite(&zero, 1, 1, debug_fp); |
425 lfile_rec.end = ftell(debug_fp) - file_pos; | 430 lfile_rec.end = ftello(debug_fp) - file_pos; |
426 | 431 |
427 index[2] = ftell(debug_fp); | 432 index[2] = ftello(debug_fp); |
428 fseek(debug_fp, index_pos, SEEK_SET); | 433 fseeko(debug_fp, index_pos, SEEK_SET); |
429 pst_debug_fwrite(index, index_size, 1, debug_fp); | 434 pst_debug_fwrite(index, index_size, 1, debug_fp); |
430 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); | 435 pst_debug_fwrite(&rec_type, 1, sizeof(char), debug_fp); |
431 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); | 436 pst_debug_fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); |
432 fseek(debug_fp, 0, SEEK_END); | 437 fseeko(debug_fp, 0, SEEK_END); |
433 } | 438 } |
434 | 439 |
435 | 440 |
436 void *xmalloc(size_t size) { | 441 void *xmalloc(size_t size) { |
437 void *mem = malloc(size); | 442 void *mem = malloc(size); |