@@ -215,6 +215,53 @@ static void DumpCharacter(Stream &s, const char c) {
215215 s.Printf (" \\ x%2.2x" , c);
216216}
217217
218+ // / Dump the character to a stream using OCaml string literal format.
219+ // / This matches OCaml's unsafe_escape function from bytes.ml in the standard library.
220+ static void DumpEscapedCharacterOCaml (Stream &s, const char c) {
221+ switch (c) {
222+ case ' "' :
223+ s.Printf (" \\\" " );
224+ return ;
225+ case ' \\ ' :
226+ s.Printf (" \\\\ " );
227+ return ;
228+ case ' \n ' :
229+ s.Printf (" \\ n" );
230+ return ;
231+ case ' \t ' :
232+ s.Printf (" \\ t" );
233+ return ;
234+ case ' \r ' :
235+ s.Printf (" \\ r" );
236+ return ;
237+ case ' \b ' :
238+ s.Printf (" \\ b" );
239+ return ;
240+ default :
241+ break ;
242+ }
243+
244+ // Handle printable ASCII range ' ' to '~' (32 to 126)
245+ if (c >= ' ' && c <= ' ~' ) {
246+ s.PutChar (c);
247+ return ;
248+ }
249+
250+ // Use OCaml's 3-digit decimal escape format for non-printable characters
251+ // This matches the logic in bytes.ml unsafe_escape function
252+ unsigned char a = (unsigned char )c;
253+ s.Printf (" \\ %03d" , a);
254+ }
255+
256+ // / Dump a C string as an OCaml string literal with proper escaping and quotes.
257+ static void DumpStringOCaml (Stream *s, const char *data, uint64_t string_length) {
258+ s->Printf (" \" " );
259+ for (uint64_t i = 0 ; i < string_length; ++i) {
260+ DumpEscapedCharacterOCaml (*s, data[i]);
261+ }
262+ s->Printf (" \" " );
263+ }
264+
218265// / Dump a floating point type.
219266template <typename FloatT>
220267void DumpFloatingPoint (std::ostringstream &ss, FloatT f) {
@@ -386,13 +433,21 @@ void PrintAPIntAsFloat(Stream *s, llvm::APInt apint,
386433 else
387434 apfloat.toPossiblyShortString (sv);
388435
389- s->AsRawOstream () << prefix;
390- s->AsRawOstream () << sv;
391436 // OCaml Specific:
392- // Following OCaml conventions, print the trailing "." to
437+ // Handle negative sign placement for OCaml format
438+ if (sv.size () > 0 && sv[0 ] == ' -' ) {
439+ s->AsRawOstream () << " -" ;
440+ s->AsRawOstream () << prefix;
441+ s->AsRawOstream () << llvm::StringRef (sv.data () + 1 , sv.size () - 1 );
442+ } else {
443+ s->AsRawOstream () << prefix;
444+ s->AsRawOstream () << sv;
445+ }
446+
447+ // Following OCaml conventions, print the trailing ".0" to
393448 // identify that the integer is in fact a float, but don't
394- // print any trailing zeros.
395- bool print_trailing_dot = true ;
449+ // print any trailing zeros beyond that .
450+ bool print_trailing_dot_zero = true ;
396451 for (char c : sv) {
397452 switch (c) {
398453 case ' -' :
@@ -409,14 +464,14 @@ void PrintAPIntAsFloat(Stream *s, llvm::APInt apint,
409464 continue ;
410465 default :
411466 // if we find something that is not a number such as 'e' or 'E' or '.'
412- // there is no need to print the trailing ".".
413- print_trailing_dot = false ;
467+ // there is no need to print the trailing ".0 ".
468+ print_trailing_dot_zero = false ;
414469 }
415470 break ; // we found something that is not a number, so we will not print
416- // the trailing "."
471+ // the trailing ".0 "
417472 }
418- if (print_trailing_dot ){
419- s->AsRawOstream () << " ." ;
473+ if (print_trailing_dot_zero ){
474+ s->AsRawOstream () << " .0 " ;
420475 }
421476
422477 s->AsRawOstream () << suffix;
@@ -574,19 +629,8 @@ static offset_t FormatOCamlValue(const DataExtractor &DE, Stream *s,
574629 if (error.Fail () || bytes_read < string_length) {
575630 s->Printf (" <could not read string>@" );
576631 } else {
577- const char *c_str = (const char *)&str.front ();
578- if (strlen (c_str) == string_length) {
579- /* String does not contain NUL characters */
580- s->Printf (" \" %s\" " , c_str);
581- } else {
582- s->Printf (" \" " );
583- DataExtractor cstr_data (&str.front (), str.size (),
584- process->GetByteOrder (), 8 );
585- DumpDataExtractor (cstr_data, s, 0 , lldb::eFormatChar, 1 ,
586- string_length, UINT32_MAX,
587- LLDB_INVALID_ADDRESS, 0 , 0 );
588- s->Printf (" \" " );
589- }
632+ const char *data = (const char *)&str.front ();
633+ DumpStringOCaml (s, data, string_length);
590634 print_default = false ;
591635 }
592636 }
@@ -681,7 +725,7 @@ static offset_t FormatOCamlValue(const DataExtractor &DE, Stream *s,
681725 if (int_size == 32 )
682726 s->Printf (" %ld" , (long )i);
683727 else
684- s->Printf (" %lld " , (int64_t )i);
728+ s->Printf (" %" PRIi64 , (int64_t )i);
685729 s->Printf (" %s" , suffix.c_str ());
686730 print_default = false ;
687731 }
@@ -927,11 +971,26 @@ lldb::offset_t lldb_private::DumpDataExtractor(
927971 case eFormatEnum: // Print enum value as a signed integer when we don't get
928972 // the enum type
929973 case eFormatDecimal:
930- if (item_byte_size <= 8 )
931- s->Printf (" %" PRId64,
932- DE.GetMaxS64Bitfield (&offset, item_byte_size, item_bit_size,
933- item_bit_offset));
934- else {
974+ if (item_byte_size <= 8 ) {
975+ int64_t value = DE.GetMaxS64Bitfield (&offset, item_byte_size, item_bit_size,
976+ item_bit_offset);
977+ // CR sspies: This is special cases for OCaml values. Consider wrapping
978+ // it in a guard.
979+ // Format as unboxed OCaml integer
980+ std::string suffix = " " ;
981+ if (item_byte_size == 4 ) suffix = " l" ;
982+ else if (item_byte_size == 8 ) suffix = " L" ;
983+ else if (item_byte_size == 2 ) suffix = " " ; // int16 - no specific suffix
984+ else if (item_byte_size == 1 ) suffix = " " ; // int8 - no specific suffix
985+ // Add "n" suffix for nativeint when it's pointer-sized (could be 4 or 8 bytes)
986+
987+
988+ if (value < 0 ) {
989+ s->Printf (" -#%" PRId64 " %s" , -value, suffix.c_str ());
990+ } else {
991+ s->Printf (" #%" PRId64 " %s" , value, suffix.c_str ());
992+ }
993+ } else {
935994 const bool is_signed = true ;
936995 const unsigned radix = 10 ;
937996 offset = DumpAPInt (s, DE, offset, item_byte_size, is_signed, radix);
0 commit comments