| /**CFile**************************************************************** |
| |
| FileName [cmdPlugin.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Command processing package.] |
| |
| Synopsis [Integrating external binary.] |
| |
| Author [Alan Mishchenko, Niklas Een] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - September 29, 2010.] |
| |
| Revision [$Id: cmdPlugin.c,v 1.00 2010/09/29 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #ifdef WIN32 |
| #include <io.h> |
| #include <process.h> |
| #else |
| #include <unistd.h> |
| #endif |
| |
| #include "base/abc/abc.h" |
| #include "base/main/mainInt.h" |
| #include "cmd.h" |
| #include "cmdInt.h" |
| #include "misc/util/utilSignal.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /* |
| |
| -------- Original Message -------- |
| Subject: ABC/ZZ integration |
| Date: Wed, 29 Sep 2010 00:34:32 -0700 |
| From: Niklas Een <niklas@een.se> |
| To: Alan Mishchenko <alanmi@EECS.Berkeley.EDU> |
| |
| Hi Alan, |
| |
| Since the interface is file-based, it is important that we generate |
| good, unique filenames (we may run multiple instances of ABC in the |
| same directory), so I have attached some portable code for doing that |
| (tmpFile.c). You can integrate it appropriately. |
| |
| This is how my interface is meant to work: |
| |
| (1) As part of your call to Bip, give it first argument "-abc". |
| This will alter Bip's behavior slightly. |
| |
| (2) To list the commands, call 'bip -list-commands'. |
| My commands begin with a comma (so that's my prefix). |
| |
| (3) All commands expect an input file and an output file. |
| The input file should be in AIGER format. |
| The output will be a text file. |
| Example: |
| bip -input=tmp.aig -output=tmp.out ,pdr -check -prop=5 |
| |
| So you just auto-generate the two temporary files (output file is |
| closed and left empty) and stitch the ABC command line at the end. |
| All you need to check for is if the ABC line begins with a comma. |
| |
| (4) The result written to the output file will contain a number |
| of object. Each object is on a separate line of the form: |
| |
| <object name>: <object data> |
| |
| That is: name, colon, space, data, newline. If you see a name you don't |
| recognize, just skip that line (so you will ignore future extensions by me). |
| I currently define the following objects: |
| |
| result: |
| counter-example: |
| proof-invariant: |
| bug-free-depth: |
| abstraction: |
| |
| "result:" is one of "proved", "failed", "undetermined" (=reached resource limit), "error" |
| (only used by the abstraction command, and only if resource limit was so tight that the |
| abstraction was still empty -- no abstraction is returned in this special case). |
| |
| "counter-example:" -- same format as before |
| |
| "proof-invariant:" contains an text-encoded single-output AIG. If you want |
| you can parse it and validate the invariant. |
| |
| "bug-free-depth:" the depth up to which the procedure has checked for counter-example. |
| Starts at -1 (not even the initial states have been verified). |
| |
| "abstraction:" -- same format as before |
| |
| (5) I propose that you add a command "load_plugin <path/binary>". That way Bob can put |
| Bip where ever he likes and just modify his abc_rc file. |
| |
| The intention is that ABC can read this file and act on it without knowing what |
| particular command was used. If there is an abstraction, you will always apply it. |
| If there is a "bug-free-depth" you will store that data somewhere so that Bob can query |
| it through the Python interface, and so on. If we need different actions for different |
| command, then we add a new object for the new action. |
| |
| // N. |
| |
| */ |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Abc_GetBinaryName( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| char * pTemp; |
| int i; |
| Vec_PtrForEachEntry( char *, pAbc->vPlugInComBinPairs, pTemp, i ) |
| { |
| i++; |
| if ( strcmp( pTemp, argv[0] ) == 0 ) |
| return (char *)Vec_PtrEntry( pAbc->vPlugInComBinPairs, i ); |
| } |
| assert( 0 ); |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Read flop map.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Abc_ManReadFile( char * pFileName ) |
| { |
| FILE * pFile; |
| Vec_Str_t * vStr; |
| int c; |
| pFile = fopen( pFileName, "r" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open file \"%s\".\n", pFileName ); |
| return NULL; |
| } |
| vStr = Vec_StrAlloc( 100 ); |
| while ( (c = fgetc(pFile)) != EOF ) |
| Vec_StrPush( vStr, (char)c ); |
| Vec_StrPush( vStr, '\0' ); |
| fclose( pFile ); |
| return vStr; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Read flop map.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Abc_ManReadBinary( char * pFileName, char * pToken ) |
| { |
| Vec_Int_t * vMap = NULL; |
| Vec_Str_t * vStr; |
| char * pStr; |
| int i, Length; |
| vStr = Abc_ManReadFile( pFileName ); |
| if ( vStr == NULL ) |
| return NULL; |
| pStr = Vec_StrArray( vStr ); |
| pStr = strstr( pStr, pToken ); |
| if ( pStr != NULL ) |
| { |
| pStr += strlen( pToken ); |
| vMap = Vec_IntAlloc( 100 ); |
| Length = strlen( pStr ); |
| for ( i = 0; i < Length; i++ ) |
| { |
| if ( pStr[i] == '0' || pStr[i] == '?' ) |
| Vec_IntPush( vMap, 0 ); |
| else if ( pStr[i] == '1' ) |
| Vec_IntPush( vMap, 1 ); |
| if ( ('a' <= pStr[i] && pStr[i] <= 'z') || |
| ('A' <= pStr[i] && pStr[i] <= 'Z') ) |
| break; |
| } |
| } |
| Vec_StrFree( vStr ); |
| return vMap; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Read flop map.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ManReadInteger( char * pFileName, char * pToken ) |
| { |
| int Result = -1; |
| Vec_Str_t * vStr; |
| char * pStr; |
| vStr = Abc_ManReadFile( pFileName ); |
| if ( vStr == NULL ) |
| return -1; |
| pStr = Vec_StrArray( vStr ); |
| pStr = strstr( pStr, pToken ); |
| if ( pStr != NULL ) |
| Result = atoi( pStr + strlen(pToken) ); |
| Vec_StrFree( vStr ); |
| return Result; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Read flop map.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ManReadStatus( char * pFileName, char * pToken ) |
| { |
| int Result = -1; |
| Vec_Str_t * vStr; |
| char * pStr; |
| vStr = Abc_ManReadFile( pFileName ); |
| if ( vStr == NULL ) |
| return -1; |
| pStr = Vec_StrArray( vStr ); |
| pStr = strstr( pStr, pToken ); |
| if ( pStr != NULL ) |
| { |
| if ( strncmp(pStr+8, "proved", 6) == 0 ) |
| Result = 1; |
| else if ( strncmp(pStr+8, "failed", 6) == 0 ) |
| Result = 0; |
| } |
| Vec_StrFree( vStr ); |
| return Result; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Work-around to insert 0s for PIs without fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Abc_ManExpandCex( Gia_Man_t * pGia, Vec_Int_t * vCex ) |
| { |
| Vec_Int_t * vCexNew; |
| Gia_Obj_t * pObj; |
| int i, k; |
| |
| // start with register outputs |
| vCexNew = Vec_IntAlloc( Vec_IntSize(vCex) ); |
| Gia_ManForEachRo( pGia, pObj, i ) |
| Vec_IntPush( vCexNew, 0 ); |
| |
| ABC_FREE( pGia->pRefs ); |
| Gia_ManCreateRefs( pGia ); |
| k = Gia_ManRegNum( pGia ); |
| while ( 1 ) |
| { |
| Gia_ManForEachPi( pGia, pObj, i ) |
| { |
| if ( Gia_ObjRefNum(pGia, pObj) == 0 ) |
| Vec_IntPush( vCexNew, 0 ); |
| else |
| { |
| if ( k == Vec_IntSize(vCex) ) |
| break; |
| Vec_IntPush( vCexNew, Vec_IntEntry(vCex, k++) ); |
| } |
| } |
| if ( k == Vec_IntSize(vCex) ) |
| break; |
| } |
| return vCexNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Procedure to convert the AIG from text into binary form.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static unsigned textToBin(char* text, unsigned long text_sz) |
| { |
| char* dst = text; |
| const char* src = text; |
| unsigned sz, i; |
| sscanf(src, "%u ", &sz); |
| while(*src++ != ' '); |
| for ( i = 0; i < sz; i += 3 ) |
| { |
| dst[0] = (char)( (unsigned)src[0] - '0') | (((unsigned)src[1] - '0') << 6); |
| dst[1] = (char)(((unsigned)src[1] - '0') >> 2) | (((unsigned)src[2] - '0') << 4); |
| dst[2] = (char)(((unsigned)src[2] - '0') >> 4) | (((unsigned)src[3] - '0') << 2); |
| src += 4; |
| dst += 3; |
| } |
| return sz; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives AIG from the text string in the file.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Gia_Man_t * Abc_ManReadAig( char * pFileName, char * pToken ) |
| { |
| Gia_Man_t * pGia = NULL; |
| unsigned nBinaryPart; |
| Vec_Str_t * vStr; |
| char * pStr, * pEnd; |
| vStr = Abc_ManReadFile( pFileName ); |
| if ( vStr == NULL ) |
| return NULL; |
| pStr = Vec_StrArray( vStr ); |
| pStr = strstr( pStr, pToken ); |
| if ( pStr != NULL ) |
| { |
| // skip token |
| pStr += strlen(pToken); |
| // skip spaces |
| while ( *pStr == ' ' ) |
| pStr++; |
| // set the end at newline |
| for ( pEnd = pStr; *pEnd; pEnd++ ) |
| if ( *pEnd == '\r' || *pEnd == '\n' ) |
| { |
| *pEnd = 0; |
| break; |
| } |
| // convert into binary AIGER |
| nBinaryPart = textToBin( pStr, strlen(pStr) ); |
| // dump it into file |
| if ( 0 ) |
| { |
| FILE * pFile = fopen( "test.aig", "wb" ); |
| fwrite( pStr, 1, nBinaryPart, pFile ); |
| fclose( pFile ); |
| } |
| // derive AIG |
| pGia = Gia_AigerReadFromMemory( pStr, nBinaryPart, 0, 0, 0 ); |
| } |
| Vec_StrFree( vStr ); |
| return pGia; |
| |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cmd_CommandAbcPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| char * pFileIn, * pFileOut; |
| Vec_Str_t * vCommand; |
| Vec_Int_t * vCex; |
| FILE * pFile; |
| Gia_Man_t * pGia; |
| int i, fd; |
| abctime clk; |
| int fLeaveFiles; |
| /* |
| Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); |
| if ( pNtk == NULL ) |
| { |
| Abc_Print( -1, "Current network does not exist\n" ); |
| return 1; |
| } |
| if ( !Abc_NtkIsStrash( pNtk) ) |
| { |
| Abc_Print( -1, "The current network is not an AIG. Cannot continue.\n" ); |
| return 1; |
| } |
| */ |
| |
| if ( pAbc->pGia == NULL ) |
| { |
| if (argc == 2 && strcmp(argv[1], "-h") == 0) |
| { |
| // Run command to produce help string: |
| vCommand = Vec_StrAlloc( 100 ); |
| Vec_StrAppend( vCommand, Abc_GetBinaryName( pAbc, argc, argv ) ); |
| Vec_StrAppend( vCommand, " -abc " ); |
| Vec_StrAppend( vCommand, argv[0] ); |
| Vec_StrAppend( vCommand, " -h" ); |
| Vec_StrPush( vCommand, 0 ); |
| Util_SignalSystem( Vec_StrArray(vCommand) ); |
| Vec_StrFree( vCommand ); |
| } |
| else |
| { |
| Abc_Print( -1, "Current AIG does not exist (try command &ps).\n" ); |
| } |
| return 1; |
| } |
| |
| // create temp file |
| fd = Util_SignalTmpFile( "__abctmp_", ".aig", &pFileIn ); |
| if ( fd == -1 ) |
| { |
| Abc_Print( -1, "Cannot create a temporary file.\n" ); |
| return 1; |
| } |
| #ifdef WIN32 |
| _close( fd ); |
| #else |
| close( fd ); |
| #endif |
| |
| // create temp file |
| fd = Util_SignalTmpFile( "__abctmp_", ".out", &pFileOut ); |
| if ( fd == -1 ) |
| { |
| ABC_FREE( pFileIn ); |
| Abc_Print( -1, "Cannot create a temporary file.\n" ); |
| return 1; |
| } |
| #ifdef WIN32 |
| _close( fd ); |
| #else |
| close( fd ); |
| #endif |
| |
| |
| // write current network into a file |
| /* |
| { |
| extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); |
| Aig_Man_t * pAig; |
| pAig = Abc_NtkToDar( pNtk, 0, 1 ); |
| Ioa_WriteAiger( pAig, pFileIn, 0, 0 ); |
| Aig_ManStop( pAig ); |
| } |
| */ |
| // check what to do with the files |
| fLeaveFiles = 0; |
| if ( strcmp( argv[argc-1], "!" ) == 0 ) |
| { |
| Abc_Print( 0, "Input file \"%s\" and output file \"%s\" are not deleted.\n", pFileIn, pFileOut ); |
| fLeaveFiles = 1; |
| argc--; |
| } |
| |
| // create input file |
| Gia_AigerWrite( pAbc->pGia, pFileIn, 0, 0 ); |
| |
| // create command line |
| vCommand = Vec_StrAlloc( 100 ); |
| Vec_StrAppend( vCommand, Abc_GetBinaryName( pAbc, argc, argv ) ); |
| // add input/output file |
| Vec_StrAppend( vCommand, " -abc" ); |
| // Vec_StrAppend( vCommand, " -input=C:/_projects/abc/_TEST/hwmcc/139442p0.aig" ); |
| Vec_StrAppend( vCommand, " -input=" ); |
| Vec_StrAppend( vCommand, pFileIn ); |
| Vec_StrAppend( vCommand, " -output=" ); |
| Vec_StrAppend( vCommand, pFileOut ); |
| // add other arguments |
| for ( i = 0; i < argc; i++ ) |
| { |
| Vec_StrAppend( vCommand, " " ); |
| Vec_StrAppend( vCommand, argv[i] ); |
| } |
| Vec_StrPush( vCommand, 0 ); |
| |
| // run the command line |
| //printf( "Running command line: %s\n", Vec_StrArray(vCommand) ); |
| |
| clk = Abc_Clock(); |
| if ( Util_SignalSystem( Vec_StrArray(vCommand) ) ) |
| { |
| Abc_Print( -1, "The following command has returned non-zero exit status:\n" ); |
| Abc_Print( -1, "\"%s\"\n", Vec_StrArray(vCommand) ); |
| return 1; |
| } |
| clk = Abc_Clock() - clk; |
| Vec_StrFree( vCommand ); |
| |
| // check if the output file exists |
| if ( (pFile = fopen( pFileOut, "r" )) == NULL ) |
| { |
| Abc_Print( -1, "There is no output file \"%s\".\n", pFileOut ); |
| return 1; |
| } |
| fclose( pFile ); |
| |
| // process the output |
| if ( Extra_FileSize(pFileOut) > 0 ) |
| { |
| // get status |
| pAbc->Status = Abc_ManReadStatus( pFileOut, "result:" ); |
| // get bug-free depth |
| pAbc->nFrames = Abc_ManReadInteger( pFileOut, "bug-free-depth:" ); |
| // get abstraction |
| pAbc->pGia->vFlopClasses = Abc_ManReadBinary( pFileOut, "abstraction:" ); |
| // get counter-example |
| vCex = Abc_ManReadBinary( pFileOut, "counter-example:" ); |
| if ( vCex ) |
| { |
| int nFrames, nRemain; |
| |
| nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia); |
| nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia); |
| if ( nRemain != 0 ) |
| { |
| Vec_Int_t * vTemp; |
| Abc_Print( 1, "Adjusting counter-example by adding zeros for PIs without fanout.\n" ); |
| // expand the counter-example to include PIs without fanout |
| vCex = Abc_ManExpandCex( pAbc->pGia, vTemp = vCex ); |
| Vec_IntFree( vTemp ); |
| } |
| |
| nFrames = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) / Gia_ManPiNum(pAbc->pGia); |
| nRemain = (Vec_IntSize(vCex) - Gia_ManRegNum(pAbc->pGia)) % Gia_ManPiNum(pAbc->pGia); |
| if ( nRemain != 0 ) |
| Abc_Print( 1, "Counter example has a wrong length.\n" ); |
| else |
| { |
| Abc_Print( 1, "Problem is satisfiable. Found counter-example in frame %d. ", nFrames-1 ); |
| Abc_PrintTime( 1, "Time", clk ); |
| ABC_FREE( pAbc->pCex ); |
| pAbc->pCex = Abc_CexCreate( Gia_ManRegNum(pAbc->pGia), Gia_ManPiNum(pAbc->pGia), Vec_IntArray(vCex), nFrames-1, 0, 0 ); |
| |
| // Abc_CexPrint( pAbc->pCex ); |
| |
| // if ( !Gia_ManVerifyCex( pAbc->pGia, pAbc->pCex, 0 ) ) |
| // Abc_Print( 1, "Generated counter-example is INVALID.\n" ); |
| |
| // remporary work-around to detect the output number - October 18, 2010 |
| pAbc->pCex->iPo = Gia_ManFindFailedPoCex( pAbc->pGia, pAbc->pCex, 0 ); |
| if ( pAbc->pCex->iPo == -1 ) |
| { |
| Abc_Print( 1, "Generated counter-example is INVALID.\n" ); |
| ABC_FREE( pAbc->pCex ); |
| } |
| else |
| { |
| Abc_Print( 1, "Returned counter-example successfully verified in ABC.\n" ); |
| } |
| } |
| Vec_IntFreeP( &vCex ); |
| } |
| // get AIG if present |
| pGia = Abc_ManReadAig( pFileOut, "aig:" ); |
| if ( pGia != NULL ) |
| { |
| Gia_ManStopP( &pAbc->pGia ); |
| pAbc->pGia = pGia; |
| } |
| } |
| |
| // clean up |
| Util_SignalTmpFileRemove( pFileIn, fLeaveFiles ); |
| Util_SignalTmpFileRemove( pFileOut, fLeaveFiles ); |
| |
| ABC_FREE( pFileIn ); |
| ABC_FREE( pFileOut ); |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cmd_CommandAbcLoadPlugIn( Abc_Frame_t * pAbc, int argc, char ** argv ) |
| { |
| int fPath, fVerbose; |
| int fd = -1, RetValue = -1, c; |
| FILE * pFile = NULL; |
| char * pStrDirBin = NULL, * pStrSection = NULL; |
| Vec_Str_t * sCommandLine = NULL; |
| char * pTempFile = NULL; |
| char pBuffer[1000]; |
| |
| // set defaults |
| fPath = 0; |
| fVerbose = 0; |
| |
| Extra_UtilGetoptReset(); |
| while ( ( c = Extra_UtilGetopt( argc, argv, "vph" ) ) != EOF ) |
| { |
| switch ( c ) |
| { |
| case 'p': |
| fPath ^= 1; |
| break; |
| case 'v': |
| fVerbose ^= 1; |
| break; |
| default: |
| goto usage; |
| } |
| } |
| |
| if ( argc != globalUtilOptind + 2 ) |
| goto usage; |
| |
| pStrDirBin = argv[argc-2]; |
| pStrSection = argv[argc-1]; |
| |
| // check if the file exists |
| if ( !fPath ) |
| { |
| FILE* pFile = fopen( pStrDirBin, "r" ); |
| |
| if ( !pFile ) |
| { |
| Abc_Print( ABC_ERROR, "Cannot run the binary \"%s\". File does not exist.\n", pStrDirBin ); |
| goto cleanup; |
| } |
| |
| fclose( pFile ); |
| } |
| |
| // create temp file |
| fd = Util_SignalTmpFile( "__abctmp_", ".txt", &pTempFile ); |
| |
| if ( fd == -1 ) |
| { |
| Abc_Print( ABC_ERROR, "Cannot create a temporary file.\n" ); |
| goto cleanup; |
| } |
| |
| #ifdef WIN32 |
| _close( fd ); |
| #else |
| close( fd ); |
| #endif |
| |
| // get command list |
| sCommandLine = Vec_StrAlloc(1000); |
| |
| Vec_StrPrintF(sCommandLine, "%s -abc -list-commands > %s", pStrDirBin, pTempFile ); |
| Vec_StrPush(sCommandLine, '\0'); |
| |
| if(fVerbose) |
| { |
| Abc_Print(ABC_VERBOSE, "Running command %s\n", Vec_StrArray(sCommandLine)); |
| } |
| |
| RetValue = Util_SignalSystem( Vec_StrArray(sCommandLine) ); |
| |
| if ( RetValue != 0 ) |
| { |
| Abc_Print( ABC_ERROR, "Command \"%s\" failed.\n", Vec_StrArray(sCommandLine) ); |
| goto cleanup; |
| } |
| |
| // create commands |
| pFile = fopen( pTempFile, "r" ); |
| |
| if ( pFile == NULL ) |
| { |
| Abc_Print( -1, "Cannot open file with the list of commands.\n" ); |
| |
| RetValue = -1; |
| goto cleanup; |
| } |
| |
| while ( fgets( pBuffer, 1000, pFile ) != NULL ) |
| { |
| if ( pBuffer[strlen(pBuffer)-1] == '\n' ) |
| pBuffer[strlen(pBuffer)-1] = 0; |
| |
| Cmd_CommandAdd( pAbc, pStrSection, pBuffer, Cmd_CommandAbcPlugIn, 1 ); |
| |
| Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pBuffer) ); |
| Vec_PtrPush( pAbc->vPlugInComBinPairs, Extra_UtilStrsav(pStrDirBin) ); |
| |
| if ( fVerbose ) |
| { |
| Abc_Print(ABC_VERBOSE, "Creating command %s with binary %s\n", pBuffer, pStrDirBin); |
| } |
| } |
| |
| cleanup: |
| |
| if( pFile ) |
| fclose( pFile ); |
| |
| if( pTempFile ) |
| Util_SignalTmpFileRemove( pTempFile, 0 ); |
| |
| Vec_StrFreeP(&sCommandLine); |
| |
| ABC_FREE( pTempFile ); |
| |
| return RetValue; |
| |
| usage: |
| |
| Abc_Print( -2, "usage: load_plugin [-pvh] <plugin_dir\\binary_name> <section_name>\n" ); |
| Abc_Print( -2, "\t loads external binary as a plugin\n" ); |
| Abc_Print( -2, "\t-p : toggle searching the command in PATH [default = %s].\n", fPath? "yes": "no" ); |
| Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); |
| Abc_Print( -2, "\t-h : print the command usage\n"); |
| |
| return 1; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |