Page 1 of 1
Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 4:05 am
by vibhory2j
the puts(), putch() function, given in bran's tutorial, prints all the strings, characters corectly on the console.
but the funtion putch() is unable to print any integer value on the console. the function does nothing when asked to print any integer value.
i tried it this way (as given in tutorial) :-
int i;
i = 10/2;
puthch(i);
what could be the problem???
any help.... thanks in advance
cheers
Re:Test kernels refuses to print to screen
Posted: Mon Nov 07, 2005 6:16 am
by Solar
vibhory2j wrote:
the puts(), putch() function, given in bran's tutorial, prints all the strings, characters corectly on the console.
but the funtion putch() is unable to print any integer value on the console.
I get an access error on osdever.net ATM, and putch() isn't a standard function, so this is guesswork. But:
1) you didn't really write [tt]puthch(i);[/tt], I hope, as this is spelled incorrectyl;
2) are you sure that putch() is actually
intended to print integers? Try feeding it values between, say, 65 and 90. If you see uppercase characters, that putch() accepts int
but interprets them as char values. That is common in C I/O, to make room for the non-char value of EOF.
Re:Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 6:27 am
by Cjmovie
Yes, putch is intended for characters. To try and help you understand, vibhory2j, you may want to look up ASCII.
For the record, here is a method of writing a number to output that _SHOULD_ work:
Code: Select all
void PrintInt(unsigned int a){
while(a > 0){
putch(a % 10);
a /= 10;
}
}
Re:Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 7:07 am
by Solar
Cjmovie wrote:
For the record, here is a method of writing a number to output that _SHOULD_ work...
Your function prints last digit first, which probably is not what you intended, and makes the same mistake vibhory2j did originally (printing integers instead of character values), which is
certainly not what you intended.
Here's code handling both int and unsigned int correctly, including sign and INT_MIN handling for twos-complement / ASCII machines. Untested but confident.
Code: Select all
#include <limits.h>
void PrintUInt( unsigned int a )
{
if ( a > 9 )
{
PrintUInt( a / 10 );
}
putch( ( a % 10 ) + '0' );
}
void PrintInt( int a )
{
if ( a < 0 )
{
putch( '-' );
if ( a == INT_MIN )
{
PrintUInt( ((unsigned int) INT_MAX) + 1 );
}
else
{
PrintUInt( a * -1 );
}
}
}
Re:Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 7:31 am
by Candy
Solar wrote:
Your code eats the stack alive and doesn't handle with locales in which the minus should follow the number.
Point being, you don't care about what it doesn't do or you'd end up with something like GNU Hello, which is the best example ever of an over-engineered project. It's a hello world, with autoconf, automake, locale support etc. Or try GNU True, which is a very long program that only returns true. Based on a define, which defines what it returns (the default program is called false).
Re:Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 8:42 am
by Solar
Candy wrote:
Your code eats the stack alive...
Maximum recursion depth is 5 for 16bit, 10 for 32bit or 20 for 64bit. The version I showed works correctly regardless of word width and is simpler than one using an internal buffer. But well, since you asked for it, see bottom of this post...
...and doesn't handle with locales in which the minus should follow the number.
I feel that kernel code should ignore locale issues because of the code bloat involved, especially in a minor case as to whether the minus should lead or trail. (And how numbers are usually grouped, e.g. commas every three digits etc.) You'd have to cater for EBCDIC, for example, where digits don't occupy consecutive places in the code tables...
Point being, you don't care about what it doesn't do or you'd end up with something like GNU Hello, which is the best example ever of an over-engineered project.
Agreed. But printing decimal numbers most-significant digit first is not negotiable IMNSHO.
It's a hello world, with autoconf, automake, locale support etc.
Nice hint, I always wanted to learn about autoconf and automake.
But now for the non-recursive PrintInt() as requested by Candy:
Code: Select all
/* 5 for 16bit, 10 for 32bit, 20 for 64bit 'int' */
#define PRINTINT_MAXLEN 10
void PrintUInt( unsigned int a )
{
char buffer[ PRINTINT_MAXLEN + 1 ];
unsigned int p = PRINTINT_MAXLEN;
buffer[ p ] = '\0';
while ( a )
{
buffer[ --p ] = ( a % 10 ) + '0';
a /= 10;
}
puts( buffer + p );
}
[tt]PrintInt()[/tt] remains the same. Still assumes two's-complement, ASCII machines
and does not take locales into account. If you're feeling reckless, you could drag in <math.h> and <stdlib.h> and determine the max. amount of digits using a log2() on UINT_MAX and using dynamically allocated memory, but that'd be about as much overkill as properly formatting the number according to current setlocale()...
Re:Bran's tutorial - putch()
Posted: Mon Nov 07, 2005 3:32 pm
by Cjmovie
Solar wrote:
Cjmovie wrote:
For the record, here is a method of writing a number to output that _SHOULD_ work...
Your function prints last digit first, which probably is not what you intended, and makes the same mistake vibhory2j did originally (printing integers instead of character values), which is
certainly not what you intended.
Here's code handling both int and unsigned int correctly, including sign and INT_MIN handling for twos-complement / ASCII machines. Untested but confident.
Code: Select all
#include <limits.h>
void PrintUInt( unsigned int a )
{
if ( a > 9 )
{
PrintUInt( a / 10 );
}
putch( ( a % 10 ) + '0' );
}
void PrintInt( int a )
{
if ( a < 0 )
{
putch( '-' );
if ( a == INT_MIN )
{
PrintUInt( ((unsigned int) INT_MAX) + 1 );
}
else
{
PrintUInt( a * -1 );
}
}
}
Ooooh, last time I try to help out before school right after waking up from 2 hours of sleep while starting my history project due today.....
lol
Re:Bran's tutorial - putch()
Posted: Tue Nov 08, 2005 12:26 pm
by vibhory2j
referring to the code by solar :-
Code: Select all
#include <limits.h>
void PrintUInt( unsigned int a )
{
if ( a > 9 )
{
PrintUInt( a / 10 );
}
putch( ( a % 10 ) + '0' );
}
void PrintInt( int a )
{
if ( a < 0 )
{
putch( '-' );
if ( a == INT_MIN )
{
PrintUInt( ((unsigned int) INT_MAX) + 1 );
}
else
{
PrintUInt( a * -1 );
}
}
}
i will try to put this in to my kernel. but i suspect the use of include file limits.h as we can't nse built in libraries in the kernel source.
am i right or wrong??? please clarify it....
cheers
Re:Bran's tutorial - putch()
Posted: Tue Nov 08, 2005 12:34 pm
by pradeep
Let me make a guess?
If the header file is going to call any system calls are other library routines then you can't have it in your kernel. Suppose if the header file is standalone library then you can have it in your kernel.Because i am doing kernel in asm i don't know much about C.
Please correct me if i am wrong?
Re:Bran's tutorial - putch()
Posted: Tue Nov 08, 2005 5:47 pm
by AR
limits.h is part of the freestanding environment (The "not-running-on-an-OS" environment), basically it's just a header full of defines declaring "sizes" (ranges) of variable types.
If you built a cross compiler, <limits.h> will be part of your freestanding environment and should work fine (provided you aren't using "-nostdinc" on the commandline).
Re:Bran's tutorial - putch()
Posted: Wed Nov 09, 2005 12:24 am
by Solar
You can use whatever part of the standard library you implemented. <limits.h> is so easy it can actually be auto-generated, as it merely contains a bunch of #define statements referring to the size of integers of your system.
Edit: You might want to have a look at my signature... PDCLib 0.2 isn't much from the user-space perspective, but it has all the freestanding headers (including <limits.h>), and is especially targeted at OS dev'ers like us here, meaning it's dead-easy to adapt to your wishes. Just stay away from the <string.h> functions until 0.3, there are some really stupid bugs in there.