1
0
Files
irix-657m-src/irix/cmd/btool/btool_lib.c
2022-09-29 17:59:04 +03:00

308 lines
6.3 KiB
C

#ifndef _KERNEL
/* Source for the branch tool libraries. */
#include "btool_defs.h" /* For other declarations. */
#include <stdio.h>
btool_log_t Btool_branches;
static need_case = 0;
/*
NAME:
long
btool_branch(number, truth_value)
long truth_value;
long number;
PURPOSE:
This routine is called every time an expression is evaluated in order
to make a branch decision (e.g. in an if statement, while statement
etc.). It keeps track of the branches that were taken and the
direction they were taken. This is done by updating the btool_branches
array.
PRECONDITIONS:
1. 0 <= number < NUM_BRANCHES
2. truth_value is equal to 0 or 1
POSTCONDITIONS:
If truth_value is equal to 0 the branch-taken-false-counter for
the branch with number number will be incremented by one\**
The counters are not checked for overflows because even if an
overflow occurs, you still will get the information that this branch
was taken, but the number will be incorrect.
If truth_value is equal to 1 the branch-taken-true-counter
will be incremented. The return value is truth_value.
ERRORS:
1. The routine ignores this branch (caller's responsibility).
2. It is not checked if truth_value is in its range
(caller's responsibility).
*/
long
btool_branch(number, truth_value)
long number, truth_value;
{
if (number < 0 || number >= NUM_BRANCHES)
{
fprintf(stderr,"Bogus number %d ignored\n", number);
}
else
{
if (truth_value)
{
Btool_branches[number].true_count++;
}
else
{
Btool_branches[number].false_count++;
}
}
return (truth_value);
}
void
btool_func(number)
long number;
{
if (number < 0 || number >= NUM_BRANCHES)
fprintf(stderr,"Bogus number %d ignored\n", number);
else
Btool_branches[number].true_count++;
return;
}
/*
NAME:
long
btool_switch(switch_expr)
long switch_expr;
PURPOSE:
This function is called when a switch statement is encountered. It
purpose is to set the need_case flag to 1. This tells the
btool_case routine that the switch statement was entered by
evaluating the switch expression. This is a way to determine the
fall-through and goto-into-case-statement cases.
PRECONDITIONS:
POSTCONDITIONS:
The need_case variable is set equal to 1. The routine's return
value is switch_expr.
ERRORS:
*/
long
btool_switch(switch_expr)
long switch_expr;
{
need_case = 1;
return(switch_expr);
}
/*
NAME:
btool_case(number);
long number;
PURPOSE:
This routine is called every time a case statement is encountered.
Its function is to keep track of the cases that were taken. Like
btool_branch it also uses the btool_branches array to store this
information. The need_case flag is checked to see if the case
statement was entered by evaluating the switch statement.
PRECONDITIONS:
1. 0 <= number < NUM_BRANCHES
POSTCONDITIONS:
If the need_case flag is equal to 1 then the
branch-taken-true-counter for the branch (case) with number
number will be incremented by one and need_case will be set to 0.
If need_case is not equal to 1 nothing will happen.
ERRORS:
1. The routine ignores the branch (case) (caller's responsibility).
*/
void
btool_case(number)
long number;
{
if (number < 0 || number >= NUM_BRANCHES)
{
fprintf(stderr,"Bogus number %d ignored\n", number);
}
else
{
if (need_case)
{
Btool_branches[number].true_count++;
need_case =0;
}
/* Else this must be a fall-through case */
}
}
/*
NAME:
btool_writelog(filename);
char *filename;
PURPOSE:
This is the last routine called. Its purpose is to write out all
the data collected by the other routines. The input for this routine
is the name of the log file. You can use any name you want.
PRECONDITIONS:
1. It must be possible to open the file for writing.
2. It must be possible to write all data to file.
POSTCONDITIONS:
A log file names 'filename' will be created. The return code is 0.
ERRORS:
1. The routine will return with error code -1.
2. The routine will return with error code -1.
*/
int
btool_writelog(filename)
char *filename;
{
register int error = 0;
register int i;
register FILE *file;
file = fopen(filename, "w");
if (NULL == file)
{
fprintf(stderr, "Can't open branch output file %s.\n", filename);
error = -1;
}
for (i = 0; i < NUM_BRANCHES; i++)
{
if (fprintf(file, "%08d %d %d\n", i, Btool_branches[i].true_count,
Btool_branches[i].false_count)<0)
{
error = -1;
i=NUM_BRANCHES;
}
}
if (EOF == fclose(file))
{
fprintf(stderr, "Can't close branch output file %s.\n", filename);
error = -1;
}
return(error);
}
#else /* _KERNEL */
#ifdef __BTOOL__
#include "btool_defs.h" /* For other declarations. */
#include "sys/types.h"
#include "sys/systm.h"
#include "sys/errno.h"
#include "sys/atomic_ops.h"
int badbtool;
btool_log_t Btool_branches;
#pragma btool_prevent
long
btool_branch(unsigned long number, long truth_value)
{
int *a;
if (number >= NUM_BRANCHES) {
badbtool++;
} else {
if (truth_value)
a = &Btool_branches[number].true_count;
else
a = &Btool_branches[number].false_count;
atomicAddInt(a, 1);
}
return (truth_value);
}
void
btool_func(unsigned long number)
{
if (number >= NUM_BRANCHES)
badbtool++;
else
atomicAddInt(&Btool_branches[number].true_count, 1);
return;
}
/*
* The need_case stuff just plain doesn't work in the face of interrupts.
* From a code coverage perspective I don't see why it matters - ones
* wants to know whether code was executed - doesn't really matter how
* it got there..
*/
long
btool_switch(long switch_expr)
{
return(switch_expr);
}
void
btool_case(unsigned long number)
{
if (number >= NUM_BRANCHES)
badbtool++;
else
atomicAddInt(&Btool_branches[number].true_count, 1);
}
/*
* data access routines - called from syssgi
*/
int
btool_size(void)
{
return sizeof(Btool_branches);
}
int
btool_getinfo(void *b)
{
if (copyout(Btool_branches, b, sizeof(Btool_branches)))
return EFAULT;
return 0;
}
void
btool_reinit(void)
{
bzero(Btool_branches, sizeof(Btool_branches));
}
#pragma btool_unprevent
#else /* !__BTOOL__ */
#include "sys/errno.h"
int btool_size(void) { return 0; }
/* ARGSUSED */
int btool_getinfo(void *b) { return EINVAL; }
void btool_reinit(void) {}
#endif
#endif