view src/readpstlog.c @ 118:0f1492b7fe8b

patch from Fridrich Strba for building on mingw and general cleanup of autoconf files add processing for pst files of type 0x0f start adding support for properly building and installing libpst.so and the header files required to use it. remove version.h since the version number is now in config.h more const correctness issues regarding getopt()
author Carl Byington <carl@five-ten-sg.com>
date Sat, 31 Jan 2009 12:12:36 -0800
parents 987aa872294e
children bdb38b434c0a
line wrap: on
line source

#include "define.h"

#define BUF_SIZE 4096

void 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* const* argv) {
    int identity = 0;
    int level = 0;
    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;
    int c;
    char ch;
    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) {
        ch = c;
        switch(ch) {
            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) {
            off_t i[x+1]; // plus 1 because 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) {
                fseeko(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))) {
                    unsigned int 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 (fseeko(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;
}

void 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");
}


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;
}