48
|
1 #include "define.h"
|
|
2
|
16
|
3 #include <stdio.h>
|
|
4 #include <ctype.h>
|
|
5 #include <string.h>
|
|
6
|
|
7 #ifndef _WIN32
|
|
8 # include <unistd.h>
|
|
9 #endif
|
|
10
|
|
11 #ifndef __GNUC__
|
|
12 # include "XGetopt.h"
|
|
13 #endif
|
|
14
|
|
15
|
|
16 #define BUF_SIZE 4096
|
|
17
|
|
18 int usage();
|
|
19 size_t get(void * buf, int size, unsigned int count, FILE *fp);
|
|
20 int split_args(char *args, int **targ);
|
|
21 int is_in(int a, int *b, int c);
|
|
22
|
|
23 int main(int argc, char** argv) {
|
52
|
24 int identity = 0;
|
|
25 int level = 0;
|
46
|
26 off_t *i = NULL;
|
52
|
27 int x, ptr, stop=0, flag;
|
|
28 char *fname, *buf, rec_type;
|
|
29 unsigned char version;
|
|
30 int *show_type=NULL, show_size=0;
|
|
31 int *ex_type=NULL, ex_size=0;
|
|
32 unsigned int funcname=0, filename=0, text=0, end=0, dtype=0, line=0, c;
|
|
33 FILE *fp;
|
|
34 struct pst_debug_file_rec_m mfile_rec;
|
|
35 struct pst_debug_file_rec_l lfile_rec;
|
|
36 char format = 'D'; // default
|
|
37 while ((c = getopt(argc, argv, "f:t:x:")) != -1) {
|
|
38 switch(c) {
|
|
39 case 'f':
|
|
40 // change the output format
|
|
41 format = toupper(optarg[0]);
|
|
42 break;
|
|
43 case 't':
|
|
44 //change the type of statements shown
|
|
45 show_size = split_args(optarg, &show_type);
|
|
46 // type = atoi(optarg);
|
|
47 break;
|
|
48 case 'x':
|
|
49 // change the type of statements excluded
|
|
50 ex_size = split_args(optarg, &ex_type);
|
|
51 break;
|
|
52 }
|
|
53 }
|
|
54 if (argc > optind) {
|
|
55 fname = argv[optind++];
|
|
56 } else {
|
|
57 usage();
|
|
58 exit(2);
|
|
59 }
|
16
|
60
|
52
|
61 fp = fopen(fname, "rb");
|
|
62 if (fp == NULL) {
|
|
63 printf("Error. couldn't open debug file\n");
|
|
64 return 2;
|
|
65 }
|
|
66 if (get(&version, sizeof(char), 1, fp)==0) {
|
|
67 printf("Error. could not read version byte from front of file");
|
|
68 return 3;
|
|
69 }
|
16
|
70
|
52
|
71 if (version > DEBUG_VERSION) {
|
|
72 printf("Version number is higher than the format I know about.");
|
|
73 return 4;
|
|
74 }
|
16
|
75
|
52
|
76 buf = (char*) xmalloc(BUF_SIZE);
|
16
|
77
|
52
|
78 while (!stop) {
|
48
|
79 off_t temp;
|
52
|
80 if (fread(&temp, sizeof(off_t), 1, fp)<=0) break;
|
48
|
81 x = (int)temp;
|
52
|
82 ptr = 0;
|
|
83 if (x > 0) {
|
|
84 if (i) free(i);
|
|
85 i = (off_t*)xmalloc(sizeof(off_t)*(x+1));
|
|
86 // plus 1 cause we want to read the offset of the next index
|
|
87 if (get(i, sizeof(off_t), x+1, fp)==0) {
|
|
88 // we have reached the end of the debug file
|
|
89 printf("oh dear. we must now end\n");
|
|
90 break;
|
|
91 }
|
|
92 while (ptr < x) {
|
|
93 fseek(fp, i[ptr++], SEEK_SET);
|
|
94 get(&rec_type, 1, sizeof(char), fp);
|
|
95 if (rec_type == 'L') {
|
|
96 get(&lfile_rec, sizeof(lfile_rec), 1, fp);
|
|
97 funcname=lfile_rec.funcname;
|
|
98 filename=lfile_rec.filename;
|
|
99 text = lfile_rec.text;
|
|
100 end = lfile_rec.end;
|
|
101 dtype = lfile_rec.type;
|
|
102 line = lfile_rec.line;
|
|
103 } else if (rec_type == 'M') {
|
|
104 get(&mfile_rec, sizeof(mfile_rec), 1, fp);
|
|
105 funcname = mfile_rec.funcname;
|
|
106 filename = mfile_rec.filename;
|
|
107 text = mfile_rec.text;
|
|
108 end = mfile_rec.end;
|
|
109 dtype = mfile_rec.type;
|
|
110 line = mfile_rec.line;
|
|
111 }
|
|
112 if (dtype == DEBUG_FUNCENT_NO) level++;
|
|
113 if ((show_type == NULL || is_in(dtype, show_type, show_size)) &&
|
|
114 (ex_type == NULL || !is_in(dtype, ex_type, ex_size))) {
|
|
115 c = 0; flag = 0;
|
|
116 while (c < end) {
|
|
117 int ii = (level-1) * 4;
|
|
118 if (ii < 0) ii = 0;
|
|
119 if (ii > 64) ii = 64;
|
|
120 char indent[ii+1];
|
|
121 memset(indent, ' ', ii);
|
|
122 indent[ii] = '\0';
|
|
123 if (c + (BUF_SIZE-1) < end) {
|
|
124 get(buf, 1, BUF_SIZE-1, fp);
|
|
125 buf[BUF_SIZE-1] = '\0';
|
|
126 c += BUF_SIZE-1;
|
|
127 } else {
|
|
128 get(buf, 1, end-c, fp);
|
|
129 buf[end-c] = '\0';
|
|
130 c = end;
|
|
131 }
|
|
132 if (flag == 0) {
|
|
133 if (format == 'I') { // indented text format
|
|
134 char *b = buf+text;
|
|
135 identity++;
|
|
136 //printf("%s %d %s/%s[%d]: ", indent, identity, &buf[filename], &buf[funcname], line);
|
|
137 printf("%s %s/%s[%d]: ", indent, &buf[filename], &buf[funcname], line);
|
|
138 while (b) {
|
|
139 char *p = strchr(b, '\n');
|
|
140 if (p) {
|
|
141 *p = '\0';
|
|
142 printf("%s\n%s ", b, indent);
|
|
143 b = p + 1;
|
|
144 }
|
|
145 else {
|
|
146 printf("%s", b);
|
|
147 b = NULL;
|
|
148 }
|
|
149 }
|
|
150 }
|
|
151 else if (format == 'T') { // text format
|
|
152 printf("%s/%s[%d]: %s", &buf[filename], &buf[funcname], line, &buf[text]);
|
|
153 } else {
|
|
154 printf("Type: %d\nFile[line]: %s[%d]\nFunction:%s\nText:%s", dtype,
|
|
155 &buf[filename], line, &buf[funcname], &buf[text]);
|
|
156 }
|
|
157 flag = 1;
|
|
158 } else {
|
|
159 if (format == 'I') {
|
|
160 char *b = buf;
|
|
161 while (b) {
|
|
162 char *p = strchr(b, '\n');
|
|
163 if (p) {
|
|
164 *p = '\0';
|
|
165 printf("%s\n%s ", b, indent);
|
|
166 b = p + 1;
|
|
167 }
|
|
168 else {
|
|
169 printf("%s", b);
|
|
170 b = NULL;
|
|
171 }
|
|
172 }
|
|
173 }
|
|
174 else printf("%s", buf);
|
|
175 }
|
|
176 }
|
|
177 printf("\n");
|
|
178 }
|
|
179 if (dtype == DEBUG_FUNCRET_NO) level--;
|
|
180 }
|
|
181 if (fseek(fp, i[ptr], SEEK_SET)==-1) {
|
|
182 printf("finished\n");
|
|
183 break;
|
|
184 }
|
|
185 } else {
|
|
186 printf("...no more items\n");
|
|
187 break;
|
|
188 }
|
|
189 }
|
|
190 free(buf);
|
|
191 fclose(fp);
|
|
192 if (format == 'I') printf("final indent level = %i\n", level);
|
|
193 return 0;
|
16
|
194 }
|
36
|
195
|
43
|
196 size_t get(void *buf, int size, unsigned int count, FILE *fp) {
|
52
|
197 size_t z;
|
|
198 if ((z=fread(buf, size, count, fp)) < count) {
|
|
199 printf("Read Failed! (size=%d, count=%d,z=%ld)\n", size, count, (long)z);
|
|
200 exit(1);
|
|
201 }
|
|
202 return z;
|
16
|
203 }
|
|
204
|
|
205 int usage() {
|
52
|
206 printf("readlog -t[show_type] -x[exclude_type] -f[format] filename\n");
|
|
207 printf("\tformat:\n\t\tt: text log format\n");
|
|
208 printf("\t\ti: indented text log format\n");
|
|
209 printf("\tshow_type:\n\t\tcomma separated list of types to show "
|
|
210 "[ie, 2,4,1,6]\n");
|
|
211 printf("\texclude_type:\n\t\tcomma separated list of types to exclude "
|
|
212 "[ie, 1,5,3,7]\n");
|
|
213 return 0;
|
16
|
214 }
|
|
215
|
36
|
216
|
16
|
217 int split_args(char *args, int **targ) {
|
52
|
218 int count = 1, *i, x, z;
|
|
219 char *tmp = args, *y;
|
|
220 if (*targ != NULL) {
|
|
221 free(*targ);
|
|
222 }
|
|
223 // find the number of tokens in the string. Starting
|
|
224 // from 1 cause there will always be one
|
|
225 while ((tmp = strchr(tmp, ',')) != NULL) {
|
|
226 tmp++; count++;
|
|
227 }
|
|
228 *targ = (int*)xmalloc(count * sizeof(int));
|
|
229 i = *targ; // for convienience
|
|
230 tmp = args;
|
|
231 z = 0;
|
|
232 for (x = 0; x < count; x++) {
|
|
233 y = strtok(tmp, ",");
|
|
234 tmp = NULL; // must be done after first call
|
|
235 if (y != NULL) {
|
|
236 i[x] = atoi(y);
|
|
237 z++;
|
|
238 }
|
|
239 }
|
|
240 return z;
|
16
|
241 }
|
|
242
|
36
|
243
|
16
|
244 // checks to see if the first arg is in the array of the second arg,
|
|
245 // the size of which is specified with the third arg. If the second
|
36
|
246 // arg is NULL, then it is obvious that it is not there.
|
16
|
247 int is_in(int a, int *b, int c){
|
52
|
248 int d = 0;
|
|
249 if (b == NULL || c == 0) { // no array or no items in array
|
|
250 return 0;
|
|
251 }
|
|
252 while (d < c) {
|
|
253 if (a == b[d]) return 1;
|
|
254 d++;
|
|
255 }
|
|
256 return 0;
|
16
|
257 }
|