| /* |
| * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include <stdio.h> |
| #include <stdarg.h> |
| #include <assert.h> |
| #include <ctype.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| |
| /*************************************************************/ |
| |
| #include "nsk_tools.h" |
| |
| /*************************************************************/ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /*************************************************************/ |
| |
| static struct { |
| int verbose; |
| int tracing; |
| int nComplains; |
| } nsk_context = {NSK_FALSE, NSK_TRACE_NONE, 0}; |
| |
| void nsk_setVerboseMode(int verbose) { |
| nsk_context.verbose = verbose; |
| } |
| |
| int nsk_getVerboseMode() { |
| return nsk_context.verbose; |
| } |
| |
| void nsk_setTraceMode(int mode) { |
| nsk_context.tracing = mode; |
| } |
| |
| int nsk_getTraceMode() { |
| return nsk_context.tracing; |
| } |
| |
| /*************************************************************/ |
| |
| static const char* file_basename(const char* fullname) { |
| const char* p; |
| const char* base = fullname;; |
| |
| if (fullname == NULL) |
| return NULL; |
| |
| for (p = fullname; *p != '\0'; p++) { |
| if (*p == '/' || *p == '\\') |
| base = p + 1; |
| } |
| return base; |
| } |
| |
| /*************************************************************/ |
| |
| void nsk_display(const char format[], ...) { |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvdisplay(NULL,0,format,ap); |
| va_end(ap); |
| } |
| |
| void nsk_ldisplay(const char file[], int line, const char format[], ...) { |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvdisplay(file,line,format,ap); |
| va_end(ap); |
| } |
| |
| void nsk_vdisplay(const char format[], va_list ap) { |
| nsk_lvdisplay(NULL,0,format,ap); |
| } |
| |
| void nsk_lvdisplay(const char file[], int line, const char format[], va_list ap) |
| { |
| if (!nsk_context.verbose) |
| return; |
| if (file != NULL) |
| (void) nsk_printf("- %s, %d: ",file_basename(file),line); |
| (void) nsk_vprintf(format,ap); |
| } |
| |
| /*************************************************************/ |
| |
| void nsk_complain(const char format[], ...) { |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvcomplain(NULL,0,format,ap); |
| va_end(ap); |
| } |
| |
| void nsk_lcomplain(const char file[], int line, const char format[], ...) |
| { |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvcomplain(file,line,format,ap); |
| va_end(ap); |
| } |
| |
| void nsk_vcomplain(const char format[], va_list ap) { |
| nsk_lvcomplain(NULL,0,format,ap); |
| } |
| |
| void nsk_lvcomplain(const char file[], int line, |
| const char format[], va_list ap) |
| { |
| char msg_buf[1024]; |
| nsk_context.nComplains++; |
| if (!nsk_context.verbose) { |
| if ( nsk_context.nComplains > NSK_MAX_COMPLAINS_NON_VERBOSE ) { |
| return; |
| } |
| |
| if ( nsk_context.nComplains == NSK_MAX_COMPLAINS_NON_VERBOSE ) { |
| nsk_printf("# ...\n" |
| "# ERROR: too many complains, giving up to save disk space (CR 6341460)\n" |
| "# Please rerun the test with -verbose option to listen to the entire song\n"); |
| return; |
| } |
| } |
| |
| // Generate the message into a temp buffer since we can't call vfprintf on it twice, |
| // and also may need to modify a copy of the message slightly. |
| (void) vsnprintf(msg_buf, sizeof(msg_buf), format, ap); |
| |
| // Print a fake exception with the error for failure analysis. |
| // Do this only for the first complaint. |
| if (nsk_context.nComplains == 1) { |
| char msg_buf2[sizeof(msg_buf)]; |
| char* nl_ptr; |
| strncpy(msg_buf2, msg_buf, sizeof(msg_buf2)); |
| // Only include up to the 1st newline in the exception's error message. |
| nl_ptr = strchr(msg_buf2, '\n'); |
| if (nl_ptr != NULL) { |
| nl_ptr++; // Skip past the newline char. |
| *nl_ptr = '\0'; // Terminate the string after the newline char. |
| } else if (strlen(msg_buf2) != 0) { |
| msg_buf2[strlen(msg_buf2)-1] = '\n'; // Make sure we have a newline char at the end. |
| } |
| (void) nsk_printf("The following fake exception stacktrace is for failuire analysis. \n"); |
| (void) nsk_printf("nsk.share.Fake_Exception_for_RULE_Creation: "); |
| if (file != NULL) { |
| (void) nsk_printf("(%s:%d) ", file_basename(file), line); |
| } |
| (void) nsk_printf(msg_buf2); |
| (void) nsk_printf("\tat nsk_lvcomplain(%s:%d)\n", file_basename(__FILE__), __LINE__); |
| } |
| |
| if (file != NULL) { |
| (void) nsk_printf("# ERROR: %s, %d: ", file_basename(file), line); |
| } else { |
| (void) nsk_printf("# ERROR: "); |
| } |
| (void) nsk_printf(msg_buf); |
| } |
| |
| /*************************************************************/ |
| |
| void nsk_ltrace(int mode, const char file[], int line, const char format[], ...) { |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvtrace(mode,file,line,format,ap); |
| va_end(ap); |
| } |
| |
| void nsk_lvtrace(int mode, const char file[], int line, const char format[], va_list ap) |
| { |
| if ((nsk_context.tracing & mode) == 0) { |
| return; |
| } |
| |
| { |
| const char* prefix; |
| switch (mode) { |
| case NSK_TRACE_BEFORE: |
| prefix = ">>"; |
| break; |
| case NSK_TRACE_AFTER: |
| prefix = "<<"; |
| break; |
| default: |
| prefix = ".."; |
| break; |
| } |
| |
| (void) nsk_printf("- %s, %d: %s ",file_basename(file),line,prefix); |
| (void) nsk_vprintf(format,ap); |
| } |
| } |
| |
| /*************************************************************/ |
| |
| int nsk_lverify(int value, const char file[], int line, const char format[], ...) |
| { |
| int fail=0; |
| va_list ap; |
| va_start(ap,format); |
| nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap); |
| if (!value) { |
| nsk_lvcomplain(file,line,format,ap); |
| nsk_printf("# verified assertion is FALSE\n"); |
| fail=1; |
| }; |
| va_end(ap); |
| return !fail; |
| } |
| |
| /*************************************************************/ |
| |
| int nsk_vprintf(const char format[], va_list ap) { |
| int x = vfprintf(stdout,format,ap); |
| int err = fflush(stdout); |
| if (err != 0) { |
| printf("stdout: fflush failed - err=%d errno=%d x=%d\n", err, errno, x); |
| fprintf(stderr, "stderr: fflush failed - err=%d errno=%d x=%d\n", err, errno, x); |
| } |
| assert(err == 0); |
| return x; |
| } |
| |
| int nsk_printf(const char format[], ...) { |
| int x; |
| va_list ap; |
| va_start(ap,format); |
| x = nsk_vprintf(format,ap); |
| va_end(ap); |
| return x; |
| } |
| |
| /*************************************************************/ |
| |
| #define MAX_HEX_COLUMNS 255 |
| |
| void nsk_printHexBytes(const char indent[], int columns, |
| size_t size, const unsigned char bytes[]) { |
| char hex[MAX_HEX_COLUMNS * 3 + 1]; |
| char ascii[MAX_HEX_COLUMNS + 1]; |
| char buf[16]; |
| |
| size_t i; |
| |
| if (size <= 0 || bytes == NULL) |
| return; |
| |
| for (i = 0; i < size; i += columns) { |
| int j; |
| |
| hex[0] = '\0'; |
| ascii[0] = '\0'; |
| |
| for (j = 0; j < columns && (i + j) < size; j++) { |
| unsigned int b = (unsigned int)bytes[i + j] & 0xFF; |
| char ch = (char)bytes[i + j]; |
| |
| if (!(isascii(ch) && isprint(ch))) ch = '.'; |
| sprintf(buf, " %02X", b); |
| strcat(hex, buf); |
| ascii[j] = ch; |
| } |
| |
| ascii[j] = '\0'; |
| if (j < columns) { |
| for (; j < columns; j++) { |
| strcat(hex, " "); |
| } |
| } |
| |
| nsk_printf("%s0x%08X: %s %s\n", indent, (int)i, hex, ascii); |
| } |
| } |
| |
| /*************************************************************/ |
| |
| const char* nsk_null_string(const char* str) { |
| return (str == NULL)? "<NULL>" : str; |
| } |
| |
| /*************************************************************/ |
| |
| #ifdef __cplusplus |
| } |
| #endif |