3636#include <stddef.h>
3737#include <stdint.h>
3838#include <stdbool.h>
39+ #include <limits.h>
3940
4041//==============================================================================
4142// HELPER FUNCTIONS
@@ -308,6 +309,44 @@ static void Dmod_Print_Hex64( char** Buffer, size_t* Pos, size_t Size, uint64_t
308309 }
309310}
310311
312+ static void Dmod_Print_Octal ( char * * Buffer , size_t * Pos , size_t Size , uint32_t Value , int * Count )
313+ {
314+ char Temp [12 ]; // Enough for 11 octal digits (32-bit)
315+ int i = 0 ;
316+
317+ // Convert to octal string (reversed)
318+ do
319+ {
320+ Temp [i ++ ] = '0' + (Value & 0x7 );
321+ Value >>= 3 ;
322+ } while ( Value > 0 );
323+
324+ // Print in correct order
325+ while ( i > 0 )
326+ {
327+ Dmod_Print_Char ( Buffer , Pos , Size , Temp [-- i ], Count );
328+ }
329+ }
330+
331+ static void Dmod_Print_Octal64 ( char * * Buffer , size_t * Pos , size_t Size , uint64_t Value , int * Count )
332+ {
333+ char Temp [23 ]; // Enough for 22 octal digits (64-bit)
334+ int i = 0 ;
335+
336+ // Convert to octal string (reversed)
337+ do
338+ {
339+ Temp [i ++ ] = '0' + (Value & 0x7 );
340+ Value >>= 3 ;
341+ } while ( Value > 0 );
342+
343+ // Print in correct order
344+ while ( i > 0 )
345+ {
346+ Dmod_Print_Char ( Buffer , Pos , Size , Temp [-- i ], Count );
347+ }
348+ }
349+
311350//==============================================================================
312351// PUBLIC FUNCTIONS
313352//==============================================================================
@@ -356,11 +395,47 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
356395 }
357396
358397 // Parse length modifier
359- bool IsLongLong = false;
360- if ( * Format == 'l' && * (Format + 1 ) == 'l' )
398+ typedef enum {
399+ LEN_NONE , // default (int/unsigned int)
400+ LEN_HH , // char
401+ LEN_H , // short
402+ LEN_L , // long
403+ LEN_LL , // long long
404+ LEN_Z // size_t
405+ } LengthModifier ;
406+
407+ LengthModifier LenMod = LEN_NONE ;
408+
409+ if ( * Format == 'h' )
361410 {
362- IsLongLong = true;
363- Format += 2 ;
411+ if ( * (Format + 1 ) == 'h' )
412+ {
413+ LenMod = LEN_HH ;
414+ Format += 2 ;
415+ }
416+ else
417+ {
418+ LenMod = LEN_H ;
419+ Format ++ ;
420+ }
421+ }
422+ else if ( * Format == 'l' )
423+ {
424+ if ( * (Format + 1 ) == 'l' )
425+ {
426+ LenMod = LEN_LL ;
427+ Format += 2 ;
428+ }
429+ else
430+ {
431+ LenMod = LEN_L ;
432+ Format ++ ;
433+ }
434+ }
435+ else if ( * Format == 'z' )
436+ {
437+ LenMod = LEN_Z ;
438+ Format ++ ;
364439 }
365440
366441 // Handle format specifiers
@@ -389,11 +464,33 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
389464
390465 case 'd' :
391466 case 'i' : {
392- if ( IsLongLong )
467+ if ( LenMod == LEN_LL )
393468 {
394469 int64_t Value = va_arg ( Args , int64_t );
395470 Dmod_Print_LongLong ( BufPtr , & Pos , Size , Value , & Count );
396471 }
472+ else if ( LenMod == LEN_L || LenMod == LEN_Z )
473+ {
474+ // long and size_t/ssize_t are typically same size
475+ long Value = va_arg ( Args , long );
476+ #if LONG_MAX == INT64_MAX
477+ Dmod_Print_LongLong ( BufPtr , & Pos , Size , (int64_t )Value , & Count );
478+ #else
479+ Dmod_Print_Int ( BufPtr , & Pos , Size , (int32_t )Value , & Count );
480+ #endif
481+ }
482+ else if ( LenMod == LEN_HH )
483+ {
484+ // char is promoted to int in varargs
485+ int Value = va_arg ( Args , int );
486+ Dmod_Print_Int ( BufPtr , & Pos , Size , (int32_t )(signed char )Value , & Count );
487+ }
488+ else if ( LenMod == LEN_H )
489+ {
490+ // short is promoted to int in varargs
491+ int Value = va_arg ( Args , int );
492+ Dmod_Print_Int ( BufPtr , & Pos , Size , (int32_t )(short )Value , & Count );
493+ }
397494 else
398495 {
399496 int32_t Value = va_arg ( Args , int32_t );
@@ -403,11 +500,33 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
403500 }
404501
405502 case 'u' : {
406- if ( IsLongLong )
503+ if ( LenMod == LEN_LL )
407504 {
408505 uint64_t Value = va_arg ( Args , uint64_t );
409506 Dmod_Print_ULongLong ( BufPtr , & Pos , Size , Value , & Count );
410507 }
508+ else if ( LenMod == LEN_L || LenMod == LEN_Z )
509+ {
510+ // unsigned long and size_t are typically same size
511+ unsigned long Value = va_arg ( Args , unsigned long );
512+ #if ULONG_MAX == UINT64_MAX
513+ Dmod_Print_ULongLong ( BufPtr , & Pos , Size , (uint64_t )Value , & Count );
514+ #else
515+ Dmod_Print_UInt ( BufPtr , & Pos , Size , (uint32_t )Value , & Count );
516+ #endif
517+ }
518+ else if ( LenMod == LEN_HH )
519+ {
520+ // unsigned char is promoted to int in varargs
521+ unsigned int Value = va_arg ( Args , unsigned int );
522+ Dmod_Print_UInt ( BufPtr , & Pos , Size , (uint32_t )(unsigned char )Value , & Count );
523+ }
524+ else if ( LenMod == LEN_H )
525+ {
526+ // unsigned short is promoted to int in varargs
527+ unsigned int Value = va_arg ( Args , unsigned int );
528+ Dmod_Print_UInt ( BufPtr , & Pos , Size , (uint32_t )(unsigned short )Value , & Count );
529+ }
411530 else
412531 {
413532 uint32_t Value = va_arg ( Args , uint32_t );
@@ -417,11 +536,30 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
417536 }
418537
419538 case 'x' : {
420- if ( IsLongLong )
539+ if ( LenMod == LEN_LL )
421540 {
422541 uint64_t Value = va_arg ( Args , uint64_t );
423542 Dmod_Print_Hex64 ( BufPtr , & Pos , Size , Value , false, & Count );
424543 }
544+ else if ( LenMod == LEN_L || LenMod == LEN_Z )
545+ {
546+ unsigned long Value = va_arg ( Args , unsigned long );
547+ #if ULONG_MAX == UINT64_MAX
548+ Dmod_Print_Hex64 ( BufPtr , & Pos , Size , (uint64_t )Value , false, & Count );
549+ #else
550+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )Value , false, & Count );
551+ #endif
552+ }
553+ else if ( LenMod == LEN_HH )
554+ {
555+ unsigned int Value = va_arg ( Args , unsigned int );
556+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )(unsigned char )Value , false, & Count );
557+ }
558+ else if ( LenMod == LEN_H )
559+ {
560+ unsigned int Value = va_arg ( Args , unsigned int );
561+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )(unsigned short )Value , false, & Count );
562+ }
425563 else
426564 {
427565 uint32_t Value = va_arg ( Args , uint32_t );
@@ -431,11 +569,30 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
431569 }
432570
433571 case 'X' : {
434- if ( IsLongLong )
572+ if ( LenMod == LEN_LL )
435573 {
436574 uint64_t Value = va_arg ( Args , uint64_t );
437575 Dmod_Print_Hex64 ( BufPtr , & Pos , Size , Value , true, & Count );
438576 }
577+ else if ( LenMod == LEN_L || LenMod == LEN_Z )
578+ {
579+ unsigned long Value = va_arg ( Args , unsigned long );
580+ #if ULONG_MAX == UINT64_MAX
581+ Dmod_Print_Hex64 ( BufPtr , & Pos , Size , (uint64_t )Value , true, & Count );
582+ #else
583+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )Value , true, & Count );
584+ #endif
585+ }
586+ else if ( LenMod == LEN_HH )
587+ {
588+ unsigned int Value = va_arg ( Args , unsigned int );
589+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )(unsigned char )Value , true, & Count );
590+ }
591+ else if ( LenMod == LEN_H )
592+ {
593+ unsigned int Value = va_arg ( Args , unsigned int );
594+ Dmod_Print_Hex ( BufPtr , & Pos , Size , (uint32_t )(unsigned short )Value , true, & Count );
595+ }
439596 else
440597 {
441598 uint32_t Value = va_arg ( Args , uint32_t );
@@ -444,6 +601,39 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
444601 break ;
445602 }
446603
604+ case 'o' : {
605+ if ( LenMod == LEN_LL )
606+ {
607+ uint64_t Value = va_arg ( Args , uint64_t );
608+ Dmod_Print_Octal64 ( BufPtr , & Pos , Size , Value , & Count );
609+ }
610+ else if ( LenMod == LEN_L || LenMod == LEN_Z )
611+ {
612+ unsigned long Value = va_arg ( Args , unsigned long );
613+ #if ULONG_MAX == UINT64_MAX
614+ Dmod_Print_Octal64 ( BufPtr , & Pos , Size , (uint64_t )Value , & Count );
615+ #else
616+ Dmod_Print_Octal ( BufPtr , & Pos , Size , (uint32_t )Value , & Count );
617+ #endif
618+ }
619+ else if ( LenMod == LEN_HH )
620+ {
621+ unsigned int Value = va_arg ( Args , unsigned int );
622+ Dmod_Print_Octal ( BufPtr , & Pos , Size , (uint32_t )(unsigned char )Value , & Count );
623+ }
624+ else if ( LenMod == LEN_H )
625+ {
626+ unsigned int Value = va_arg ( Args , unsigned int );
627+ Dmod_Print_Octal ( BufPtr , & Pos , Size , (uint32_t )(unsigned short )Value , & Count );
628+ }
629+ else
630+ {
631+ uint32_t Value = va_arg ( Args , uint32_t );
632+ Dmod_Print_Octal ( BufPtr , & Pos , Size , Value , & Count );
633+ }
634+ break ;
635+ }
636+
447637 case 'p' : {
448638 void * Ptr = va_arg ( Args , void * );
449639 Dmod_Print_Pointer ( BufPtr , & Pos , Size , Ptr , & Count );
@@ -471,11 +661,28 @@ int Dmod_VSnPrintf_Impl( char* Buffer, size_t Size, const char* Format, va_list
471661 }
472662 }
473663 // Print length modifier if present
474- if ( IsLongLong )
664+ if ( LenMod == LEN_HH )
665+ {
666+ Dmod_Print_Char ( BufPtr , & Pos , Size , 'h' , & Count );
667+ Dmod_Print_Char ( BufPtr , & Pos , Size , 'h' , & Count );
668+ }
669+ else if ( LenMod == LEN_H )
670+ {
671+ Dmod_Print_Char ( BufPtr , & Pos , Size , 'h' , & Count );
672+ }
673+ else if ( LenMod == LEN_L )
674+ {
675+ Dmod_Print_Char ( BufPtr , & Pos , Size , 'l' , & Count );
676+ }
677+ else if ( LenMod == LEN_LL )
475678 {
476679 Dmod_Print_Char ( BufPtr , & Pos , Size , 'l' , & Count );
477680 Dmod_Print_Char ( BufPtr , & Pos , Size , 'l' , & Count );
478681 }
682+ else if ( LenMod == LEN_Z )
683+ {
684+ Dmod_Print_Char ( BufPtr , & Pos , Size , 'z' , & Count );
685+ }
479686 Dmod_Print_Char ( BufPtr , & Pos , Size , * Format , & Count );
480687 break ;
481688 }
0 commit comments