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