Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!bloom-beacon!mit-eddie!uw-beaver!ssc-vax!uvicctr!tholm From: tholm@uvicctr.UUCP (Terrence W. Holm) Newsgroups: comp.os.minix Subject: ic(1), part 3 of 3 Message-ID: <417@uvicctr.UUCP> Date: 17 May 88 23:43:29 GMT Reply-To: tholm@uvicctr.UUCP (Terrence W. Holm) Organization: University of Victoria, Victoria B.C. Canada Lines: 770 EFTH Minix report #13 - May 1988 - ic(1) [part 3 of 3] echo x - ic_input.c gres '^X' '' > ic_input.c << '/' X/****************************************************************/ X/* */ X/* ic_input.c */ X/* */ X/* Character input routines for the */ X/* "Integer Calculator". */ X/* */ X/****************************************************************/ X/* origination 1988-Apr-7 T. Holm */ X/* added cmd line args 1988-May-13 T. Holm */ X/****************************************************************/ X X X X#include X#include X#include X X#include "ic.h" X X X X Xstatic struct sgttyb saved_mode; Xstatic struct tchars saved_chars; X X X X X X X/****************************************************************/ X/* */ X/* Save_Term() */ X/* */ X/* Save the current terminal characteristics. */ X/* */ X/****************************************************************/ X X XSave_Term() X X { X ioctl( 0, TIOCGETP, &saved_mode ); X ioctl( 0, TIOCGETC, &saved_chars ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Set_Term() */ X/* */ X/* Set up the terminal characteristics for ic. */ X/* */ X/****************************************************************/ X X XSet_Term() X X { X struct sgttyb ic_mode; X struct tchars ic_chars; X X ic_mode = saved_mode; X ic_chars = saved_chars; X X X /* No tab expansion, no echo, cbreak mode */ X X ic_mode.sg_flags = ic_mode.sg_flags & ~XTABS & ~ECHO | CBREAK; X X X /* Change the interrupt character to ^C, ignore ^S & ^Q */ X X ic_chars.t_intrc = '\003'; X ic_chars.t_startc = '\377'; X ic_chars.t_stopc = '\377'; X X ioctl( 0, TIOCSETP, &ic_mode ); X ioctl( 0, TIOCSETC, &ic_chars ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Reset_Term() */ X/* */ X/* Restore the terminal characteristics. */ X/* */ X/****************************************************************/ X X XReset_Term() X X { X ioctl( 0, TIOCSETP, &saved_mode ); X ioctl( 0, TIOCSETC, &saved_chars ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Get_Char() */ X/* */ X/* Return the next input character. Upper case */ X/* is mapped to lower case. Escape sequences */ X/* are mapped to special codes (msb set). */ X/* */ X/****************************************************************/ X X Xint Get_Char() X X { X int c; X X X /* fflush() used because Minix does not automatically */ X /* flush the output. */ X X fflush( stdout ); X X X if ( (c = Getc()) == EOF ) X return( EOF ); X X c &= 0x7f; X X X if ( isupper(c) ) X return( tolower(c) ); X X X if ( c == ESCAPE ) X if ( (c=Getc()) != '[' ) X { X ungetc( c, stdin ); X return( ESCAPE ); X } X else X { X c = Getc() | 0x80; X X if ( c == ESC_HOME || c == ESC_UP || c == ESC_PGUP || X c == ESC_LEFT || c == ESC_5 || c == ESC_RIGHT || X c == ESC_END || c == ESC_DOWN || c == ESC_PGDN || X c == ESC_PLUS || c == ESC_MINUS ) X return( c ); X else X return( ESCAPE ); X } X X X return( c ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Init_Getc( argc, argv ) */ X/* */ X/* Give Getc() references to the command line */ X/* arguments. */ X/* */ X/****************************************************************/ X X X Xstatic int args_remaining; Xstatic char **args_pointer; Xstatic int args_index; X X X XInit_Getc( argc, argv ) X int argc; X char *argv[]; X X { X args_remaining = argc - 1; X args_pointer = &argv[1]; X args_index = 0; X } X X X X X X X X X/****************************************************************/ X/* */ X/* Getc() */ X/* */ X/* Get the next input character from the command */ X/* line if there is some more, else from stdin. */ X/* */ X/****************************************************************/ X X Xint Getc() X X { X int c; X X if ( args_remaining > 0 ) X if ( (c = args_pointer[ 0 ][ args_index++ ]) == '\0' ) X { X --args_remaining; X ++args_pointer; X args_index = 0; X X if ( args_remaining > 0 ) X return( '\n' ); X } X else X return( c ); X X return( getchar() ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Get_Base( character ) */ X/* */ X/* Return an appropriate base number for the */ X/* given character code. Used by 'i' and 'o'. */ X/* */ X/****************************************************************/ X X Xint Get_Base( code ) X char code; X X { X switch ( code ) X { X case 'h' : return( HEXADECIMAL ); X X case 'd' : return( DECIMAL ); X X case 'o' : return( OCTAL ); X X case 'b' : return( BINARY ); X X case 'a' : return( ASCII ); X X default : return( ERROR ); X } X } / echo x - ic_output.c gres '^X' '' > ic_output.c << '/' X/****************************************************************/ X/* */ X/* ic_output.c */ X/* */ X/* Output routines for the "Integer Calculator". */ X/* */ X/****************************************************************/ X/* origination 1988-Apr-6 T. Holm */ X/****************************************************************/ X X X X X#include X X#include "ic.h" X X X X X X X/****************************************************************/ X/* Code for handling termcap */ X/****************************************************************/ X X X#define TC_BUFFER 1024 /* Size of termcap(3) buffer */ X#define TC_STRINGS 200 /* Enough room for cm,cl,so,se */ X X X X Xstatic char *Tmove; /* (cm) - Format for tgoto */ Xstatic char *Tclr_all; /* (cl) - String to clear screen */ Xstatic char *Treverse; /* (so) - String to reverse mode */ Xstatic char *Tnormal; /* (se) - String to undo reverse */ X X X X X X X X/****************************************************************/ X/* */ X/* Init_Termcap() */ X/* */ X/* Initializes the external variables for the */ X/* current terminal. */ X/* */ X/* NULL is returned on error conditions. */ X/* */ X/****************************************************************/ X X XInit_Termcap() X { X char *term; X char buffer[ TC_BUFFER ]; X static char strings[ TC_STRINGS ]; X char *s = &strings[0]; X X term = getenv( "TERM" ); X X if ( term == NULL ) X return( NULL ); X X if ( tgetent( buffer, term ) != 1 ) X return( NULL ); X X X X if ( (Tmove=tgetstr( "cm", &s )) == NULL ) X return( NULL ); X X if ( (Tclr_all=tgetstr( "cl", &s )) == NULL ) X return( NULL ); X X if ( (Treverse=tgetstr( "so", &s )) == NULL ) X { X Treverse = s; X *s = '\0'; X ++s; X } X X if ( (Tnormal=tgetstr( "se", &s )) == NULL ) X { X Tnormal = s; X *s = '\0'; X ++s; X } X X return( EOF ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Move( column, line ) */ X/* */ X/* Use the termcap string to move the cursor. */ X/* */ X/****************************************************************/ X X XMove( column, line ) X int column; X int line; X X { X Puts( tgoto( Tmove, column, line ) ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Puts( string ) */ X/* */ X/* Write the given termcap string to the standard */ X/* output device. */ X/* */ X/****************************************************************/ X X XPuts( string ) X char *string; X X { X int Putchar(); X X tputs( string, 1, Putchar ); X } X X XPutchar( c ) X char c; X X { X putchar( c ); X } X X X X X X X X X/****************************************************************/ X/* Output routines */ X/****************************************************************/ X X X X X/****************************************************************/ X/* */ X/* Draw_Help_Screen() */ X/* */ X/****************************************************************/ X X XDraw_Help_Screen() X X { X Puts( Tclr_all ); /* Clear the screen */ X X printf( "\n\n " ); X Puts( Treverse ); X printf( "IC COMMANDS" ); X Puts( Tnormal ); X printf( "\n\n\n" ); X X printf( " h Help ENTER Push stack\n" ); X printf( " i Input base (h d o b) DEL Clear entry\n" ); X printf( " PGDN l Last top of stack\n" ); X printf( " m Minix shell . Change sign\n" ); X printf( " o Output base (h d o b a) + Add\n" ); X printf( " DOWN p Pop stack - Subtract\n" ); X printf( " END q Quit * Multiply\n" ); X printf( " LEFT r Recall (0-9) / Divide\n" ); X printf( " RIGHT s Store [+] (0-9) %% Remainder\n" ); X printf( " t Translate (char) ~ Not\n" ); X printf( " PGUP w Write top to scratch pad & And\n" ); X printf( " UP x Exchange top of stack | Or\n" ); X printf( " HOME z Zero all state ^ Exclusive-or\n\n\n" ); X X printf( "\n\nPress a key to continue..." ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Draw_Prompt( string ) */ X/* */ X/* Write a message in the "wait" area. */ X/* */ X/****************************************************************/ X X XDraw_Prompt( string ) X char *string; X X { X Move( WAIT_COLUMN, WAIT_LINE ); X X Puts( Treverse ); X printf( string ); X Puts( Tnormal ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Erase_Prompt() */ X/* */ X/* Erase the message in the "wait" area. */ X/* */ X/****************************************************************/ X XErase_Prompt() X X { X Move( WAIT_COLUMN, WAIT_LINE ); X X printf( " " ); X X Move( WAIT_COLUMN, WAIT_LINE ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Draw_Screen( state ) */ X/* */ X/* Redraw everything. */ X/* */ X/****************************************************************/ X X XDraw_Screen( s ) X ic_state *s; X X { X Puts( Tclr_all ); /* Clear the screen */ X X Draw_Stack( s ); X Draw_Registers( s ); X X X Move( STATUS_COLUMN, STATUS_LINE ); X X printf( "Input base = %2d ", s->input_base ); X X if ( s->output_base == ASCII ) X printf( "Output is ASCII " ); X else X printf( "Output base = %2d ", s->output_base ); X X if ( (int) s->scratch_pad != NULL ) X printf( "Scratch file = %s", s->file_name ); X X Move( WAIT_COLUMN, WAIT_LINE ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Draw_Stack( state ) */ X/* */ X/* Redraw the stack. */ X/* */ X/****************************************************************/ X X XDraw_Stack( s ) X ic_state *s; X X { X int i; X X for ( i = STACK_SIZE-1; i >= 0; --i ) X { X Move( STACK_COLUMN, STACK_LINE + STACK_SIZE - 1 - i ); X X if ( i >= s->stack_size ) X printf( "%*c", s->output_base == BINARY ? 32 : 17, ' ' ); X else X Print_Number( stdout, s->stack[i], s->output_base ); X } X X Move( WAIT_COLUMN, WAIT_LINE ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Draw_Registers( state ) */ X/* */ X/* Redraw the registers. Note that only registers */ X/* in use are displayed. A register only drops */ X/* out of use after a 'z' command, which will */ X/* explicitly clear the display, thus we never */ X/* have to "wipe off" a value, as the */ X/* Draw_Stack() routine must. */ X/* */ X/****************************************************************/ X X XDraw_Registers( s ) X ic_state *s; X X { X int i; X X for ( i = 0; i < REGISTERS; ++i ) X { X if ( (1 << i) & s->register_mask ) X { X Move( REG_COLUMN, REG_LINE + i ); X Print_Number( stdout, s->registers[i], s->output_base ); X printf( " (r%1d)", i ); X } X } X X Move( WAIT_COLUMN, WAIT_LINE ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Draw_Top_of_Stack( state ) */ X/* */ X/* Redraw only the entry on the top of the stack. */ X/* */ X/****************************************************************/ X X XDraw_Top_of_Stack( s ) X ic_state *s; X X { X Move( STACK_COLUMN, STACK_LINE + STACK_SIZE - 1 ); X X Print_Number( stdout, s->stack[0], s->output_base ); X X Move( WAIT_COLUMN, WAIT_LINE ); X } X X X X X X X X X/****************************************************************/ X/* */ X/* Print_Number( stream, number, output_base ) */ X/* */ X/* Output the "number" to "stream" in the */ X/* specified "output_base". */ X/* */ X/****************************************************************/ X X XPrint_Number( stream, number, output_base ) X FILE *stream; X long int number; X int output_base; X X { X switch ( output_base ) X { X case HEXADECIMAL : fprintf( stream, "%12X", number ); X break; X X X case DECIMAL : fprintf( stream, "%12D", number ); X break; X X X case OCTAL : fprintf( stream, "%12O", number ); X break; X X X case BINARY : { X unsigned long int mask; X char pad = ' '; X X for ( mask = 0x80000000; mask > 1; mask >>= 1 ) X putc( ( mask & number ) ? (pad = '0', '1') : pad, stream ); X X putc( ( 0x01 & number ) ? '1' : '0', stream ); X X break; X } X X X case ASCII : { X char c = number & 0x7f; X X if ( (number & ~ 0x7fL) == 0 ) X fprintf( stream, "%15c", ' ' ); X else X fprintf( stream, "%12X + ", number & ~ 0x7fL ); X X if ( c < ' ' ) X fprintf( stream, "^%c", c + '@' ); X else if ( c == ' ' ) X fprintf( stream, "sp" ); X else if ( c < 0x7f ) X fprintf( stream, " %c", c ); X else X fprintf( stream, "^?" ); X X break; X } X X default : fprintf( stderr, "Internal failure (output base)\n" ); X Sigint(); X } X } / -------------------------------------------------------------------- Edwin L. Froese (in London for the month) Terrence W. Holm {uw-beaver,ubc-cs}!uvicctr!sirius!tholm