File: diagnostics.cpp

package info (click to toggle)
polyml 5.8.1-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 57,736 kB
  • sloc: cpp: 44,918; ansic: 26,921; asm: 13,495; sh: 4,670; makefile: 610; exp: 525; python: 253; awk: 91
file content (205 lines) | stat: -rw-r--r-- 4,613 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
    Title:      Diagnostics

    Copyright (c) 2011, 2015, 2018, 2019 David C.J. Matthews

    Copyright (c) 2000
        Cambridge University Technical Services Limited

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License version 2.1 as published by the Free Software Foundation.
    
    This library 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
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#elif defined(_WIN32)
#include "winconfig.h"
#else
#error "No configuration file"
#endif

#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif

#ifdef HAVE_ASSERT_H 
#include <assert.h>
#define ASSERT(x)   assert(x)
#else
#define ASSERT(x)
#endif

#if (defined(_WIN32))
#include "winstartup.h"
#include "winguiconsole.h"
#endif

#if (defined(_WIN32))
#include <tchar.h>
#endif

#include "errors.h"
#include "noreturn.h"
#include "globals.h"
#include "diagnostics.h"
#include "mpoly.h"

extern FILE *polyStdout;

unsigned debugOptions = 0; // Debugging options requested on command line.

void Exit(const char *msg, ...)
{
    va_list vl;
    fprintf(polyStdout, "\n");
    va_start(vl, msg);
    vfprintf(polyStdout, msg, vl);
    va_end(vl);
    fprintf(polyStdout, "\n");
    fflush(polyStdout);
#if (defined(_WIN32))
    if (useConsole)
    {
        MessageBox(hMainWindow, _T("Poly/ML has exited"), _T("Poly/ML"), MB_OK);
    }
#endif
    exit(1);
}

// Error condition.  This should really be replaced either with ASSERTs
// or exceptions.
void Crash(const char *msg, ...)
{
    va_list vl;
    fprintf(polyStdout, "\n");
    va_start(vl, msg);
    vfprintf(polyStdout, msg, vl);
    va_end(vl);
    fprintf(polyStdout, "\n");
    fflush(polyStdout);

#if (defined(_WIN32))
    if (useConsole)
    {
        MessageBox(hMainWindow, _T("Poly/ML has exited"), _T("Poly/ML"), MB_OK);
    }
#else    
    {
        sigset_t set;
        sigemptyset(&set);
        sigprocmask(SIG_SETMASK,&set,NULL);
    }
#endif

    ASSERT(0); // Force a core dump

    abort();
    exit(1);
}

void ExitWithError(const char *msg, int err)
{
    fputs("\n", polyStdout);
    fputs(msg, polyStdout);
    const char *errorMsg = stringFromErrorCode(err);
    if (errorMsg != NULL) puts(errorMsg);

    fputs("\n", polyStdout);
    fflush(polyStdout);
#if (defined(_WIN32))
    if (useConsole)
    {
        MessageBox(hMainWindow, _T("Poly/ML has exited"), _T("Poly/ML"), MB_OK);
    }
#endif
    exit(1);
}

#if (defined(_WIN32))
// Default is to log with OutputDebugString
static FILE *logStream = NULL;
#else
// Default is to log to stdout
static FILE *logStream = stdout;
#endif

void SetLogFile(const TCHAR *fileName)
{
#if (defined(_WIN32) && defined(UNICODE))
    FILE *stream = _wfopen(fileName, L"w");
    if (stream == NULL)
        fprintf(polyStdout, "Unable to open debug file %S\n", fileName);
    else logStream = stream;
#else
    FILE *stream = fopen(fileName, "w");
    if (stream == NULL)
        fprintf(polyStdout, "Unable to open debug file %s\n", fileName);
    else logStream = stream;
#endif
}

// For the moment log to stdout
void Log(const char *msg, ...)
{
    va_list vl;
    va_start(vl, msg);
    if (logStream) vfprintf(logStream, msg, vl);
#if (defined(_WIN32))
    char buff[1024];
    if (_vsnprintf(buff, sizeof(buff), msg, vl) > 0)
        ::OutputDebugStringA(buff);
#endif
    va_end(vl);
    if (logStream) fflush(logStream);
}

// Log the size of a space as a comprehensible number
void LogSize(uintptr_t wordSize)
{
    uintptr_t size = wordSize * sizeof(PolyWord);
    if (size < 10*1024)
        Log("%zu", size);
    else
    {
        double s = (double)size;
        if (s < 1024000.0)
            Log("%1.2fK", s / 1024.0);
        else if (s < 1000.0 * 1024.0 * 1024.0)
            Log("%1.2fM", s / (1024.0 * 1024.0));
        else Log("%1.2fG", s / (1024.0 * 1024.0 * 1024.0));
    }
}