2 * (c)2006 Galois Connections, Inc.
16 /* This is the runtime support for the Haskell Program Coverage (hpc) toolkit,
23 static int hpc_inited
= 0; // Have you started this component?
24 static FILE *tixFile
; // file being read/written
25 static int tix_ch
; // current char
26 static StgWord64 magicTixNumber
; // Magic/Hash number to mark .tix files
28 typedef struct _Info
{
29 char *modName
; // name of module
30 int tickCount
; // number of ticks
31 int tickOffset
; // offset into a single large .tix Array
32 StgWord64
*tixArr
; // tix Array from the program execution (local for this module)
36 // This is a cruel hack, we should completely redesign the format specifier handling in the RTS.
38 #define PRIuWORD64 "lu"
40 #define PRIuWORD64 "llu"
45 StgWord64
*tixBoxes
= 0; // local copy of tixBoxes array, from file.
46 int totalTixes
= 0; // total number of tix boxes.
50 static char *tixFilename
;
52 static void failure(char *msg
) {
53 printf("Hpc failure: %s\n",msg
);
54 printf("(perhaps remove .tix file?)\n");
59 static int init_open(char *filename
)
61 tixFile
= fopen(filename
,"r");
65 tix_ch
= getc(tixFile
);
69 static void expect(char c
) {
71 printf("Hpc: parse failed (%c,%c)\n",tix_ch
,c
);
74 tix_ch
= getc(tixFile
);
77 static void ws(void) {
78 while (tix_ch
== ' ') {
79 tix_ch
= getc(tixFile
);
83 static char *expectString(void) {
87 while (tix_ch
!= '"') {
88 tmp
[tmp_ix
++] = tix_ch
;
89 tix_ch
= getc(tixFile
);
98 static StgWord64
expectWord64(void) {
100 while (isdigit(tix_ch
)) {
101 tmp
= tmp
* 10 + (tix_ch
-'0');
102 tix_ch
= getc(tixFile
);
107 static void hpc_init(void) {
111 if (hpc_inited
!= 0) {
117 tixFilename
= (char *) malloc(strlen(prog_name
) + 6);
118 sprintf(tixFilename
, "%s.tix", prog_name
);
120 if (init_open(tixFilename
)) {
128 magicTixNumber
= expectWord64();
132 while(tix_ch
!= ']') {
133 tmpModule
= (Info
*)calloc(1,sizeof(Info
));
136 tmpModule
-> modName
= expectString();
140 tmpModule
-> tickCount
= (int)expectWord64();
145 tmpModule
-> tickOffset
= totalTixes
;
146 totalTixes
+= tmpModule
-> tickCount
;
148 tmpModule
-> tixArr
= 0;
153 nextModule
->next
=tmpModule
;
155 nextModule
=tmpModule
;
164 tixBoxes
= (StgWord64
*)calloc(totalTixes
,sizeof(StgWord64
));
167 for(i
= 0;i
< totalTixes
;i
++) {
172 tixBoxes
[i
] = expectWord64();
179 // later, we will find a binary specific
180 magicTixNumber
= (StgWord64
)0;
184 /* Called on a per-module basis, at startup time, declaring where the tix boxes are stored in memory.
185 * This memory can be uninitized, because we will initialize it with either the contents
186 * of the tix file, or all zeros.
190 hs_hpc_module(char *modName
,int modCount
,StgWord64
*tixArr
) {
191 Info
*tmpModule
, *lastModule
;
195 printf("hs_hpc_module(%s,%d)\n",modName
,modCount
);
203 for(;tmpModule
!= 0;tmpModule
= tmpModule
->next
) {
204 if (!strcmp(tmpModule
->modName
,modName
)) {
205 if (tmpModule
->tickCount
!= modCount
) {
206 failure("inconsistent number of tick boxes");
208 assert(tmpModule
->tixArr
== 0);
209 assert(tixBoxes
!= 0);
210 tmpModule
->tixArr
= tixArr
;
211 for(i
=0;i
< modCount
;i
++) {
212 tixArr
[i
] = tixBoxes
[i
+ tmpModule
->tickOffset
];
216 lastModule
= tmpModule
;
218 // Did not find entry so add one on.
219 tmpModule
= (Info
*)calloc(1,sizeof(Info
));
220 tmpModule
->modName
= modName
;
221 tmpModule
->tickCount
= modCount
;
223 tmpModule
->tickOffset
= lastModule
->tickOffset
+ lastModule
->tickCount
;
225 tmpModule
->tickOffset
= 0;
227 tmpModule
->tixArr
= tixArr
;
228 for(i
=0;i
< modCount
;i
++) {
236 lastModule
->next
=tmpModule
;
240 printf("end: hs_hpc_module\n");
244 /* This is called after all the modules have registered their local tixboxes,
245 * and does a sanity check: are we good to go?
252 printf("startupHpc\n");
255 if (hpc_inited
== 0) {
262 for(;tmpModule
!= 0;tmpModule
= tmpModule
->next
) {
263 if (!tmpModule
->tixArr
) {
264 fprintf(stderr
,"error: module %s did not register any hpc tick data\n",
266 fprintf(stderr
,"(perhaps remove %s ?)\n",tixFilename
);
273 /* Called at the end of execution, to write out the Hpc *.tix file
274 * for this exection. Safe to call, even if coverage is not used.
285 if (hpc_inited
== 0) {
289 FILE *f
= fopen(tixFilename
,"w");
293 fprintf(f
,"Tix %" PRIuWORD64
" [", magicTixNumber
);
295 for(;tmpModule
!= 0;tmpModule
= tmpModule
->next
) {
301 fprintf(f
,"(\"%s\",%u)",
303 tmpModule
->tickCount
);
305 fprintf(stderr
,"%s: %u (offset=%u)\n",
307 tmpModule
->tickCount
,
308 tmpModule
->tickOffset
);
315 for(;tmpModule
!= 0;tmpModule
= tmpModule
->next
) {
316 if (!tmpModule
->tixArr
) {
317 fprintf(stderr
,"warning: module %s did not register any hpc tick data\n",
321 for(i
= 0;i
< tmpModule
->tickCount
;i
++) {
328 if (tmpModule
->tixArr
) {
329 fprintf(f
,"%" PRIuWORD64
,tmpModule
->tixArr
[i
]);