profio.c (6532B)
1 /* C compiler: prof.out input 2 3 prof.out format: 4 #files 5 name 6 ... (#files-1 times) 7 #functions 8 name file# x y count caller file x y 9 ... (#functions-1 times) 10 #points 11 file# x y count 12 ... (#points-1 times) 13 */ 14 #include "c.h" 15 16 17 struct count { /* count data: */ 18 int x, y; /* source coordinate */ 19 int count; /* associated execution count */ 20 }; 21 22 #define MAXTOKEN 64 23 24 struct file { /* per-file prof.out data: */ 25 struct file *link; /* link to next file */ 26 char *name; /* file name */ 27 int size; /* size of counts[] */ 28 int count; /* counts[0..count-1] hold valid data */ 29 struct count *counts; /* count data */ 30 struct func { /* function data: */ 31 struct func *link; /* link to next function */ 32 char *name; /* function name */ 33 struct count count; /* total number of calls */ 34 struct caller { /* caller data: */ 35 struct caller *link; /* link to next caller */ 36 char *name; /* caller's name */ 37 char *file; /* call site: file, x, y */ 38 int x, y; 39 int count; /* number of calls from this site */ 40 } *callers; 41 } *funcs; /* list of functions */ 42 } *filelist; 43 FILE *fp; 44 45 /* acaller - add caller and site (file,x,y) to callee's callers list */ 46 static void acaller(char *caller, char *file, int x, int y, int count, struct func *callee) { 47 struct caller *q; 48 49 assert(callee); 50 for (q = callee->callers; q && (caller != q->name 51 || file != q->file || x != q->x || y != q->y); q = q->link) 52 ; 53 if (!q) { 54 struct caller **r; 55 NEW(q, PERM); 56 q->name = caller; 57 q->file = file; 58 q->x = x; 59 q->y = y; 60 q->count = 0; 61 for (r = &callee->callers; *r && (strcmp(q->name, (*r)->name) > 0 62 || strcmp(q->file, (*r)->file) > 0 || q->y > (*r)->y || q->y > (*r)->y); r = &(*r)->link) 63 ; 64 q->link = *r; 65 *r = q; 66 } 67 q->count += count; 68 } 69 70 /* compare - return <0, 0, >0 if a<b, a==b, a>b, resp. */ 71 static int compare(struct count *a, struct count *b) { 72 if (a->y == b->y) 73 return a->x - b->x; 74 return a->y - b->y; 75 } 76 77 /* findfile - return file name's file list entry, or 0 */ 78 static struct file *findfile(char *name) { 79 struct file *p; 80 81 for (p = filelist; p; p = p->link) 82 if (p->name == name) 83 return p; 84 return 0; 85 } 86 87 /* afunction - add function name and its data to file's function list */ 88 static struct func *afunction(char *name, char *file, int x, int y, int count) { 89 struct file *p = findfile(file); 90 struct func *q; 91 92 assert(p); 93 for (q = p->funcs; q && name != q->name; q = q->link) 94 ; 95 if (!q) { 96 struct func **r; 97 NEW(q, PERM); 98 q->name = name; 99 q->count.x = x; 100 q->count.y = y; 101 q->count.count = 0; 102 q->callers = 0; 103 for (r = &p->funcs; *r && compare(&q->count, &(*r)->count) > 0; r = &(*r)->link) 104 ; 105 q->link = *r; 106 *r = q; 107 } 108 q->count.count += count; 109 return q; 110 } 111 112 /* apoint - append execution point i to file's data */ 113 static void apoint(int i, char *file, int x, int y, int count) { 114 struct file *p = findfile(file); 115 116 assert(p); 117 if (i >= p->size) { 118 int j; 119 if (p->size == 0) { 120 p->size = i >= 200 ? 2*i : 200; 121 p->counts = newarray(p->size, sizeof *p->counts, PERM); 122 } else { 123 struct count *new; 124 p->size = 2*i; 125 new = newarray(p->size, sizeof *new, PERM); 126 for (j = 0; j < p->count; j++) 127 new[j] = p->counts[j]; 128 p->counts = new; 129 } 130 for (j = p->count; j < p->size; j++) { 131 static struct count z; 132 p->counts[j] = z; 133 } 134 } 135 p->counts[i].x = x; 136 p->counts[i].y = y; 137 p->counts[i].count += count; 138 if (i >= p->count) 139 p->count = i + 1; 140 } 141 142 /* findcount - return count associated with (file,x,y) or -1 */ 143 int findcount(char *file, int x, int y) { 144 static struct file *cursor; 145 146 if (cursor == 0 || cursor->name != file) 147 cursor = findfile(file); 148 if (cursor) { 149 int l, u; 150 struct count *c = cursor->counts; 151 for (l = 0, u = cursor->count - 1; l <= u; ) { 152 int k = (l + u)/2; 153 if (c[k].y > y || c[k].y == y && c[k].x > x) 154 u = k - 1; 155 else if (c[k].y < y || c[k].y == y && c[k].x < x) 156 l = k + 1; 157 else 158 return c[k].count; 159 } 160 } 161 return -1; 162 } 163 164 /* findfunc - return count associated with function name in file or -1 */ 165 int findfunc(char *name, char *file) { 166 static struct file *cursor; 167 168 if (cursor == 0 || cursor->name != file) 169 cursor = findfile(file); 170 if (cursor) { 171 struct func *p; 172 for (p = cursor->funcs; p; p = p->link) 173 if (p->name == name) 174 return p->count.count; 175 } 176 return -1; 177 } 178 179 /* getd - read a nonnegative number */ 180 static int getd(void) { 181 int c, n = 0; 182 183 while ((c = getc(fp)) != EOF && (c == ' ' || c == '\n' || c == '\t')) 184 ; 185 if (c >= '0' && c <= '9') { 186 do 187 n = 10*n + (c - '0'); 188 while ((c = getc(fp)) >= '0' && c <= '9'); 189 return n; 190 } 191 return -1; 192 } 193 194 /* getstr - read a string */ 195 static char *getstr(void) { 196 int c; 197 char buf[MAXTOKEN], *s = buf; 198 199 while ((c = getc(fp)) != EOF && c != ' ' && c != '\n' && c != '\t') 200 if (s - buf < (int)sizeof buf - 2) 201 *s++ = c; 202 *s = 0; 203 return s == buf ? (char *)0 : string(buf); 204 } 205 206 /* gather - read prof.out data from fd */ 207 static int gather(void) { 208 int i, nfiles, nfuncs, npoints; 209 char *files[64]; 210 211 if ((nfiles = getd()) < 0) 212 return 0; 213 assert(nfiles < NELEMS(files)); 214 for (i = 0; i < nfiles; i++) { 215 if ((files[i] = getstr()) == 0) 216 return -1; 217 if (!findfile(files[i])) { 218 struct file *new; 219 NEW(new, PERM); 220 new->name = files[i]; 221 new->size = new->count = 0; 222 new->counts = 0; 223 new->funcs = 0; 224 new->link = filelist; 225 filelist = new; 226 } 227 } 228 if ((nfuncs = getd()) < 0) 229 return -1; 230 for (i = 0; i < nfuncs; i++) { 231 struct func *q; 232 char *name, *file; 233 int f, x, y, count; 234 if ((name = getstr()) == 0 || (f = getd()) <= 0 235 || (x = getd()) < 0 || (y = getd()) < 0 || (count = getd()) < 0) 236 return -1; 237 q = afunction(name, files[f-1], x, y, count); 238 if ((name = getstr()) == 0 || (file = getstr()) == 0 239 || (x = getd()) < 0 || (y = getd()) < 0) 240 return -1; 241 if (*name != '?') 242 acaller(name, file, x, y, count, q); 243 } 244 if ((npoints = getd()) < 0) 245 return -1; 246 for (i = 0; i < npoints; i++) { 247 int f, x, y, count; 248 if ((f = getd()) < 0 || (x = getd()) < 0 || (y = getd()) < 0 249 || (count = getd()) < 0) 250 return -1; 251 if (f) 252 apoint(i, files[f-1], x, y, count); 253 } 254 return 1; 255 } 256 257 /* process - read prof.out data from file */ 258 int process(char *file) { 259 int more; 260 261 if ((fp = fopen(file, "r")) != NULL) { 262 struct file *p; 263 while ((more = gather()) > 0) 264 ; 265 fclose(fp); 266 if (more < 0) 267 return more; 268 for (p = filelist; p; p = p->link) 269 qsort(p->counts, p->count, sizeof *p->counts, 270 (int (*)(const void *, const void *)) 271 compare); 272 273 return 1; 274 } 275 return 0; 276 }