ncurses 4.1
[ncurses.git] / ncurses / lib_trace.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22 /*
23  *      lib_trace.c - Tracing/Debugging routines
24  */
25
26 #ifndef TRACE
27 #define TRACE                   /* turn on internal defs for this module */
28 #endif
29
30 #include <curses.priv.h>
31
32 MODULE_ID("$Id: lib_trace.c,v 1.23 1997/05/02 00:13:07 tom Exp $")
33
34 #include <ctype.h>
35 #if HAVE_FCNTL_H
36 #include <fcntl.h>
37 #endif
38
39 unsigned _nc_tracing = 0;
40 const char *_nc_tputs_trace = "";
41 long _nc_outchars;
42 int _nc_optimize_enable = OPTIMIZE_ALL;
43
44 static FILE *   tracefp;        /* default to writing to stderr */
45
46 void trace(const unsigned int tracelevel)
47 {
48 static bool     been_here = FALSE;
49
50         _nc_tracing = tracelevel;
51         if (! been_here && tracelevel) {
52                 been_here = TRUE;
53
54                 if ((tracefp = fopen("trace", "w")) == 0) {
55                         perror("curses: Can't open 'trace' file: ");
56                         exit(EXIT_FAILURE);
57                 }
58                 /* Try to set line-buffered mode, or (failing that) unbuffered,
59                  * so that the trace-output gets flushed automatically at the
60                  * end of each line.  This is useful in case the program dies. 
61                  */
62 #if HAVE_SETVBUF        /* ANSI */
63                 (void) setvbuf(tracefp, (char *)0, _IOLBF, 0);
64 #elif HAVE_SETBUF       /* POSIX */
65                 (void) setbuffer(tracefp, (char *)0);
66 #endif
67                 _tracef("TRACING NCURSES version %s (%d)",
68                         NCURSES_VERSION, NCURSES_VERSION_PATCH);
69         }
70 }
71
72 const char *_nc_visbuf2(int bufnum, const char *buf)
73 /* visibilize a given string */
74 {
75 char *vbuf;
76 char *tp;
77 int c;
78
79         if (buf == 0)
80             return("(null)");
81
82         tp = vbuf = _nc_trace_buf(bufnum, (strlen(buf) * 4) + 5);
83         *tp++ = '"';
84         while ((c = *buf++) != '\0') {
85                 if (c == '"') {
86                         *tp++ = '\\'; *tp++ = '"';
87                 } else if (is7bits(c) && (isgraph(c) || c == ' ')) {
88                         *tp++ = c;
89                 } else if (c == '\n') {
90                         *tp++ = '\\'; *tp++ = 'n';
91                 } else if (c == '\r') {
92                         *tp++ = '\\'; *tp++ = 'r';
93                 } else if (c == '\b') {
94                         *tp++ = '\\'; *tp++ = 'b';
95                 } else if (c == '\033') {
96                         *tp++ = '\\'; *tp++ = 'e';
97                 } else if (is7bits(c) && iscntrl(c)) {
98                         *tp++ = '\\'; *tp++ = '^'; *tp++ = '@' + c;
99                 } else {
100                         sprintf(tp, "\\%03o", c & 0xff);
101                         tp += strlen(tp);
102                 }
103         }
104         *tp++ = '"';
105         *tp++ = '\0';
106         return(vbuf);
107 }
108
109 const char *_nc_visbuf(const char *buf)
110 {
111         return _nc_visbuf2(0, buf);
112 }
113
114 void
115 _tracef(const char *fmt, ...)
116 {
117 static const char Called[] = T_CALLED("");
118 static const char Return[] = T_RETURN("");
119 static int level;
120 va_list ap;
121 bool    before = FALSE;
122 bool    after = FALSE;
123 int     doit = _nc_tracing;
124
125         if (strlen(fmt) >= sizeof(Called) - 1) {
126                 if (!strncmp(fmt, Called, sizeof(Called)-1)) {
127                         before = TRUE;
128                         level++;
129                 } else if (!strncmp(fmt, Return, sizeof(Return)-1)) {
130                         after = TRUE;
131                 }
132                 if (before || after) {
133                         if ((level <= 1)
134                          || (doit & TRACE_ICALLS) != 0)
135                                 doit &= (TRACE_CALLS|TRACE_CCALLS);
136                         else
137                                 doit = 0;
138                 }
139         }
140
141         if (doit != 0) {
142                 if (tracefp == 0)
143                         tracefp = stderr;
144                 if (before || after) {
145                         int n;
146                         for (n = 1; n < level; n++)
147                                 fputs("+ ", tracefp);
148                 }
149                 va_start(ap, fmt);
150                 vfprintf(tracefp, fmt, ap);
151                 fputc('\n', tracefp);
152                 va_end(ap);
153                 fflush(tracefp);
154         }
155
156         if (after && level)
157                 level--;
158 }
159
160 /* Trace 'int' return-values */
161 int _nc_retrace_int(int code)
162 {
163         T((T_RETURN("%d"), code));
164         return code;
165 }
166
167 /* Trace 'char*' return-values */
168 char * _nc_retrace_ptr(char * code)
169 {
170         T((T_RETURN("%s"), _nc_visbuf(code)));
171         return code;
172 }
173
174 /* Trace 'WINDOW *' return-values */
175 WINDOW *_nc_retrace_win(WINDOW *code)
176 {
177         T((T_RETURN("%p"), code));
178         return code;
179 }