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