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

        scheduler_printer.c

        Read Appendix D in order to understand how to use this routine.
        The routine can be used as is, or you can simplify it to more
        easily fit in with your OS502 code.

        Revision History:
                1.1    December 1990    Initial release
****************************************************************************/

#include                 "global.h"
#include                 "syscalls.h"
#include                 "z502.h"
#include                 "protos.h"
#include                 "stdio.h"
#include                 "string.h"

INT16           SP_target_pid = -1;
INT16           SP_pid_states[SP_NUMBER_OF_STATES][SP_MAX_NUMBER_OF_PIDS];
INT16           SP_number_of_pids[] = { 0, 0, 0, 0, 0, 0, 0 };
INT32           SP_time = -1;
char            SP_action[ SP_LENGTH_OF_ACTION + 1 ] = { '\0' };
INT16           SP_file_mode_given = 0;

FILE            *SP_file_ptr;

char            *mode_name[] = {"NEW:", "RUNNING:", "READY  :", 
                        "WAITING:", "SUSPEND:", "SWAPPED:", "TERMINATED:" };

void            SP_do_output( char * );


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

        SP_setup_file

        This routine allows the caller to set up information showing that
        data should be placed in a file.

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

void SP_setup_file( INT16 mode, FILE *data )
    {
    if ( mode != SP_FILE_MODE )
        {
        printf( "Illegal mode specified in SP_setup_file.\n" );
        return;
    }
    SP_file_mode_given = 1;
    SP_file_ptr        = data;
}


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

        SP_setup_action

        This routine allows the caller to set up a string indicating
        the action that will be performed.

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

void SP_setup_action( INT16 mode, char *data )
    {
    if ( mode != SP_ACTION_MODE )
        {
        printf( "Illegal mode specified in SP_setup_action.\n" );
        return;
    }
    if ( strlen( data) > SP_LENGTH_OF_ACTION )
        {
        printf( "Illegal ACTION entered in SP_setup.\n" );
        return;
    }
    (void)strncpy( SP_action, data, SP_LENGTH_OF_ACTION);
}

/****************************************************************************

        SP_setup

        This routine allows the caller to set up all the information
        that will eventually be printed.
        NOTE: The type of data passed in here depends on the mode specified.

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

void SP_setup( INT16 mode, INT32 data )
    {
    INT16       index;

    switch( mode )
        {
        case SP_TIME_MODE:      
                        if ( data < 0 )
                            {
                            printf( "Illegal TIME entered in SP_setup.\n" );
                            return;
                        }
                        SP_time            = (INT32)data % 100000L;
                        break;
        case SP_TARGET_MODE:
                        if ( data < 0 || data > 99 )
                            {
                            printf( "Illegal PID entered in SP_setup.\n" );
                            return;
                        }
                            
                        SP_target_pid      = (INT16)data;
                        break;
        case SP_NEW_MODE:       
        case SP_READY_MODE:   
        case SP_RUNNING_MODE:
        case SP_WAITING_MODE:
        case SP_SUSPENDED_MODE:
        case SP_SWAPPED_MODE: 
        case SP_TERMINATED_MODE:   
                        if ( data < 0 || data > 99 )
                            {
                            printf( "Illegal PID entered in SP_setup.\n" );
                            return;
                        }
                        index = SP_number_of_pids[mode - SP_STATE_MODE_START];
                        if ( index >= SP_MAX_NUMBER_OF_PIDS )
                            {
                            printf( "Too many PIDs for this mode " );
                            printf( "entered in SP_setup.\n" );
                            return;
                        }
                        SP_pid_states[mode - SP_NEW_MODE][index] 
                                                        = (INT16)data;
                        SP_number_of_pids[ mode - SP_STATE_MODE_START ]++;
                        break;
        default:        printf( "ERROR - illegal mode to SP_setup\n" );
    }

}                                               /* End of SP_setup      */

/****************************************************************************

        SP_print_header

        SP_print_header prints the line of text that is defined in the 
        include file. 

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

void    SP_print_header( void )
    {
    SP_do_output( SP_HEADER_STRING );

}                                               /* End of SP_print_header*/


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

        SP_print_line

        SP_print_line prints out all the data that has been sent to the 
        routine via various SP_setup commands. After the print is complete, 
        the setup data  ( except file_ptr ) is deleted.   

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


void    SP_print_line( void )
    {
    char        output_line[400];
    char        temp[12];
    INT16       index;
    INT16       ind;
    INT16       pos;
    BOOL        mode_print_done;


    sprintf( output_line, "%5ld", SP_time );             /* Time         */
    if ( SP_time == -1 )
        sprintf( output_line, "%s", "     " );

    sprintf( temp, " %3d ", SP_target_pid );            /* Target Pid   */
    if ( SP_target_pid < 0 )
        sprintf( temp, "%s", "     " );
    (void)strcat( output_line, temp );

    sprintf( temp, "  %8s", SP_action );                 /* Action       */
    (void)strcat( output_line, temp );

    index = SP_RUNNING_MODE - SP_STATE_MODE_START;      /* Running proc.*/
    if ( SP_number_of_pids[ index ] > 0 )
        sprintf( temp, " %3d", SP_pid_states[index][0] );
    else
        sprintf( temp, "    " );
    (void)strcat( output_line, temp );

    index = SP_NEW_MODE - SP_STATE_MODE_START;          /* New proc.*/
    if ( SP_number_of_pids[ index ] > 0 )
        sprintf( temp, " %3d ", SP_pid_states[index][0] );
    else
        sprintf( temp, "    " );
    (void)strcat( output_line, temp );

    index = SP_TERMINATED_MODE - SP_STATE_MODE_START;   /* Done proc.*/
    if ( SP_number_of_pids[ index ] > 0 )
        sprintf( temp, "%3d ", SP_pid_states[index][0] );
    else
        sprintf( temp, "     " );
    (void)strcat( output_line, temp );
    SP_do_output( output_line );
    strcpy( output_line, "" );

    mode_print_done = FALSE;
    for ( ind = SP_READY_MODE; ind <= SP_SWAPPED_MODE; ind++ )
        {
        index = ind - SP_STATE_MODE_START;
        if ( SP_number_of_pids[ index ] > 0 )
            {
            (void)strcat( output_line, mode_name[ index ] );
            for (pos = 0; pos < SP_number_of_pids[index]; pos++ )
                {
                sprintf( temp, " %d", SP_pid_states[index][pos] );
                (void)strcat( output_line, temp );
            }
            mode_print_done = TRUE;
            (void)strcat( output_line, "\n" );
            SP_do_output( output_line );
            strcpy( output_line, "                                 " );
        }                                               /* End of if */
    }                                                   /* End of for*/
    if ( mode_print_done == FALSE )
        SP_do_output( "\n" );

    /*                  Initialize everything                           */

    SP_time = -1;
    strcpy( SP_action, "" );
    SP_target_pid = -1;
    for ( index = 0 ; index <= SP_TERMINATED_MODE - SP_NEW_MODE; index++ )
        SP_number_of_pids[ index ] = 0;

}                                               /* End of SP_print_line */

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

        SP_do_output

        This little routine simply directs output either to a file or
        to the terminal.

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

void    SP_do_output( char *text )
    {
    if (SP_file_mode_given)
        fprintf( SP_file_ptr, "%s", text );
    else
        printf( "%s", text );
}                                               /* End of SP_do_output */
