1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5//*****************************************************************************
6// This code supports formatting a method and it's signature in a friendly
7// and consistent format.
8//
9//*****************************************************************************
10#include "stdafx.h"
11#include "prettyprintsig.h"
12#include "utilcode.h"
13#include "metadata.h"
14#include "corpriv.h"
15
16/***********************************************************************/
17// Null-terminates the string held in "out"
18
19static WCHAR* asStringW(CQuickBytes *out)
20{
21 CONTRACTL
22 {
23 NOTHROW;
24 INJECT_FAULT(return NULL;);
25 }
26 CONTRACTL_END
27
28 SIZE_T oldSize = out->Size();
29 if (FAILED(out->ReSizeNoThrow(oldSize + 1)))
30 return 0;
31 WCHAR * cur = (WCHAR *) ((BYTE *) out->Ptr() + oldSize);
32 *cur = 0;
33 return((WCHAR*) out->Ptr());
34} // static WCHAR* asStringW()
35
36// Null-terminates the string held in "out"
37
38static CHAR* asStringA(CQuickBytes *out)
39{
40 CONTRACTL
41 {
42 NOTHROW;
43 INJECT_FAULT(return NULL;);
44 }
45 CONTRACTL_END
46
47 SIZE_T oldSize = out->Size();
48 if (FAILED(out->ReSizeNoThrow(oldSize + 1)))
49 return 0;
50 CHAR * cur = (CHAR *) ((BYTE *) out->Ptr() + oldSize);
51 *cur = 0;
52 return((CHAR*) out->Ptr());
53} // static CHAR* asStringA()
54
55/***********************************************************************/
56// Appends the str to "out"
57// The string held in "out" is not NULL-terminated. asStringW() needs to
58// be called for the NULL-termination
59
60static HRESULT appendStrW(CQuickBytes *out, const WCHAR* str)
61{
62 CONTRACTL
63 {
64 NOTHROW;
65 INJECT_FAULT(return E_OUTOFMEMORY;);
66 }
67 CONTRACTL_END
68
69 SIZE_T len = wcslen(str) * sizeof(WCHAR);
70 SIZE_T oldSize = out->Size();
71 if (FAILED(out->ReSizeNoThrow(oldSize + len)))
72 return E_OUTOFMEMORY;
73 WCHAR * cur = (WCHAR *) ((BYTE *) out->Ptr() + oldSize);
74 memcpy(cur, str, len);
75 // Note no trailing null!
76 return S_OK;
77} // static HRESULT appendStrW()
78
79// Appends the str to "out"
80// The string held in "out" is not NULL-terminated. asStringA() needs to
81// be called for the NULL-termination
82
83static HRESULT appendStrA(CQuickBytes *out, const CHAR* str)
84{
85 CONTRACTL
86 {
87 NOTHROW;
88 INJECT_FAULT(return E_OUTOFMEMORY;);
89 }
90 CONTRACTL_END
91
92 SIZE_T len = strlen(str) * sizeof(CHAR);
93 SIZE_T oldSize = out->Size();
94 if (FAILED(out->ReSizeNoThrow(oldSize + len)))
95 return E_OUTOFMEMORY;
96 CHAR * cur = (CHAR *) ((BYTE *) out->Ptr() + oldSize);
97 memcpy(cur, str, len);
98 // Note no trailing null!
99 return S_OK;
100} // static HRESULT appendStrA()
101
102
103static HRESULT appendStrNumW(CQuickBytes *out, int num)
104{
105 CONTRACTL
106 {
107 NOTHROW;
108 INJECT_FAULT(return E_OUTOFMEMORY;);
109 }
110 CONTRACTL_END
111
112 WCHAR buff[32];
113 swprintf_s(buff, 32, W("%d"), num);
114 return appendStrW(out, buff);
115} // static HRESULT appendStrNumW()
116
117static HRESULT appendStrNumA(CQuickBytes *out, int num)
118{
119 CONTRACTL
120 {
121 NOTHROW;
122 INJECT_FAULT(return E_OUTOFMEMORY;);
123 }
124 CONTRACTL_END
125
126 CHAR buff[32];
127 sprintf_s(buff, 32, "%d", num);
128 return appendStrA(out, buff);
129} // static HRESULT appendStrNumA()
130
131static HRESULT appendStrHexW(CQuickBytes *out, int num)
132{
133 CONTRACTL
134 {
135 NOTHROW;
136 INJECT_FAULT(return E_OUTOFMEMORY;);
137 }
138 CONTRACTL_END
139
140 WCHAR buff[32];
141 swprintf_s(buff, 32, W("%08X"), num);
142 return appendStrW(out, buff);
143} // static HRESULT appendStrHexW()
144
145static HRESULT appendStrHexA(CQuickBytes *out, int num)
146{
147 CONTRACTL
148 {
149 NOTHROW;
150 INJECT_FAULT(return E_OUTOFMEMORY;);
151 }
152 CONTRACTL_END
153
154 CHAR buff[32];
155 sprintf_s(buff, 32, "%08X", num);
156 return appendStrA(out, buff);
157} // static HRESULT appendStrHexA()
158
159/***********************************************************************/
160
161LPCWSTR PrettyPrintSigWorker(
162 PCCOR_SIGNATURE & typePtr, // type to convert,
163 size_t typeLen, // length of type
164 const WCHAR * name, // can be "", the name of the method for this sig
165 CQuickBytes * out, // where to put the pretty printed string
166 IMetaDataImport * pIMDI); // Import api to use.
167
168//*****************************************************************************
169//*****************************************************************************
170// pretty prints 'type' to the buffer 'out' returns a pointer to the next type,
171// or 0 on a format failure
172
173static PCCOR_SIGNATURE PrettyPrintType(
174 PCCOR_SIGNATURE typePtr, // type to convert,
175 size_t typeLen, // Maximum length of the type
176 CQuickBytes * out, // where to put the pretty printed string
177 IMetaDataImport * pIMDI) // ptr to IMDInternal class with ComSig
178{
179 mdToken tk;
180 const WCHAR * str;
181 WCHAR rcname[MAX_CLASS_NAME];
182 HRESULT hr;
183 unsigned __int8 elt = *typePtr++;
184 PCCOR_SIGNATURE typeEnd = typePtr + typeLen;
185
186 switch(elt)
187 {
188 case ELEMENT_TYPE_VOID:
189 str = W("void");
190 goto APPEND;
191
192 case ELEMENT_TYPE_BOOLEAN:
193 str = W("bool");
194 goto APPEND;
195
196 case ELEMENT_TYPE_CHAR:
197 str = W("wchar");
198 goto APPEND;
199
200 case ELEMENT_TYPE_I1:
201 str = W("int8");
202 goto APPEND;
203
204 case ELEMENT_TYPE_U1:
205 str = W("unsigned int8");
206 goto APPEND;
207
208 case ELEMENT_TYPE_I2:
209 str = W("int16");
210 goto APPEND;
211
212 case ELEMENT_TYPE_U2:
213 str = W("unsigned int16");
214 goto APPEND;
215
216 case ELEMENT_TYPE_I4:
217 str = W("int32");
218 goto APPEND;
219
220 case ELEMENT_TYPE_U4:
221 str = W("unsigned int32");
222 goto APPEND;
223
224 case ELEMENT_TYPE_I8:
225 str = W("int64");
226 goto APPEND;
227
228 case ELEMENT_TYPE_U8:
229 str = W("unsigned int64");
230 goto APPEND;
231
232 case ELEMENT_TYPE_R4:
233 str = W("float32");
234 goto APPEND;
235
236 case ELEMENT_TYPE_R8:
237 str = W("float64");
238 goto APPEND;
239
240 case ELEMENT_TYPE_U:
241 str = W("unsigned int");
242 goto APPEND;
243
244 case ELEMENT_TYPE_I:
245 str = W("int");
246 goto APPEND;
247
248 case ELEMENT_TYPE_OBJECT:
249 str = W("class System.Object");
250 goto APPEND;
251
252 case ELEMENT_TYPE_STRING:
253 str = W("class System.String");
254 goto APPEND;
255
256 case ELEMENT_TYPE_CANON_ZAPSIG:
257 str = W("class System.__Canon");
258 goto APPEND;
259
260 case ELEMENT_TYPE_TYPEDBYREF:
261 str = W("refany");
262 goto APPEND;
263
264 APPEND:
265 appendStrW(out, str);
266 break;
267
268 case ELEMENT_TYPE_VALUETYPE:
269 str = W("value class ");
270 goto DO_CLASS;
271
272 case ELEMENT_TYPE_CLASS:
273 str = W("class ");
274 goto DO_CLASS;
275
276 DO_CLASS:
277 typePtr += CorSigUncompressToken(typePtr, &tk);
278 appendStrW(out, str);
279 rcname[0] = 0;
280 str = rcname;
281
282 if (TypeFromToken(tk) == mdtTypeRef)
283 {
284 hr = pIMDI->GetTypeRefProps(tk, 0, rcname, NumItems(rcname), 0);
285 }
286 else if (TypeFromToken(tk) == mdtTypeDef)
287 {
288 hr = pIMDI->GetTypeDefProps(tk, rcname, NumItems(rcname), 0, 0, 0);
289 }
290 else
291 {
292 _ASSERTE(!"Unknown token type encountered in signature.");
293 str = W("<UNKNOWN>");
294 }
295
296 appendStrW(out, str);
297 break;
298
299 case ELEMENT_TYPE_SZARRAY:
300 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
301 appendStrW(out, W("[]"));
302 break;
303
304 case ELEMENT_TYPE_ARRAY:
305 {
306 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
307 unsigned rank = CorSigUncompressData(typePtr);
308 PREFIX_ASSUME(rank <= 0xffffff);
309
310 // <TODO>TODO what is the syntax for the rank 0 case? </TODO>
311 if (rank == 0)
312 {
313 appendStrW(out, W("[??]"));
314 }
315 else
316 {
317 _ASSERTE(rank != 0);
318 int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank);
319 int* sizes = &lowerBounds[rank];
320 memset(lowerBounds, 0, sizeof(int)*2*rank);
321
322 unsigned numSizes = CorSigUncompressData(typePtr);
323 _ASSERTE(numSizes <= rank);
324 unsigned int i;
325 for(i =0; i < numSizes; i++)
326 sizes[i] = CorSigUncompressData(typePtr);
327
328 unsigned numLowBounds = CorSigUncompressData(typePtr);
329 _ASSERTE(numLowBounds <= rank);
330 for(i = 0; i < numLowBounds; i++)
331 lowerBounds[i] = CorSigUncompressData(typePtr);
332
333 appendStrW(out, W("["));
334 for(i = 0; i < rank; i++)
335 {
336 if (sizes[i] != 0 && lowerBounds[i] != 0)
337 {
338 if (lowerBounds[i] == 0)
339 appendStrNumW(out, sizes[i]);
340 else
341 {
342 appendStrNumW(out, lowerBounds[i]);
343 appendStrW(out, W("..."));
344 if (sizes[i] != 0)
345 appendStrNumW(out, lowerBounds[i] + sizes[i] + 1);
346 }
347 }
348 if (i < rank-1)
349 appendStrW(out, W(","));
350 }
351 appendStrW(out, W("]"));
352 }
353 }
354 break;
355
356 case ELEMENT_TYPE_MVAR:
357 appendStrW(out, W("!!"));
358 appendStrNumW(out, CorSigUncompressData(typePtr));
359 break;
360
361 case ELEMENT_TYPE_VAR:
362 appendStrW(out, W("!"));
363 appendStrNumW(out, CorSigUncompressData(typePtr));
364 break;
365
366 case ELEMENT_TYPE_GENERICINST:
367 {
368 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
369 unsigned ntypars = CorSigUncompressData(typePtr);
370 appendStrW(out, W("<"));
371 for (unsigned i = 0; i < ntypars; i++)
372 {
373 if (i > 0)
374 appendStrW(out, W(","));
375 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
376 }
377 appendStrW(out, W(">"));
378 }
379 break;
380
381 case ELEMENT_TYPE_MODULE_ZAPSIG:
382 appendStrW(out, W("[module#"));
383 appendStrNumW(out, CorSigUncompressData(typePtr));
384 appendStrW(out, W(", token#"));
385 typePtr += CorSigUncompressToken(typePtr, &tk);
386 appendStrHexW(out, tk);
387 appendStrW(out, W("]"));
388 break;
389
390 case ELEMENT_TYPE_FNPTR:
391 appendStrW(out, W("fnptr "));
392 PrettyPrintSigWorker(typePtr, (typeEnd - typePtr), W(""), out, pIMDI);
393 break;
394
395 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
396 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
397 appendStrW(out, W("native "));
398 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
399 break;
400
401 // Modifiers or depedant types
402 case ELEMENT_TYPE_PINNED:
403 str = W(" pinned");
404 goto MODIFIER;
405
406 case ELEMENT_TYPE_PTR:
407 str = W("*");
408 goto MODIFIER;
409
410 case ELEMENT_TYPE_BYREF:
411 str = W("&");
412 goto MODIFIER;
413
414 MODIFIER:
415 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
416 appendStrW(out, str);
417 break;
418
419 default:
420 case ELEMENT_TYPE_SENTINEL:
421 case ELEMENT_TYPE_END:
422 _ASSERTE(!"Unknown Type");
423 return(typePtr);
424 break;
425 }
426 return(typePtr);
427} // static PCCOR_SIGNATURE PrettyPrintType()
428
429//*****************************************************************************
430// Converts a com signature to a text signature.
431//
432// Note that this function DOES NULL terminate the result signature string.
433//*****************************************************************************
434LPCWSTR PrettyPrintSigLegacy(
435 PCCOR_SIGNATURE typePtr, // type to convert,
436 unsigned typeLen, // length of type
437 const WCHAR * name, // can be "", the name of the method for this sig
438 CQuickBytes * out, // where to put the pretty printed string
439 IMetaDataImport * pIMDI) // Import api to use.
440{
441 return PrettyPrintSigWorker(typePtr, typeLen, name, out, pIMDI);
442} // LPCWSTR PrettyPrintSigLegacy()
443
444LPCWSTR PrettyPrintSigWorker(
445 PCCOR_SIGNATURE & typePtr, // type to convert,
446 size_t typeLen, // length of type
447 const WCHAR * name, // can be "", the name of the method for this sig
448 CQuickBytes * out, // where to put the pretty printed string
449 IMetaDataImport * pIMDI) // Import api to use.
450{
451 out->Shrink(0);
452 unsigned numTyArgs = 0;
453 unsigned numArgs;
454 PCCOR_SIGNATURE typeEnd = typePtr + typeLen; // End of the signature.
455
456 if (name != 0) // 0 means a local var sig
457 {
458 // get the calling convention out
459 unsigned callConv = CorSigUncompressData(typePtr);
460
461 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
462 {
463 PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
464 if (name != 0 && *name != 0)
465 {
466 appendStrW(out, W(" "));
467 appendStrW(out, name);
468 }
469 return(asStringW(out));
470 }
471
472 if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)
473 appendStrW(out, W("instance "));
474
475 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
476 {
477 appendStrW(out, W("generic "));
478 numTyArgs = CorSigUncompressData(typePtr);
479 }
480
481 static const WCHAR * const callConvNames[IMAGE_CEE_CS_CALLCONV_MAX] =
482 {
483 W(""),
484 W("unmanaged cdecl "),
485 W("unmanaged stdcall "),
486 W("unmanaged thiscall "),
487 W("unmanaged fastcall "),
488 W("vararg "),
489 W("<error> "),
490 W("<error> "),
491 W(""),
492 W(""),
493 W(""),
494 W("native vararg ")
495 };
496
497 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) < IMAGE_CEE_CS_CALLCONV_MAX)
498 {
499 appendStrW(out, callConvNames[callConv & IMAGE_CEE_CS_CALLCONV_MASK]);
500 }
501
502
503 numArgs = CorSigUncompressData(typePtr);
504 // do return type
505 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
506
507 }
508 else
509 {
510 numArgs = CorSigUncompressData(typePtr);
511 }
512
513 if (name != 0 && *name != 0)
514 {
515 appendStrW(out, W(" "));
516 appendStrW(out, name);
517 }
518 appendStrW(out, W("("));
519
520 bool needComma = false;
521
522 while (numArgs)
523 {
524 if (typePtr >= typeEnd)
525 break;
526
527 if (*typePtr == ELEMENT_TYPE_SENTINEL)
528 {
529 if (needComma)
530 appendStrW(out, W(","));
531 appendStrW(out, W("..."));
532 typePtr++;
533 }
534 else
535 {
536 if (numArgs <= 0)
537 break;
538 if (needComma)
539 appendStrW(out, W(","));
540 typePtr = PrettyPrintType(typePtr, (typeEnd - typePtr), out, pIMDI);
541 --numArgs;
542 }
543 needComma = true;
544 }
545 appendStrW(out, W(")"));
546 return (asStringW(out));
547} // LPCWSTR PrettyPrintSigWorker()
548
549
550// Internal implementation of PrettyPrintSig().
551
552HRESULT PrettyPrintSigWorkerInternal(
553 PCCOR_SIGNATURE & typePtr, // type to convert,
554 size_t typeLen, // length of type
555 const CHAR * name, // can be "", the name of the method for this sig
556 CQuickBytes * out, // where to put the pretty printed string
557 IMDInternalImport * pIMDI); // Import api to use.
558
559static HRESULT PrettyPrintClass(
560 PCCOR_SIGNATURE &typePtr, // type to convert
561 PCCOR_SIGNATURE typeEnd, // end of the signature.
562 CQuickBytes *out, // where to put the pretty printed string
563 IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig
564
565
566#ifdef _PREFAST_
567#pragma warning(push)
568#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
569#endif
570//*****************************************************************************
571//*****************************************************************************
572// pretty prints 'type' to the buffer 'out' returns a pointer to the next type,
573// or 0 on a format failure
574
575__checkReturn
576static HRESULT PrettyPrintTypeA(
577 PCCOR_SIGNATURE &typePtr, // type to convert,
578 size_t typeLen, // Maximum length of the type.
579 CQuickBytes *out, // where to put the pretty printed string
580 IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig
581{
582 CONTRACTL
583 {
584 NOTHROW;
585 INJECT_FAULT(return E_OUTOFMEMORY;);
586 }
587 CONTRACTL_END
588
589 mdToken tk; // A type's token.
590 const CHAR *str; // Temporary string.
591 HRESULT hr; // A result.
592
593 PCCOR_SIGNATURE typeEnd = typePtr + typeLen; // End of the signature.
594 unsigned __int8 elt = *typePtr++;
595
596 switch(elt) {
597 case ELEMENT_TYPE_VOID:
598 str = "void";
599 goto APPEND;
600
601 case ELEMENT_TYPE_BOOLEAN:
602 str = "bool";
603 goto APPEND;
604
605 case ELEMENT_TYPE_CHAR:
606 str = "wchar";
607 goto APPEND;
608
609 case ELEMENT_TYPE_I1:
610 str = "int8";
611 goto APPEND;
612
613 case ELEMENT_TYPE_U1:
614 str = "unsigned int8";
615 goto APPEND;
616
617 case ELEMENT_TYPE_I2:
618 str = "int16";
619 goto APPEND;
620
621 case ELEMENT_TYPE_U2:
622 str = "unsigned int16";
623 goto APPEND;
624
625 case ELEMENT_TYPE_I4:
626 str = "int32";
627 goto APPEND;
628
629 case ELEMENT_TYPE_U4:
630 str = "unsigned int32";
631 goto APPEND;
632
633 case ELEMENT_TYPE_I8:
634 str = "int64";
635 goto APPEND;
636
637 case ELEMENT_TYPE_U8:
638 str = "unsigned int64";
639 goto APPEND;
640
641 case ELEMENT_TYPE_R4:
642 str = "float32";
643 goto APPEND;
644
645 case ELEMENT_TYPE_R8:
646 str = "float64";
647 goto APPEND;
648
649 case ELEMENT_TYPE_U:
650 str = "unsigned int";
651 goto APPEND;
652
653 case ELEMENT_TYPE_I:
654 str = "int";
655 goto APPEND;
656
657 case ELEMENT_TYPE_OBJECT:
658 str = "class System.Object";
659 goto APPEND;
660
661 case ELEMENT_TYPE_STRING:
662 str = "class System.String";
663 goto APPEND;
664
665 case ELEMENT_TYPE_CANON_ZAPSIG:
666 str = "class System.__Canon";
667 goto APPEND;
668
669 case ELEMENT_TYPE_TYPEDBYREF:
670 str = "refany";
671 goto APPEND;
672
673 APPEND:
674 IfFailGo(appendStrA(out, str));
675 break;
676
677 case ELEMENT_TYPE_INTERNAL:
678 void* pMT;
679 pMT = *((void* UNALIGNED *)typePtr);
680 typePtr += sizeof(void*);
681 CHAR tempBuffer[64];
682 sprintf_s(tempBuffer, 64, "pMT: %p", pMT);
683 IfFailGo(appendStrA(out, tempBuffer));
684 break;
685
686 case ELEMENT_TYPE_VALUETYPE:
687 str = "value class ";
688 goto DO_CLASS;
689
690 case ELEMENT_TYPE_CLASS:
691 str = "class ";
692 goto DO_CLASS;
693
694 DO_CLASS:
695 IfFailGo(appendStrA(out, str));
696 IfFailGo(PrettyPrintClass(typePtr, typeEnd, out, pIMDI));
697 break;
698
699 case ELEMENT_TYPE_CMOD_REQD:
700 str = "required_modifier ";
701 goto CMOD;
702
703 case ELEMENT_TYPE_CMOD_OPT:
704 str = "optional_modifier ";
705 goto CMOD;
706
707 CMOD:
708 IfFailGo(appendStrA(out, str));
709 IfFailGo(PrettyPrintClass(typePtr, typeEnd, out, pIMDI));
710 IfFailGo(appendStrA(out, " "));
711 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
712 break;
713
714 case ELEMENT_TYPE_SZARRAY:
715 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
716 IfFailGo(appendStrA(out, "[]"));
717 break;
718
719 case ELEMENT_TYPE_ARRAY:
720 {
721 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
722 unsigned rank = CorSigUncompressData(typePtr);
723 PREFIX_ASSUME(rank <= 0xffffff);
724 // <TODO>TODO what is the syntax for the rank 0 case? </TODO>
725 if (rank == 0)
726 {
727 IfFailGo(appendStrA(out, "[??]"));
728 }
729 else
730 {
731 _ASSERTE(rank != 0);
732 int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank);
733 int* sizes = &lowerBounds[rank];
734 memset(lowerBounds, 0, sizeof(int)*2*rank);
735
736 unsigned numSizes = CorSigUncompressData(typePtr);
737 _ASSERTE(numSizes <= rank);
738 unsigned int i;
739 for(i =0; i < numSizes; i++)
740 sizes[i] = CorSigUncompressData(typePtr);
741
742 unsigned numLowBounds = CorSigUncompressData(typePtr);
743 _ASSERTE(numLowBounds <= rank);
744 for(i = 0; i < numLowBounds; i++)
745 lowerBounds[i] = CorSigUncompressData(typePtr);
746
747 IfFailGo(appendStrA(out, "["));
748 for(i = 0; i < rank; i++)
749 {
750 if (sizes[i] != 0 && lowerBounds[i] != 0)
751 {
752 if (lowerBounds[i] == 0)
753 appendStrNumA(out, sizes[i]);
754 else
755 {
756 appendStrNumA(out, lowerBounds[i]);
757 IfFailGo(appendStrA(out, "..."));
758 if (sizes[i] != 0)
759 appendStrNumA(out, lowerBounds[i] + sizes[i] + 1);
760 }
761 }
762 if (i < rank-1)
763 IfFailGo(appendStrA(out, ","));
764 }
765 IfFailGo(appendStrA(out, "]"));
766 }
767 }
768 break;
769
770 case ELEMENT_TYPE_MVAR:
771 IfFailGo(appendStrA(out, "!!"));
772 appendStrNumA(out, CorSigUncompressData(typePtr));
773 break;
774
775 case ELEMENT_TYPE_VAR:
776 IfFailGo(appendStrA(out, "!"));
777 appendStrNumA(out, CorSigUncompressData(typePtr));
778 break;
779
780 case ELEMENT_TYPE_GENERICINST:
781 {
782 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
783 unsigned ntypars = CorSigUncompressData(typePtr);
784 IfFailGo(appendStrA(out, "<"));
785 for (unsigned i = 0; i < ntypars; i++)
786 {
787 if (i > 0)
788 IfFailGo(appendStrA(out, ","));
789 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
790 }
791 IfFailGo(appendStrA(out, ">"));
792 }
793 break;
794
795 case ELEMENT_TYPE_MODULE_ZAPSIG:
796 IfFailGo(appendStrA(out, "[module#"));
797 appendStrNumA(out, CorSigUncompressData(typePtr));
798 IfFailGo(appendStrA(out, ", token#"));
799 typePtr += CorSigUncompressToken(typePtr, &tk);
800 IfFailGo(appendStrHexA(out, tk));
801 IfFailGo(appendStrA(out, "]"));
802 break;
803
804 case ELEMENT_TYPE_FNPTR:
805 IfFailGo(appendStrA(out, "fnptr "));
806 IfFailGo(PrettyPrintSigWorkerInternal(typePtr, (typeEnd - typePtr), "", out,pIMDI));
807 break;
808
809 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
810 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
811 IfFailGo(appendStrA(out, "native "));
812 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
813 break;
814
815 // Modifiers or dependent types
816 case ELEMENT_TYPE_PINNED:
817 str = " pinned";
818 goto MODIFIER;
819
820 case ELEMENT_TYPE_PTR:
821 str = "*";
822 goto MODIFIER;
823
824 case ELEMENT_TYPE_BYREF:
825 str = "&";
826 goto MODIFIER;
827
828 MODIFIER:
829 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
830 IfFailGo(appendStrA(out, str));
831 break;
832
833 default:
834 case ELEMENT_TYPE_SENTINEL:
835 case ELEMENT_TYPE_END:
836 hr = E_INVALIDARG;
837 break;
838 }
839 ErrExit:
840 return hr;
841} // PrettyPrintTypeA
842#ifdef _PREFAST_
843#pragma warning(pop)
844#endif
845
846// pretty prints the class 'type' to the buffer 'out'
847static HRESULT PrettyPrintClass(
848 PCCOR_SIGNATURE &typePtr, // type to convert
849 PCCOR_SIGNATURE typeEnd, // end of the signature.
850 CQuickBytes *out, // where to put the pretty printed string
851 IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig
852{
853 CONTRACTL
854 {
855 NOTHROW;
856 INJECT_FAULT(return E_OUTOFMEMORY;);
857 }
858 CONTRACTL_END
859
860 mdToken tk;
861 const CHAR *str; // type's token.
862 LPCUTF8 pNS; // type's namespace.
863 LPCUTF8 pN; // type's name.
864 HRESULT hr; // result
865
866 IfFailGo(CorSigUncompressToken_EndPtr(typePtr, typeEnd, &tk));
867 str = "<UNKNOWN>";
868
869 if (TypeFromToken(tk) == mdtTypeSpec)
870 {
871 ULONG cSig;
872 PCCOR_SIGNATURE sig;
873 IfFailGo(pIMDI->GetSigFromToken(tk, &cSig, &sig));
874 IfFailGo(PrettyPrintTypeA(sig, cSig, out, pIMDI));
875 }
876 else
877 {
878 if (TypeFromToken(tk) == mdtTypeRef)
879 {
880 //<TODO>@consider: assembly name?</TODO>
881 if (FAILED(pIMDI->GetNameOfTypeRef(tk, &pNS, &pN)))
882 {
883 pNS = pN = "Invalid TypeRef record";
884 }
885 }
886 else
887 {
888 _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
889 if (FAILED(pIMDI->GetNameOfTypeDef(tk, &pN, &pNS)))
890 {
891 pNS = pN = "Invalid TypeDef record";
892 }
893 }
894
895 if (pNS && *pNS)
896 {
897 IfFailGo(appendStrA(out, pNS));
898 IfFailGo(appendStrA(out, NAMESPACE_SEPARATOR_STR));
899 }
900 IfFailGo(appendStrA(out, pN));
901 }
902 return S_OK;
903
904ErrExit:
905 return hr;
906} // static HRESULT PrettyPrintClass()
907
908//*****************************************************************************
909// Converts a com signature to a text signature.
910//
911// Note that this function DOES NULL terminate the result signature string.
912//*****************************************************************************
913HRESULT PrettyPrintSigInternalLegacy(
914 PCCOR_SIGNATURE typePtr, // type to convert,
915 unsigned typeLen, // length of type
916 const CHAR * name, // can be "", the name of the method for this sig
917 CQuickBytes * out, // where to put the pretty printed string
918 IMDInternalImport * pIMDI) // Import api to use.
919{
920 CONTRACTL
921 {
922 NOTHROW;
923 INJECT_FAULT(return E_OUTOFMEMORY;);
924 }
925 CONTRACTL_END
926
927 return PrettyPrintSigWorkerInternal(typePtr, typeLen, name, out, pIMDI);
928} // HRESULT PrettyPrintSigInternalLegacy()
929
930HRESULT PrettyPrintSigWorkerInternal(
931 PCCOR_SIGNATURE & typePtr, // type to convert,
932 size_t typeLen, // length of type
933 const CHAR * name, // can be "", the name of the method for this sig
934 CQuickBytes * out, // where to put the pretty printed string
935 IMDInternalImport * pIMDI) // Import api to use.
936{
937 CONTRACTL
938 {
939 NOTHROW;
940 INJECT_FAULT(return E_OUTOFMEMORY;);
941 }
942 CONTRACTL_END
943
944 HRESULT hr = S_OK;
945 unsigned numArgs; // Count of arugments to function, or count of local vars.
946 unsigned numTyArgs = 0;
947 PCCOR_SIGNATURE typeEnd = typePtr + typeLen;
948 bool needComma = false;
949
950 out->Shrink(0);
951
952 if (name != 0) // 0 means a local var sig
953 {
954 // get the calling convention out
955 unsigned callConv = CorSigUncompressData(typePtr);
956
957 if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
958 {
959 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
960 if (name != 0 && *name != 0)
961
962 {
963 IfFailGo(appendStrA(out, " "));
964 IfFailGo(appendStrA(out, name));
965 }
966 goto ErrExit;
967 }
968
969 if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)
970 IfFailGo(appendStrA(out, "instance "));
971
972 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
973 {
974 IfFailGo(appendStrA(out, "generic "));
975 numTyArgs = CorSigUncompressData(typePtr);
976 }
977
978 static const CHAR* const callConvNames[IMAGE_CEE_CS_CALLCONV_MAX] =
979 {
980 "",
981 "unmanaged cdecl ",
982 "unmanaged stdcall ",
983 "unmanaged thiscall ",
984 "unmanaged fastcall ",
985 "vararg ",
986 "<error> ",
987 "<error> ",
988 "",
989 "",
990 "",
991 "native vararg "
992 };
993
994 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) < IMAGE_CEE_CS_CALLCONV_MAX)
995 {
996 appendStrA(out, callConvNames[callConv & IMAGE_CEE_CS_CALLCONV_MASK]);
997 }
998
999 numArgs = CorSigUncompressData(typePtr);
1000 // do return type
1001 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
1002 }
1003 else
1004 {
1005 numArgs = CorSigUncompressData(typePtr);
1006 }
1007
1008 if (name != 0 && *name != 0)
1009 {
1010 IfFailGo(appendStrA(out, " "));
1011 IfFailGo(appendStrA(out, name));
1012 }
1013 IfFailGo(appendStrA(out, "("));
1014
1015 while (numArgs)
1016 {
1017 if (typePtr >= typeEnd)
1018 break;
1019
1020 if (*typePtr == ELEMENT_TYPE_SENTINEL)
1021 {
1022 if (needComma)
1023 IfFailGo(appendStrA(out, ","));
1024 IfFailGo(appendStrA(out, "..."));
1025 ++typePtr;
1026 }
1027 else
1028 {
1029 if (needComma)
1030 IfFailGo(appendStrA(out, ","));
1031 IfFailGo(PrettyPrintTypeA(typePtr, (typeEnd - typePtr), out, pIMDI));
1032 --numArgs;
1033 }
1034 needComma = true;
1035 }
1036 IfFailGo(appendStrA(out, ")"));
1037 if (asStringA(out) == 0)
1038 IfFailGo(E_OUTOFMEMORY);
1039
1040 ErrExit:
1041 return hr;
1042} // HRESULT PrettyPrintSigWorkerInternal()
1043