itoa please...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Tom

itoa please...

Post by Tom »

hello,

I need an itoa funciton that doen't crash PMode. (look using google and still no help)
does anyone have a itoa funcion, with all the code for reverse & strcat & other stuff it needs?

Thank you
Schol-R-LEA

Re:itoa please...

Post by Schol-R-LEA »

I can't give you all of it, but since I wrote two of the routines you'll need in another thread earlier, you might as well use them. though I haven't tested them and cannot guarantee that they won't need debugging.

Code: Select all

;;; void* memcpy(void* to, const void* from, size_t count)

extrn memcpy

_memcpy:
   push ebp
   mov ebp, esp
   mov esi, [ebp + 8]    ; first arg - src pointer
   mov edi, [ebp +12]   ; 2nd arg - dest pointer
   mov ecx, [ebp + 16] ; 3rd arg - string size in bytes
   mov eax, edi             ; return value - save now, before EDI gets trashed
   cdl                             ; make sure direction flag set correctly
   rep movsb                 ; block-copy from src to dest
   pop ebp                     ; restore caller's stack frame
   ret

;;  void* memset(void* buf, int ch, size_t cont)
extrn memset

_memset:
   push ebp
   mov ebp, esp
   mov edi, [ebp + 8]    ; first arg - buffer pointer
   mov edi, [ebp +12]   ; 2nd arg - value to write
   mov eax, [ebp + 16] ; 3rd arg - string size in bytes
   push edi             ; return value - save now, before EDI gets trashed
   cdl                      ; make sure direction flag set correctly
   rep stosb
   pop eax              ; recover return value
   pop ebp              ; restore caller's stack frame
   ret
With these two, and a simple implementation of strlen(), it should be trivial to implement strcat() and strcpy() as preprocessor macros:

Code: Select all

#define strcat(x,y) memcat((void *)(x + strlen(x) +1), (void *)(y), (strlen(y) +1))
#define strcpy(x,y) memcpy((void *)(x), (void *)(y), (strlen(x) +1))
Again, this is not tested code; if you borrow it, be proepared to do some debugging. Note that while this is a traditional implementation approach, you may want to code them as true functions for the sake of increased robustness.

As always, comments and corrections are welcome.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:itoa please...

Post by Pype.Clicker »

just notifying a typo :
cdl is no valid ASM. the instruction is CLD
Tim

Re:itoa please...

Post by Tim »

I posted an itoa implementation (for hex, at least) quite recently. It should be easy to modify to decimal or any other base.
Tim Robinson wrote:

Code: Select all

/* str must be at least 9 chars long */
void str_to_hex(char *str, unsigned long num)
{
    static char hexdigits[] = "0123456789abcdef";
    char str[9], *ptr;

    ptr = str + 9;
    *ptr = '\0';
    do
    {
        ptr--;
        *ptr = hexdigits[num % 16];
        num >>= 4;
    } while (num > 0);
}
Tom

Re:itoa please...

Post by Tom »

so num % 16 would be num % 10?
Tim

Re:itoa please...

Post by Tim »

Yes.

Actually, I'll post the generic code, because I've used one or two hex-only tricks in my original. This is the starting point for an strtoul() function (which you can look up in your C reference).

Code: Select all

/* str must be long enough */
void num_to_str(char *str, unsigned long num, unsigned base)
{
    /* extend this for bases beyond 16 */
    static char digits[] = "0123456789abcdef";
    char buf[20], *ptr;

    ptr = buf + sizeof(buf) - 1;
    *ptr = '\0';
    do
    {
        ptr--;
        *ptr = digits[num % base];
        num /= base;
    } while (num > 0);

    strcpy(str, buf);
}
Tom

Re:itoa please...

Post by Tom »

