1b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/*
2b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
4b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Licensed under the Apache License, Version 2.0 (the "License");
5b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * you may not use this file except in compliance with the License.
6b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * You may obtain a copy of the License at
7b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
8b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *     http://www.apache.org/licenses/LICENSE-2.0
9b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
10b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Unless required by applicable law or agreed to in writing, software
11b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * distributed under the License is distributed on an "AS IS" BASIS,
12b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * See the License for the specific language governing permissions and
14b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * limitations under the License.
15b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
16b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/**
17b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * @file picodbg.c
18b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
19b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Provides functions and macros to debug the Pico system and to trace
20b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * the execution of its code.
21b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
22b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
23b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * All rights reserved.
24b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen *
25b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * History:
26b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen * - 2009-04-20 -- initial version
27b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen */
28b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
29b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
30b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenextern "C" {
31b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
32b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if 0
33b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
34b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
35b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
36b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
37b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if defined(PICO_DEBUG)
38b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
39b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Two variants of colored console output are implemented:
40b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   COLOR_MODE_WINDOWS
41b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      uses the Windows API function SetConsoleTextAttribute
42b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   COLOR_MODE_ANSI
43b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen      uses ANSI escape codes */
44b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if defined(_WIN32)
45b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define COLOR_MODE_WINDOWS
46b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#else
47b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define COLOR_MODE_ANSI
48b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
49b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
50b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
51b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <stdio.h>
52b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <stdlib.h>
53b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
54b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <stdarg.h>
55b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <string.h>
56b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
57b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include "picodbg.h"
58b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
59b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
60b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Maximum length of a formatted tracing message */
61b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define MAX_MESSAGE_LEN         999
62b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
63b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Maximum length of contextual information */
64b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define MAX_CONTEXT_LEN         499
65b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
66b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Maximum length of filename filter */
67b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define MAX_FILTERFN_LEN         16
68b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
69b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Delimiter used in debug messages */
70b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define MSG_DELIM               "|"
71b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
72b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Standard output file for debug messages */
73b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define STDDBG                  stdout /* or stderr */
74b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
75b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Default setup */
76b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICODBG_DEFAULT_LEVEL   PICODBG_LOG_LEVEL_WARN
77b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICODBG_DEFAULT_FILTERFN   ""
78b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICODBG_DEFAULT_FORMAT  \
79b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME | PICODBG_SHOW_FUNCTION)
80b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define PICODBG_DEFAULT_COLOR   1
81b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
82b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
83b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Current log level */
84b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int logLevel = PICODBG_DEFAULT_LEVEL;
85b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
86b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Current log filter (filename) */
87b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic char logFilterFN[MAX_FILTERFN_LEN + 1];
88b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
89b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Current log file or NULL if no log file is set */
90b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic FILE *logFile = NULL;
91b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
92b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Current output format */
93b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int logFormat = PICODBG_DEFAULT_FORMAT;
94b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
95b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Color mode for console output (0 : disable colors, != 0 : enable colors */
96b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int optColor = 0;
97b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
98b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Buffer for context information */
99b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic char ctxbuf[MAX_CONTEXT_LEN + 1];
100b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
101b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Buffer to format tracing messages */
102b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic char msgbuf[MAX_MESSAGE_LEN + 1];
103b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
104b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
105b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* *** Support for colored text output to console *****/
106b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
107b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
108b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* Console text colors */
109b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenenum color_t {
110b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* order matches Windows color codes */
111b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorBlack,
112b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorBlue,
113b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorGreen,
114b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorCyan,
115b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorRed,
116b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorPurple,
117b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorBrown,
118b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightGray,
119b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorDarkGray,
120b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightBlue,
121b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightGreen,
122b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightCyan,
123b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightRed,
124b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorLightPurple,
125b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorYellow,
126b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    ColorWhite
127b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen};
128b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
129b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
130b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic enum color_t picodbg_getLevelColor(int level)
131b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
132b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    switch (level) {
133b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICODBG_LOG_LEVEL_ERROR: return ColorLightRed;
134b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICODBG_LOG_LEVEL_WARN : return ColorYellow;
135b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICODBG_LOG_LEVEL_INFO : return ColorGreen;
136b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICODBG_LOG_LEVEL_DEBUG: return ColorLightGray;
137b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case PICODBG_LOG_LEVEL_TRACE: return ColorDarkGray;
138b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
139b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return ColorWhite;
140b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
141b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
142b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
143b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#if defined(COLOR_MODE_WINDOWS)
144b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
145b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#define WIN32_LEAN_AND_MEAN
146b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#include <windows.h>
147b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
148b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int picodbg_setTextAttr(FILE *stream, int attr)
149b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
150b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    HANDLE hConsole;
151b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
152b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (stream == stdout) {
153b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
154b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else if (stream == stderr) {
155b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        hConsole = GetStdHandle(STD_ERROR_HANDLE);
156b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
157b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        hConsole = INVALID_HANDLE_VALUE;
158b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
159b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
160b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (hConsole != INVALID_HANDLE_VALUE) {
161b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        /* do nothing if console output is redirected to a file */
162b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (GetFileType(hConsole) == FILE_TYPE_CHAR) {
163b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            CONSOLE_SCREEN_BUFFER_INFO csbi;
164b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            GetConsoleScreenBufferInfo(hConsole, &csbi);
165b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            SetConsoleTextAttribute(hConsole, (WORD) attr);
166b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            return (int) csbi.wAttributes;
167b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
168b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
169b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
170b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return 0;
171b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
172b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
173b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#elif defined(COLOR_MODE_ANSI)
174b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
175b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int picodbg_setTextAttr(FILE *stream, int attr)
176b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
177b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    const char *c = "";
178b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
179b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (attr == -1) {
180b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        c = "0";
181b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else switch (attr) {
182b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorBlack:       c = "0;30"; break;
183b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorRed:         c = "0;31"; break;
184b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorGreen:       c = "0;32"; break;
185b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorBrown:       c = "0;33"; break;
186b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorBlue:        c = "0;34"; break;
187b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorPurple:      c = "0;35"; break;
188b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorCyan:        c = "0;36"; break;
189b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightGray:   c = "0;37"; break;
190b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorDarkGray:    c = "1;30"; break;
191b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightRed:    c = "1;31"; break;
192b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightGreen:  c = "1;32"; break;
193b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorYellow:      c = "1;33"; break;
194b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightBlue:   c = "1;34"; break;
195b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightPurple: c = "1;35"; break;
196b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorLightCyan:   c = "1;36"; break;
197b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        case ColorWhite:       c = "1;37"; break;
198b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
199b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
200b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    fprintf(stream, "\x1b[%sm", c);
201b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return -1;
202b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
203b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
204b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#else
205b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
206b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic int picodbg_setTextAttr(FILE *stream, int attr)
207b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
208b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* avoid 'unreferenced formal parameter' */
209b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (void) stream;
210b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    (void) attr;
211b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return 0;
212b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
213b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
214b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
215b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
216b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
217b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* *** Auxiliary routines *****/
218b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
219b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
220b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic const char *picodbg_fileTitle(const char *file)
221b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
222b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    const char *name = file, *str = file;
223b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
224b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    /* try to extract file name without path in a platform independent
225b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen       way, i.e., skip all chars preceding path separator chars like
226b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen       '/' (Unix, MacOSX), '\' (Windows, DOS), and ':' (MacOS9) */
227b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    while (*str) {
228b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if ((*str == '\\') || (*str == '/') || (*str == ':')) {
229b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            name = str + 1;
230b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
231b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        str++;
232b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
233b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
234b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return name;
235b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
236b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
237b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
238b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void picodbg_logToStream(int level, int donewline,
239b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                                const char *context, const char *msg)
240b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
241b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    int oldAttr = 0;
242b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
243b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (optColor) {
244b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        oldAttr = picodbg_setTextAttr(STDDBG, picodbg_getLevelColor(level));
245b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
246b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
247b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    fprintf(STDDBG, "%s%s", context, msg);
248b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (donewline) fprintf(STDDBG, "\n");
249b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (logFile != NULL) {
250b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        fprintf(logFile, "%s%s", context, msg);
251b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (donewline) fprintf(logFile, "\n");
252b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
253b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
254b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (optColor) {
255b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picodbg_setTextAttr(STDDBG, oldAttr);
256b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
257b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
258b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
259b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
260b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* *** Exported routines *****/
261b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
262b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
263b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_initialize(int level)
264b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
265b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logLevel  = level;
266b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    strcpy(logFilterFN, PICODBG_DEFAULT_FILTERFN);
267b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logFile   = NULL;
268b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logFormat = PICODBG_DEFAULT_FORMAT;
269b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    optColor  = PICODBG_DEFAULT_COLOR;
270b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE);
271b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
272b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
273b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
274b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_terminate()
275b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
276b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (logFile != NULL) {
277b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        fclose(logFile);
278b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
279b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
280b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logLevel = 0;
281b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logFile  = NULL;
282b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
283b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
284b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
285b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_setLogLevel(int level)
286b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
287b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE);
288b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logLevel = level;
289b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
290b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
291b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
292b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_setLogFilterFN(const char *name)
293b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
294b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    strcpy(logFilterFN, name);
295b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
296b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
297b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
298b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_setLogFile(const char *name)
299b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
300b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (logFile != NULL) {
301b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        fclose(logFile);
302b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
303b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
304b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if ((name != NULL) && (strlen(name) > 0)) {
305b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        logFile = fopen(name, "wt");
306b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
307b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        logFile = NULL;
308b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
309b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
310b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
311b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
312b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_enableColors(int flag)
313b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
314b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    optColor = (flag != 0);
315b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
316b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
317b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
318b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_setOutputFormat(unsigned int format)
319b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
320b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    logFormat = format;
321b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
322b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
323b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
324b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenconst char *picodbg_varargs(const char *format, ...)
325b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
326b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    int len;
327b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
328b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    va_list argptr;
329b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    va_start(argptr, format);
330b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
331b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    len = vsprintf(msgbuf, format, argptr);
332b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT_RANGE(len, 0, MAX_MESSAGE_LEN);
333b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
334b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    return msgbuf;
335b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
336b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
337b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
338b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_log(int level, int donewline, const char *file, int line,
339b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                 const char *func, const char *msg)
340b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
341b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    char cb[MAX_CONTEXT_LEN + 1];
342b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
343b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE);
344b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
345b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if ((level <= logLevel) &&
346b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) {
347b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        /* compose output format string */
348b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        strcpy(ctxbuf, "*** ");
349b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (logFormat & PICODBG_SHOW_LEVEL) {
350b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            switch (level) {
351b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                case PICODBG_LOG_LEVEL_ERROR:
352b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    strcat(ctxbuf, "error" MSG_DELIM);
353b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
354b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                case PICODBG_LOG_LEVEL_WARN:
355b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    strcat(ctxbuf, "warn " MSG_DELIM);
356b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
357b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                case PICODBG_LOG_LEVEL_INFO:
358b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    strcat(ctxbuf, "info " MSG_DELIM);
359b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
360b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                case PICODBG_LOG_LEVEL_DEBUG:
361b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    strcat(ctxbuf, "debug" MSG_DELIM);
362b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
363b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                case PICODBG_LOG_LEVEL_TRACE:
364b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    strcat(ctxbuf, "trace" MSG_DELIM);
365b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
366b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                default:
367b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                    break;
368b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
369b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
370b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (logFormat & PICODBG_SHOW_DATE) {
371b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* nyi */
372b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
373b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (logFormat & PICODBG_SHOW_TIME) {
374b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            /* nyi */
375b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
376b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (logFormat & PICODBG_SHOW_SRCNAME) {
377b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            sprintf(cb, "%-10s", picodbg_fileTitle(file));
378b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            strcat(ctxbuf, cb);
379b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (logFormat & PICODBG_SHOW_SRCLINE) {
380b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                sprintf(cb, "(%d)", line);
381b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                strcat(ctxbuf, cb);
382b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
383b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            strcat(ctxbuf, MSG_DELIM);
384b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
385b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        if (logFormat & PICODBG_SHOW_FUNCTION) {
386b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            if (strlen(func) > 0) {
387b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                sprintf(cb, "%-18s", func);
388b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                strcat(ctxbuf, cb);
389b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen                strcat(ctxbuf, MSG_DELIM);
390b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            }
391b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        }
392b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
393b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picodbg_logToStream(level, donewline, ctxbuf, msg);
394b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
395b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
396b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
397b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
398b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_log_msg(int level, const char *file, const char *msg)
399b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
400b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    PICODBG_ASSERT_RANGE(level, 0, PICODBG_LOG_LEVEL_TRACE);
401b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
402b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if ((level <= logLevel) &&
403b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        ((strlen(logFilterFN) == 0) || !strcmp(logFilterFN, picodbg_fileTitle(file)))) {
404b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        picodbg_logToStream(level, 0, "", msg);
405b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
406b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
407b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
408b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
409b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenvoid picodbg_assert(const char *file, int line, const char *func, const char *expr)
410b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen{
411b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    if (strlen(func) > 0) {
412b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        fprintf(STDDBG, "assertion failed: %s, file %s, function %s, line %d",
413b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            expr, picodbg_fileTitle(file), func, line);
414b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    } else {
415b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen        fprintf(STDDBG, "assertion failed: %s, file %s, line %d",
416b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen            expr, picodbg_fileTitle(file), line);
417b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    }
418b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picodbg_terminate();
419b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    abort();
420b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
421b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
422b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
423b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#else
424b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
425b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* To prevent warning about "translation unit is empty" when
426b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen   diagnostic output is disabled. */
427b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chenstatic void picodbg_dummy(void) {
428b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen    picodbg_dummy();
429b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
430b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
431b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif /* defined(PICO_DEBUG) */
432b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
433b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#ifdef __cplusplus
434b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen}
435b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen#endif
436b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
437b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen
438b190149a69b110e6719ce0a41877a683f8db7ae7Charles Chen/* end */
439