Page 1 of 2

itoa please...

Posted: Mon Sep 30, 2002 4:10 pm
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

Re:itoa please...

Posted: Tue Oct 01, 2002 1:19 am
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.

Re:itoa please...

Posted: Tue Oct 01, 2002 1:59 am
by Pype.Clicker
just notifying a typo :
cdl is no valid ASM. the instruction is CLD

Re:itoa please...

Posted: Tue Oct 01, 2002 10:26 am
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);
}

Re:itoa please...

Posted: Tue Oct 01, 2002 10:27 am
by Tom
so num % 16 would be num % 10?

Re:itoa please...

Posted: Tue Oct 01, 2002 10:41 am
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);
}

Re:itoa please...

Posted: Tue Oct 01, 2002 3:29 pm
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 :'(

Re:itoa please...

Posted: Tue Oct 01, 2002 3:48 pm
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].

Re:itoa please...

Posted: Tue Oct 01, 2002 4:21 pm
by Tom
still prints I beams.......................an also, you got to see FritzOS pk0.7 code...................

Re:itoa please...

Posted: Wed Oct 02, 2002 5:32 am
by Tim
Well, why don't you debug your OS, and I'll debug mine...?

Re:itoa please...

Posted: Wed Oct 02, 2002 5:33 am
by Tom
because....I've tried every itoa I can find :P

Re:itoa please...

Posted: Wed Oct 02, 2002 5:35 am
by Tom
could I see your itoa?

Re:itoa please...

Posted: Wed Oct 02, 2002 5:43 am
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/

Re:itoa please...

Posted: Wed Oct 02, 2002 4:47 pm
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;
}

Re:itoa please...

Posted: Thu Oct 03, 2002 7:29 am
by Tom
ok that one was full of bugs...trying another one....