#pragma extend

#define  RMXRET  int
#define  RMXOBJ  int
#include <rmx.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>

#define  FALSE   0
#define  TRUE    ~FALSE

int      ci_tkn, co_tkn, cmd_tkn, first, last_status;

char     *ffirst( char * ), *fnext();

/****************************************************************************/
/* explain_ccode_and_die - outputs explanation of erroneous condition code  */
/* and aborts execution                                                     */
/****************************************************************************/

const char whilel[]  = "while loading command";
const char whilee[]  = "while executing command";

void explain_ccode_and_die( int ccode, const char *msg )
    {
    int     status;
    char    buff[50];
        
    buff[0] = 0;
    rqcformatexception( buff, 50, ccode, 1, &status );

    if ( status != E_OK )
        sprintf( buff, "%04X: E$UNKNOWN$EXCEPTION", ccode );
    else
        (void)cstr( buff, buff );

    printf( "\n%s, %s\n", buff, msg );
    exit( ccode );
    }

/****************************************************************************/
/* execcmd - execute a single command                                       */
/****************************************************************************/

void execcmd( char *cmd )
    {
    int status, cmd_status;

    udistr( cmd, cmd );    
    rqcsendcommand( cmd_tkn, cmd, &cmd_status, &status );

    if ( ( status != E_OK ) && ( status != E_CONTINUED ) )
        explain_ccode_and_die( status, whilel );
    
    if ( cmd_status != E_OK )
        explain_ccode_and_die( cmd_status, whilee );

    last_status = status;
    }
                    
/****************************************************************************/
/* execcmds - executes command(s)                                           */
/****************************************************************************/

void execcmds( char *cmd )
    {
    char *this, *next;

    this = cmd;

    while ( ( next = strchr( this, '!' ) ) != NULL )
        {
        *next++ = '\0';
        execcmd( this );
        this = next;
        }
    
    execcmd( this );
    }

/****************************************************************************/
/* substitute - replaces occurrences of "%<subchar>" with "replacement"     */
/****************************************************************************/

void substitute( char *in_cmd, char subchar, char *replacement, char *out_cmd )
    {
    char *i, *o, *r, c;

    i = in_cmd;
    o = out_cmd;
    
    while ( ( c = *i++ ) != '\0' )
        {
        if ( ( c == '%' ) && ( *i == subchar ) )
            {
            i++;
            r = replacement;
            
            while ((c = *r++) != '\0')
                *o++ = c;
            }
        else
            *o++ = c;
        }

    *o = '\0';
    }

/****************************************************************************/
/* syntax - indicates syntax error, explains the proper syntax and exits    */
/****************************************************************************/

void syntax()
    {
    printf( "\n\nIMPROPER COMMAND SYNTAX !!!\n\n" );
    printf( "USE: for %%<c> in (<item>[ <item>]*) do <command> [!<command>]*\n\n" );
    exit( 0 );
    }

/****************************************************************************/
/* main                                                                     */
/****************************************************************************/

int main( int argc, char *argv[] )
    {
    char in_cmd[128], out_cmd[256], excp_info[5], *list[30], subchar,
         *filename, *l;
    int  status, first, success, index, lindex, indexx;

    excp_info[4] = NO_EXCEPTIONS;
    rqsetexceptionhandler( excp_info, &status );
    
    ci_tkn = rqcgetinputconnection( CONSOLE_INPUT_DEVICE, &status );

    if ( status == E_OK )
        co_tkn = rqcgetoutputconnection( CONSOLE_OUTPUT_DEVICE, OVER_PREPOSITION, &status );
    
    if ( status == E_OK )
        cmd_tkn = rqccreatecommandconnection( ci_tkn, co_tkn, 0, &status );
    
    if ( status != E_OK )
        explain_ccode_and_die( status, whilee );

    if ( argc < 6 )
        syntax();
    
    if (    ( strlen( argv[1] ) != 2 )
         || ( argv[1][0] != '%' )
         || ( strcmpi( argv[2], "in" ) != 0 )
         || ( argv[3][0] != '(' )               )
        syntax();
    
    subchar = argv[1][1];
    argv[3] = &argv[3][1];
    lindex = -1;
    index = 2;

    do
        {
        ++lindex;
        ++index;
        list[lindex] = argv[index];
        }
    while ( argv[index][strlen( argv[index] ) - 1] != ')' );
    
    argv[index][strlen( argv[index] ) - 1] = '\0';

    if ( strcmpi( argv[++index], "do" ) != 0 )
        syntax();
    
    strcpy( in_cmd, argv[++index] );
        
    for ( ++index; index < argc; index++ )
        {
        strcat( in_cmd, " " );
        strcat( in_cmd, argv[index] );
        }

    for ( index = 0; index <= lindex; index++ )
        {
        if (    ( strchr( list[index], '*' ) != NULL )
             || ( strchr( list[index], '?' ) != NULL ) )
            {
            filename = ffirst( list[index] );
            
            while ( filename != NULL )
                {
                substitute( in_cmd, subchar, filename, out_cmd );
                last_status = E_OK;
                execcmds( out_cmd );
               
                if ( last_status != E_OK )
                    explain_ccode_and_die( last_status, whilee ); 
               
                filename = fnext();
                }
            }
        else
            {
            l = list[index];
            while ( *l == ' ' ) l++;
            
            if (*l != '\0' )
                {
                substitute( in_cmd, subchar, list[index], out_cmd );
                execcmds( out_cmd );
                }
            }
        }
        
    exit( 0 );
    }

