Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

171 lines
3.8 KiB
C

#ifndef lint
static char sccsid[] = "@(#)bb_link.c 1.1 92/07/30 Copyr 1987 Sun Micro";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/file.h>
#include "strings.h"
/*
* CAVEAT: If you change the format of the following structure,
* you must also change the code generator. (cf., cgrdr/pcc.c)
*
* Iropt made me do this.
*/
struct bblink {
int initflag; /* 1 if initialized */
char *filename; /* source file name */
unsigned int *counters; /* array of basic block counters */
int ncntrs; /* num of elements in counters[] */
struct bblink *next; /* chain to next structure */
};
static struct bblink *linkhdr=NULL;
static int __tcov_init = 0;
static void __tcov_init_func();
/* import */
extern int getpid();
/* export */
void __bb_init_func (/*bb*/);
/*
* __tcov_exit - this routine is called from the standard exit routine
* via the on_exit() routine.
* It dumps the values of the counters to the appropriate
* .d files.
*/
static void
__tcov_exit(retcode)
int retcode;
{
FILE *dotd_fp;
FILE *tmp_fp;
unsigned int *bb;
int line;
int count;
int c;
int n;
int fd;
int tries;
struct bblink *linkp;
static int beenhere;
char tmp[50];
char *lock = "/tmp/tcov.lock";
extern int errno;
if (beenhere) {
unlink(lock);
_exit(retcode);
}
for (tries = 0; tries < 5; tries++) {
fd = open(lock, O_CREAT | O_EXCL, 666);
if (fd == -1) {
sleep(1);
} else {
break;
}
}
if (fd != -1) {
close(fd);
} else {
fprintf(stderr, "Tcov lock file is busy - could not write data\n");
_exit(retcode);
}
beenhere = 1;
sprintf(tmp, "/tmp/count.%d", getpid());
for (linkp = linkhdr; linkp != NULL; linkp = linkp->next) {
dotd_fp = fopen(linkp->filename, "r");
if (dotd_fp == NULL) {
fprintf(stderr, "count: Could not open %s, errno %d\n",
linkp->filename, errno);
continue;
}
tmp_fp = fopen(tmp, "w");
if (tmp_fp == NULL) {
fclose(dotd_fp);
fprintf(stderr, "count: Could not create tmp file\n");
continue;
}
bb = linkp->counters;
n = linkp->ncntrs;
while (n > 0 && fscanf(dotd_fp, "%d %d", &line, &count) == 2) {
count += *bb;
bb++;
fprintf(tmp_fp, "%d %d\n", line, count);
n--;
}
if (n != 0) {
fprintf(stderr, "%s: Corrupt file: %d blocks left\n",
linkp->filename, n);
}
fclose(dotd_fp);
fclose(tmp_fp);
dotd_fp = fopen(linkp->filename, "w");
if (dotd_fp == NULL) {
unlink(tmp);
continue;
}
tmp_fp = fopen(tmp, "r");
if (tmp_fp == NULL) {
unlink(tmp);
fclose(dotd_fp);
continue;
}
while ((c = getc(tmp_fp)) != EOF) {
putc(c, dotd_fp);
}
fclose(dotd_fp);
fclose(tmp_fp);
unlink(tmp);
}
unlink(lock);
}
/*
* Routines compiled with the -a option call __bb_init_func
* the first time they are called. They pass an initialized
* bblink structure, which associates a source file name with
* a list of counters for each basic block in the source file.
*
* History: this is copied from the Fortran version of bb_link.c.
* The old C version didn't have a __bb_init_func, since the
* bb_count preprocessor happily generated N similar but slightly
* different versions of the same function (1 per source file).
*
* A more recent change is to require the compiler(s) to allocate
* static storage for the bblink structure and the array of counters.
* This used to call malloc(), which caused a great deal of trouble
* with programs that use sbrk().
*/
void
__bb_init_func ( bb )
struct bblink *bb;
{
/*
* first time a tcov-compiled routine is called,
* arm the tcov exit handler. Earlier versions
* used to catch signals here. Bad idea for a test
* coverage analyzer.
*/
if (!__tcov_init) {
on_exit(__tcov_exit, 0);
__tcov_init = 1;
}
if (bb != NULL) {
bb->next = linkhdr;
linkhdr = bb;
}
bb->initflag = 1;
}