1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* //device/tools/dmtracedump/CreateTrace.c
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project** Copyright 2006, The Android Open Source Project
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
5de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** Licensed under the Apache License, Version 2.0 (the "License");
6de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** you may not use this file except in compliance with the License.
7de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
9de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro**     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project**
11de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** Unless required by applicable law or agreed to in writing, software
12de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** distributed under the License is distributed on an "AS IS" BASIS,
13de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro** See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project** limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a test file in the format required by dmtrace.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define NOT_VM
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Profile.h"        // from VM header
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <assert.h>
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <sys/time.h>
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <time.h>
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <ctype.h>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Values from the header of the data file.
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct DataHeader {
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int magic;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short version;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    short offsetToData;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long long startWhen;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} DataHeader;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define VERSION 2
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint versionNumber = VERSION;
474d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipinceint verbose = 0;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectDataHeader header = { 0x574f4c53, VERSION, sizeof(DataHeader), 0LL };
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *versionHeader = "*version\n";
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *clockDef = "clock=thread-cpu\n";
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *keyThreads =
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project"*threads\n"
564d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince"1      main\n"
574d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince"2      foo\n"
584d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince"3      bar\n"
594d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince"4      blah\n";
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *keyEnd = "*end\n";
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct dataRecord {
644d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    unsigned int        time;
654d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    int                 threadId;
664d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    unsigned int        action;         /* 0=entry, 1=exit, 2=exception exit */
674d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    char                *fullName;
684d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    char                *className;
694d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    char                *methodName;
704d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    char                *signature;
714d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    unsigned int        methodId;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} dataRecord;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdataRecord *records;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define BUF_SIZE 1024
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar buf[BUF_SIZE];
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttypedef struct stack {
804d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    dataRecord  **frames;
814d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    int         indentLevel;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} stack;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* Mac OS doesn't have strndup(), so implement it here.
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectchar *strndup(const char *src, size_t len)
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *dest = (char *) malloc(len + 1);
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    strncpy(dest, src, len);
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dest[len] = 0;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dest;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse the input file.  It looks something like this:
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * # This is a comment line
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4  1 A
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 6  1  B
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8  1  B
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10 1 A
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * where the first column is the time, the second column is the thread id,
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and the third column is the method (actually just the class name).  The
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * number of spaces between the 2nd and 3rd columns is the indentation and
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * determines the call stack.  Each called method must be indented by one
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * more space.  In the example above, A is called at time 4, A calls B at
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * time 6, B returns at time 8, and A returns at time 10.  Thread 1 is the
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only thread that is running.
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * An alternative file format leaves out the first two columns:
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  B
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  B
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In this file format, the thread id is always 1, and the time starts at
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2 and increments by 2 for each line.
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid parseInputFile(const char *inputFileName)
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int time = 0, threadId;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int linenum = 0;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int nextRecord = 0;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int indentLevel = 0;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stack *callStack;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *inputFp = fopen(inputFileName, "r");
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (inputFp == NULL) {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        perror(inputFileName);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Count the number of lines in the buffer */
1354d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    int numRecords = 0;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int maxThreadId = 1;
1374d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    int maxFrames = 0;
1384d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    char *indentEnd;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fgets(buf, BUF_SIZE, inputFp)) {
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *cp = buf;
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '#')
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1434d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        numRecords += 1;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (isdigit(*cp)) {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int time = strtoul(cp, &cp, 0);
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (isspace(*cp))
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cp += 1;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int threadId = strtoul(cp, &cp, 0);
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (maxThreadId < threadId)
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                maxThreadId = threadId;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1524d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        indentEnd = cp;
1534d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        while (isspace(*indentEnd))
1544d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            indentEnd += 1;
1554d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        if (indentEnd - cp + 1 > maxFrames)
1564d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            maxFrames = indentEnd - cp + 1;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int numThreads = maxThreadId + 1;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Add space for a sentinel record at the end */
1614d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    numRecords += 1;
1624d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince    records = (dataRecord *) malloc(sizeof(dataRecord) * numRecords);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    callStack = (stack *) malloc(sizeof(stack) * numThreads);
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int ii;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (ii = 0; ii < numThreads; ++ii) {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        callStack[ii].frames = NULL;
1674d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        callStack[ii].indentLevel = 0;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    rewind(inputFp);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fgets(buf, BUF_SIZE, inputFp)) {
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int indent;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int action;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *save_cp;
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        linenum += 1;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char *cp = buf;
1784d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Skip lines that start with '#' */
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '#')
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
1824d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince
1834d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        /* Get time and thread id */
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isdigit(*cp)) {
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* If the line does not begin with a digit, then fill in
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * default values for the time and threadId.
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            time += 2;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            threadId = 1;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            time = strtoul(cp, &cp, 0);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (isspace(*cp))
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cp += 1;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            threadId = strtoul(cp, &cp, 0);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += 1;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Allocate space for the thread stack, if necessary
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (callStack[threadId].frames == NULL) {
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dataRecord **stk;
2014d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            stk = (dataRecord **) malloc(sizeof(dataRecord *) * maxFrames);
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            callStack[threadId].frames = stk;
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        indentLevel = callStack[threadId].indentLevel;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        save_cp = cp;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (isspace(*cp)) {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += 1;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        indent = cp - save_cp + 1;
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].time = time;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].threadId = threadId;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        save_cp = cp;
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (*cp != '\n')
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += 1;
217de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Remove trailing spaces */
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp -= 1;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (isspace(*cp))
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp -= 1;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp += 1;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        len = cp - save_cp;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].fullName = strndup(save_cp, len);
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Parse the name to support "class.method signature" */
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].className = NULL;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].methodName = NULL;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].signature = NULL;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp = strchr(save_cp, '.');
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cp) {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            len = cp - save_cp;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (len > 0)
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                records[nextRecord].className = strndup(save_cp, len);
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            save_cp = cp + 1;
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp = strchr(save_cp, ' ');
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cp == NULL)
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cp = strchr(save_cp, '\n');
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cp && cp > save_cp) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                len = cp - save_cp;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                records[nextRecord].methodName = strndup(save_cp, len);
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                save_cp = cp + 1;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cp = strchr(save_cp, ' ');
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (cp == NULL)
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    cp = strchr(save_cp, '\n');
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (cp && cp > save_cp) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    len = cp - save_cp;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    records[nextRecord].signature = strndup(save_cp, len);
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2534d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        if (verbose) {
2544d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            printf("Indent: %d; IndentLevel: %d; Line: %s", indent, indentLevel, buf);
2554d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        }
2564d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        action = 0;
2584d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        if (indent == indentLevel + 1) { // Entering a method
2594d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            if (verbose)
2604d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                printf("  Entering %s\n", records[nextRecord].fullName);
2614d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            callStack[threadId].frames[indentLevel] = &records[nextRecord];
2624d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        } else if (indent == indentLevel) { // Exiting a method
2634d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            // Exiting method must be currently on top of stack (unless stack is empty)
2644d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            if (callStack[threadId].frames[indentLevel - 1] == NULL) {
2654d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                if (verbose)
2664d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                    printf("  Exiting %s (past bottom of stack)\n", records[nextRecord].fullName);
2674d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                callStack[threadId].frames[indentLevel - 1] = &records[nextRecord];
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                action = 1;
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
2704d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                if (indentLevel < 1) {
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fprintf(stderr, "Error: line %d: %s", linenum, buf);
2724d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                    fprintf(stderr, "  expected positive (>0) indentation, found %d\n",
2734d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                            indent);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    exit(1);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
2764d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                char *name = callStack[threadId].frames[indentLevel - 1]->fullName;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (strcmp(name, records[nextRecord].fullName) == 0) {
2784d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                    if (verbose)
2794d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                        printf("  Exiting %s\n", name);
2804d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                    action = 1;
2814d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                } else { // exiting method doesn't match stack's top method
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fprintf(stderr, "Error: line %d: %s", linenum, buf);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fprintf(stderr, "  expected exit from %s\n",
2844d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                            callStack[threadId].frames[indentLevel - 1]->fullName);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    exit(1);
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nextRecord != 0) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fprintf(stderr, "Error: line %d: %s", linenum, buf);
2914d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                fprintf(stderr, "  expected indentation %d [+1], found %d\n",
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        indentLevel, indent);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exit(1);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
2964d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            if (verbose) {
2974d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                printf("  Nonzero indent at first record\n");
2984d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                printf("  Entering %s\n", records[nextRecord].fullName);
2994d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            }
3004d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This is the first line of data, so we allow a larger
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // initial indent.  This allows us to test popping off more
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // frames than we entered.
3044d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            indentLevel = indent - 1;
3054d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            callStack[threadId].frames[indentLevel] = &records[nextRecord];
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3074d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (action == 0)
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indentLevel += 1;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            indentLevel -= 1;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        records[nextRecord].action = action;
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        callStack[threadId].indentLevel = indentLevel;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        nextRecord += 1;
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Mark the last record with a sentinel */
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&records[nextRecord], 0, sizeof(dataRecord));
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write values to the binary data file.
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid write2LE(FILE* fp, unsigned short val)
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc(val & 0xff, fp);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc(val >> 8, fp);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid write4LE(FILE* fp, unsigned int val)
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc(val & 0xff, fp);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 8) & 0xff, fp);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 16) & 0xff, fp);
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 24) & 0xff, fp);
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid write8LE(FILE* fp, unsigned long long val)
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc(val & 0xff, fp);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 8) & 0xff, fp);
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 16) & 0xff, fp);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 24) & 0xff, fp);
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 32) & 0xff, fp);
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 40) & 0xff, fp);
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 48) & 0xff, fp);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    putc((val >> 56) & 0xff, fp);
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeDataRecord(FILE *dataFp, int threadId, unsigned int methodVal,
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                   unsigned int elapsedTime)
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (versionNumber == 1)
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        putc(threadId, dataFp);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write2LE(dataFp, threadId);
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write4LE(dataFp, methodVal);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write4LE(dataFp, elapsedTime);
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeDataHeader(FILE *dataFp)
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timeval tv;
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    struct timezone tz;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gettimeofday(&tv, &tz);
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned long long startTime = tv.tv_sec;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startTime = (startTime << 32) | tv.tv_usec;
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    header.version = versionNumber;
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write4LE(dataFp, header.magic);
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write2LE(dataFp, header.version);
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write2LE(dataFp, header.offsetToData);
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    write8LE(dataFp, startTime);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeKeyMethods(FILE *keyFp)
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataRecord *pRecord, *pNext;
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *methodStr = "*methods\n";
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fwrite(methodStr, strlen(methodStr), 1, keyFp);
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* Assign method ids in multiples of 4 */
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    unsigned int methodId = 0;
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pRecord = records; pRecord->fullName; ++pRecord) {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pRecord->methodId)
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            continue;
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int id = ++methodId << 2;
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pRecord->methodId = id;
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* Assign this id to all the other records that have the
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * same name.
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (pNext = pRecord + 1; pNext->fullName; ++pNext) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pNext->methodId)
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                continue;
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (strcmp(pRecord->fullName, pNext->fullName) == 0)
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                pNext->methodId = id;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pRecord->className == NULL || pRecord->methodName == NULL) {
4024d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            fprintf(keyFp, "0x%x        %s      m       ()\n",
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pRecord->methodId, pRecord->fullName);
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (pRecord->signature == NULL) {
4054d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            fprintf(keyFp, "0x%x        %s      %s      ()\n",
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pRecord->methodId, pRecord->className,
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pRecord->methodName);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
4094d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            fprintf(keyFp, "0x%x        %s      %s      %s\n",
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pRecord->methodId, pRecord->className,
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pRecord->methodName, pRecord->signature);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeKeys(FILE *keyFp)
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(keyFp, "%s%d\n%s", versionHeader, versionNumber, clockDef);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fwrite(keyThreads, strlen(keyThreads), 1, keyFp);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    writeKeyMethods(keyFp);
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fwrite(keyEnd, strlen(keyEnd), 1, keyFp);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeDataRecords(FILE *dataFp)
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dataRecord *pRecord;
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (pRecord = records; pRecord->fullName; ++pRecord) {
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        unsigned int val = METHOD_COMBINE(pRecord->methodId, pRecord->action);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        writeDataRecord(dataFp, pRecord->threadId, val, pRecord->time);
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid writeTrace(const char* traceFileName)
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    FILE *fp = fopen(traceFileName, "w");
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (fp == NULL) {
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        perror(traceFileName);
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    writeKeys(fp);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    writeDataHeader(fp);
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    writeDataRecords(fp);
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fclose(fp);
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint parseOptions(int argc, char **argv)
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int err = 0;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (1) {
4514d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        int opt = getopt(argc, argv, "v:d");
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opt == -1)
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opt) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'v':
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                versionNumber = strtoul(optarg, NULL, 0);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (versionNumber != 1 && versionNumber != 2) {
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    fprintf(stderr, "Error: version number (%d) must be 1 or 2\n",
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            versionNumber);
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    err = 1;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
4634d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince            case 'd':
4644d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                verbose = 1;
4654d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince                break;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                err = 1;
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return err;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char** argv)
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *inputFile;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char *traceFileName = NULL;
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int len;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (parseOptions(argc, argv) || argc - optind != 2) {
4814d9b60166efe75325efc76823dab0181a78ca445Rodrigo Ipince        fprintf(stderr, "Usage: %s [-v version] [-d] input_file trace_prefix\n",
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                argv[0]);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exit(1);
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    inputFile = argv[optind++];
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    parseInputFile(inputFile);
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    traceFileName = argv[optind++];
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    writeTrace(traceFileName);
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 0;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
494