diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c index bbe3b7d8e..aae2f47d8 100644 --- a/src/base/cmd/cmd.c +++ b/src/base/cmd/cmd.c @@ -98,6 +98,7 @@ void Cmd_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0 ); Cmd_CommandAdd( pAbc, "Basic", "abcrc", CmdCommandAbcrc, 0 ); Cmd_CommandAdd( pAbc, "Basic", "history", CmdCommandHistory, 0 ); + Cmd_CommandAdd( pAbc, "Basic", "hi", CmdCommandHistory, 0 ); Cmd_CommandAdd( pAbc, "Basic", "alias", CmdCommandAlias, 0 ); Cmd_CommandAdd( pAbc, "Basic", "unalias", CmdCommandUnalias, 0 ); Cmd_CommandAdd( pAbc, "Basic", "help", CmdCommandHelp, 0 ); @@ -441,38 +442,31 @@ int CmdCommandAbcrc( Abc_Frame_t * pAbc, int argc, char **argv ) int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) { char * pName, * pStr = NULL; - int i, c; + char ** ppMatches = NULL; + int * pIds = NULL; + int i; int nPrints = 20; int nPrinted = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default : - goto usage; - } - } - if ( argc > globalUtilOptind + 2 ) + if ( argc == 2 && !strcmp(argv[1], "-h") ) + goto usage; + if ( argc > 3 ) goto usage; // parse arguments: can be [substring] [number] in either order - if ( argc == globalUtilOptind + 1 ) + if ( argc == 2 ) { // one argument: either number or substring - pStr = argv[globalUtilOptind]; + pStr = argv[1]; if ( pStr && pStr[0] >= '1' && pStr[0] <= '9' ) { nPrints = atoi(pStr); pStr = NULL; } } - else if ( argc == globalUtilOptind + 2 ) + else if ( argc == 3 ) { // two arguments: substring and number - char * arg1 = argv[globalUtilOptind]; - char * arg2 = argv[globalUtilOptind + 1]; + char * arg1 = argv[1]; + char * arg2 = argv[2]; // Try to parse second argument as number if ( arg2[0] >= '1' && arg2[0] <= '9' ) @@ -500,14 +494,22 @@ int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) fprintf( pAbc->Out, "%4d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); } else { - // Search string provided, show up to nPrints matching entries - Vec_PtrForEachEntry( char *, pAbc->aHistory, pName, i ) + // Search string provided, select up to nPrints most recent matching entries + ppMatches = ABC_ALLOC( char *, nPrints ); + pIds = ABC_ALLOC( int, nPrints ); + Vec_PtrForEachEntryReverse( char *, pAbc->aHistory, pName, i ) if ( strstr(pName, pStr) ) { - fprintf( pAbc->Out, "%4d : %s\n", Vec_PtrSize(pAbc->aHistory)-i, pName ); + pIds[nPrinted] = Vec_PtrSize(pAbc->aHistory)-i; + ppMatches[nPrinted] = pName; if ( ++nPrinted >= nPrints ) break; } + // Print the selected entries in reverse so larger history indices appear first + for ( i = nPrinted - 1; i >= 0; i-- ) + fprintf( pAbc->Out, "%4d : %s\n", pIds[i], ppMatches[i] ); + ABC_FREE( pIds ); + ABC_FREE( ppMatches ); } return 0; diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c index e8e28078f..f0d8fc2dd 100644 --- a/src/base/cmd/cmdUtils.c +++ b/src/base/cmd/cmdUtils.c @@ -25,7 +25,6 @@ #include ABC_NAMESPACE_IMPL_START - // proper declaration of isspace //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -393,9 +392,51 @@ int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) ***********************************************************************/ char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed ) { - // as of today, no history substitution - *changed = 0; - return line; + char * pBeg = line, * pEnd, * pStr; + int iRecall, nSize; + while ( *pBeg && isspace((unsigned char)*pBeg) ) + pBeg++; + if ( *pBeg == 0 ) + { + *changed = 0; + return line; + } + pEnd = pBeg; + while ( *pEnd && !isspace((unsigned char)*pEnd) ) + pEnd++; + if ( *pEnd ) + { + char * pTemp = pEnd; + while ( *pTemp && isspace((unsigned char)*pTemp) ) + pTemp++; + if ( *pTemp ) + { + *changed = 0; + return line; + } + } + if ( *pBeg < '1' || *pBeg > '9' ) + { + *changed = 0; + return line; + } + for ( pStr = pBeg; pStr < pEnd; pStr++ ) + if ( *pStr < '0' || *pStr > '9' ) + { + *changed = 0; + return line; + } + iRecall = atoi( pBeg ); + nSize = Vec_PtrSize( pAbc->aHistory ); + if ( iRecall < 1 || iRecall > nSize ) + { + fprintf( pAbc->Err, "History entry %d does not exist.\n", iRecall ); + line[0] = 0; + *changed = 0; + return line; + } + *changed = 1; + return (char *)Vec_PtrEntry( pAbc->aHistory, nSize - iRecall ); } /**Function************************************************************* @@ -905,4 +946,3 @@ void Cmd_CommandSGen( Abc_Frame_t * pAbc, int nParts, int nIters, int fVerbose ) /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END - diff --git a/src/base/main/mainReal.c b/src/base/main/mainReal.c index 3c5d67b3f..9589d5239 100644 --- a/src/base/main/mainReal.c +++ b/src/base/main/mainReal.c @@ -56,6 +56,7 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. #endif #include "base/abc/abc.h" +#include "base/cmd/cmdInt.h" #include "mainInt.h" #include "base/wlc/wlc.h" @@ -363,9 +364,15 @@ int Abc_RealMain( int argc, char * argv[] ) // execute commands given by the user while ( !feof(stdin) ) { + int did_subst; // print command line prompt and // get the command from the user sCommand = Abc_UtilsGetUsersInput( pAbc ); + sCommand = CmdHistorySubstitution( pAbc, sCommand, &did_subst ); + if ( sCommand == NULL ) + break; + if ( did_subst ) + fprintf( pAbc->Out, "%s\n", sCommand ); // execute the user's command fStatus = Cmd_CommandExecute( pAbc, sCommand );