Added backend & sample for Android
[openal-soft/android/lowlatency.git] / android / jni / tremolo / annotate.c
blobd2748ab2bf59845f0c9c4f1a12bccaae9aefe541
1 #include <stdio.h>
2 #include <stdlib.h>
4 typedef struct
6 char *name;
7 int offset;
8 int count;
9 float percent;
11 Profile_Entry;
13 static const char *profile_filename;
14 static const char *map_filename;
15 static int granularity;
16 static int *profile;
17 static int profile_len;
18 static Profile_Entry *functionTable;
19 static int numFunctions;
20 static int maxFunctions;
22 static void read_args(int argc, const char *argv[])
24 if (argc < 3)
26 fprintf(stderr, "annotate <profile file> <map file>\n");
27 fclose(stderr);
28 exit(EXIT_FAILURE);
30 profile_filename = argv[1];
31 map_filename = argv[2];
34 static void read_profile()
36 FILE *in = fopen(profile_filename, "rb");
38 if (in == NULL)
40 fprintf(stderr, "Failed to open profile file '%s'\n",
41 profile_filename);
42 fclose(stderr);
43 exit(EXIT_FAILURE);
46 fseek(in, 0, SEEK_END);
47 profile_len = (int)ftell(in)-8;
48 fseek(in, 0, SEEK_SET);
50 if ((fgetc(in) != 'P') ||
51 (fgetc(in) != 'R') ||
52 (fgetc(in) != '0') ||
53 (fgetc(in) != 'F'))
55 fclose(in);
56 fprintf(stderr, "'%s' is not a profile file\n",
57 profile_filename);
58 fclose(stderr);
59 exit(EXIT_FAILURE);
62 fread(&granularity, 4, 1, in);
63 profile = malloc(profile_len);
64 if (profile == NULL)
66 fclose(in);
67 fprintf(stderr, "Out of memory reading profile\n");
68 fclose(stderr);
69 exit(EXIT_FAILURE);
72 fread(profile, 4, profile_len>>2, in);
73 fclose(in);
76 static void addFn(const char *text, int offset)
78 if (numFunctions == maxFunctions)
80 int newSize = maxFunctions*2;
82 if (newSize == 0)
83 newSize = 128;
85 functionTable = realloc(functionTable,
86 newSize*sizeof(Profile_Entry));
87 if (functionTable == NULL)
89 fprintf(stderr, "Out of memory reading mapfile\n");
90 fflush(stderr);
91 exit(EXIT_FAILURE);
93 maxFunctions = newSize;
96 functionTable[numFunctions].name = malloc(strlen(text)+1);
97 strcpy(functionTable[numFunctions].name, text);
98 functionTable[numFunctions].offset = offset;
99 functionTable[numFunctions].count = 0;
100 functionTable[numFunctions].percent = 0.0;
101 //fprintf(stdout, "%s %x\n", functionTable[numFunctions].name,
102 // functionTable[numFunctions].offset);
103 numFunctions++;
106 static void read_map()
108 FILE *in = fopen(map_filename, "rb");
109 char text[2048];
111 if (in == NULL)
113 fprintf(stderr, "Failed to open map file '%s'\n",
114 map_filename);
115 fclose(stderr);
116 exit(EXIT_FAILURE);
119 functionTable = NULL;
120 numFunctions = 0;
121 maxFunctions = 0;
123 addFn("Address 0", 0);
125 while (!feof(in))
127 int offset;
128 char c;
129 char *t;
131 /* Skip over any whitespace */
134 c = fgetc(in);
136 while (((c == 32) || (c == 9)) && (!feof(in)));
137 ungetc(c, in);
139 /* Try to read an offset */
140 if (fscanf(in, "0x%x", &offset) != 1)
142 goto over;
144 /* Skip over any whitespace */
147 c = fgetc(in);
149 while ((c == 32) && (!feof(in)));
150 ungetc(c, in);
152 /* Names never start with . or (*/
153 if ((c != '_') &&
154 ((c < 'a') || (c > 'z')) &&
155 ((c < 'A') || (c > 'Z')))
156 goto over;
158 /* Read the name */
159 t = text;
162 c = fgetc(in);
163 *t++ = c;
165 while (c > 32);
166 t[-1] = 0;
168 /* Now there should be nothing left on this line */
169 if ((c != 10) && (c != 13))
170 goto over;
172 /* And put the return back */
173 ungetc(c, in);
175 if (t != text)
177 addFn(text, offset);
180 over:
181 /* Skip to the end of the line */
184 c = fgetc(in);
186 while ((c >= 32) && (!feof(in)));
188 /* Skip over any newlines */
189 while (((c == 10) || (c == 13)) && (!feof(in)))
191 c = fgetc(in);
194 /* And put the first non whitespace/non return char back */
195 ungetc(c, in);
198 fclose(in);
201 static void show_profile()
203 int i;
205 for (i=0; i < numFunctions; i++)
207 fprintf(stdout, "%08x (%6.2f%%: %6d) %s\n",
208 functionTable[i].offset,
209 functionTable[i].percent,
210 functionTable[i].count,
211 functionTable[i].name);
215 int byAddress(const void *_e1, const void *_e2)
217 const Profile_Entry *e1 = (const Profile_Entry *)_e1;
218 const Profile_Entry *e2 = (const Profile_Entry *)_e2;
220 return e1->offset - e2->offset;
223 int byTime(const void *_e1, const void *_e2)
225 const Profile_Entry *e1 = (const Profile_Entry *)_e1;
226 const Profile_Entry *e2 = (const Profile_Entry *)_e2;
228 return e2->count - e1->count;
231 static void process_profile()
233 int next;
234 int fn;
235 int idx;
236 int max;
237 int total;
239 /* Sort into address order */
240 qsort(functionTable,
241 numFunctions,
242 sizeof(Profile_Entry),
243 byAddress);
245 /* Run through the profile adding it to the appropriate function */
246 fn = -1; /* Which function are we looking at */
247 next = -1; /* At what address should we move to the next function */
248 idx = 0; /* Where are we in the profile */
249 max = profile_len>>2;
250 total = 0;
251 for (idx = 0; idx < max; idx++)
253 while ((idx<<(granularity+2)) >= next)
255 /* Move to the next function */
256 fn++;
257 //fprintf(stdout, "Will be on fn %s until we pass %x\n",
258 // functionTable[fn].name, functionTable[fn+1].offset);
259 next = 0x7FFFFFFF;
260 if (fn+1 < numFunctions)
262 next = functionTable[fn+1].offset;
265 //fprintf(stdout, "fn=%d count=%d idx=%d next=%x\n",
266 // fn, functionTable[fn].count, idx, next);
267 functionTable[fn].count += profile[idx];
268 total += profile[idx];
271 for (fn = 0; fn < numFunctions; fn++)
273 functionTable[fn].percent = 100.0*functionTable[fn].count/total;
276 fprintf(stdout, "Profile by Address\n");
277 show_profile();
279 /* Sort into time order */
280 qsort(functionTable,
281 numFunctions,
282 sizeof(Profile_Entry),
283 byTime);
285 fprintf(stdout, "\n\n");
286 fprintf(stdout, "Profile by Time\n");
287 show_profile();
290 int main(int argc, const char *argv[])
292 read_args(argc, argv);
294 read_profile();
295 read_map();
297 process_profile();
299 return EXIT_SUCCESS;