288 lines
8.5 KiB
C
288 lines
8.5 KiB
C
// Copyright 2007 Georgia Institute of Technology. All rights reserved.
|
|
/**
|
|
* @file common.h
|
|
*
|
|
* The bare necessities of FASTlib programming in C, including
|
|
* standard types, formatted messages to stderr, and useful libraries
|
|
* and compiler directives.
|
|
*
|
|
* This file should be included before all built-in libraries because
|
|
* it includes the _REENTRANT definition needed for thread-safety.
|
|
* Files base.h or fastlib.h include this file first and may serve as
|
|
* surrogates.
|
|
*
|
|
* @see compiler.h
|
|
*/
|
|
|
|
#ifndef BASE_COMMON_H
|
|
#define BASE_COMMON_H
|
|
|
|
#ifndef _REENTRANT
|
|
#define _REENTRANT
|
|
#endif
|
|
|
|
#include "base/basic_types.h"
|
|
#include "compiler.h"
|
|
#include "ansi_colors.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
EXTERN_C_BEGIN
|
|
|
|
/** A no-op used in some macros. */
|
|
#define NOP ((void)0)
|
|
|
|
|
|
|
|
/* Types and definitions to assist managment of problem scale. */
|
|
|
|
/* Ensure that one and only one problem scale is selected. */
|
|
#if defined(SCALE_MASSIVE)
|
|
#if defined(SCALE_LARGE) || defined(SCALE_NORMAL)
|
|
#error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined.
|
|
#endif
|
|
#elif defined(SCALE_LARGE)
|
|
#if defined(SCALE_NORMAL)
|
|
#error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined.
|
|
#endif
|
|
#elif !defined(SCALE_NORMAL)
|
|
#define SCALE_NORMAL
|
|
#endif
|
|
|
|
/**
|
|
* Index type used in FASTlib for array sizes, etc.
|
|
*
|
|
* Define one of the following (default SCALE_NORMAL):
|
|
*
|
|
* SCALE_NORMAL - Problems are as large can be indexed with your
|
|
* machine's standard integers. As of 2007, this is 32 bits.
|
|
*
|
|
* SCALE_LARGE - Problems are as large as your machine's architecture
|
|
* can support. Unless you have more than 2 billion data points,
|
|
* this will waste some space and reduce cache efficiency.
|
|
*
|
|
* SCALE_MASSIVE - Problems are 64-bit indexed even on 32-bit
|
|
* machines, rendering them larger than RAM.
|
|
*
|
|
* Values are signed to allow uninitialized indices of -1 as well as
|
|
* consideration of potentially negative differences between indices.
|
|
*/
|
|
#if defined(SCALE_MASSIVE)
|
|
typedef int64 index_t; /* For larger than RAM data sets. */
|
|
#elif defined(SCALE_LARGE)
|
|
typedef ssize_t index_t; /* As large as this machine can handle. */
|
|
#elif defined(SCALE_NORMAL)
|
|
typedef int index_t; /* Normal sized data; usually 32-bit. */
|
|
#endif
|
|
|
|
/**
|
|
* Length modifier for emitting index_t with printf.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* index_t i = 42;
|
|
* printf("%"LI"d\n", i);
|
|
* @endcode
|
|
*/
|
|
#if defined(SCALE_MASSIVE)
|
|
#define LI L64
|
|
#elif defined(SCALE_LARGE)
|
|
#define LI "l" /* TODO: confirm correct. */
|
|
#elif defined(SCALE_NORMAL)
|
|
#define LI ""
|
|
#endif
|
|
|
|
/** Size of a kilobyte in bytes. */
|
|
#define KILOBYTE (((size_t)1) << 10)
|
|
/** Size of a megabyte in bytes. */
|
|
#define MEGABYTE (((size_t)1) << 20)
|
|
/** Size of a gigabyte in bytes. */
|
|
#define GIGABYTE (((size_t)1) << 30)
|
|
/* Add more of these as necessary. */
|
|
|
|
|
|
|
|
/* Tools for FASTlib stderr messages, warnings, and errors. */
|
|
|
|
/** Whether to segfault instead of calling C's abort(). */
|
|
extern int segfault_on_abort;
|
|
/** Whether to treat nonfatal warnings as fatal. */
|
|
extern int abort_on_nonfatal;
|
|
/** Whether to wait for user input after nonfatal warnings. */
|
|
extern int pause_on_nonfatal;
|
|
/** Whether to print call locations for notifications. */
|
|
extern int print_notify_locs;
|
|
|
|
/** Different types of messages FASTlib prints to stderr. */
|
|
typedef enum {
|
|
/** Message for an unrecoverable error. */
|
|
FL_MSG_FATAL = 0,
|
|
/** Message for a potentially recoverable warning. */
|
|
FL_MSG_NONFATAL = 1,
|
|
/** Message for a significant but non-problematic event. */
|
|
FL_MSG_NOTIFY_STAR = 2,
|
|
/** Message for a standard, non-problematic event. */
|
|
FL_MSG_NOTIFY = 3
|
|
} fl_msg_t;
|
|
|
|
/** Default markers for FASTlib messages. */
|
|
extern char fl_msg_marker[];
|
|
/** Default colors for FASTlib message markers. */
|
|
extern const char * fl_msg_color[];
|
|
|
|
/**
|
|
* Terminates with an error, flushing all streams.
|
|
*
|
|
* Behavior adjustable with segfault_on_abort, which may be handy for
|
|
* valgrind or other debuggers.
|
|
*/
|
|
COMPILER_NO_RETURN
|
|
void fl_abort(void);
|
|
|
|
/**
|
|
* Waits for the user to press return.
|
|
*
|
|
* This function will obliterate anything in the stdin buffer.
|
|
*/
|
|
void fl_pause(void);
|
|
|
|
/** Prints a colored message header. */
|
|
void fl_print_msg_header(char marker, const char *color);
|
|
|
|
/** Print a location in code. */
|
|
void fl_print_msg_loc(const char *file, const char *func, int line);
|
|
|
|
/** Implementation for FATAL. */
|
|
COMPILER_NO_RETURN
|
|
COMPILER_PRINTF(4, 5)
|
|
void fl_print_fatal_msg(const char *file, const char *func, int line,
|
|
const char* format, ...);
|
|
|
|
/** Implementation for NONFATAL, NOTIFY_STAR, and NOTIFY. */
|
|
COMPILER_PRINTF(5, 6)
|
|
void fl_print_msg(const char *file, const char *func, int line,
|
|
fl_msg_t msg_type, const char* format, ...);
|
|
|
|
/**
|
|
* Aborts, printing call location and a message to stderr.
|
|
*
|
|
* @param msg_params format string and variables, as in printf
|
|
*/
|
|
#define FATAL(msg_params...) (fl_print_fatal_msg( \
|
|
__FILE__, __FUNCTION__, __LINE__, msg_params))
|
|
|
|
/**
|
|
* (Possibly) aborts or pauses, printing call location and a message
|
|
* to stderr.
|
|
*
|
|
* @param msg_params format string and variables, as in printf
|
|
*/
|
|
#define NONFATAL(msg_params...) (fl_print_msg( \
|
|
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NONFATAL, msg_params))
|
|
|
|
/**
|
|
* Prints (possibly) call location and a message with special marker
|
|
* to stderr.
|
|
*
|
|
* @param msg_params format string and variables, as in printf
|
|
*/
|
|
#define NOTIFY_STAR(msg_params...) (fl_print_msg( \
|
|
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY_STAR, msg_params))
|
|
|
|
/**
|
|
* Prints (possibly) call location and a message with standard marker
|
|
* to stderr.
|
|
*
|
|
* @param msg_params format string and variables, as in printf
|
|
*/
|
|
#define NOTIFY(msg_params...) (fl_print_msg( \
|
|
__FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY, msg_params))
|
|
|
|
/**
|
|
* Prints a progress bar using ANSI commands to stay in place.
|
|
*
|
|
* For proper formatting, desc should be 22 characters or fewer and
|
|
* the program should avoid output of other text while emitting a
|
|
* progress bar. When finished with a progress bar, emit a newline
|
|
* ('\n') to keep the bar on screen or a line of spaces followed by a
|
|
* carriage return ('\r') to clear it.
|
|
*
|
|
* @param name printed next to the progress bar; max 22 characters
|
|
* @param perc percentage of bar filled; should range from 0 to 100
|
|
*/
|
|
void fl_print_progress(const char *name, int perc);
|
|
|
|
|
|
|
|
/* Tools for expressing success or failure of FASTlib functions. */
|
|
|
|
/**
|
|
* Type for indicating success or failure.
|
|
*
|
|
* Return these rather than ints to indicate your functions' results;
|
|
* ints are interchangeably interpreted with either zero or nonzero
|
|
* for success, but values of this type have fixed meaning.
|
|
*
|
|
* You may extend the meaning of this type in your code by instead
|
|
* returning integer values other than SUCCESS_FAIL or SUCCESS_PASS,
|
|
* but ensure that all failure values are less than or equal to
|
|
* SUCCESS_FAIL, all success values are greater than or equal to
|
|
* SUCCESS_PASS, and all warning values are in between.
|
|
*
|
|
* Because the values given below are subject to change, special
|
|
* values should be expressed as deltas, e.g. SUCCESS_FAIL - 5. If
|
|
* you need more than 64 warning values, etc., consider instead using
|
|
* an additional pointer argument to return an error code.
|
|
*/
|
|
typedef enum {
|
|
/** Upper-bound value indicating failed operation. */
|
|
SUCCESS_FAIL = 63,
|
|
/** A generic warning value. */
|
|
SUCCESS_WARN = 96,
|
|
/** Lower-bound value indicating successful operation. */
|
|
SUCCESS_PASS = 128
|
|
} success_t;
|
|
|
|
/**
|
|
* True on SUCCESS_PASS or greater; false otherwise.
|
|
*
|
|
* Distinct from !FAILED(x). Optimized for the passing case.
|
|
*/
|
|
#define PASSED(x) (likely((x) >= SUCCESS_PASS))
|
|
|
|
/**
|
|
* True on SUCCESS_FAIL or less; false otherwise.
|
|
*
|
|
* Distinct from !PASSED(x). Optimized for the non-failing case.
|
|
*/
|
|
#define FAILED(x) (unlikely((x) <= SUCCESS_FAIL))
|
|
|
|
/**
|
|
* Asserts that an operation succeeds; otherwise, aborts.
|
|
*
|
|
* This optimized check occurs regardless of debug mode.
|
|
*/
|
|
#define MUST_PASS(x) \
|
|
(likely(x >= SUCCESS_PASS) ? NOP : FATAL("MUST_PASS failed: %s", #x))
|
|
|
|
/**
|
|
* Asserts that an operation does not fail; otherwise, aborts.
|
|
*
|
|
* This optimized check occurs regardless of debug mode.
|
|
*/
|
|
#define MUST_NOT_FAIL(x) \
|
|
(likely(x > SUCCESS_FAIL) ? NOP : FATAL("MUST_NOT_FAIL failed: %s", #x))
|
|
|
|
/** Converts C library non-negative success into a success_t. */
|
|
#define SUCCESS_FROM_C(x) (unlikely((x) < 0) ? SUCCESS_FAIL : SUCCESS_PASS)
|
|
|
|
|
|
|
|
EXTERN_C_END
|
|
|
|
#endif /* BASE_COMMON_H */
|