ncurses 6.0 - patch 20160910
[ncurses.git] / ncurses / trace / varargs.c
1 /****************************************************************************
2  * Copyright (c) 2001-2008,2012 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28
29 /****************************************************************************
30  *  Author: Thomas E. Dickey 2001                                           *
31  ****************************************************************************/
32
33 #include <curses.priv.h>
34
35 #include <ctype.h>
36
37 MODULE_ID("$Id: varargs.c,v 1.11 2012/10/27 21:03:28 tom Exp $")
38
39 #ifdef TRACE
40
41 #define MAX_PARMS 10
42
43 typedef enum {
44     atUnknown = 0, atInteger, atFloat, atPoint, atString
45 } ARGTYPE;
46
47 #define VA_INT(type) ival = (int) va_arg(ap, type)
48 #define VA_FLT(type) fval = va_arg(ap, type)
49 #define VA_PTR(type) pval = (char *)va_arg(ap, type)
50 #define VA_STR(type) sval = va_arg(ap, type)
51
52 #define MyBuffer _nc_globals.tracearg_buf
53 #define MyLength _nc_globals.tracearg_used
54
55 /*
56  * Returns a string that represents the parameter list of a printf-style call.
57  */
58 NCURSES_EXPORT(char *)
59 _nc_varargs(const char *fmt, va_list ap)
60 {
61     static char dummy[] = "";
62
63     char buffer[BUFSIZ];
64     const char *param;
65     int n;
66
67     if (fmt == 0 || *fmt == '\0')
68         return dummy;
69     if (MyLength == 0)
70         MyBuffer = typeMalloc(char, MyLength = BUFSIZ);
71     if (MyBuffer == 0)
72         return dummy;
73     *MyBuffer = '\0';
74
75     while (*fmt != '\0') {
76         if (*fmt == '%') {
77             char *pval = 0;     /* avoid const-cast */
78             const char *sval = "";
79             double fval = 0.0;
80             int done = FALSE;
81             int ival = 0;
82             int type = 0;
83             ARGTYPE parm[MAX_PARMS];
84             int parms = 0;
85             ARGTYPE used = atUnknown;
86
87             while (*++fmt != '\0' && !done) {
88
89                 if (*fmt == '*') {
90                     VA_INT(int);
91                     if (parms < MAX_PARMS)
92                         parm[parms++] = atInteger;
93                 } else if (isalpha(UChar(*fmt))) {
94                     done = TRUE;
95                     switch (*fmt) {
96                     case 'Z':   /* FALLTHRU */
97                     case 'h':   /* FALLTHRU */
98                     case 'l':   /* FALLTHRU */
99                         done = FALSE;
100                         type = *fmt;
101                         break;
102                     case 'i':   /* FALLTHRU */
103                     case 'd':   /* FALLTHRU */
104                     case 'u':   /* FALLTHRU */
105                     case 'x':   /* FALLTHRU */
106                     case 'X':   /* FALLTHRU */
107                         if (type == 'l')
108                             VA_INT(long);
109                         else if (type == 'Z')
110                             VA_INT(size_t);
111                         else
112                             VA_INT(int);
113                         used = atInteger;
114                         break;
115                     case 'f':   /* FALLTHRU */
116                     case 'e':   /* FALLTHRU */
117                     case 'E':   /* FALLTHRU */
118                     case 'g':   /* FALLTHRU */
119                     case 'G':   /* FALLTHRU */
120                         VA_FLT(double);
121                         used = atFloat;
122                         break;
123                     case 'c':
124                         VA_INT(int);
125                         used = atInteger;
126                         break;
127                     case 's':
128                         VA_STR(const char *);
129                         used = atString;
130                         break;
131                     case 'p':
132                         VA_PTR(void *);
133                         used = atPoint;
134                         break;
135                     case 'n':
136                         VA_PTR(int *);
137                         used = atPoint;
138                         break;
139                     default:
140                         break;
141                     }
142                 } else if (*fmt == '%') {
143                     done = TRUE;
144                 }
145                 if (used != atUnknown && parms < MAX_PARMS) {
146                     parm[parms++] = used;
147                     for (n = 0; n < parms; ++n) {
148                         used = parm[n];
149                         param = buffer;
150                         switch (used) {
151                         case atInteger:
152                             _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
153                                         "%d", ival);
154                             break;
155                         case atFloat:
156                             _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
157                                         "%f", fval);
158                             break;
159                         case atPoint:
160                             _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
161                                         "%p", pval);
162                             break;
163                         case atString:
164                             param = _nc_visbuf2(1, sval);
165                             break;
166                         case atUnknown:
167                         default:
168                             _nc_STRCPY(buffer, "?", sizeof(buffer));
169                             break;
170                         }
171                         MyLength += strlen(param) + 2;
172                         MyBuffer = typeRealloc(char, MyLength, MyBuffer);
173                         if (MyBuffer != 0) {
174                             _nc_SPRINTF(MyBuffer + strlen(MyBuffer),
175                                         _nc_SLIMIT(MyLength - strlen(MyBuffer))
176                                         ", %s", param);
177                         }
178                     }
179                 }
180                 used = atUnknown;
181             }
182         } else {
183             fmt++;
184         }
185     }
186
187     return (MyBuffer ? MyBuffer : dummy);
188 }
189 #else
190 EMPTY_MODULE(_nc_varargs)
191 #endif