367 lines
11 KiB
C++
367 lines
11 KiB
C++
/************************************************************************
|
|
*
|
|
* display.cpp - Definitions of the result display subsystem
|
|
*
|
|
* $Id: display.cpp 648752 2008-04-16 17:01:56Z faridz $
|
|
*
|
|
************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h> /* for fflush(), printf(), puts(), ... */
|
|
#include <string.h> /* for strchr() */
|
|
|
|
#include "cmdopt.h" /* for target_name -should this be moved? */
|
|
#include "exec.h" /* for get_signame */
|
|
|
|
#include "display.h"
|
|
#include "target.h" /* for target_status */
|
|
|
|
|
|
/**
|
|
ProcessStatus enum lookup table for 'short' (6 character) strings.
|
|
*/
|
|
static const char* const
|
|
short_st_name [ST_LAST] = {
|
|
"OK", /*ST_OK*/
|
|
"COMP", /*ST_COMPILE*/
|
|
"LINK", /*ST_LINK*/
|
|
"EXIST", /*ST_EXIST*/
|
|
"XPERM", /*ST_EXECUTE_FLAG*/
|
|
"EXEC", /*ST_EXECUTE*/
|
|
"NOUT", /*ST_NO_OUTPUT*/
|
|
"OUTPUT", /*ST_NO_REF*/
|
|
"BREF", /*ST_BAD_REF*/
|
|
"DIFF", /*ST_BAD_OUTPUT*/
|
|
"FORMAT", /*ST_FORMAT*/
|
|
"OFLOW", /*ST_OVERFLOW*/
|
|
"ERROR", /*ST_SYSTEM_ERROR*/
|
|
"KILLED", /*ST_KILLED*/
|
|
"NKILL" /*ST_NOT_KILLED*/
|
|
};
|
|
|
|
|
|
/**
|
|
ProcessStatus enum lookup table for descriptive strings.
|
|
*/
|
|
static const char* const
|
|
verbose_st_name [ST_LAST] = {
|
|
"OK", /*ST_OK*/
|
|
"Program failed to compile.", /*ST_COMPILE*/
|
|
"Program failed to link.", /*ST_LINK*/
|
|
"Program executable not found.", /*ST_EXIST*/
|
|
"Program not executable.", /*ST_EXECUTE_FLAG*/
|
|
"Program failed to execute.", /*ST_EXECUTE*/
|
|
"Program generated no output.", /*ST_NO_OUTPUT*/
|
|
"Program reference output missing.", /*ST_NO_REF*/
|
|
"Bad reference.", /*ST_BAD_REF*/
|
|
"Program produced unexpected output.", /*ST_BAD_OUTPUT*/
|
|
"Program produced output in unexpected format.", /*ST_FORMAT*/
|
|
"Arithmetic overflow.", /*ST_OVERFLOW*/
|
|
"System error occurred.", /*ST_SYSTEM_ERROR*/
|
|
"Process killed after a timeout.", /*ST_KILLED*/
|
|
"Failed to kill process after a timeout." /*ST_NOT_KILLED*/
|
|
};
|
|
|
|
|
|
/**
|
|
Prints an argv array, quoting elelemnts containing spaces.
|
|
*/
|
|
static int
|
|
print_argv (const char* const argv[], int newline)
|
|
{
|
|
assert (0 != argv);
|
|
|
|
const char* const* parg = argv;
|
|
|
|
int nchars = 0;
|
|
|
|
for (parg = argv; *parg; ++parg) {
|
|
|
|
const char *fmt = "%s ";
|
|
|
|
if (strchr (*parg, ' '))
|
|
fmt = "\"%s\" ";
|
|
|
|
nchars += printf (fmt, *parg);
|
|
}
|
|
|
|
if (newline)
|
|
puts ("");
|
|
|
|
return nchars;
|
|
}
|
|
|
|
|
|
/**
|
|
Generates output header, designed for text output and console viewing.
|
|
*/
|
|
static void
|
|
print_header_plain (const char* const argv[])
|
|
{
|
|
(void)&argv;
|
|
|
|
puts ("NAME STATUS WARN ASSERTS "
|
|
"FAILED PERCNT USER SYS REAL");
|
|
}
|
|
|
|
|
|
/**
|
|
Generates output header in verbose mode.
|
|
*/
|
|
static void
|
|
print_header_verbose (const char* const argv[])
|
|
{
|
|
print_argv (argv, 1 /* append newline */);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Generates target name listing, designed for text output and console viewing.
|
|
*/
|
|
static void
|
|
print_target_plain (const struct target_opts *defaults)
|
|
{
|
|
const char* const target_name = get_target ();
|
|
|
|
assert (0 == defaults->verbose);
|
|
|
|
printf ("%-40.40s ", target_name);
|
|
|
|
/* flush to prevent killing a signal from not displaying the text */
|
|
fflush (stdout);
|
|
}
|
|
|
|
|
|
/**
|
|
Generates target name listing, designed for text output and console viewing.
|
|
*/
|
|
static void
|
|
print_target_verbose (const struct target_opts *defaults)
|
|
{
|
|
assert (defaults->verbose);
|
|
|
|
printf ("%s ", "Executing \"");
|
|
print_argv (defaults->argv, 0 /* no newline */);
|
|
|
|
/* print stdin, stdout, and stderr redirections */
|
|
if (defaults->infname && *defaults->infname)
|
|
printf (" <%s", defaults->infname);
|
|
|
|
if (defaults->outfname && *defaults->outfname)
|
|
printf (" >%s 2>&1", defaults->outfname);
|
|
|
|
puts ("\"");
|
|
|
|
/* flush to prevent killing a signal from not displaying the text */
|
|
fflush (stdout);
|
|
}
|
|
|
|
|
|
/**
|
|
Generates target result listing, designed for text output and console
|
|
viewing.
|
|
*/
|
|
static void print_status_plain (const struct target_status* status)
|
|
{
|
|
unsigned valid_timing;
|
|
assert (0 != status);
|
|
assert (ST_OK <= status->status && ST_LAST > status->status);
|
|
|
|
valid_timing = status->usr_time != (clock_t)-1
|
|
&& status->sys_time != (clock_t)-1
|
|
&& ST_NOT_KILLED != status->status;
|
|
|
|
if (status->status) /* if status is set, print it */
|
|
printf ("%6s", short_st_name [status->status]);
|
|
else if (status->signaled) /* if exit signal is non-zero, print it */
|
|
printf ("%6s", get_signame (status->exit));
|
|
else if (status->exit) /* if exit code is non-zero, print it */
|
|
printf ("%6d", status->exit);
|
|
else
|
|
printf (" 0");
|
|
|
|
printf (" %4u", status->c_warn + status->l_warn + status->t_warn);
|
|
|
|
/* Print assetions, if any registered */
|
|
if ( (unsigned)-1 != status->assert
|
|
&& 0 == status->status
|
|
&& 0 == status->exit) {
|
|
if (status->assert) {
|
|
const int percnt = int ( 100.0
|
|
* (status->assert - status->failed)
|
|
/ status->assert);
|
|
printf (" %7u %6u %5d%%", status->assert, status->failed, percnt);
|
|
}
|
|
else {
|
|
printf (" 0 %6u 100%%", status->failed);
|
|
}
|
|
}
|
|
else if (valid_timing || status->wall_time != (clock_t)-1)
|
|
printf (" ");
|
|
|
|
/* Print timings, if available */
|
|
if (valid_timing)
|
|
printf (" %7.3f %7.3f", (float)status->usr_time / TICKS_PER_SEC,
|
|
(float)status->sys_time / TICKS_PER_SEC);
|
|
else if (status->wall_time != (clock_t)-1)
|
|
printf (" ");
|
|
|
|
if (status->wall_time != (clock_t)-1)
|
|
printf (" %7.3f\n", (float)status->wall_time / TICKS_PER_SEC);
|
|
else
|
|
puts ("");
|
|
}
|
|
|
|
|
|
/**
|
|
Generates verbose target result listing.
|
|
*/
|
|
static void
|
|
print_status_verbose (const struct target_status* status)
|
|
{
|
|
unsigned valid_timing;
|
|
|
|
assert (0 != status);
|
|
assert (ST_OK <= status->status && ST_LAST > status->status);
|
|
|
|
valid_timing = status->usr_time != (clock_t)-1
|
|
&& status->sys_time != (clock_t)-1
|
|
&& ST_NOT_KILLED != status->status;
|
|
|
|
if (status->status) /* if status is set, print it */
|
|
printf (" Status: %s\n", verbose_st_name [status->status]);
|
|
else if (status->signaled) /* if exit signal is non-zero, print it */
|
|
printf (" Process signalled: %s\n", get_signame (status->exit));
|
|
else {
|
|
printf (" Exit status: %6d%s\n"
|
|
" Compiler warnings: %6u\n"
|
|
" Linker warnings: %6u\n"
|
|
" Runtime warnings: %6u\n",
|
|
status->exit, 0 == status->exit ? " (success)" : "",
|
|
status->c_warn,
|
|
status->l_warn,
|
|
status->t_warn);
|
|
|
|
/* Print assetions, if any registered */
|
|
if ((unsigned)-1 != status->assert && status->assert) {
|
|
printf (" Failed assertions: %6u\n"
|
|
" Total assertions: %6u\n",
|
|
status->failed, status->assert);
|
|
}
|
|
}
|
|
|
|
/* Print timings, if available */
|
|
if (valid_timing) {
|
|
const float wall = (float)status->wall_time / TICKS_PER_SEC;
|
|
const float user = (float)status->usr_time / TICKS_PER_SEC;
|
|
const float sys = (float)status->sys_time / TICKS_PER_SEC;
|
|
|
|
printf (" Times:\n"
|
|
" Real %7.3fs\n"
|
|
" User %7.3fs\n"
|
|
" Sys %7.3fs\n",
|
|
wall, user, sys);
|
|
}
|
|
|
|
puts ("");
|
|
}
|
|
|
|
|
|
/**
|
|
Placholder output footer function, unneeded for text output and console
|
|
viewing.
|
|
*/
|
|
static void
|
|
print_footer_plain (int count, const struct target_status *summary)
|
|
{
|
|
/* compute cumulative times for all targets */
|
|
const float wall = (float)summary->wall_time / TICKS_PER_SEC;
|
|
const float user = (float)summary->usr_time / TICKS_PER_SEC;
|
|
const float sys = (float)summary->sys_time / TICKS_PER_SEC;
|
|
|
|
printf ("PROGRAM SUMMARY:\n"
|
|
" Programs: %9d\n"
|
|
" Non-zero exit status: %9d\n"
|
|
" Signalled: %9d\n"
|
|
" Compiler warnings: %9u\n"
|
|
" Linker warnings: %9u\n"
|
|
" Runtime warnings: %9u\n",
|
|
count,
|
|
summary->exit,
|
|
summary->signaled,
|
|
summary->c_warn,
|
|
summary->l_warn,
|
|
summary->t_warn);
|
|
|
|
if ((unsigned)-1 != summary->assert) {
|
|
/* print assertion counters only when they're valid */
|
|
printf (" Assertions: %9u\n"
|
|
" Failed assertions: %9u\n",
|
|
summary->assert,
|
|
summary->failed);
|
|
}
|
|
|
|
printf ( " Cumulative times:\n"
|
|
" Real %7.3fs\n"
|
|
" User %7.3fs\n"
|
|
" Sys %7.3fs\n",
|
|
wall,
|
|
user,
|
|
sys);
|
|
}
|
|
|
|
|
|
static void
|
|
print_footer_verbose (int count, const struct target_status *summary)
|
|
{
|
|
print_footer_plain (count, summary);
|
|
}
|
|
|
|
|
|
/**
|
|
Sets the output functions referenced.
|
|
*/
|
|
void set_output_format (enum OutputFmt format)
|
|
{
|
|
if (FMT_VERBOSE == format) {
|
|
print_header = print_header_verbose;
|
|
print_target = print_target_verbose;
|
|
print_status = print_status_verbose;
|
|
print_footer = print_footer_verbose;
|
|
}
|
|
else {
|
|
/* only two formats implemented */
|
|
assert (FMT_PLAIN == format);
|
|
|
|
print_header = print_header_plain;
|
|
print_target = print_target_plain;
|
|
print_status = print_status_plain;
|
|
print_footer = print_footer_plain;
|
|
}
|
|
}
|
|
|
|
|
|
void (*print_header) (const char* const[]) = print_header_plain;
|
|
void (*print_target) (const struct target_opts*) = print_target_plain;
|
|
void (*print_status) (const struct target_status*) = print_status_plain;
|
|
void (*print_footer) (int, const struct target_status*) = print_footer_plain;
|