Mercurial > libpst
view src/readpstlog.c @ 59:7d5c637aaafb
General cleanup and code fixes.
Use autoscan to cleanup our autoconf system.
Use autoconf to detect when we need to use our XGetopt files and other header files.
Decode BCC field.
Fix missing LE32_CPU byte swapping for FILETIME types.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 14 Feb 2008 14:55:32 -0800 |
parents | 034641c26ab9 |
children | b12f4e50e2e8 |
line wrap: on
line source
#include "define.h" #include <stdio.h> #include <ctype.h> #include <string.h> #ifndef _WIN32 # include <unistd.h> #endif #ifndef __GNUC__ # include "XGetopt.h" #endif #define BUF_SIZE 4096 int usage(); size_t get(void * buf, int size, unsigned int count, FILE *fp); int split_args(char *args, int **targ); int is_in(int a, int *b, int c); int main(int argc, char** argv) { int identity = 0; int level = 0; off_t *i = NULL; int x, ptr, stop=0, flag; char *fname, *buf, rec_type; unsigned char version; int *show_type=NULL, show_size=0; int *ex_type=NULL, ex_size=0; unsigned int funcname=0, filename=0, text=0, end=0, dtype=0, line=0, c; FILE *fp; struct pst_debug_file_rec_m mfile_rec; struct pst_debug_file_rec_l lfile_rec; char format = 'D'; // default while ((c = getopt(argc, argv, "f:t:x:")) != -1) { switch(c) { case 'f': // change the output format format = toupper(optarg[0]); break; case 't': //change the type of statements shown show_size = split_args(optarg, &show_type); // type = atoi(optarg); break; case 'x': // change the type of statements excluded ex_size = split_args(optarg, &ex_type); break; } } if (argc > optind) { fname = argv[optind++]; } else { usage(); exit(2); } fp = fopen(fname, "rb"); if (fp == NULL) { printf("Error. couldn't open debug file\n"); return 2; } if (get(&version, sizeof(char), 1, fp)==0) { printf("Error. could not read version byte from front of file"); return 3; } if (version > DEBUG_VERSION) { printf("Version number is higher than the format I know about."); return 4; } buf = (char*) xmalloc(BUF_SIZE); while (!stop) { off_t temp; if (fread(&temp, sizeof(off_t), 1, fp)<=0) break; x = (int)temp; ptr = 0; if (x > 0) { if (i) free(i); i = (off_t*)xmalloc(sizeof(off_t)*(x+1)); // plus 1 cause we want to read the offset of the next index if (get(i, sizeof(off_t), x+1, fp)==0) { // we have reached the end of the debug file printf("oh dear. we must now end\n"); break; } while (ptr < x) { fseek(fp, i[ptr++], SEEK_SET); get(&rec_type, 1, sizeof(char), fp); if (rec_type == 'L') { get(&lfile_rec, sizeof(lfile_rec), 1, fp); funcname=lfile_rec.funcname; filename=lfile_rec.filename; text = lfile_rec.text; end = lfile_rec.end; dtype = lfile_rec.type; line = lfile_rec.line; } else if (rec_type == 'M') { get(&mfile_rec, sizeof(mfile_rec), 1, fp); funcname = mfile_rec.funcname; filename = mfile_rec.filename; text = mfile_rec.text; end = mfile_rec.end; dtype = mfile_rec.type; line = mfile_rec.line; } if (dtype == DEBUG_FUNCENT_NO) level++; if ((show_type == NULL || is_in(dtype, show_type, show_size)) && (ex_type == NULL || !is_in(dtype, ex_type, ex_size))) { c = 0; flag = 0; while (c < end) { int ii = (level-1) * 4; if (ii < 0) ii = 0; if (ii > 64) ii = 64; char indent[ii+1]; memset(indent, ' ', ii); indent[ii] = '\0'; if (c + (BUF_SIZE-1) < end) { get(buf, 1, BUF_SIZE-1, fp); buf[BUF_SIZE-1] = '\0'; c += BUF_SIZE-1; } else { get(buf, 1, end-c, fp); buf[end-c] = '\0'; c = end; } if (flag == 0) { if (format == 'I') { // indented text format char *b = buf+text; identity++; //printf("%s %d %s/%s[%d]: ", indent, identity, &buf[filename], &buf[funcname], line); printf("%s %s/%s[%d]: ", indent, &buf[filename], &buf[funcname], line); while (b) { char *p = strchr(b, '\n'); if (p) { *p = '\0'; printf("%s\n%s ", b, indent); b = p + 1; } else { printf("%s", b); b = NULL; } } } else if (format == 'T') { // text format printf("%s/%s[%d]: %s", &buf[filename], &buf[funcname], line, &buf[text]); } else { printf("Type: %d\nFile[line]: %s[%d]\nFunction:%s\nText:%s", dtype, &buf[filename], line, &buf[funcname], &buf[text]); } flag = 1; } else { if (format == 'I') { char *b = buf; while (b) { char *p = strchr(b, '\n'); if (p) { *p = '\0'; printf("%s\n%s ", b, indent); b = p + 1; } else { printf("%s", b); b = NULL; } } } else printf("%s", buf); } } printf("\n"); } if (dtype == DEBUG_FUNCRET_NO) level--; } if (fseek(fp, i[ptr], SEEK_SET)==-1) { printf("finished\n"); break; } } else { printf("...no more items\n"); break; } } free(buf); fclose(fp); if (format == 'I') printf("final indent level = %i\n", level); return 0; } size_t get(void *buf, int size, unsigned int count, FILE *fp) { size_t z; if ((z=fread(buf, size, count, fp)) < count) { printf("Read Failed! (size=%d, count=%d,z=%ld)\n", size, count, (long)z); exit(1); } return z; } int usage() { printf("readlog -t[show_type] -x[exclude_type] -f[format] filename\n"); printf("\tformat:\n\t\tt: text log format\n"); printf("\t\ti: indented text log format\n"); printf("\tshow_type:\n\t\tcomma separated list of types to show " "[ie, 2,4,1,6]\n"); printf("\texclude_type:\n\t\tcomma separated list of types to exclude " "[ie, 1,5,3,7]\n"); return 0; } int split_args(char *args, int **targ) { int count = 1, *i, x, z; char *tmp = args, *y; if (*targ != NULL) { free(*targ); } // find the number of tokens in the string. Starting // from 1 cause there will always be one while ((tmp = strchr(tmp, ',')) != NULL) { tmp++; count++; } *targ = (int*)xmalloc(count * sizeof(int)); i = *targ; // for convienience tmp = args; z = 0; for (x = 0; x < count; x++) { y = strtok(tmp, ","); tmp = NULL; // must be done after first call if (y != NULL) { i[x] = atoi(y); z++; } } return z; } // checks to see if the first arg is in the array of the second arg, // the size of which is specified with the third arg. If the second // arg is NULL, then it is obvious that it is not there. int is_in(int a, int *b, int c){ int d = 0; if (b == NULL || c == 0) { // no array or no items in array return 0; } while (d < c) { if (a == b[d]) return 1; d++; } return 0; }