📄 fstdio.h
字号:
/* fstdio.h : FritzOS Standard I/O Header File For The FritzOS C++ Kernel Copyright (C) 2002 Tom Fritz * This program is a part of the FritzOS kernel, and may be freely * copied under the terms of the GNU General Public License (GPL), * version 2, or at your option any later version. For more info, look at the COPYING file.*/// defines:#ifndef FSTDIO_H#define FSTDIO_H// Includes:#include "types.h" // need USHORT, and UCHAR#include "x86.h" // need outportb#include "stdarg.h" // need va_list, va_end and va_start#include "string.h" // need strcpy#define WHITE_BLACK 0x07 // white on black text#define RED_GREEN 0x26 // red on green text#define BLUE_BLACK 1 // Blue on black#define RED_BLACK 4 // red on black#define PURPLE_BLACK 0x5 // purple on black#define YELLOW_BLACK 0x6 // yellow on black#define LIGHTBLUE_BLACK 0x9 // light blue on black#define DARKBLUE_BLACK 0x8 // dark blue on black#define GREEN_BLACK 10 // green on black#define MAGENTA_BLACK 12 // magenta on black#define LIGHTESTBLUE_BLACK 0xB // very light blue on black// For looping so many times:#define LOOP( x, y ) for ( x = 0; x < ( y ); x++ )// For moving the cursor back to 0, 0#define GOHOME gotoxy( 0, 0 )#define NULL 0// Printf Defines:#define PR_LJ 0x01 // left Justify#define PR_CA 0x02 // Use A-F Instead Of a-f For Hex Numbers#define PR_SG 0x04 // Signed Numeric Conversion ( %d vs. %u )#define PR_32 0x08 // Long ( 32-bit ) Numeric Conversion#define PR_16 0x10 // Short ( 16-bit ) Numeric Conversion#define PR_WS 0x20 // PR_SG set and num was < 0#define PR_LZ 0x40 // Pad Left With '0' Instead Of ' '#define PR_FP 0x80 // Pointers Are Far// Largest number handled is 2 ^ 32 - 1, lowest radix handled is 8.// 2 ^ 32 - 1 in base 8 has 11 digits ( add 5 for trailing NULL and for slop )#define PR_BUFLEN 16// Typedefs:typedef int ( * fnptr_t ) ( unsigned c, void** helper );// voids:void Freeze(); // freeze the computer//*********// NOTE: k_printf HAS BEEN REMOVED because printf has more use.//*********// doprintf: printf with hex and other printing optionsint doprintf( const char *fmt, va_list args, fnptr_t fn, void *ptr );// printf - standard printfvoid printf( const char *msg, ... );// printfhelp: help printfstatic int printfhelp( unsigned c, void **ptr );// smprintf - small printf e.g. no args like %svoid smprintf( char* message );// putch - put a single charactervoid putch( UCHAR c );// update_cursor - update the cursor's placevoid update_cursor();// setcolor - set printf & putch colorvoid setcolor( unsigned color );// start textmode stuff that the OS needs to keep track of, and other thingsextern "C" void start_textmode(); // NOTE: I use the extern "C" so that the ASM module can call this.. // even though start_textmode is defined here.// gotoxy: move the cursor to the x and y positionsvoid gotoxy( int x, int y );// Clear Screen to the current color selected by setcolorvoid clrscr();// Simple Print C++ Functionsvoid Print( char* msg, ... ); // Print Stringsvoid Print( char putch ); // Print Charactersvoid Print( int num ); // Print Numbers// data:int cur_cursorX, cur_cursorY; // this is for keeping track of the text mode cursorstatic unsigned short *vgaadr; // the VGA addressstatic unsigned textattrib, scrwidth, scrheight; // the text color, the screen width, & height////////////////////////////////////////////////////////////////////////////////////////////////////////////////*************************************************************************************************************//// Freeze the computer// example: Freeze();void Freeze(){ while( 1 ) ;}//*************************************************************************************************************//// Example: Look at printf for more information on how to use this.int doprintf( const char *fmt, va_list args, fnptr_t fn, void *ptr ){ unsigned state, flags, radix, actual_wd, count, given_wd; unsigned char *where, buf[ PR_BUFLEN ]; long num; state = flags = count = given_wd = 0;// Begin scanning format specifier list for ( ; *fmt; fmt++ ) { switch ( state ) { // STATE 0: AWAITING % case 0: if ( *fmt != '%' ) // not %... { fn ( *fmt, &ptr ); // ...just echo it count++; break; }// Found %, get next character and advance state to check if next char is a flag state++; fmt++; // FALL THROUGH // STATE 1: AWAITING FLAGS ( % - 0 ) case 1: if ( *fmt == '%' ) // %% { fn ( *fmt, &ptr ); count++; state = flags = given_wd = 0; break; } if ( *fmt == '-' ) { if ( flags & PR_LJ ) // %-- is illegal state = flags = given_wd = 0; else flags |= PR_LJ; break; }// Not a flag char: advance state to check if it's field width state++;// Check now for '%0...' if ( *fmt == '0' ) { flags |= PR_LZ; fmt++; } // FALL THROUGH // STATE 2: AWAITING (NUMERIC) FIELD WIDTH case 2: if ( *fmt >= '0' && *fmt <= '9' ) { given_wd = 10 * given_wd + ( *fmt - '0' ); break; }// Not field width: advance state to check if it's a modifier state++; // FALL THROUGH // STATE 3: AWAITING MODIFIER CHARS ( FNlh ) case 3: if ( *fmt == 'F' ) { flags |= PR_FP; break; } if ( *fmt == 'N' ) break; if ( *fmt == 'l' ) { flags |= PR_32; break; } if ( *fmt == 'h' ) { flags |= PR_16; break; }// Not modifier: advance state to check if it's a conversion char state++; // FALL THROUGH// STATE 4: AWAITING CONVERSION CHARS ( Xxpndiuocs ) case 4: where = buf + PR_BUFLEN - 1; *where = '\0'; switch ( *fmt ) { case 'X': flags |= PR_CA; // FALL THROUGH// xxx - far pointers (%Fp, %Fn) not yet supported case 'x': case 'p': case 'n': radix = 16; goto DO_NUM; case 'd': case 'i': flags |= PR_SG; // FALL THROUGH case 'u': radix = 10; goto DO_NUM; case 'o': radix = 8;// Load the value to be printed. l=long=32 bits:DO_NUM: if ( flags & PR_32 ) num = va_arg( args, unsigned long );// h=short=16 bits ( signed or unsigned ) else if ( flags & PR_16 ) { if ( flags & PR_SG ) num = va_arg( args, short ); else num = va_arg( args, unsigned short ); }// No h nor l: sizeof(int) bits ( signed or unsigned ) else { if ( flags & PR_SG ) num = va_arg( args, int ); else num = va_arg( args, unsigned int ); }// Take care of sign if ( flags & PR_SG ) { if ( num < 0 ) { flags |= PR_WS; num = -num; } }// Convert binary to octal/decimal/hex ASCII// The math here is ALWAYS unsigned do { unsigned long temp; temp = ( unsigned long ) num % radix; where--; if ( temp < 10 ) *where = temp + '0'; else if ( flags & PR_CA ) *where = temp - 10 + 'A'; else *where = temp - 10 + 'a'; num = ( unsigned long ) num / radix; } while ( num != 0 ); goto EMIT; case 'c':// Disallow pad-left-with-zeroes for %c flags &= ~PR_LZ; where--; *where = ( unsigned char )va_arg(args, unsigned char); actual_wd = 1; goto EMIT2; case 's':// Disallow pad-left-with-zeroes for %s flags &= ~PR_LZ; where = va_arg( args, unsigned char * );EMIT: actual_wd = strlen( ( char* )where ); if ( flags & PR_WS ) actual_wd++;// If we pad left with ZEROES, do the sign now if ( ( flags & ( PR_WS | PR_LZ ) ) == ( PR_WS | PR_LZ ) ) { fn( '-', &ptr ); count++; }// pad on left with spaces or zeroes ( for right justify )EMIT2: if ( ( flags & PR_LJ ) == 0 ) { while ( given_wd > actual_wd ) { fn( flags & PR_LZ ? '0' : ' ', &ptr ); count++; given_wd--; } }// If we pad left with SPACES, do the sign now if ( ( flags & ( PR_WS | PR_LZ ) ) == PR_WS ) { fn( '-' , &ptr ); count++; }// Emit string/char/converted number while ( *where != '\0' ) { fn( *where++, &ptr ); count++; }// pad on right with spaces ( for left justify ) if ( given_wd < actual_wd ) given_wd = 0; else given_wd -= actual_wd; for ( ; given_wd; given_wd-- ) { fn( ' ', &ptr ); count++; } break; default: break; } default: state = flags = given_wd = 0; break; } } return count;}//*************************************************************************************************************//void putch( UCHAR c ){ unsigned att; att = textattrib << 8; // backspace if ( c == 0x08 ) { if ( cur_cursorX != 0 ) cur_cursorX--; else if ( cur_cursorX == 0 && cur_cursorY > 0 ) { cur_cursorY--; cur_cursorX = scrwidth - 1; // minus 1 because it'll be off screen or not move if // == scrwidth update_cursor(); return; } } // tab else if ( c == 0x09 ) { cur_cursorX += 4; // tabs are 4 spaces in FOS } // carriage return else if ( c == '\r' ) { cur_cursorX = 0; } // new line else if ( c == '\n' ) // in FOS, a '\n' is a new line at the start of the line { cur_cursorX = 0; cur_cursorY++; } // ASCII characters - 123...abc... else if ( c >= ' ' ) { unsigned short *where; where = vgaadr + ( cur_cursorY * scrwidth + cur_cursorX ); *where = c | att; cur_cursorX++; } if ( cur_cursorX >= scrwidth ) { cur_cursorX = 0; cur_cursorY++; } update_cursor();}//*************************************************************************************************************//void start_textmode(){ cur_cursorX = 0; cur_cursorY = 0; gotoxy( 0, 0 ); vgaadr = ( unsigned short * ) 0xb8000; textattrib = WHITE_BLACK; // white on black scrwidth = 80; scrheight = 25;}//*************************************************************************************************************//void gotoxy( int x, int y ){ USHORT position = ( y * scrwidth + x ); // cursor LOW port to vga INDEX register outportb( 0x3D4, 0x0F ); outportb( 0x3D5, ( UCHAR ) ( position & 0xFF ) ); // cursor HIGH port to vga INDEX register outportb( 0x3D4, 0x0E ); outportb( 0x3D5, ( UCHAR ) ( ( position >> 8 ) & 0xFF ) ); cur_cursorX = x; cur_cursorY = y;}//*************************************************************************************************************//void update_cursor(){ gotoxy( cur_cursorX, cur_cursorY );}//*************************************************************************************************************//void setcolor( unsigned color ){ textattrib = color;}//*************************************************************************************************************//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; }}//*************************************************************************************************************//// Example: Look at printf for more information on how to use this function.static int printfhelp( unsigned c, void **ptr ){ putch( c ); return 0;}//*************************************************************************************************************//void printf( const char *msg, ... ){ va_list printfargs; va_start( printfargs, msg); ( void ) doprintf ( msg, printfargs, printfhelp, NULL ); va_end( printfargs );}//*************************************************************************************************************//// Example: clrscr(); // Clear Screenvoid clrscr(){ // For checking how many times to put blanks int i; // Go back to the first place: GOHOME; LOOP ( i, scrwidth * scrheight ) putch( ' ' ); // Put the cursor back to the first place GOHOME;}//*************************************************************************************************************//// NOTE: C++ Code.// Example: Print( "Your Message and % args" );void Print( char* msg, ... ){ va_list args; va_start( args, msg ); (void)doprintf( msg, args, printfhelp, NULL ); va_end(args);}// Example: Print( 'C' );void Print( char putc ){ putch( putc );}// Example: Print( 1 );void Print( int num ){ printf( "%d", num );}#endif// End of fstdio.h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -