printf.c revision c70b19501f800cb911ac906c7fb153c4a37f5f57
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Steve Fink 6 * Copyright (C) 2006 Ian Wienand 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 24#include <assert.h> 25#include <stdlib.h> 26 27#include "printf.h" 28#include "type.h" 29#include "value.h" 30#include "expr.h" 31#include "zero.h" 32#include "param.h" 33#include "lens_default.h" 34 35struct param_enum { 36 struct value array; 37 int percent; 38 size_t *future_length; 39 char *format; 40 char const *ptr; 41 char const *end; 42}; 43 44static struct param_enum * 45param_printf_init(struct value *cb_args, size_t nargs, 46 struct value_dict *arguments) 47{ 48 assert(nargs == 1); 49 50 /* We expect a char array pointer. */ 51 if (cb_args->type->type != ARGTYPE_POINTER 52 || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY 53 || (cb_args->type->u.ptr_info.info->u.array_info.elt_type->type 54 != ARGTYPE_CHAR)) 55 return NULL; 56 57 struct param_enum *self = malloc(sizeof(*self)); 58 if (self == NULL) { 59 fail: 60 free(self); 61 return NULL; 62 } 63 64 if (value_init_deref(&self->array, cb_args) < 0) 65 goto fail; 66 67 assert(self->array.type->type == ARGTYPE_ARRAY); 68 69 self->format = (char *)value_get_data(&self->array, arguments); 70 if (self->format == NULL) 71 goto fail; 72 73 size_t size = value_size(&self->array, arguments); 74 if (size == (size_t)-1) 75 goto fail; 76 77 self->percent = 0; 78 self->ptr = self->format; 79 self->end = self->format + size; 80 self->future_length = NULL; 81 return self; 82} 83 84static void 85drop_future_length(struct param_enum *self) 86{ 87 if (self->future_length != NULL) { 88 free(self->future_length); 89 self->future_length = NULL; 90 } 91} 92 93static int 94form_next_param(struct param_enum *self, 95 enum arg_type format_type, enum arg_type elt_type, 96 unsigned hlf, unsigned lng, char *len_buf, size_t len_buf_len, 97 struct arg_type_info *infop) 98{ 99 /* XXX note: Some types are wrong because we lack 100 ARGTYPE_LONGLONG, ARGTYPE_UCHAR and ARGTYPE_SCHAR. */ 101 assert(lng <= 2); 102 assert(hlf <= 2); 103 static enum arg_type ints[] = 104 { ARGTYPE_CHAR, ARGTYPE_SHORT, ARGTYPE_INT, 105 ARGTYPE_LONG, ARGTYPE_ULONG }; 106 static enum arg_type uints[] = 107 { ARGTYPE_CHAR, ARGTYPE_USHORT, ARGTYPE_UINT, 108 ARGTYPE_ULONG, ARGTYPE_ULONG }; 109 110 struct arg_type_info *elt_info = NULL; 111 if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER) 112 elt_info = type_get_simple(elt_type); 113 else if (format_type == ARGTYPE_INT) 114 format_type = ints[2 + lng - hlf]; 115 else if (format_type == ARGTYPE_UINT) 116 format_type = uints[2 + lng - hlf]; 117 118 119 if (format_type == ARGTYPE_ARRAY) { 120 struct expr_node *node = NULL; 121 if (len_buf_len != 0 122 || self->future_length != NULL) { 123 struct tmp { 124 struct expr_node node; 125 struct arg_type_info type; 126 }; 127 struct tmp *len = malloc(sizeof(*len)); 128 if (len == NULL) { 129 fail: 130 free(len); 131 return -1; 132 } 133 134 len->type.type = ARGTYPE_LONG; 135 136 long l; 137 if (self->future_length != NULL) { 138 l = *self->future_length; 139 drop_future_length(self); 140 } else { 141 l = atol(len_buf); 142 } 143 144 expr_init_const_word(&len->node, l, &len->type, 0); 145 146 node = build_zero_w_arg(&len->node, 1); 147 if (node == NULL) 148 goto fail; 149 150 } else { 151 node = expr_node_zero(); 152 } 153 154 assert(node != NULL); 155 type_init_array(infop, elt_info, 0, node, 1); 156 157 } else if (format_type == ARGTYPE_POINTER) { 158 type_init_pointer(infop, elt_info, 1); 159 160 } else { 161 *infop = *type_get_simple(format_type); 162 } 163 164 return 0; 165} 166 167static int 168param_printf_next(struct param_enum *self, struct arg_type_info *infop, 169 int *insert_stop) 170{ 171 unsigned hlf = 0; 172 unsigned lng = 0; 173 enum arg_type format_type = ARGTYPE_VOID; 174 enum arg_type elt_type = ARGTYPE_VOID; 175 char len_buf[25] = {}; 176 size_t len_buf_len = 0; 177 struct lens *lens = NULL; 178 179 for (; self->ptr < self->end; ++self->ptr) { 180 if (!self->percent) { 181 if (*self->ptr == '%') 182 self->percent = 1; 183 continue; 184 } 185 186 switch (*self->ptr) { 187 case '#': case ' ': case '-': 188 case '+': case 'I': case '\'': 189 /* These are only important for formatting, 190 * not for interpreting the type. */ 191 continue; 192 193 case '*': 194 /* Length parameter given in the next 195 * argument. */ 196 if (self->future_length == NULL) 197 /* This should really be an assert, 198 * but we can't just fail on invalid 199 * format string. */ 200 self->future_length 201 = malloc(sizeof(*self->future_length)); 202 203 if (self->future_length != NULL) { 204 ++self->ptr; 205 format_type = ARGTYPE_INT; 206 break; 207 } 208 209 case '0': 210 case '1': case '2': case '3': 211 case '4': case '5': case '6': 212 case '7': case '8': case '9': 213 /* Field length likewise, but we need to parse 214 * this to attach the appropriate string 215 * length expression. */ 216 if (len_buf_len < sizeof(len_buf) - 1) 217 len_buf[len_buf_len++] = *self->ptr; 218 continue; 219 220 case 'h': 221 if (hlf < 2) 222 hlf++; 223 continue; 224 225 case 'l': 226 if (lng < 2) 227 lng++; 228 continue; 229 230 case 'q': 231 lng = 2; 232 continue; 233 234 case 'L': /* long double */ 235 lng = 1; 236 continue; 237 238 case 'j': /* intmax_t */ 239 /* XXX ABI should know */ 240 lng = 2; 241 continue; 242 243 case 't': /* ptrdiff_t */ 244 case 'Z': case 'z': /* size_t */ 245 lng = 1; /* XXX ABI should tell */ 246 continue; 247 248 case 'd': 249 case 'i': 250 format_type = ARGTYPE_INT; 251 self->percent = 0; 252 break; 253 254 case 'o': 255 lens = &octal_lens; 256 goto uint; 257 258 case 'x': case 'X': 259 lens = &hex_lens; 260 case 'u': 261 uint: 262 format_type = ARGTYPE_UINT; 263 self->percent = 0; 264 break; 265 266 case 'e': case 'E': 267 case 'f': case 'F': 268 case 'g': case 'G': 269 case 'a': case 'A': 270 format_type = ARGTYPE_DOUBLE; 271 self->percent = 0; 272 break; 273 274 case 'C': /* like "lc" */ 275 if (lng == 0) 276 lng++; 277 case 'c': 278 /* XXX "lc" means wchar_t string. */ 279 format_type = ARGTYPE_CHAR; 280 self->percent = 0; 281 break; 282 283 case 'S': /* like "ls" */ 284 if (lng == 0) 285 lng++; 286 case 's': 287 format_type = ARGTYPE_ARRAY; 288 /* XXX "ls" means wchar_t string. */ 289 elt_type = ARGTYPE_CHAR; 290 self->percent = 0; 291 lens = &string_lens; 292 break; 293 294 case 'p': 295 case 'n': /* int* where to store no. of printed chars. */ 296 format_type = ARGTYPE_POINTER; 297 elt_type = ARGTYPE_VOID; 298 self->percent = 0; 299 break; 300 301 case 'm': /* (glibc) print argument of errno */ 302 case '%': 303 lng = 0; 304 hlf = 0; 305 self->percent = 0; 306 continue; 307 308 default: 309 continue; 310 } 311 312 /* If we got here, the type must have been set. */ 313 assert(format_type != ARGTYPE_VOID); 314 315 if (form_next_param(self, format_type, elt_type, hlf, lng, 316 len_buf, len_buf_len, infop) < 0) 317 return -1; 318 319 infop->lens = lens; 320 infop->own_lens = 0; 321 322 return 0; 323 } 324 325 infop->type = ARGTYPE_VOID; 326 return 0; 327} 328 329static enum param_status 330param_printf_stop(struct param_enum *self, struct value *value) 331{ 332 if (self->future_length != NULL 333 && value_extract_word(value, (long *)self->future_length, NULL) < 0) 334 drop_future_length(self); 335 336 return PPCB_CONT; 337} 338 339static void 340param_printf_done(struct param_enum *context) 341{ 342 free(context); 343} 344 345void 346param_pack_init_printf(struct param *param, struct expr_node *arg, int own_arg) 347{ 348 param_init_pack(param, arg, 1, own_arg, 349 ¶m_printf_init, ¶m_printf_next, 350 ¶m_printf_stop, ¶m_printf_done); 351} 352