1 /* radare - LGPL - Copyright 2007-2020 - pancake & Skia */
2 
3 #include "r_cons.h"
4 #include "r_util.h"
5 #include "r_util/r_print.h"
6 #include "r_reg.h"
7 #define NOPTR 0
8 #define PTRSEEK 1
9 #define PTRBACK 2
10 #define NULLPTR 3
11 #define STRUCTPTR 100
12 #define NESTEDSTRUCT 1
13 #define STRUCTFLAG 10000
14 #define NESTDEPTH 14
15 #define ARRAYINDEX_COEF 10000
16 
17 #define MUSTSEE (mode & R_PRINT_MUSTSEE && mode & R_PRINT_ISFIELD && !(mode & R_PRINT_JSON))
18 #define ISQUIET (mode & R_PRINT_QUIET)
19 #define MUSTSET (mode & R_PRINT_MUSTSET && mode & R_PRINT_ISFIELD && setval)
20 #define SEEVALUE (mode & R_PRINT_VALUE)
21 #define MUSTSEEJSON (mode & R_PRINT_JSON && mode & R_PRINT_ISFIELD)
22 #define MUSTSEESTRUCT (mode & R_PRINT_STRUCT)
23 
24 //this define is used as a way to acknowledge when updateAddr should take len
25 //as real len of the buffer
26 #define THRESHOLD (-4444)
27 
28 //TODO REWRITE THIS IS BECOMING A NIGHTMARE
29 
updateAddr(const ut8 * buf,int len,int endian,ut64 * addr,ut64 * addr64)30 static float updateAddr(const ut8 *buf, int len, int endian, ut64 *addr, ut64 *addr64) {
31 	float f = 0.0;
32 	// assert sizeof (float) == sizeof (ut32))
33 	// XXX 999 is used as an implicit buffer size, we should pass the buffer size to every function too, otherwise this code will give us some problems
34 	if (len >= THRESHOLD - 7 && len < THRESHOLD) {
35 		len = len + THRESHOLD; // get the real len to avoid oob
36 	} else {
37 		len = 999;
38 	}
39 	if (len < 1) {
40 		return 0;
41 	}
42 	if (len >= sizeof (float)) {
43 		r_mem_swaporcopy ((ut8*)&f, buf, sizeof (float), endian);
44 	}
45 	if (addr && len > 3) {
46 		ut32 tmpaddr = r_read_ble32 (buf, endian);
47 		*addr = (ut64)tmpaddr;
48 	}
49 	if (addr64 && len > 7) {
50 		*addr64 = r_read_ble64 (buf, endian);
51 	}
52 	return f;
53 }
54 
r_get_size(RNum * num,ut8 * buf,int endian,const char * s)55 static int r_get_size(RNum *num, ut8 *buf, int endian, const char *s) {
56 	size_t len = strlen (s);
57 	if (s[0] == '*' && len >= 4) { // value pointed by the address
58 		ut64 addr;
59 		int offset = (int)r_num_math (num, s + 1);
60 		(void)updateAddr (buf + offset, 999, endian, &addr, NULL);
61 		return addr;
62 	}
63 	// flag handling doesnt seems to work here
64 	return r_num_math (num, s);
65 }
66 
r_print_format_u128(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)67 static void r_print_format_u128(const RPrint* p, int endian, int mode,
68 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
69 	ut64 low = r_read_ble64 (buf, endian);
70 	ut64 hig = r_read_ble64 (buf + 8, endian);
71 	if (MUSTSEEJSON) {
72 		p->cb_printf ("\"");
73 	} else if (!SEEVALUE && !ISQUIET) {
74 		p->cb_printf ("0x%08"PFMT64x" = (uint128_t)", seeki);
75 	}
76 	if (endian) {
77 		p->cb_printf ("0x%016"PFMT64x"", low);
78 		p->cb_printf ("%016"PFMT64x, hig);
79 	} else {
80 		p->cb_printf ("0x%016"PFMT64x"", hig);
81 		p->cb_printf ("%016"PFMT64x, low);
82 	}
83 	if (MUSTSEEJSON) {
84 		const char *end = endian? "big": "little";
85 		p->cb_printf ("\",\"endian\":\"%s\",\"ctype\":\"uint128_t\"}", end);
86 	}
87 }
88 
r_print_format_quadword(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)89 static void r_print_format_quadword(const RPrint* p, int endian, int mode,
90 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
91 	ut64 addr64;
92 	int elem = -1;
93 	if (size >= ARRAYINDEX_COEF) {
94 		elem = size / ARRAYINDEX_COEF - 1;
95 		size %= ARRAYINDEX_COEF;
96 	}
97 	updateAddr (buf + i, size - i, endian, NULL, &addr64);
98 	if (MUSTSET) {
99 		p->cb_printf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*8:0));
100 	} else if (MUSTSEE) {
101 		if (!SEEVALUE && !ISQUIET) {
102 			p->cb_printf ("0x%08"PFMT64x" = (qword)",
103 				seeki + ((elem >= 0)? elem * 8: 0));
104 		}
105 		if (size == -1) {
106 			if (addr64 == UT32_MAX || ((st64)addr64 < 0 && (st64)addr64 > -4096)) {
107 				p->cb_printf ("%d", (int)(addr64));
108 			} else {
109 				p->cb_printf ("0x%016"PFMT64x, addr64);
110 			}
111 		} else {
112 			if (!SEEVALUE) {
113 				p->cb_printf ("[ ");
114 			}
115 			while (size--) {
116 				updateAddr (buf + i, size - i, endian, NULL, &addr64);
117 				if (elem == -1 || elem == 0) {
118 					p->cb_printf ("0x%016"PFMT64x, addr64);
119 					if (elem == 0) {
120 						elem = -2;
121 					}
122 				}
123 				if (size != 0 && elem == -1) {
124 					p->cb_printf (", ");
125 				}
126 				if (elem > -1) {
127 					elem--;
128 				}
129 				i += 8;
130 			}
131 			if (!SEEVALUE) {
132 				p->cb_printf (" ]");
133 			}
134 		}
135 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
136 		if (size == -1) {
137 			p->cb_printf ("%"PFMT64d, addr64);
138 		} else {
139 			p->cb_printf ("[ ");
140 			while (size--) {
141 				updateAddr (buf + i, size - i, endian, NULL, &addr64);
142 				if (elem == -1 || elem == 0) {
143 					p->cb_printf ("%"PFMT64d, addr64);
144 					if (elem == 0) {
145 						elem = -2;
146 					}
147 				}
148 				if (size != 0 && elem == -1) {
149 					p->cb_printf (", ");
150 				}
151 				if (elem > -1) {
152 					elem--;
153 				}
154 				i += 8;
155 			}
156 			p->cb_printf (" ]");
157 		}
158 		if (MUSTSEEJSON) {
159 			p->cb_printf ("}");
160 		}
161 	}
162 }
163 
r_print_format_byte(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)164 static void r_print_format_byte(const RPrint* p, int endian, int mode,
165 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
166 	int elem = -1;
167 	if (size >= ARRAYINDEX_COEF) {
168 		elem = size / ARRAYINDEX_COEF - 1;
169 		size %= ARRAYINDEX_COEF;
170 	}
171 	if (MUSTSET) {
172 		p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki + ((elem >= 0) ? elem : 0));
173 	} else if (MUSTSEE) {
174 		if (!SEEVALUE && !ISQUIET) {
175 			p->cb_printf ("0x%08"PFMT64x" = ", seeki + ((elem >= 0) ? elem : 0));
176 		}
177 		if (size == -1) {
178 			p->cb_printf ("0x%02x", buf[i]);
179 		} else {
180 			if (!SEEVALUE) {
181 				p->cb_printf ("[ ");
182 			}
183 			while (size--) {
184 				if (elem == -1 || elem == 0) {
185 					p->cb_printf ("0x%02x", buf[i]);
186 					if (elem == 0) {
187 						elem = -2;
188 					}
189 				}
190 				if (size != 0 && elem == -1) {
191 					p->cb_printf (", ");
192 				}
193 				if (elem > -1) {
194 					elem--;
195 				}
196 				i++;
197 			}
198 			if (!SEEVALUE) {
199 				p->cb_printf (" ]");
200 			}
201 		}
202 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
203 		if (size == -1) {
204 			p->cb_printf ("%d", buf[i]);
205 		} else {
206 			p->cb_printf ("[ ");
207 			const char *comma = "";
208 			while (size--) {
209 				if (elem == -1 || elem == 0) {
210 					p->cb_printf ("%s%d", comma, buf[i]);
211 					comma = ",";
212 					if (elem == 0) {
213 						elem = -2;
214 					}
215 				}
216 				if (elem > -1) {
217 					elem--;
218 				}
219 				i++;
220 			}
221 			p->cb_printf (" ]");
222 		}
223 		if (MUSTSEEJSON) {
224 			p->cb_printf ("}");
225 		}
226 	}
227 }
228 
229 // Return number of consumed bytes
r_print_format_uleb(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)230 static int r_print_format_uleb(const RPrint* p, int endian, int mode,
231 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
232 	int elem = -1;
233 	int s = 0, offset = 0;
234 	ut64 value = 0;
235 	if (size >= ARRAYINDEX_COEF) {
236 		elem = size / ARRAYINDEX_COEF - 1;
237 		size %= ARRAYINDEX_COEF;
238 	}
239 	if (MUSTSET) {
240 		ut8 *tmp;
241 		char *nbr;
242 		do {
243 			r_uleb128_decode (buf+i, &s, &value);
244 			i += s;
245 			offset += s;
246 		} while (elem--);
247 		tmp = (ut8*) r_uleb128_encode (r_num_math (NULL, setval), &s);
248 		nbr = r_hex_bin2strdup (tmp, s);
249 		p->cb_printf ("\"wx %s\" @ 0x%08"PFMT64x"\n", nbr, seeki+offset-s);
250 		free (tmp);
251 		free (nbr);
252 	} else if (MUSTSEE) {
253 		if (!SEEVALUE && !ISQUIET) {
254 			p->cb_printf ("0x%08" PFMT64x " = ", seeki);
255 		}
256 		if (size==-1) {
257 			r_uleb128_decode (buf+i, &offset, &value);
258 			p->cb_printf ("%"PFMT64d, value);
259 		} else {
260 			if (!SEEVALUE) {
261 				p->cb_printf ("[ ");
262 			}
263 			while (size--) {
264 				if (elem == -1 || elem == 0) {
265 					r_uleb128_decode (buf+i, &s, &value);
266 					i += s;
267 					offset += s;
268 					p->cb_printf ("%"PFMT64d, value);
269 					if (elem == 0) {
270 						elem = -2;
271 					}
272 				}
273 				if (size != 0 && elem == -1) {
274 					p->cb_printf (", ");
275 				}
276 				if (elem > -1) {
277 					elem--;
278 				}
279 			}
280 			if (!SEEVALUE) {
281 				p->cb_printf (" ]");
282 			}
283 		}
284 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
285 		if (size==-1) {
286 			r_uleb128_decode (buf+i, &offset, &value);
287 			p->cb_printf ("\"%"PFMT64d"\"", value);
288 		} else {
289 			p->cb_printf ("[ ");
290 			while (size--) {
291 				if (elem == -1 || elem == 0) {
292 					r_uleb128_decode (buf+i, &s, &value);
293 					i += s;
294 					offset += s;
295 					p->cb_printf ("\"%"PFMT64d"\"", value);
296 					if (elem == 0) {
297 						elem = -2;
298 					}
299 				}
300 				if (size != 0 && elem == -1) {
301 					p->cb_printf (", ");
302 				}
303 				if (elem > -1) {
304 					elem--;
305 				}
306 			}
307 			p->cb_printf (" ]");
308 		}
309 		if (MUSTSEEJSON) {
310 			p->cb_printf ("}");
311 		}
312 	}
313 	return offset;
314 }
315 
r_print_format_char(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)316 static void r_print_format_char(const RPrint* p, int endian, int mode,
317 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
318 	int elem = -1;
319 	if (size >= ARRAYINDEX_COEF) {
320 		elem = size/ARRAYINDEX_COEF-1;
321 		size %= ARRAYINDEX_COEF;
322 	}
323 	if (MUSTSET) {
324 		p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
325 	} else if (MUSTSEE) {
326 		if (!SEEVALUE && !ISQUIET) {
327 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 2 : 0)); //XXX:: shouldn't it be elem*1??
328 		}
329 		if (size == -1) {
330 			p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
331 		} else {
332 			if (!SEEVALUE) {
333 				p->cb_printf ("[ ");
334 			}
335 			while (size--) {
336 				if (elem == -1 || elem == 0) {
337 					p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
338 					if (elem == 0) {
339 						elem = -2;
340 					}
341 				}
342 				if (size != 0 && elem == -1) {
343 					p->cb_printf (", ");
344 				}
345 				if (elem > -1) {
346 					elem--;
347 				}
348 				i++;
349 			}
350 			if (!SEEVALUE) {
351 				p->cb_printf (" ]");
352 			}
353 		}
354 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
355 		if (size == -1) {
356 			p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
357 		} else {
358 			p->cb_printf ("[ ");
359 			while (size--) {
360 				if (elem == -1 || elem == 0) {
361 					p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
362 					if (elem == 0) {
363 						elem = -2;
364 					}
365 				}
366 				if (size != 0 && elem == -1) {
367 					p->cb_printf (", ");
368 				}
369 				if (elem > -1) {
370 					elem--;
371 				}
372 				i++;
373 			}
374 			p->cb_printf (" ]");
375 		}
376 		if (MUSTSEEJSON) {
377 			p->cb_printf ("}");
378 		}
379 	}
380 }
381 
r_print_format_decchar(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)382 static void r_print_format_decchar(const RPrint* p, int endian, int mode,
383 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
384 	int elem = -1;
385 	if (size >= ARRAYINDEX_COEF) {
386 		elem = size/ARRAYINDEX_COEF-1;
387 		size %= ARRAYINDEX_COEF;
388 	}
389 	if (MUSTSET) {
390 		p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
391 	} else if (MUSTSEE) {
392 		if (!SEEVALUE && !ISQUIET) {
393 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem : 0));
394 		}
395 		if (size == -1) {
396 			p->cb_printf ("%d", buf[i]);
397 		} else {
398 			if (!SEEVALUE) {
399 				p->cb_printf ("[ ");
400 			}
401 			while (size--) {
402 				if (elem == -1 || elem == 0) {
403 					p->cb_printf ("%d", buf[i]);
404 					if (elem == 0) {
405 						elem = -2;
406 					}
407 				}
408 				if (size != 0 && elem == -1) {
409 					p->cb_printf (", ");
410 				}
411 				if (elem > -1) {
412 					elem--;
413 				}
414 				i++;
415 			}
416 			if (!SEEVALUE) {
417 				p->cb_printf (" ]");
418 			}
419 		}
420 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
421 		if (size == -1) {
422 			p->cb_printf ("\"%d\"", buf[i]);
423 		} else {
424 			p->cb_printf ("[ ");
425 			while (size--) {
426 				if (elem == -1 || elem == 0) {
427 					p->cb_printf ("\"%d\"", buf[i]);
428 					if (elem == 0) {
429 						elem = -2;
430 					}
431 				}
432 				if (size != 0 && elem == -1) {
433 					p->cb_printf (", ");
434 				}
435 				if (elem > -1) {
436 					elem--;
437 				}
438 				i++;
439 			}
440 			p->cb_printf (" ]");
441 		}
442 		if (MUSTSEEJSON) {
443 			p->cb_printf ("}");
444 		}
445 	}
446 }
447 
r_print_format_string(const RPrint * p,ut64 seeki,ut64 addr64,ut64 addr,int is64,int mode)448 static int r_print_format_string(const RPrint* p, ut64 seeki, ut64 addr64, ut64 addr, int is64, int mode) {
449 	ut8 buffer[255];
450 	buffer[0] = 0;
451 	if (!p->iob.read_at) {
452 		eprintf ("(cannot read memory)\n");
453 		return -1;
454 	}
455 	const ut64 at = (is64 == 1)? addr64: (ut64)addr;
456 	int res = p->iob.read_at (p->iob.io, at, buffer, sizeof (buffer) - 8);
457 	if (MUSTSEEJSON) {
458 		char *encstr = r_str_utf16_encode ((const char *)buffer, -1);
459 		if (encstr) {
460 			p->cb_printf ("%"PFMT64d",\"string\":\"%s\"}", seeki, encstr);
461 			free (encstr);
462 		}
463 	} else if (MUSTSEESTRUCT) {
464 		char *encstr = r_str_utf16_encode ((const char *)buffer, -1);
465 		if (encstr) {
466 			p->cb_printf ("\"%s\"", encstr);
467 			free (encstr);
468 		}
469 	} else if (MUSTSEE) {
470 		if (!SEEVALUE && !ISQUIET) {
471 			p->cb_printf ("0x%08" PFMT64x " = ", seeki);
472 		}
473 		if (!SEEVALUE) {
474 			if (ISQUIET) {
475 				if (addr == 0LL) {
476 					p->cb_printf ("NULL");
477 				} else if (addr == UT32_MAX || addr == UT64_MAX) {
478 					p->cb_printf ("-1");
479 				} else {
480 					p->cb_printf ("0x%08" PFMT64x " ", addr);
481 				}
482 			} else {
483 				p->cb_printf ("0x%08" PFMT64x " -> 0x%08" PFMT64x " ", seeki, addr);
484 			}
485 		}
486 		if (res > 0 && buffer[0] != 0xff && buffer[1] != 0xff) {
487 			p->cb_printf ("\"%s\"", buffer);
488 		}
489 	}
490 	return 0;
491 }
492 
r_print_format_time(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)493 static void r_print_format_time(const RPrint* p, int endian, int mode,
494 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
495 	ut64 addr;
496 	struct tm timestruct;
497 	int elem = -1;
498 	if (size >= ARRAYINDEX_COEF) {
499 		elem = size/ARRAYINDEX_COEF-1;
500 		size %= ARRAYINDEX_COEF;
501 	}
502 	updateAddr (buf + i, size - i, endian, &addr, NULL);
503 	if (MUSTSET) {
504 		p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
505 	} else if (MUSTSEE) {
506 		char *timestr = malloc (ASCTIME_BUF_MINLEN);
507 		if (!timestr) {
508 			return;
509 		}
510 		r_asctime_r (gmtime_r ((time_t*)&addr, &timestruct), timestr);
511 		*(timestr+24) = '\0';
512 		if (!SEEVALUE && !ISQUIET) {
513 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
514 		}
515 		if (size==-1) {
516 			p->cb_printf ("%s", timestr);
517 		} else {
518 			if (!SEEVALUE) {
519 				p->cb_printf ("[ ");
520 			}
521 			while (size--) {
522 				updateAddr (buf + i, size - i, endian, &addr, NULL);
523 				r_asctime_r (gmtime_r ((time_t*)&addr, &timestruct), timestr);
524 				*(timestr+24) = '\0';
525 				if (elem == -1 || elem == 0) {
526 					p->cb_printf ("%s", timestr);
527 					if (elem == 0) {
528 						elem = -2;
529 					}
530 				}
531 				if (size != 0 && elem == -1) {
532 					p->cb_printf (", ");
533 				}
534 				if (elem > -1) {
535 					elem--;
536 				}
537 				i += 4;
538 			}
539 			if (!SEEVALUE) {
540 				p->cb_printf (" ]");
541 			}
542 		}
543 		free (timestr);
544 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
545 		char *timestr = malloc (ASCTIME_BUF_MINLEN);
546 		if (!timestr) {
547 			return;
548 		}
549 		r_asctime_r (gmtime_r ((time_t*)&addr, &timestruct), timestr);
550 		*(timestr+24) = '\0';
551 		if (size==-1) {
552 			p->cb_printf ("\"%s\"", timestr);
553 		} else {
554 			p->cb_printf ("[ ");
555 			while (size--) {
556 				updateAddr (buf + i, size - i, endian, &addr, NULL);
557 				r_asctime_r (gmtime_r ((time_t*)&addr, &timestruct), timestr);
558 				*(timestr+24) = '\0';
559 				if (elem == -1 || elem == 0) {
560 					p->cb_printf ("\"%s\"", timestr);
561 					if (elem == 0) {
562 						elem = -2;
563 					}
564 				}
565 				if (size != 0 && elem == -1) {
566 					p->cb_printf (", ");
567 				}
568 				if (elem > -1) {
569 					elem--;
570 				}
571 				i += 4;
572 			}
573 			p->cb_printf (" ]");
574 		}
575 		free (timestr);
576 		if (MUSTSEEJSON) {
577 			p->cb_printf ("}");
578 		}
579 	}
580 }
581 
582 // TODO: support unsigned int?
r_print_format_hex(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)583 static void r_print_format_hex(const RPrint* p, int endian, int mode,
584 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
585 	ut64 addr;
586 	int elem = -1;
587 	if (size >= ARRAYINDEX_COEF) {
588 		elem = size/ARRAYINDEX_COEF-1;
589 		size %= ARRAYINDEX_COEF;
590 	}
591 	updateAddr (buf + i, size - i, endian, &addr, NULL);
592 	if (MUSTSET) {
593 		p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
594 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
595 		p->cb_printf ("%"PFMT64d, addr);
596 	} else if (MUSTSEE) {
597 		if (!SEEVALUE && !ISQUIET) {
598 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
599 		}
600 		if (size == -1) {
601 			if (addr == UT64_MAX || addr == UT32_MAX) {
602 				p->cb_printf ("-1");
603 			} else {
604 				p->cb_printf ("%"PFMT64d, addr);
605 			}
606 		} else {
607 			if (!SEEVALUE) {
608 				p->cb_printf ("[ ");
609 			}
610 			while (size--) {
611 				updateAddr (buf + i, size - i, endian, &addr, NULL);
612 				if (elem == -1 || elem == 0) {
613 					if (ISQUIET) {
614 						if (addr == UT64_MAX || addr == UT32_MAX) {
615 							p->cb_printf ("-1");
616 						} else {
617 							p->cb_printf ("%"PFMT64d, addr);
618 						}
619 					} else {
620 						p->cb_printf ("%"PFMT64d, addr);
621 					}
622 					if (elem == 0) {
623 						elem = -2;
624 					}
625 				}
626 				if (size != 0 && elem == -1) {
627 					p->cb_printf (", ");
628 				}
629 				if (elem > -1) {
630 					elem--;
631 				}
632 				i += 4;
633 			}
634 			if (!SEEVALUE) {
635 				p->cb_printf (" ]");
636 			}
637 		}
638 	} else if (MUSTSEEJSON) {
639 		if (size == -1) {
640 			p->cb_printf ("%"PFMT64d, addr);
641 		} else {
642 			p->cb_printf ("[ ");
643 			while (size--) {
644 				updateAddr (buf + i, size - i, endian, &addr, NULL);
645 				if (elem == -1 || elem == 0) {
646 					p->cb_printf ("%"PFMT64d, addr);
647 					if (elem == 0) {
648 						elem = -2;
649 					}
650 				}
651 				if (size != 0 && elem == -1) {
652 					p->cb_printf (", ");
653 				}
654 				if (elem > -1) {
655 					elem--;
656 				}
657 				i+=4;
658 			}
659 			p->cb_printf (" ]");
660 		}
661 		p->cb_printf ("}");
662 	}
663 }
664 
r_print_format_int(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)665 static void r_print_format_int(const RPrint* p, int endian, int mode,
666 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
667 	ut64 addr;
668 	int elem = -1;
669 	if (size >= ARRAYINDEX_COEF) {
670 		elem = size/ARRAYINDEX_COEF-1;
671 		size %= ARRAYINDEX_COEF;
672 	}
673 	updateAddr (buf + i, size - i, endian, &addr, NULL);
674 	if (MUSTSET) {
675 		p->cb_printf ("wv4 %s @ %"PFMT64d"\n", setval, seeki+((elem>=0)?elem*4:0));
676 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
677 		p->cb_printf ("0x%08"PFMT64x, addr);
678 	} else if (MUSTSEE) {
679 		if (!SEEVALUE && !ISQUIET) {
680 			p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
681 		}
682 		if (size == -1) {
683 			p->cb_printf ("%"PFMT64d, (st64)(st32)addr);
684 		} else {
685 			if (!SEEVALUE) {
686 				p->cb_printf ("[ ");
687 			}
688 			while (size--) {
689 				updateAddr (buf + i, size - i, endian, &addr, NULL);
690 				if (elem == -1 || elem == 0) {
691 					p->cb_printf ("%"PFMT64d, (st64)(st32)addr);
692 					if (elem == 0) {
693 						elem = -2;
694 					}
695 				}
696 				if (size != 0 && elem == -1) {
697 					p->cb_printf (", ");
698 				}
699 				if (elem > -1) {
700 					elem--;
701 				}
702 				i += 4;
703 			}
704 			if (!SEEVALUE) {
705 				p->cb_printf (" ]");
706 			}
707 		}
708 	} else if (MUSTSEEJSON) {
709 		if (size == -1) {
710 			p->cb_printf ("%"PFMT64d, addr);
711 		} else {
712 			p->cb_printf ("[ ");
713 			while (size--) {
714 				updateAddr (buf + i, size - i, endian, &addr, NULL);
715 				if (elem == -1 || elem == 0) {
716 					p->cb_printf ("%"PFMT64d, addr);
717 					if (elem == 0) {
718 						elem = -2;
719 					}
720 				}
721 				if (size != 0 && elem == -1) {
722 					p->cb_printf (", ");
723 				}
724 				if (elem > -1) {
725 					elem--;
726 				}
727 				i+=4;
728 			}
729 			p->cb_printf (" ]");
730 		}
731 		p->cb_printf ("}");
732 	}
733 }
734 
r_print_format_disasm(const RPrint * p,ut64 seeki,int size)735 static int r_print_format_disasm(const RPrint* p, ut64 seeki, int size) {
736 	ut64 prevseeki = seeki;
737 
738 	if (!p->disasm || !p->user) {
739 		return 0;
740 	}
741 
742 	size = R_MAX (1, size);
743 
744 	while (size-- > 0) {
745 		seeki += p->disasm (p->user, seeki);
746 	}
747 
748 	return seeki - prevseeki;
749 }
750 
r_print_format_octal(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)751 static void r_print_format_octal(const RPrint* p, int endian, int mode,
752 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
753 	ut64 addr;
754 	int elem = -1;
755 	if (size >= ARRAYINDEX_COEF) {
756 		elem = size/ARRAYINDEX_COEF-1;
757 		size %= ARRAYINDEX_COEF;
758 	}
759 	updateAddr (buf + i, size - i, endian, &addr, NULL);
760 	if (MUSTSET) {
761 		p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
762 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
763 		p->cb_printf ("0%"PFMT64o, addr);
764 	} else if (MUSTSEE) {
765 		if (!SEEVALUE && !ISQUIET) {
766 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
767 		}
768 		if (!SEEVALUE) {
769 			p->cb_printf ("(octal) ");
770 		}
771 		if (size == -1) {
772 			p->cb_printf (" 0%08"PFMT64o, addr);
773 		} else {
774 			if (!SEEVALUE) {
775 				p->cb_printf ("[ ");
776 			}
777 			while (size--) {
778 				updateAddr (buf + i, size - i, endian, &addr, NULL);
779 				if (elem == -1 || elem == 0) {
780 					p->cb_printf ("0%08"PFMT64o, addr);
781 					if (elem == 0) {
782 						elem = -2;
783 					}
784 				}
785 				if (size != 0 && elem == -1) {
786 					p->cb_printf (", ");
787 				}
788 				if (elem > -1) {
789 					elem--;
790 				}
791 				i+=4;
792 			}
793 			if (!SEEVALUE) {
794 				p->cb_printf (" ]");
795 			}
796 		}
797 	} else if (MUSTSEEJSON) {
798 		if (size == -1) {
799 			p->cb_printf ("%"PFMT64d, addr);
800 		} else {
801 			p->cb_printf ("[ ");
802 			while (size--) {
803 				updateAddr (buf, i, endian, &addr, NULL);
804 				if (elem == -1 || elem == 0) {
805 					p->cb_printf ("%"PFMT64d, addr);
806 					if (elem == 0) {
807 						elem = -2;
808 					}
809 				}
810 				if (size != 0 && elem == -1) {
811 					p->cb_printf (", ");
812 				}
813 				if (elem > -1) {
814 					elem--;
815 				}
816 				i+=4;
817 			}
818 			p->cb_printf (" ]");
819 		}
820 		p->cb_printf ("}");
821 	}
822 }
823 
r_print_format_hexflag(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)824 static void r_print_format_hexflag(const RPrint* p, int endian, int mode,
825 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
826 	ut64 addr = 0;
827 	int elem = -1;
828 	if (size >= ARRAYINDEX_COEF) {
829 		elem = size/ARRAYINDEX_COEF-1;
830 		size %= ARRAYINDEX_COEF;
831 	}
832 	updateAddr (buf + i, size - i, endian, &addr, NULL);
833 	if (MUSTSET) {
834 		p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
835 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
836 		p->cb_printf ("0x%08"PFMT64x, addr & UT32_MAX);
837 	} else if (MUSTSEE) {
838 		ut32 addr32 = (ut32)addr;
839 		if (!SEEVALUE && !ISQUIET) {
840 			p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
841 		}
842 		if (size==-1) {
843 			if (ISQUIET && (addr32 == UT32_MAX)) {
844 				p->cb_printf ("-1");
845 			} else {
846 				p->cb_printf ("0x%08"PFMT64x, (ut64)addr32);
847 			}
848 		} else {
849 			if (!SEEVALUE) {
850 				p->cb_printf ("[ ");
851 			}
852 			while (size--) {
853 				updateAddr (buf + i, size - i, endian, &addr, NULL);
854 				if (elem == -1 || elem == 0) {
855 					p->cb_printf ("0x%08"PFMT64x, addr);
856 					if (elem == 0) {
857 						elem = -2;
858 					}
859 				}
860 				if (size != 0 && elem == -1) {
861 					p->cb_printf (", ");
862 				}
863 				if (elem > -1) {
864 					elem--;
865 				}
866 				i+=4;
867 			}
868 			if (!SEEVALUE) {
869 				p->cb_printf (" ]");
870 			}
871 		}
872 	} else if (MUSTSEEJSON) {
873 		if (size == -1) {
874 			p->cb_printf ("%"PFMT64d, addr);
875 		} else {
876 			p->cb_printf ("[ ");
877 			while (size--) {
878 				updateAddr (buf + i, size - i, endian, &addr, NULL);
879 				if (elem == -1 || elem == 0) {
880 					p->cb_printf ("%"PFMT64d, addr);
881 					if (elem == 0) {
882 						elem = -2;
883 					}
884 				}
885 				if (size != 0 && elem == -1) {
886 					p->cb_printf (",");
887 				}
888 				if (elem > -1) {
889 					elem--;
890 				}
891 				i += 4;
892 			}
893 			p->cb_printf (" ]");
894 		}
895 		p->cb_printf ("}");
896 	}
897 }
898 
r_print_format_10bytes(const RPrint * p,int mode,const char * setval,ut64 seeki,ut64 addr,ut8 * buf)899 static int r_print_format_10bytes(const RPrint* p, int mode, const char *setval,
900 		ut64 seeki, ut64 addr, ut8* buf) {
901 	ut8 buffer[255];
902 	int j;
903 	if (MUSTSET) {
904 		p->cb_printf ("?e pf B not yet implemented\n");
905 	} else if (mode & R_PRINT_DOT) {
906 		for (j = 0; j<10; j++) {
907 			p->cb_printf ("%02x ", buf[j]);
908 		}
909 	} else if (MUSTSEE) {
910 		if (!p->iob.read_at) {
911 			printf ("(cannot read memory)\n");
912 			return -1;
913 		}
914 		p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
915 		if (!SEEVALUE && !ISQUIET) {
916 			p->cb_printf ("0x%08" PFMT64x " = ", seeki);
917 		}
918 		for (j=0; j<10; j++) {
919 			p->cb_printf ("%02x ", buf[j]);
920 		}
921 		if (!SEEVALUE) {
922 			p->cb_printf (" ... (");
923 		}
924 		for (j = 0; j < 10; j++) {
925 			if (!SEEVALUE) {
926 				if (IS_PRINTABLE (buf[j])) {
927 					p->cb_printf ("%c", buf[j]);
928 				} else {
929 					p->cb_printf (".");
930 				}
931 			}
932 		}
933 		if (!SEEVALUE) {
934 			p->cb_printf (")");
935 		}
936 	} else if (MUSTSEEJSON) {
937 		if (!p->iob.read_at) {
938 			printf ("(cannot read memory)\n");
939 			return -1;
940 		} else {
941 			p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
942 		}
943 		p->cb_printf ("[ %d", buf[0]);
944 		j = 1;
945 		for (; j < 10; j++) {
946 			p->cb_printf (", %d", buf[j]);
947 		}
948 		p->cb_printf ("]");
949 		return 0;
950 	}
951 	return 0;
952 }
953 
r_print_format_hexpairs(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)954 static int r_print_format_hexpairs(const RPrint* p, int endian, int mode,
955 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
956 	int j;
957 	size = (size == -1) ? 1 : size;
958 	if (MUSTSET) {
959 		p->cb_printf ("?e pf X not yet implemented\n");
960 	} else if (mode & R_PRINT_DOT) {
961 		for (j = 0; j < size; j++) {
962 			p->cb_printf ("%02x", buf[i + j]);
963 		}
964 	} else if (MUSTSEE) {
965 		size = (size < 1) ? 1 : size;
966 		if (!SEEVALUE && !ISQUIET) {
967 			p->cb_printf ("0x%08" PFMT64x " = ", seeki);
968 		}
969 		for (j = 0; j < size; j++) {
970 			p->cb_printf ("%02x ", buf[i + j]);
971 		}
972 		if (!SEEVALUE) {
973 			p->cb_printf (" ... (");
974 		}
975 		for (j=0; j<size; j++) {
976 			if (!SEEVALUE) {
977 				if (IS_PRINTABLE (buf[j])) {
978 					p->cb_printf ("%c", buf[i+j]);
979 				} else {
980 					p->cb_printf (".");
981 				}
982 			}
983 		}
984 		p->cb_printf (")");
985 	} else if (MUSTSEEJSON || MUSTSEESTRUCT) {
986 		size = (size < 1) ? 1 : size;
987 		p->cb_printf ("[ %d", buf[0]);
988 		j = 1;
989 		for (; j < 10; j++) {
990 			p->cb_printf (", %d", buf[j]);
991 		}
992 		p->cb_printf ("]");
993 		if (MUSTSEEJSON) {
994 			p->cb_printf ("}");
995 		}
996 		return size;
997 	}
998 	return size;
999 }
1000 
r_print_format_float(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1001 static void r_print_format_float(const RPrint* p, int endian, int mode,
1002 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1003 	float val_f = 0.0f;
1004 	ut64 addr = 0;
1005 	int elem = -1;
1006 	if (size >= ARRAYINDEX_COEF) {
1007 		elem = size/ARRAYINDEX_COEF - 1;
1008 		size %= ARRAYINDEX_COEF;
1009 	}
1010 	val_f = updateAddr (buf + i, 999, endian, &addr, NULL);
1011 	if (MUSTSET) {
1012 		p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval,
1013 			seeki + ((elem >= 0) ? elem * 4 : 0));
1014 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1015 		p->cb_printf ("%.9g", val_f);
1016 	} else {
1017 		if (MUSTSEE) {
1018 			if (!SEEVALUE && !ISQUIET) {
1019 				p->cb_printf ("0x%08"PFMT64x" = ",
1020 					seeki + ((elem >= 0) ? elem * 4 : 0));
1021 			}
1022 		}
1023 		if (size == -1) {
1024 			p->cb_printf ("%.9g", val_f);
1025 		} else {
1026 			if (!SEEVALUE) {
1027 				p->cb_printf ("[ ");
1028 			}
1029 			while (size--) {
1030 				val_f = updateAddr (buf + i, 9999, endian, &addr, NULL);
1031 				if (elem == -1 || elem == 0) {
1032 					p->cb_printf ("%.9g", val_f);
1033 					if (elem == 0) {
1034 						elem = -2;
1035 					}
1036 				}
1037 				if (size != 0 && elem == -1) {
1038 					p->cb_printf (", ");
1039 				}
1040 				if (elem > -1) {
1041 					elem--;
1042 				}
1043 				i += 4;
1044 			}
1045 			if (!SEEVALUE) {
1046 				p->cb_printf (" ]");
1047 			}
1048 		}
1049 		if (MUSTSEEJSON) {
1050 			p->cb_printf ("}");
1051 		}
1052 	}
1053 }
1054 
1055 
r_print_format_double(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1056 static void r_print_format_double(const RPrint* p, int endian, int mode,
1057 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1058 	double val_f = 0.0;
1059 	ut64 addr = 0;
1060 	int elem = -1;
1061 	if (size >= ARRAYINDEX_COEF) {
1062 		elem = size/ARRAYINDEX_COEF - 1;
1063 		size %= ARRAYINDEX_COEF;
1064 	}
1065 	updateAddr (buf + i, 999, endian, &addr, NULL);
1066 	r_mem_swaporcopy ((ut8*)&val_f, buf + i, sizeof (double), endian);
1067 	if (MUSTSET) {
1068 		p->cb_printf ("wv8 %s @ 0x%08"PFMT64x"\n", setval,
1069 			seeki + ((elem >= 0) ? elem * 8 : 0));
1070 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1071 		p->cb_printf ("%.17g", val_f);
1072 	} else {
1073 		if (MUSTSEE) {
1074 			if (!SEEVALUE && !ISQUIET) {
1075 				p->cb_printf ("0x%08"PFMT64x" = ",
1076 					seeki + ((elem >= 0) ? elem * 8 : 0));
1077 			}
1078 		}
1079 		if (size == -1) {
1080 			p->cb_printf ("%.17g", val_f);
1081 		} else {
1082 			if (!SEEVALUE) {
1083 				p->cb_printf ("[ ");
1084 			}
1085 			while (size--) {
1086 				// XXX this 999 is scary
1087 				updateAddr (buf + i, 9999, endian, &addr, NULL);
1088 				r_mem_swaporcopy ((ut8*)&val_f, buf + i, sizeof (double), endian);
1089 				if (elem == -1 || elem == 0) {
1090 					p->cb_printf ("%.17g", val_f);
1091 					if (elem == 0) {
1092 						elem = -2;
1093 					}
1094 				}
1095 				if (size != 0 && elem == -1) {
1096 					p->cb_printf (", ");
1097 				}
1098 				if (elem > -1) {
1099 					elem--;
1100 				}
1101 				i += 8;
1102 			}
1103 			if (!SEEVALUE) {
1104 				p->cb_printf (" ]");
1105 			}
1106 		}
1107 		if (MUSTSEEJSON) {
1108 			p->cb_printf ("}");
1109 		}
1110 	}
1111 }
1112 
r_print_format_word(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1113 static void r_print_format_word(const RPrint* p, int endian, int mode,
1114 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1115 	ut64 addr;
1116 	int elem = -1;
1117 	if (size >= ARRAYINDEX_COEF) {
1118 		elem = size/ARRAYINDEX_COEF-1;
1119 		size %= ARRAYINDEX_COEF;
1120 	}
1121 	addr = endian
1122 		? (*(buf + i)) << 8 | (*(buf + i + 1))
1123 		: (*(buf + i + 1)) << 8 | (*(buf + i));
1124 	if (MUSTSET) {
1125 		p->cb_printf ("wv2 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*2:0));
1126 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1127 		if (size == -1) {
1128 			p->cb_printf ("0x%04"PFMT64x, addr);
1129 		}
1130 		while ((size -= 2) > 0) {
1131 			addr = endian
1132 				? (*(buf+i))<<8 | (*(buf+i+1))
1133 				: (*(buf+i+1))<<8 | (*(buf+i));
1134 			if (elem == -1 || elem == 0) {
1135 				p->cb_printf ("%"PFMT64d, addr);
1136 				if (elem == 0) {
1137 					elem = -2;
1138 				}
1139 			}
1140 			if (size != 0 && elem == -1) {
1141 				p->cb_printf (",");
1142 			}
1143 			if (elem > -1) {
1144 				elem--;
1145 			}
1146 			i += 2;
1147 		}
1148 	} else if (MUSTSEE) {
1149 		if (!SEEVALUE && !ISQUIET) {
1150 			p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*2:0));
1151 		}
1152 		if (size==-1) {
1153 			p->cb_printf ("0x%04"PFMT64x, addr);
1154 		} else {
1155 			if (!SEEVALUE) {
1156 				p->cb_printf ("[ ");
1157 			}
1158 			while (size--) {
1159 				addr = endian
1160 					? (*(buf+i))<<8 | (*(buf+i+1))
1161 					: (*(buf+i+1))<<8 | (*(buf+i));
1162 				if (elem == -1 || elem == 0) {
1163 					p->cb_printf ("0x%04"PFMT64x, addr);
1164 					if (elem == 0) {
1165 						elem = -2;
1166 					}
1167 				}
1168 				if (size != 0 && elem == -1) {
1169 					p->cb_printf (", ");
1170 				}
1171 				if (elem > -1) {
1172 					elem--;
1173 				}
1174 				i += 2;
1175 			}
1176 			if (!SEEVALUE) {
1177 				p->cb_printf (" ]");
1178 			}
1179 		}
1180 	} else if (MUSTSEEJSON) {
1181 		if (size==-1) {
1182 			p->cb_printf ("%"PFMT64d, addr);
1183 		} else {
1184 			p->cb_printf ("[ ");
1185 			while ( (size -= 2) >0) {
1186 				addr = endian
1187 					? (*(buf+i))<<8 | (*(buf+i+1))
1188 					: (*(buf+i+1))<<8 | (*(buf+i));
1189 				if (elem == -1 || elem == 0) {
1190 					p->cb_printf ("%"PFMT64d, addr);
1191 					if (elem == 0) {
1192 						elem = -2;
1193 					}
1194 				}
1195 				if (size != 0 && elem == -1) {
1196 					p->cb_printf (",");
1197 				}
1198 				if (elem > -1) {
1199 					elem--;
1200 				}
1201 				i += 2;
1202 			}
1203 			p->cb_printf (" ]");
1204 		}
1205 		p->cb_printf ("}");
1206 	}
1207 }
1208 
r_print_byte_escape(const RPrint * p,const char * src,char ** dst,int dot_nl)1209 static void r_print_byte_escape(const RPrint* p, const char *src, char **dst, int dot_nl) {
1210 	r_return_if_fail (p->strconv_mode);
1211 	r_str_byte_escape (src, dst, dot_nl, !strcmp (p->strconv_mode, "asciidot"), p->esc_bslash);
1212 }
1213 
r_print_format_nulltermstring(const RPrint * p,int len,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1214 static void r_print_format_nulltermstring(const RPrint* p, int len, int endian, int mode,
1215 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1216 	if (!p->iob.is_valid_offset (p->iob.io, seeki, 1)) {
1217 		ut8 ch = 0xff;
1218 		// XXX there are some cases where the memory is there but is_valid_offset fails wtf
1219 		if (p->iob.read_at (p->iob.io, seeki, &ch, 1) != 1 && ch != 0xff) {
1220 			p->cb_printf ("-1");
1221 			return;
1222 		}
1223 	}
1224 	if (p->flags & R_PRINT_FLAGS_UNALLOC && !(p->iob.io->cached & R_PERM_R)) {
1225 		ut64 total_map_left = 0;
1226 		ut64 addr = seeki;
1227 		RIOMap *map;
1228 		while (total_map_left < len
1229 		       && (map = p->iob.io->va
1230 		           ? p->iob.map_get (p->iob.io, addr)
1231 		           : p->iob.map_get_paddr (p->iob.io, addr))
1232 		       && map->perm & R_PERM_R) {
1233 			if (!r_io_map_size(map)) {
1234 				total_map_left = addr == 0 ? UT64_MAX : UT64_MAX - addr + 1;
1235 				break;
1236 			}
1237 			total_map_left += r_io_map_size (map) - (addr - (p->iob.io->va ? r_io_map_begin (map) : map->delta));
1238 			addr += total_map_left;
1239 		}
1240 		if (total_map_left < len) {
1241 			len = total_map_left;
1242 		}
1243 	}
1244 	int str_len = r_str_nlen ((char *)buf + i, len - i);
1245 	bool overflow = (size == -1 || size > len - i) && str_len == len - i;
1246 	if (MUSTSET) {
1247 		int buflen = strlen ((const char *)buf + seeki);
1248 		int vallen = strlen (setval);
1249 		char *ons, *newstring = ons = strdup (setval);
1250 		if ((newstring[0] == '\"' && newstring[vallen - 1] == '\"')
1251 				|| (newstring[0] == '\'' && newstring[vallen - 1] == '\'')) {
1252 			newstring[vallen - 1] = '\0';
1253 			newstring++;
1254 			vallen -= 2;
1255 		}
1256 		if (vallen > buflen) {
1257 			eprintf ("Warning: new string is longer than previous one\n");
1258 		}
1259 		p->cb_printf ("wx ");
1260 		for (i = 0; i < vallen; i++) {
1261 			if (i < vallen - 3 && newstring[i] == '\\' && newstring[i + 1] == 'x') {
1262 				p->cb_printf ("%c%c", newstring[i + 2], newstring[i + 3]);
1263 				i += 3;
1264 			} else {
1265 				p->cb_printf ("%2x", newstring[i]);
1266 			}
1267 		}
1268 		p->cb_printf (" @ 0x%08"PFMT64x"\n", seeki);
1269 		free (ons);
1270 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1271 		int j = i;
1272 		(MUSTSEESTRUCT) ?
1273 			p->cb_printf ("\"") :
1274 			p->cb_printf ("\\\"");
1275 		for (; j<len && ((size==-1 || size-- >0) && buf[j]) ; j++) {
1276 			char ch = buf[j];
1277 			if (ch == '"') {
1278 				p->cb_printf ("\\\"");
1279 			} else if (IS_PRINTABLE (ch)) {
1280 				p->cb_printf ("%c", ch);
1281 			} else {
1282 				p->cb_printf (".");
1283 			}
1284 		}
1285 		(MUSTSEESTRUCT) ?
1286 			p->cb_printf ("\"") :
1287 			p->cb_printf ("\\\"");
1288 	} else if (MUSTSEE) {
1289 		int j = i;
1290 		if (!SEEVALUE && !ISQUIET) {
1291 			p->cb_printf ("0x%08" PFMT64x " = %s", seeki, overflow ? "ovf " : "");
1292 		}
1293 		p->cb_printf ("\"");
1294 		for (; j < len && ((size == -1 || size-- > 0) && buf[j]) ; j++) {
1295 			char esc_str[5] = { 0 };
1296 			char *ptr = esc_str;
1297 			r_print_byte_escape (p, (char *)&buf[j], &ptr, false);
1298 			p->cb_printf ("%s", esc_str);
1299 		}
1300 		p->cb_printf ("\"");
1301 	} else if (MUSTSEEJSON) {
1302 		char *utf_encoded_buf = NULL;
1303 		p->cb_printf ("\"");
1304 		utf_encoded_buf = r_str_escape_utf8_for_json (
1305 		    (char *)buf + i, size == -1 ? str_len : R_MIN (size, str_len));
1306 		if (utf_encoded_buf){
1307 			p->cb_printf ("%s", utf_encoded_buf);
1308 			free (utf_encoded_buf);
1309 		}
1310 		p->cb_printf ("\"");
1311 		if (overflow) {
1312 			p->cb_printf (",\"overflow\":true");
1313 		}
1314 		p->cb_printf ("}");
1315 	}
1316 }
1317 
r_print_format_nulltermwidestring(const RPrint * p,const int len,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1318 static void r_print_format_nulltermwidestring(const RPrint* p, const int len, int endian, int mode,
1319 		const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1320 	if (MUSTSET) {
1321 		int vallen = strlen(setval);
1322 		char *newstring, *ons;
1323 		newstring = ons = strdup(setval);
1324 		if ((newstring[0] == '\"' && newstring[vallen-1] == '\"')
1325 				|| (newstring[0] == '\'' && newstring[vallen-1] == '\'')) {
1326 			newstring[vallen - 1] = '\0';
1327 			newstring++;
1328 			vallen -= 2;
1329 		}
1330 		if ((size = vallen) > r_wstr_clen((char*)(buf+seeki))) {
1331 			eprintf ("Warning: new string is longer than previous one\n");
1332 		}
1333 		p->cb_printf ("ww %s @ 0x%08"PFMT64x"\n", newstring, seeki);
1334 		free(ons);
1335 	} else if (MUSTSEE) {
1336 		int j = i;
1337 		if (!SEEVALUE && !ISQUIET) {
1338 			p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1339 		}
1340 		for (; j<len && ((size==-1 || size-->0) && buf[j]) ; j+=2) {
1341 			if (IS_PRINTABLE (buf[j])) {
1342 				p->cb_printf ("%c", buf[j]);
1343 			} else {
1344 				p->cb_printf (".");
1345 			}
1346 		}
1347 	} else if (MUSTSEEJSON) {
1348 		int j = i;
1349 		p->cb_printf ("%"PFMT64d",\"string\":\"", seeki);
1350 		for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j += 2) {
1351 			if (IS_PRINTABLE (buf[j])) {
1352 				p->cb_printf ("%c", buf[j]);
1353 			} else {
1354 				p->cb_printf (".");
1355 			}
1356 		}
1357 		p->cb_printf ("\"}");
1358 	}
1359 }
1360 
r_print_format_bitfield(const RPrint * p,ut64 seeki,char * fmtname,char * fieldname,ut64 addr,int mode,int size)1361 static void r_print_format_bitfield(const RPrint* p, ut64 seeki, char *fmtname,
1362 		char *fieldname, ut64 addr, int mode, int size) {
1363 	char *bitfield = NULL;
1364 	addr &= (1ULL << (size * 8)) - 1;
1365 	if (MUSTSEE && !SEEVALUE) {
1366 		p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1367 	}
1368 	bitfield = r_type_enum_getbitfield (p->sdb_types, fmtname, addr);
1369 	if (bitfield && *bitfield) {
1370 		if (MUSTSEEJSON) {
1371 			p->cb_printf ("\"%s\"}", bitfield);
1372 		} else if (MUSTSEE) {
1373 			p->cb_printf ("%s (bitfield) = %s\n", fieldname, bitfield);
1374 		}
1375 	} else {
1376 		if (MUSTSEEJSON) {
1377 			p->cb_printf ("\"`tb %s 0x%"PFMT64x"`\"}", fmtname, addr);
1378 		} else if (MUSTSEE) {
1379 			p->cb_printf ("%s (bitfield) = `tb %s 0x%"PFMT64x"`\n",
1380 				fieldname, fmtname, addr);
1381 		}
1382 	}
1383 	free (bitfield);
1384 }
1385 
r_print_format_enum(const RPrint * p,ut64 seeki,char * fmtname,char * fieldname,ut64 addr,int mode,int size)1386 static void r_print_format_enum(const RPrint* p, ut64 seeki, char *fmtname,
1387 		char *fieldname, ut64 addr, int mode, int size) {
1388 	char *enumvalue = NULL;
1389 	addr &= (1ULL << (size * 8)) - 1;
1390 	if (MUSTSEE && !SEEVALUE) {
1391 		p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1392 	}
1393 	enumvalue = r_type_enum_member (p->sdb_types, fmtname, NULL, addr);
1394 	if (enumvalue && *enumvalue) {
1395 		if (mode & R_PRINT_DOT) {
1396 			p->cb_printf ("%s.%s", fmtname, enumvalue);
1397 		} else if (MUSTSEEJSON) {
1398 			p->cb_printf ("%"PFMT64d",\"label\":\"%s\",\"enum\":\"%s\"}",
1399 				addr, enumvalue, fmtname);
1400 		} else if (MUSTSEE) {
1401 			p->cb_printf ("%s (enum %s) = 0x%"PFMT64x" ; %s\n",
1402 				fieldname, fmtname, addr, enumvalue);
1403 		} else if (MUSTSEESTRUCT) {
1404 			p->cb_printf ("%s", enumvalue);
1405 		}
1406 	} else {
1407 		if (MUSTSEEJSON) {
1408 			p->cb_printf ("%"PFMT64d",\"enum\":\"%s\"}", addr, fmtname);
1409 		} else if (MUSTSEE) {
1410 			p->cb_printf ("%s (enum %s) = 0x%"PFMT64x"\n",//`te %s 0x%x`\n",
1411 				fieldname, fmtname, addr); //enumvalue); //fmtname, addr);
1412 		}
1413 	}
1414 	free (enumvalue);
1415 }
1416 
r_print_format_register(const RPrint * p,int mode,const char * name,const char * setval)1417 static void r_print_format_register(const RPrint* p, int mode,
1418 		const char *name, const char *setval) {
1419 	if (!p || !p->get_register || !p->reg) {
1420 		return;
1421 	}
1422 	RRegItem *ri = p->get_register (p->reg, name, R_REG_TYPE_ALL);
1423 	if (ri) {
1424 		if (MUSTSET) {
1425 			p->cb_printf ("dr %s=%s\n", name, setval);
1426 		} else if (MUSTSEE) {
1427 			if (!SEEVALUE) {
1428 				p->cb_printf ("%s : 0x%08" PFMT64x "\n", ri->name, p->get_register_value (p->reg, ri));
1429 			} else {
1430 				p->cb_printf ("0x%08" PFMT64x "\n", p->get_register_value (p->reg, ri));
1431 			}
1432 		} else if (MUSTSEEJSON) {
1433 			p->cb_printf ("%"PFMT64d"}", p->get_register_value (p->reg, ri));
1434 		}
1435 	} else {
1436 		p->cb_printf ("Register %s does not exists\n", name);
1437 	}
1438 }
1439 
r_print_format_num_specifier(const RPrint * p,ut64 addr,int bytes,int sign)1440 static void r_print_format_num_specifier(const RPrint *p, ut64 addr, int bytes, int sign) {
1441 #define EXT(T) (sign ? (signed T)(addr) : (unsigned T)(addr) )
1442 	const char *fs64 = sign ? "%"PFMT64d : "%"PFMT64u;
1443 	const char *fs = sign ? "%d" : "%u";
1444 	if (bytes == 1) {
1445 		p->cb_printf (fs, EXT(char));
1446 	} else if (bytes == 2) {
1447 		p->cb_printf (fs, EXT(short));
1448 	} else if (bytes == 4) {
1449 		p->cb_printf (fs, EXT(int)); //XXX: int is not necessarily 4 bytes I guess.
1450 	} else if (bytes == 8) {
1451 		p->cb_printf (fs64, addr);
1452 	}
1453 #undef EXT
1454 }
1455 
r_print_format_num(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int bytes,int sign,int size)1456 static void r_print_format_num(const RPrint *p, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int bytes, int sign, int size) {
1457 	ut64 addr = 0LL;
1458 	int elem = -1;
1459 	if (size >= ARRAYINDEX_COEF) {
1460 		elem = size / ARRAYINDEX_COEF - 1;
1461 		size %= ARRAYINDEX_COEF;
1462 	}
1463 	if (bytes == 8) {
1464 		updateAddr (buf + i, size - i, endian, NULL, &addr);
1465 	} else {
1466 		updateAddr (buf + i, size - i, endian, &addr, NULL);
1467 	}
1468 	if (MUSTSET) {
1469 		p->cb_printf ("wv%d %s @ 0x%08"PFMT64x"\n", bytes, setval, seeki+((elem>=0)?elem*(bytes):0));
1470 	} else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1471 		r_print_format_num_specifier (p, addr, bytes, sign);
1472 	} else if (MUSTSEE) {
1473 		if (!SEEVALUE && !ISQUIET) {
1474 			p->cb_printf ("0x%08"PFMT64x" = ", seeki + ((elem >= 0)? elem * bytes: 0));
1475 		}
1476 		if (size == -1) {
1477 			r_print_format_num_specifier (p, addr, bytes, sign);
1478 		} else {
1479 			if (!SEEVALUE) {
1480 				p->cb_printf ("[ ");
1481 			}
1482 			while (size--) {
1483 				if (bytes == 8) {
1484 					updateAddr (buf + i, size - i, endian, NULL, &addr);
1485 				} else {
1486 					updateAddr (buf + i, size - i, endian, &addr, NULL);
1487 				}
1488 				if (elem == -1 || elem == 0) {
1489 					r_print_format_num_specifier (p, addr, bytes, sign);
1490 					if (elem == 0) {
1491 						elem = -2;
1492 					}
1493 				}
1494 				if (size != 0 && elem == -1) {
1495 					p->cb_printf (", ");
1496 				}
1497 				if (elem > -1) {
1498 					elem--;
1499 				}
1500 				i += bytes;
1501 			}
1502 			if (!SEEVALUE) {
1503 				p->cb_printf (" ]");
1504 			}
1505 		}
1506 	} else if (MUSTSEEJSON) {
1507 		if (size == -1) {
1508 			r_print_format_num_specifier (p, addr, bytes, sign);
1509 		} else {
1510 			p->cb_printf ("[ ");
1511 			while (size--) {
1512 				if (bytes == 8) {
1513 					updateAddr (buf + i, size, endian, NULL, &addr);
1514 				} else {
1515 					updateAddr (buf + i, size, endian, &addr, NULL);
1516 				}
1517 				if (elem == -1 || elem == 0) {
1518 					r_print_format_num_specifier (p, addr, bytes, sign);
1519 					if (elem == 0) {
1520 						elem = -2;
1521 					}
1522 				}
1523 				if (size != 0 && elem == -1) {
1524 					p->cb_printf (", ");
1525 				}
1526 				if (elem > -1) {
1527 					elem--;
1528 				}
1529 				i += bytes;
1530 			}
1531 			p->cb_printf (" ]");
1532 		}
1533 		p->cb_printf ("}");
1534 	}
1535 }
1536 
r_print_format_byname(RPrint * p,const char * name)1537 R_API const char *r_print_format_byname(RPrint *p, const char *name) {
1538 	return sdb_const_get (p->formats, name, NULL);
1539 }
1540 
1541 // XXX: this is somewhat incomplete. must be updated to handle all format chars
r_print_format_struct_size(RPrint * p,const char * f,int mode,int n)1542 R_API int r_print_format_struct_size(RPrint *p, const char *f, int mode, int n) {
1543 	char *end, *args, *fmt;
1544 	int size = 0, tabsize = 0, i, idx = 0, biggest = 0, fmt_len = 0, times = 1;
1545 	bool tabsize_set = false;
1546 	if (!f) {
1547 		return -1;
1548 	}
1549 	if (n >= 5) {  // This is the nesting level, is this not a bit arbitrary?!
1550 		return 0;
1551 	}
1552 	const char *fmt2 = sdb_get (p->formats, f, NULL);
1553 	if (!fmt2) {
1554 		fmt2 = f;
1555 	}
1556 	char *o = strdup (fmt2);
1557 	if (!o) {
1558 		return -1;
1559 	}
1560 	end = strchr (o, ' ');
1561 	fmt = o;
1562 	if (!end && !(end = strchr (o, '\0'))) {
1563 		free (o);
1564 		return -1;
1565 	}
1566 	if (*end) {
1567 		*end = 0;
1568 		args = strdup (end + 1);
1569 	} else {
1570 		args = strdup ("");
1571 	}
1572 
1573 	i = 0;
1574 	if (fmt[i] == '{') {
1575 		char *end = strchr (fmt + i + 1, '}');
1576 		if (!end) {
1577 			eprintf ("No end curly bracket.\n");
1578 			free (o);
1579 			free (args);
1580 			return -1;
1581 		}
1582 		*end = '\0';
1583 		times = r_num_math (NULL, fmt + i + 1);
1584 		fmt = end + 1;
1585 	}
1586 	if (fmt[0] == '0') {
1587 		mode |= R_PRINT_UNIONMODE;
1588 		fmt++;
1589 	} else {
1590 		mode &= ~R_PRINT_UNIONMODE;
1591 	}
1592 
1593 	int words = r_str_word_set0_stack (args);
1594 	fmt_len = strlen (fmt);
1595 	for (; i < fmt_len; i++) {
1596 		if (fmt[i] == '[') {
1597 			char *end = strchr (fmt + i,']');
1598 			if (!end) {
1599 				eprintf ("No end bracket.\n");
1600 				continue;
1601 			}
1602 			*end = '\0';
1603 			tabsize_set = true;
1604 			tabsize = r_num_math (NULL, fmt + i + 1);
1605 			*end = ']';
1606 			while (fmt[i++] != ']') {
1607 				;
1608 			}
1609 		} else {
1610 			tabsize = 1;
1611 		}
1612 
1613 		switch (fmt[i]) {
1614 		case '.':
1615 			idx--;
1616 		case 'c':
1617 		case 'b':
1618 		case 'X':
1619 			size += tabsize * 1;
1620 			break;
1621 		case 'w':
1622 			size += tabsize * 2;
1623 			break;
1624 		case ':':
1625 			idx--;
1626 		case 'd':
1627 		case 'o':
1628 		case 'i':
1629 		case 'x':
1630 		case 'f':
1631 		case 's':
1632 		case 't':
1633 			size += tabsize * 4;
1634 			break;
1635 		case 'S':
1636 		case 'q':
1637 		case 'F':
1638 			size += tabsize * 8;
1639 			break;
1640 		case 'Q': // uint128
1641 			size += tabsize * 16;
1642 			break;
1643 		case 'z':
1644 		case 'Z':
1645 			size += tabsize;
1646 			break;
1647 		case '*':
1648 			size += tabsize * (p->bits / 8);
1649 			i++;
1650 			idx--;	//no need to go ahead for args
1651 			break;
1652 		case 'B':
1653 		case 'E':
1654 			if (tabsize_set) {
1655 				if (tabsize < 1 || tabsize > 8) {
1656 					eprintf ("Unknown enum format size: %d\n", tabsize);
1657 					break;
1658 				}
1659 				size += tabsize;
1660 			} else {
1661 				size += 4; // Assuming by default enum as int
1662 			}
1663 			break;
1664 		case '?':
1665 			{
1666 			const char *wordAtIndex = NULL;
1667 			const char *format = NULL;
1668 			char *endname = NULL, *structname = NULL;
1669 			char tmp = 0;
1670 			if (words < idx) {
1671 				eprintf ("Index out of bounds\n");
1672 			} else {
1673 				wordAtIndex = r_str_word_get0 (args, idx);
1674 			}
1675 			if (!wordAtIndex) {
1676 				break;
1677 			}
1678 			structname = strdup (wordAtIndex);
1679 			if (*structname == '(') {
1680 				endname = (char*)r_str_rchr (structname, NULL, ')');
1681 			} else {
1682 				free (structname);
1683 				break;
1684 			}
1685 			if (endname) {
1686 				*endname = '\0';
1687 			}
1688 			format = strchr (structname, ' ');
1689 			if (format) {
1690 				tmp = *format;
1691 				while (tmp == ' ') {
1692 					format++;
1693 					tmp = *format;
1694 				}
1695 			} else {
1696 				format = sdb_get (p->formats, structname + 1, NULL);
1697 				if (format && !strncmp (format, f, strlen (format) - 1)) { // Avoid recursion here
1698 					free (o);
1699 					free (structname);
1700 					return -1;
1701 				}
1702 				if (!format) { // Fetch format from types db
1703 					format = r_type_format (p->sdb_types, structname + 1);
1704 				}
1705 			}
1706 			if (!format) {
1707 				eprintf ("Cannot find format for struct `%s'\n", structname + 1);
1708 				free (structname);
1709 				free (o);
1710 				return 0;
1711 			}
1712 			int newsize = r_print_format_struct_size (p, format, mode, n + 1);
1713 			if (newsize < 1) {
1714 				eprintf ("Cannot find size for `%s'\n", format);
1715 				free (structname);
1716 				free (o);
1717 				return 0;
1718 			}
1719 			if (format) {
1720 				size += tabsize * newsize;
1721 			}
1722 			free (structname);
1723 			}
1724 			break;
1725 		case '{':
1726 			while (fmt[i] != '}') {
1727 				if (!fmt[i]) {
1728 					free (o);
1729 					free (args);
1730 					return -1;
1731 				}
1732 				i++;
1733 			}
1734 			i++;
1735 			idx--;
1736 			break;
1737 		case '}':
1738 			free (o);
1739 			free (args);
1740 			return -1;
1741 		case '+':
1742 		case 'e':
1743 			idx--;
1744 			break;
1745 		case 'p':
1746 			if (fmt[i+1] == '2') {
1747 				size += tabsize * 2;
1748 			} else if (fmt[i+1] == '4') {
1749 				size += tabsize * 4;
1750 			} else if (fmt[i+1] == '8') {
1751 				size += tabsize * 8;
1752 			} else {
1753 				size += tabsize * (p->bits / 8);
1754 				break;
1755 			}
1756 			i++;
1757 			break;
1758 		case 'r':
1759 			break;
1760 		case 'n':
1761 		case 'N':
1762 			if (fmt[i+1] == '1') {
1763 				size += tabsize * 1;
1764 			} else if (fmt[i+1] == '2') {
1765 				size += tabsize * 2;
1766 			} else if (fmt[i+1] == '4') {
1767 				size += tabsize * 4;
1768 			} else if (fmt[i+1] == '8') {
1769 				size += tabsize * 8;
1770 			} else {
1771 				eprintf ("Invalid n format in (%s)\n", fmt);
1772 				free (o);
1773 				free (args);
1774 				return -2;
1775 			}
1776 			i++;
1777 			break;
1778 		case 'u':
1779 		case 'D':
1780 		case 'T':
1781 			//TODO complete this.
1782 		default:
1783 			//idx--; //Does this makes sense?
1784 			break;
1785 		}
1786 		idx++;
1787 		if (mode & R_PRINT_UNIONMODE) {
1788 			if (size > biggest) {
1789 				biggest = size;
1790 			}
1791 			size = 0;
1792 		}
1793 	}
1794 	size *= times;
1795 	free (o);
1796 	free (args);
1797 	return (mode & R_PRINT_UNIONMODE)? biggest : size;
1798 }
1799 
r_print_format_struct(RPrint * p,ut64 seek,const ut8 * b,int len,const char * name,int slide,int mode,const char * setval,char * field,int anon)1800 static int r_print_format_struct(RPrint* p, ut64 seek, const ut8* b, int len, const char *name,
1801 		int slide, int mode, const char *setval, char *field, int anon) {
1802 	const char *fmt;
1803 	char namefmt[128];
1804 	slide++;
1805 	if ((slide % STRUCTPTR) > NESTDEPTH || (slide % STRUCTFLAG)/STRUCTPTR > NESTDEPTH) {
1806 		eprintf ("Too much nested struct, recursion too deep...\n");
1807 		return 0;
1808 	}
1809 	if (anon) {
1810 		fmt = name;
1811 	} else {
1812 		fmt = sdb_get (p->formats, name, NULL);
1813 		if (!fmt) { // Fetch struct info from types DB
1814 			fmt = r_type_format (p->sdb_types, name);
1815 		}
1816 	}
1817 	if (!fmt || !*fmt) {
1818 		eprintf ("Undefined struct '%s'.\n", name);
1819 		return 0;
1820 	}
1821 	if (MUSTSEE && !SEEVALUE) {
1822 		snprintf (namefmt, sizeof (namefmt), "%%%ds", 10+6*slide%STRUCTPTR);
1823 		if (fmt[0] == '0') {
1824 			p->cb_printf (namefmt, "union");
1825 		} else {
1826 			p->cb_printf (namefmt, "struct");
1827 		}
1828 		p->cb_printf ("<%s>\n", name);
1829 	}
1830 	r_print_format (p, seek, b, len, fmt, mode, setval, field);
1831 	return r_print_format_struct_size (p, fmt, mode, 0);
1832 }
1833 
get_args_offset(const char * arg)1834 static char *get_args_offset(const char *arg) {
1835 	char *args = strchr (arg, ' ');
1836 	char *sq_bracket = strchr (arg, '[');
1837 	int max = 30;
1838 	if (args && sq_bracket) {
1839 		char *csq_bracket = strchr (arg, ']');
1840 		while (args && csq_bracket && csq_bracket > args && max--) {
1841 			args = strchr (csq_bracket, ' ');
1842 		}
1843 	}
1844 	return args;
1845 }
1846 
get_format_type(const char fmt,const char arg)1847 static char *get_format_type(const char fmt, const char arg) {
1848 	char *type = NULL;
1849 	switch (fmt) {
1850 	case 'b':
1851 	case 'C':
1852 		type = strdup ("uint8_t");
1853 		break;
1854 	case 'c':
1855 		type = strdup ("int8_t");
1856 		break;
1857 	case 'd':
1858 	case 'i':
1859 	case 'o':
1860 	case 'x':
1861 		type = strdup ("int32_t");
1862 		break;
1863 	case 'E':
1864 		type = strdup ("enum");
1865 		break;
1866 	case 'f':
1867 		type = strdup ("float");
1868 		break;
1869 	case 'F':
1870 		type = strdup ("double");
1871 		break;
1872 	case 'q':
1873 		type = strdup ("uint64_t");
1874 		break;
1875 	case 'u':
1876 		type = strdup ("uleb128_t");
1877 		break;
1878 	case 'Q':
1879 		type = strdup ("uint128_t");
1880 		break;
1881 	case 'w':
1882 		type = strdup ("uint16_t");
1883 		break;
1884 	case 'X':
1885 		type = strdup ("uint8_t[]");
1886 		break;
1887 	case 'D':
1888 	case 's':
1889 	case 'S':
1890 	case 't':
1891 	case 'z':
1892 	case 'Z':
1893 		type = strdup ("char*");
1894 		break;
1895 	case 'n':
1896 	case 'N':
1897 		switch (arg) {
1898 		case '1':
1899 			type = strdup (fmt == 'n' ? "int8_t" : "uint8_t");
1900 			break;
1901 		case '2':
1902 			type = strdup (fmt == 'n' ? "int16_t" : "uint16_t");
1903 			break;
1904 		case '4':
1905 			type = strdup (fmt == 'n' ? "int32_t" : "uint32_t");
1906 			break;
1907 		case '8':
1908 			type = strdup (fmt == 'n' ? "int64_t" : "uint64_t");
1909 			break;
1910 		}
1911 		break;
1912 	}
1913 	return type;
1914 }
1915 
1916 //TODO PJ
1917 #define MINUSONE ((void*)(size_t)-1)
1918 #define ISSTRUCT (tmp == '?' || (tmp == '*' && *(arg+1) == '?'))
r_print_format(RPrint * p,ut64 seek,const ut8 * b,const int len,const char * formatname,int mode,const char * setval,char * ofield)1919 R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
1920 		const char *formatname, int mode, const char *setval, char *ofield) {
1921 	int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
1922 	const int old_bits = p->bits;
1923 	char *args = NULL, *bracket, tmp, last = 0;
1924 	ut64 addr = 0, addr64 = 0, seeki = 0;
1925 	static int slide = 0, oldslide = 0, ident = 4;
1926 	char namefmt[32], *field = NULL;
1927 	const char *arg = NULL;
1928 	const char *fmt = NULL;
1929 	const char *argend;
1930 	int viewflags = 0;
1931 	char *oarg = NULL;
1932 	char *internal_format = NULL;
1933 
1934 	/* Load format from name into fmt */
1935 	if (!formatname) {
1936 		return 0;
1937 	}
1938 	fmt = sdb_get (p->formats, formatname, NULL);
1939 	if (!fmt) {
1940 		fmt = formatname;
1941 	}
1942 	internal_format = strdup (fmt);
1943 	fmt = internal_format;
1944 	while (*fmt && IS_WHITECHAR (*fmt)) {
1945 		fmt++;
1946 	}
1947 	argend = fmt + strlen (fmt);
1948 	arg = fmt;
1949 
1950 	nexti = nargs = i = j = 0;
1951 
1952 	if (len < 1) {
1953 		free (internal_format);
1954 		return 0;
1955 	}
1956 	// len+2 to save space for the null termination in wide strings
1957 	ut8 *buf = calloc (1, len + 2);
1958 	if (!buf) {
1959 		free (internal_format);
1960 		return 0;
1961 	}
1962 	memcpy (buf, b, len);
1963 	endian = p->big_endian;
1964 
1965 	if (ofield && ofield != MINUSONE) {
1966 		field = strdup (ofield);
1967 	}
1968 	/* get times */
1969 	otimes = times = atoi (arg);
1970 	if (times > 0) {
1971 		while (IS_DIGIT(*arg)) {
1972 			arg++;
1973 		}
1974 	}
1975 
1976 	bracket = strchr (arg,'{');
1977 	if (bracket) {
1978 		char *end = strchr (arg, '}');
1979 		if (!end) {
1980 			eprintf ("No end bracket. Try pf {ecx}b @ esi\n");
1981 			goto beach;
1982 		}
1983 		*end = '\0';
1984 		times = r_num_math (NULL, bracket + 1);
1985 		arg = end + 1;
1986 	}
1987 
1988 	if (*arg == '\0') {
1989 		goto beach;
1990 	}
1991 
1992 	/* get args */
1993 	args = get_args_offset (arg);
1994 	if (args) {
1995 		int l = 0, maxl = 0;
1996 		argend = args;
1997 		tmp = *args;
1998 		while (tmp == ' ') {
1999 			args++;
2000 			tmp = *args;
2001 		}
2002 		args = strdup (args);
2003 		nargs = r_str_word_set0_stack (args);
2004 		if (nargs == 0) {
2005 			R_FREE (args);
2006 		}
2007 		for (i = 0; i < nargs; i++) {
2008 			const char *tmp = r_str_word_get0 (args, i);
2009 			const char *nm = r_str_rchr (tmp, NULL, ')');
2010 			int len = strlen (nm ? nm + 1 : tmp);
2011 			if (len > maxl) {
2012 				maxl = len;
2013 			}
2014 		}
2015 		l++;
2016 		const char *ends = " "; // XXX trailing space warning
2017 		snprintf (namefmt, sizeof (namefmt), "%%%ds :%s",
2018 			((maxl + 1) * (1 + slide)) % STRUCTPTR, ends);
2019 	}
2020 #define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR)
2021 #define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR))
2022 	if (mode == R_PRINT_JSON && slide == 0) {
2023 		p->cb_printf ("[");
2024 	}
2025 	if (mode == R_PRINT_STRUCT) {
2026 		if (formatname && *formatname) {
2027 			if (strchr (formatname, ' ')) {
2028 				p->cb_printf ("struct {\n");
2029 			} else {
2030 				p->cb_printf ("struct %s {\n", formatname);
2031 			}
2032 		} else {
2033 			p->cb_printf ("struct {\n");
2034 		}
2035 	}
2036 	if (mode && arg[0] == '0') {
2037 		mode |= R_PRINT_UNIONMODE;
2038 		arg++;
2039 	} else {
2040 		mode &= ~R_PRINT_UNIONMODE;
2041 	}
2042 	if (mode & R_PRINT_DOT) {
2043 		char *fmtname;
2044 		if (formatname && *formatname) {
2045 			if (strchr (formatname, ' ')) {
2046 				fmtname = r_str_newf ("0x%"PFMT64x, seek);
2047 			} else {
2048 				fmtname = strdup (formatname);
2049 			}
2050 		} else {
2051 			fmtname = r_str_newf ("0x%"PFMT64x, seek);
2052 		}
2053 		p->cb_printf ("digraph g { graph [ rank=same; rankdir=LR; ];\n");
2054 		p->cb_printf ("root [ rank=1; shape=record\nlabel=\"%s", fmtname);
2055 	}
2056 
2057 	/* go format */
2058 	i = 0;
2059 	if (!times) {
2060 		otimes = times = 1;
2061 	}
2062 	for (; times; times--) { // repeat N times
2063 		const char *orig = arg;
2064 		int first = 1;
2065 		if (otimes > 1) {
2066 			if (mode & R_PRINT_JSON) {
2067 				if (otimes > times) {
2068 					p->cb_printf (",");
2069 				}
2070 				p->cb_printf ("[{\"index\":%d,\"offset\":%"PFMT64d"},", otimes-times, seek+i);
2071 			} else if (mode) {
2072 				p->cb_printf ("0x%08"PFMT64x" [%d] {\n", seek + i, otimes-times);
2073 			}
2074 		}
2075 		arg = orig;
2076 		for (idx = 0; i < len && arg < argend && *arg; arg++) {
2077 			int size = 0, elem = 0; /* size of the array, element of the array */
2078 			char *fieldname = NULL, *fmtname = NULL;
2079 			if (mode & R_PRINT_UNIONMODE) {
2080 				i = 0;
2081 			}
2082 			seeki = seek + i;
2083 			addr = 0LL;
2084 			invalid = 0;
2085 			p->bits = old_bits;
2086 			if (arg[0] == '[') {
2087 				char *end = strchr (arg,']');
2088 				if (!end) {
2089 					eprintf ("No end bracket.\n");
2090 					goto beach;
2091 				}
2092 				*end = '\0';
2093 				size = r_get_size (p->num, buf, endian, arg + 1);
2094 				arg = end + 1;
2095 				*end = ']';
2096 			} else {
2097 				size = -1;
2098 			}
2099 			int fs = r_print_format_struct_size (p, arg, 0, idx);
2100 			if (fs == -2) {
2101 				i = -1;
2102 				goto beach;
2103 			}
2104 			if (fs < 1) {
2105 				fs = 4;
2106 			}
2107 			if (i + fs - 1 < len) { // should be +7 to avoid oobread on 'q'
2108 					// Max byte number where updateAddr will look into
2109 				if (len - i < 7) {
2110 					updateAddr (buf + i, THRESHOLD - (len - i), endian, &addr, &addr64);
2111 				} else {
2112 					updateAddr (buf + i, len - i, endian, &addr, &addr64);
2113 				}
2114 				if (p->bits == 64) {
2115 					addr = addr64;
2116 				}
2117 			} else {
2118 				// eprintf ("Format strings is too big for this buffer\n");
2119 				goto beach;
2120 			}
2121 
2122 			tmp = *arg;
2123 
2124 			if (mode && !args) {
2125 				mode |= R_PRINT_ISFIELD;
2126 			}
2127 			if (!(mode & R_PRINT_QUIET)) {
2128 				if (mode & R_PRINT_MUSTSEE && otimes > 1) {
2129 					p->cb_printf ("  ");
2130 				}
2131 			}
2132 			if (idx < nargs && tmp != 'e' && isptr == 0) {
2133 				char *dot = NULL, *bracket = NULL;
2134 				if (field) {
2135 					dot = strchr (field, '.');
2136 				}
2137 				if (dot) {
2138 					*dot = '\0';
2139 				}
2140 				free (oarg);
2141 				oarg = fieldname = strdup (r_str_word_get0 (args, idx));
2142 				if (ISSTRUCT || tmp=='E' || tmp=='B' || tmp=='r') {
2143 					if (*fieldname == '(') {
2144 						fmtname = fieldname + 1;
2145 						fieldname = (char*)r_str_rchr (fieldname, NULL, ')');
2146 						if (fieldname) {
2147 							*fieldname++ = '\0';
2148 						} else {
2149 							eprintf ("Missing closing parenthesis in format ')'\n");
2150 							goto beach;
2151 						}
2152 					} else {
2153 						eprintf ("Missing name (%s)\n", fieldname);
2154 						goto beach;
2155 					}
2156 				}
2157 				if (mode && (!args || (!field && ofield != MINUSONE)
2158 						|| (field && !strncmp (field, fieldname, \
2159 							strchr (field, '[')
2160 						? strchr (field, '[') - field
2161 						: strlen (field) + 1)))) {
2162 					mode |= R_PRINT_ISFIELD;
2163 				} else {
2164 					mode &= ~R_PRINT_ISFIELD;
2165 				}
2166 
2167 				/* There we handle specific element in array */
2168 				if (field && (bracket = strchr (field, '[')) && mode & R_PRINT_ISFIELD) {
2169 					char *end = strchr (field, ']');
2170 					if (!end) {
2171 						eprintf ("Missing closing bracket\n");
2172 						goto beach;
2173 					}
2174 					*end = '\0';
2175 					elem = r_num_math (NULL, bracket + 1) + 1; // +1 to handle 0 index easily
2176 					for ( ; bracket < end; bracket++) {
2177 						*bracket = '\0';
2178 					}
2179 					size += elem * ARRAYINDEX_COEF;
2180 				} else {
2181 					elem = -1;
2182 				}
2183 				if (tmp != '.' && tmp != ':') {
2184 					idx++;
2185 					if (MUSTSEE && !SEEVALUE) {
2186 						if (!ISQUIET) {
2187 							p->cb_printf (namefmt, fieldname);
2188 						}
2189 					}
2190 				}
2191 			}
2192 		feed_me_again:
2193 			switch (isptr) {
2194 			case PTRSEEK:
2195 				{
2196 				nexti = i + (p->bits / 8);
2197 				i = 0;
2198 				if (tmp == '?') {
2199 					seeki = addr;
2200 				}
2201 				memset (buf, '\0', len);
2202 				if (MUSTSEE && !ISQUIET) {
2203 					p->cb_printf ("(*0x%"PFMT64x")", addr);
2204 				}
2205 				isptr = (addr)? PTRBACK: NULLPTR;
2206 				if (p->iob.read_at) {
2207 					p->iob.read_at (p->iob.io, (ut64)addr, buf, len - 4);
2208 					if (((i + 3) < len) || ((i + 7) < len)) {
2209 						// XXX this breaks pf *D
2210 						if (tmp != 'D') {
2211 							updateAddr (buf + i, len - i, endian, &addr, &addr64);
2212 						}
2213 					} else {
2214 						eprintf ("Likely a heap buffer overflow.\n");
2215 						goto beach;
2216 					}
2217 				} else {
2218 					eprintf ("(cannot read at 0x%08"PFMT64x", block: %s, blocksize: 0x%x)\n",
2219 							addr, b, len);
2220 					p->cb_printf ("\n");
2221 					goto beach;
2222 				}
2223 				}
2224 				break;
2225 			case PTRBACK:
2226 				// restore state after pointer seek
2227 				i = nexti;
2228 				memcpy (buf, b, len);
2229 				isptr = NOPTR;
2230 				arg--;
2231 				continue;
2232 			}
2233 			if (tmp == 0 && last != '*') {
2234 				break;
2235 			}
2236 
2237 			/* skip chars */
2238 			switch (tmp) {
2239 			case '*': // next char is a pointer
2240 				isptr = PTRSEEK;
2241 				arg++;
2242 				tmp = *arg; //last;
2243 				goto feed_me_again;
2244 			case '+': // toggle view flags
2245 				viewflags = !viewflags;
2246 				continue;
2247 			case 'e': // tmp swap endian
2248 				endian ^= 1;
2249 				continue;
2250 			case ':': // skip 4 bytes
2251 				if (size == -1) {
2252 					i += 4;
2253 				} else {
2254 					while (size--) {
2255 						i += 4;
2256 					}
2257 				}
2258 				continue;
2259 			case '.': // skip 1 byte
2260 				i += (size == -1)? 1: size;
2261 				continue;
2262 			case 'p': // pointer reference
2263 				if (*(arg + 1) == '2') {
2264 					tmp = 'w';
2265 					arg++;
2266 				} else if (*(arg + 1) == '4') {
2267 					tmp = 'x';
2268 					arg++;
2269 				} else if (*(arg + 1) == '8') {
2270 					tmp = 'q';
2271 					arg++;
2272 				} else {	//If pointer reference is not mentioned explicitly
2273 					switch (p->bits) {
2274 					case 16: tmp = 'w'; break;
2275 					case 32: tmp = 'x'; break;
2276 					default: tmp = 'q'; break;
2277 					}
2278 				}
2279 				break;
2280 			}
2281 
2282 			/* flags */
2283 			if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
2284 				char *newname = NULL;
2285 				if (!fieldname) {
2286 					newname = fieldname = r_str_newf ("pf.%"PFMT64u, seeki);
2287 				}
2288 				if (mode & R_PRINT_UNIONMODE) {
2289 					p->cb_printf ("f %s=0x%08"PFMT64x"\n", formatname, seeki);
2290 					goto beach;
2291 				} else if (tmp == '?') {
2292 					p->cb_printf ("f %s.%s_", fmtname, fieldname);
2293 				} else if (tmp == 'E') {
2294 					p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki);
2295 				} else if (slide/STRUCTFLAG>0 && idx==1) {
2296 					p->cb_printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki);
2297 				} else {
2298 					p->cb_printf ("f %s=0x%08" PFMT64x "\n", fieldname, seeki);
2299 				}
2300 				if (newname) {
2301 					R_FREE (newname);
2302 					fieldname = NULL;
2303 				}
2304 			}
2305 
2306 			/* dot */
2307 			if (mode & R_PRINT_DOT) {
2308 				if (fieldname) {
2309 					p->cb_printf ("|{0x%"PFMT64x"|%c|%s|<%s>",
2310 						seeki, tmp, fieldname, fieldname);
2311 				} else {
2312 					p->cb_printf ("|{0x%"PFMT64x"|%c|",
2313 						seeki, tmp);
2314 				}
2315 			}
2316 
2317 			/* json */
2318 			if (MUSTSEEJSON && mode & R_PRINT_JSON) {
2319 				if (oldslide <= slide) {
2320 					if (first) {
2321 						first = 0;
2322 					} else {
2323 						p->cb_printf (",");
2324 					}
2325 				} else if (oldslide) {
2326 					p->cb_printf ("]},");
2327 					oldslide -= NESTEDSTRUCT;
2328 				}
2329 				if (fieldname) {
2330 					p->cb_printf ("{\"name\":\"%s\",\"type\":\"", fieldname);
2331 				} else {
2332 					p->cb_printf ("{\"type\":\"");
2333 				}
2334 				if (ISSTRUCT) {
2335 					p->cb_printf ("%s", fmtname);
2336 				} else {
2337 					if (tmp == 'n' || tmp == 'N') {
2338 						p->cb_printf ("%c%c", tmp, *(arg+1));
2339 					} else {
2340 						p->cb_printf ("%c", tmp);
2341 					}
2342 				}
2343 				if (isptr) {
2344 					p->cb_printf ("*");
2345 				}
2346 				p->cb_printf ("\",\"offset\":%"PFMT64d",\"value\":",
2347 					isptr? (seek + nexti - (p->bits / 8)) : seek + i);
2348 			}
2349 
2350 			/* c struct */
2351 			if (MUSTSEESTRUCT) {
2352 				char *type = get_format_type (tmp, (tmp == 'n' || tmp == 'N') ? arg[1] : 0);
2353 				if (type) {
2354 					p->cb_printf ("%*c%s %s; // ", ident, ' ', type, fieldname);
2355 				} else {
2356 					p->cb_printf ("%*cstruct %s {", ident, ' ', fieldname);
2357 				}
2358 				free (type);
2359 			}
2360 			bool noline = false;
2361 
2362 			int oi = i;
2363 			if (isptr == NULLPTR) {
2364 				if (MUSTSEEJSON) {
2365 					p->cb_printf ("\"NULL\"}");
2366 				} else if (MUSTSEE) {
2367 					p->cb_printf (" NULL\n");
2368 				}
2369 				isptr = PTRBACK;
2370 			} else {
2371 				/* format chars */
2372 				// before to enter in the switch statement check buf boundaries due to  updateAddr
2373 				// might go beyond its len and it's usually called in each of the following functions
2374 				switch (tmp) {
2375 				case 'u':
2376 					i += r_print_format_uleb (p, endian, mode, setval, seeki, buf, i, size);
2377 					break;
2378 				case 't':
2379 					r_print_format_time (p, endian, mode, setval, seeki, buf, i, size);
2380 					i += (size==-1)? 4: 4 * size;
2381 					break;
2382 				case 'q':
2383 					r_print_format_quadword (p, endian, mode, setval, seeki, buf, i, size);
2384 					i += (size == -1)? 8: 8 * size;
2385 					break;
2386 				case 'Q':
2387 					r_print_format_u128 (p, endian, mode, setval, seeki, buf, i, size);
2388 					i += (size == -1)? 16: 16 * size;
2389 					break;
2390 				case 'b':
2391 					r_print_format_byte (p, endian, mode, setval, seeki, buf, i, size);
2392 					i += (size==-1)? 1: size;
2393 					break;
2394 				case 'C':
2395 					r_print_format_decchar (p, endian, mode, setval, seeki, buf, i, size);
2396 					i += (size==-1)? 1: size;
2397 					break;
2398 				case 'c':
2399 					r_print_format_char (p, endian, mode, setval, seeki, buf, i, size);
2400 					i += (size==-1)? 1: size;
2401 					break;
2402 				case 'X':
2403 					size = r_print_format_hexpairs (p, endian, mode, setval, seeki, buf, i, size);
2404 					i += size;
2405 					break;
2406 				case 'T':
2407 					if (r_print_format_10bytes (p, mode,
2408 						setval, seeki, addr, buf) == 0) {
2409 						i += (size == -1)? 4: 4 * size;
2410 					}
2411 					break;
2412 				case 'f':
2413 					r_print_format_float (p, endian, mode, setval, seeki, buf, i, size);
2414 					i += (size == -1)? 4: 4 * size;
2415 					break;
2416 				case 'F':
2417 					r_print_format_double (p, endian, mode, setval, seeki, buf, i, size);
2418 					i += (size == -1)? 8: 8 * size;
2419 					break;
2420 				case 'i':
2421 					r_print_format_int (p, endian, mode, setval, seeki, buf, i, size);
2422 					i+= (size == -1)? 4: 4 * size;
2423 					break;
2424 				case 'd': //WHY?? help says: 0x%%08x hexadecimal value (4 bytes)
2425 					r_print_format_hex (p, endian, mode, setval, seeki, buf, i, size);
2426 					i+= (size == -1)? 4: 4 * size;
2427 					break;
2428 				case 'D':
2429 					if (MUSTSET) {
2430 						eprintf ("Set val not implemented yet for disassembler!\n");
2431 					}
2432 					if (isptr) {
2433 						if (p->bits == 64) {
2434 							i += r_print_format_disasm (p, addr64, size);
2435 						} else {
2436 							i += r_print_format_disasm (p, addr, size);
2437 						}
2438 					} else {
2439 						i += r_print_format_disasm (p, seeki, size);
2440 					}
2441 					break;
2442 				case 'o':
2443 					r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size);
2444 					i += (size == -1)? 4: 4 * size;
2445 					break;
2446 				case ';':
2447 					noline = true;
2448 					i -= (size == -1)? 4: 4 * size;
2449 					if (i < 0) {
2450 						i = 0;
2451 					}
2452 					break;
2453 				case ',':
2454 					noline = true;
2455 					i -= (size == -1)? 1: size;
2456 					if (i < 0) {
2457 						i = 0;
2458 					}
2459 					break;
2460 				case 'x':
2461 					r_print_format_hexflag (p, endian, mode, setval, seeki, buf, i, size);
2462 					i += (size == -1)? 4: 4*size;
2463 					break;
2464 				case 'w':
2465 					r_print_format_word (p, endian, mode, setval, seeki, buf, i, size);
2466 					i += (size == -1)? 2: 2 * size;
2467 					break;
2468 				case 'z': // zero terminated string
2469 					r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size);
2470 					if (size == -1) {
2471 						i += strlen ((char*)buf + i) + 1;
2472 					} else {
2473 						while (size--) {
2474 							i++;
2475 						}
2476 					}
2477 					break;
2478 				case 'Z': // zero terminated wide string
2479 					r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size);
2480 					if (size == -1) {
2481 						i += r_wstr_clen((char*)(buf+i))*2+2;
2482 					} else {
2483 						while (size--) {
2484 							i += 2;
2485 						}
2486 					}
2487 					break;
2488 				case 's':
2489 					if (MUSTSET) {
2490 						eprintf ("Set val not implemented yet for strings!\n");
2491 					}
2492 					if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0) {
2493 						i += (size==-1) ? 4 : 4*size;
2494 					}
2495 					break;
2496 				case 'S':
2497 					if (MUSTSET) {
2498 						eprintf ("Set val not implemented yet for strings!\n");
2499 					}
2500 					if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0) {
2501 						i += (size == -1) ? 8 : 8 * size;
2502 					}
2503 					break;
2504 				case 'B': // resolve bitfield
2505 					if (size >= ARRAYINDEX_COEF) {
2506 						size %= ARRAYINDEX_COEF;
2507 					}
2508 					if (MUSTSET) {
2509 						eprintf ("Set val not implemented yet for bitfields!\n");
2510 					}
2511 					r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size);
2512 					i+=(size == -1)? 1: size;
2513 					break;
2514 				case 'E': // resolve enum
2515 					if (MUSTSET) {
2516 						eprintf ("Set val not implemented yet for enums!\n");
2517 					}
2518 					if (size >= ARRAYINDEX_COEF) {
2519 						size %= ARRAYINDEX_COEF;
2520 					}
2521 					r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size);
2522 					i += (size == -1)? 1: size;
2523 					break;
2524 				case 'r':
2525 					if (fmtname) {
2526 						r_print_format_register (p, mode, fmtname, setval);
2527 					} else {
2528 						eprintf ("Unknown register\n");
2529 					}
2530 					break;
2531 				case '?':
2532 					{
2533 					int s = 0;
2534 					char *nxtfield = NULL;
2535 					char *format = NULL;
2536 					int anon = 0;
2537 					if (size >= ARRAYINDEX_COEF) {
2538 						elem = size / ARRAYINDEX_COEF - 1;
2539 						size %= ARRAYINDEX_COEF;
2540 					}
2541 					if (!(mode & R_PRINT_ISFIELD)) {
2542 						nxtfield = MINUSONE;
2543 					} else if (field) {
2544 						nxtfield = strchr (ofield, '.');
2545 					}
2546 					if (nxtfield != MINUSONE && nxtfield) {
2547 						nxtfield++;
2548 					}
2549 
2550 					if (MUSTSEE) {
2551 						if (!SEEVALUE) {
2552 							p->cb_printf ("\n");
2553 						}
2554 					}
2555 					if (MUSTSEEJSON) {
2556 						if (isptr) {
2557 							p->cb_printf ("%"PFMT64d"},", seeki);
2558 						} else {
2559 							p->cb_printf ("[");
2560 						}
2561 					}
2562 					if (MUSTSEESTRUCT) {
2563 						if (isptr) {
2564 							p->cb_printf ("%"PFMT64d, seeki);
2565 						} else {
2566 							ident += 4;
2567 							p->cb_printf ("\n");
2568 						}
2569 					}
2570 					if (mode & R_PRINT_SEEFLAGS) {
2571 						slide += STRUCTFLAG;
2572 					}
2573 					if (!fmtname) {
2574 						break;
2575 					}
2576 					format = strchr (fmtname, ' ');
2577 					if (format) {
2578 						anon = 1;
2579 						fmtname = format;
2580 						while (*fmtname == ' ') {
2581 							fmtname++;
2582 						}
2583 					}
2584 					oldslide = slide;
2585 					//slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2586 					slide += NESTEDSTRUCT;
2587 					if (size == -1) {
2588 						s = r_print_format_struct (p, seeki,
2589 									buf + i, len - i, fmtname, slide,
2590 									mode, setval, nxtfield, anon);
2591 						i += (isptr) ? (p->bits / 8) : s;
2592 						if (MUSTSEEJSON) {
2593 							if (!isptr && (!arg[1] || arg[1] == ' ')) {
2594 								p->cb_printf ("]}");
2595 							}
2596 						}
2597 					} else {
2598 						if (mode & R_PRINT_ISFIELD) {
2599 							if (!SEEVALUE) {
2600 								p->cb_printf ("[\n");
2601 							}
2602 						}
2603 						while (size--) {
2604 							if (mode && (elem == -1 || elem == 0)) {
2605 								mode |= R_PRINT_MUSTSEE;
2606 								if (elem == 0) {
2607 									elem = -2;
2608 								}
2609 							} else {
2610 								mode &= ~R_PRINT_MUSTSEE;
2611 							}
2612 							s = r_print_format_struct (p, seek+i,
2613 									buf+i, len-i, fmtname, slide, mode, setval, nxtfield, anon);
2614 							if ((MUSTSEE || MUSTSEEJSON || MUSTSEESTRUCT) && size != 0 && elem == -1) {
2615 								if (MUSTSEEJSON) {
2616 									p->cb_printf (",");
2617 								} else if (MUSTSEE || MUSTSEESTRUCT) {
2618 									p->cb_printf ("\n");
2619 								}
2620 							}
2621 							if (elem > -1) {
2622 								elem--;
2623 							}
2624 							i += (isptr) ? (p->bits / 8) : s;
2625 						}
2626 						if (mode & R_PRINT_ISFIELD) {
2627 							if (!SEEVALUE) {
2628 								p->cb_printf ("]\n");
2629 							}
2630 						}
2631 						if (MUSTSEEJSON) {
2632 							p->cb_printf ("]}");
2633 						}
2634 					}
2635 					oldslide = slide;
2636 					//slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2637 					slide -= NESTEDSTRUCT;
2638 					if (mode & R_PRINT_SEEFLAGS) {
2639 						oldslide = slide;
2640 						slide -= STRUCTFLAG;
2641 					}
2642 					break;
2643 					}
2644 				case 'n':
2645 				case 'N':
2646 					{
2647 						int bytes = 0;
2648 						int sign = (tmp == 'n') ? 1 : 0;
2649 						if (arg[1] == '1') {
2650 							bytes = 1;
2651 						} else if (arg[1] == '2') {
2652 							bytes = 2;
2653 						} else if (arg[1] == '4') {
2654 							bytes = 4;
2655 						} else if (arg[1] == '8') {
2656 							bytes = 8;
2657 						} else {
2658 							invalid = 1;
2659 							break;
2660 							//or goto beach;???
2661 						}
2662 						r_print_format_num (p, endian, mode, setval, seeki, buf, i, bytes, sign, size);
2663 						i += (size == -1)? bytes: size * bytes;
2664 						arg++;
2665 						break;
2666 					}
2667 				default:
2668 					/* ignore unknown chars */
2669 					invalid = 1;
2670 					break;
2671 				} //switch
2672 			}
2673 			if (MUSTSEESTRUCT) {
2674 				if (oldslide) {
2675 					ident -= 4;
2676 					p->cb_printf ("%*c}", ident, ' ');
2677 					oldslide -= NESTEDSTRUCT;
2678 				}
2679 				p->cb_printf ("\n");
2680 			}
2681 			if (mode & R_PRINT_DOT) {
2682 				p->cb_printf ("}");
2683 			}
2684 			if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
2685 				int sz = i - oi;
2686 				if (sz > 1) {
2687 					p->cb_printf ("fl %d @ 0x%08"PFMT64x"\n", sz, seeki);
2688 					p->cb_printf ("Cd %d @ 0x%08"PFMT64x"\n", sz, seeki);
2689 				}
2690 			}
2691 			if (viewflags && p->offname) {
2692 				const char *s = p->offname (p->user, seeki);
2693 				if (s) {
2694 					p->cb_printf ("@(%s)", s);
2695 				}
2696 				s = p->offname (p->user, addr);
2697 				if (s) {
2698 					p->cb_printf ("*(%s)", s);
2699 				}
2700 			}
2701 			if (!noline && tmp != 'D' && !invalid && !fmtname && MUSTSEE) {
2702 				p->cb_printf ("\n");
2703 			}
2704 			last = tmp;
2705 
2706 			// XXX: Due to the already noted issues with the above, we need to strip
2707 			// args from fmt:args the same way we strip fmt BUT only for enums as
2708 			// nested structs seem to be handled correctly above!
2709 			if (arg[0] == 'E') {
2710 				char *end_fmt = strchr (arg, ' ');
2711 				if (!end_fmt) {
2712 					goto beach;
2713 				}
2714 				char *next_args = strchr (end_fmt + 1, ' ');
2715 				if (next_args) {
2716 					while (*next_args != '\0') {
2717 						*end_fmt++ = *next_args++;
2718 					}
2719 				}
2720 				*end_fmt = '\0';
2721 			}
2722 		}
2723 		if (otimes > 1) {
2724 			if (MUSTSEEJSON) {
2725 				p->cb_printf ("]");
2726 			} else if (mode) {
2727 				p->cb_printf ("}\n");
2728 			}
2729 		}
2730 		arg = orig;
2731 		oldslide = 0;
2732 	}
2733 	if (mode & R_PRINT_JSON && slide == 0) {
2734 		p->cb_printf("]\n");
2735 	}
2736 	if (MUSTSEESTRUCT && slide == 0) {
2737 		p->cb_printf ("}\n");
2738 	}
2739 	if (mode & R_PRINT_DOT) {
2740 		p->cb_printf ("\"];\n}\n");
2741 		// TODO: show nested structs and field reference lines
2742 	}
2743 beach:
2744 	if (slide == 0) {
2745 		oldslide = 0;
2746 	}
2747 	free (internal_format);
2748 	free (oarg);
2749 	free (buf);
2750 	free (field);
2751 	free (args);
2752 	return i;
2753 }
2754