static int printf( char *msg, ... )
{
   char curchar = *msg;
   char* ch;
   char* str;
   unsigned long d;
   char* numstring;

   va_list args;
   va_start( args, msg );

   // keep reading the message until it's the end of the message
   while ( curchar != '\0' )
   {
      // if it is just a character, then print
      if ( curchar >= ' ' && curchar != '%' )
      {
         putch( curchar );
      }

      // it's a '%'
      else if ( curchar == '%' )
      {
         // check ahead if it's another %
         // alot of help came from my compiler book;)
         ++msg;
         curchar = *msg;
         if ( curchar == '%' )
            putch( '%' );

         // not another % -- print the character, string, or number
         else
         {
            switch ( curchar )
            {
               case 'c':
                  *ch = ( unsigned char ) va_arg( args, int );
                  putch( *ch );
                  
                  break;

               case 's':
                  str = va_arg( args, char * );
                  smprintf( str );

                  break;

               case 'd':
                  d = va_arg( args, int );
                  convertInttoString( numstring, d, 10 ); // 10 = the type of
                                 // number system
                  smprintf( numstring );

                  break;

               default:
                  putch( '%' );      // just print % when it doesn't know
                           // what to do

                  break;
            }
         }
      }

      else if ( curchar == 0x08 || curchar == 0x09 || curchar == '\r' || curchar == '\n' )
      {
         putch( curchar );
      }

      ++msg;
      curchar = *msg;
   }

   va_end( args );
}


void smprintf( char* message )
{
   char _curchar = *message;

   while ( _curchar != '\0' )
   {
      // don't check if it's greater or = to ' ' because someone might need to print \n and
      // to keep it small, just print all characters
      putch( _curchar );

      ++message;
      _curchar = *message;
   }
}

//*************************************************************************************************************
//

void convertInttoString( char *stringout, unsigned long number, unsigned base )
{
   // If base is 16, it's hex, if it's 10, it's just regular numbers
   static char digits[] = "0123456789abcdef";
   char buffer[ 20 ], *ptr;

   ptr = buffer + sizeof( buffer ) - 1;
   *ptr = '\0';

   do
   {
      ptr--;
      *ptr = digits[ number % base ];
      number /= base;
   }

   while ( number >= 0 );

   strcpy( stringout, buffer );
}

and it prints I beams on my computer when I print %d's :'(
Tim

Re:itoa please...

Post by Tim »

I confess, I never tested the code I posted... :-[

That last line should be:

Code: Select all

strcpy(stringout, ptr);
At this point, [tt]ptr[/tt] points just before the last digit we wrote, somewhere after the start of [tt]buffer[/tt]. Between the start of [tt]buffer[/tt] and [tt]ptr[/tt] there are random characters (what you saw). We want to output characters starting at [tt]ptr[/tt] and going to the end of the string.

BTW: if you want to eliminate [tt]buffer[/tt] and the call to [tt]strcpy[/tt], you could merge the string conversion routine with [tt]printf[/tt].
Tom

Re:itoa please...

Post by Tom »

still prints I beams.......................an also, you got to see FritzOS pk0.7 code...................
Tim

Re:itoa please...

Post by Tim »

Well, why don't you debug your OS, and I'll debug mine...?
Tom

Re:itoa please...

Post by Tom »

because....I've tried every itoa I can find :P
Tom

Re:itoa please...

Post by Tom »

could I see your itoa?
Tim

Re:itoa please...

Post by Tim »

I took the sensible route and borrowed all these mundane routines from the DJGPP libc.

Anyway, there's no such thing as itoa in the standard C library. The equivalents are strtoul and strtol.

See here for the various str* routines:
http://cvs.sourceforge.net/cgi-bin/view ... bc/stdlib/
Tom

Re:itoa please...

Post by Tom »

I have a half working one now...
it prints the number and then the bar character:-X
if I print 999 and then print 0 it comes out

999(bar character) 099(bar character)
is there anything wrong that I can't see?:

char* convertInttoString( long num )
{
   long x;
   long y = 0;
   long z = num;
   short   a = 1;
   char* stringout;

   if ( !num )
   {
      stringout[ 0 ] = 1;
      stringout[ 1 ] = '0';
      return;
   }
   
   if ( num < 0 )
   {
      stringout[ a++ ] = '-';
      num = -num;
   }
   
   Loop ( x, 10 )
   {
      if ( z ) y++;
      z /= 10;
   }

   stringout[ 0 ] = y + a - 1;

   while ( y-- )
   {
      stringout[ y + a ] = ( num % 10 ) + '0';
      num /= 10;
   }
   
   return stringout;
}
Tom

Re:itoa please...

Post by Tom »

ok that one was full of bugs...trying another one....
Post Reply