📄 ioreadlines.c
字号:
// find the next non-space char while ( *pTemp && (*pTemp == ' ' || *pTemp == '\t') ) pTemp++; } else { // find the third token on the line (.mv + signal + nValues + ...) pTemp = pStr; // find the next space char while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' ) pTemp++; // find the next non-space char while ( *pTemp && (*pTemp == ' ' || *pTemp == '\t') ) pTemp++; // find the next space char while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' ) pTemp++; // find the next non-space char while ( *pTemp && (*pTemp == ' ' || *pTemp == '\t') ) pTemp++; } // return this position return pTemp;}/**Function************************************************************* Synopsis [Parses one .latch line.] Description [] SideEffects [] SeeAlso []***********************************************************************/int Io_ReadLinesDotLatch( Io_Read_t * p, Io_Latch_t * pIoLatch ){ char * pTemp; // set the current parsing line p->LineCur = pIoLatch->LineLatch; // skip the latch word pTemp = strtok( p->pLines[pIoLatch->LineLatch], " \t" ); assert( strcmp( pTemp, ".latch" ) == 0 ); // get the latch input pTemp = strtok( NULL, " \t" ); if ( pTemp == NULL ) { sprintf( p->sError, "The latch directive is incomplete." ); Io_ReadPrintErrorMessage( p ); return 1; } pIoLatch->pInputName = pTemp; // get the latch output pTemp = strtok( NULL, " \t" ); if ( pTemp == NULL ) { sprintf( p->sError, "The latch directive is incomplete." ); Io_ReadPrintErrorMessage( p ); return 1; } pIoLatch->pOutputName = pTemp; // get the reset value if it exists pTemp = strtok( NULL, " \t" ); if ( pTemp ) { pIoLatch->ResValue = atoi(pTemp); if ( pIoLatch->ResValue < 0 || pIoLatch->ResValue > 1 ) { sprintf( p->sError, "The latch reset value is invalid (%s).", pTemp ); Io_ReadPrintErrorMessage( p ); return 1; } } else pIoLatch->ResValue = -1; // get the pointer to the number of reset line // this number will be used to preparset the reset table later pIoLatch->IoNode.LineNames = -1; if ( p->tLatch2ResLine ) if ( !st_lookup( p->tLatch2ResLine, pIoLatch->pOutputName, (char**)&(pIoLatch->IoNode.LineNames) ) ) { p->LineCur = pIoLatch->LineLatch; sprintf( p->sError, "The latch \"%s\" does not have .reset line.", pIoLatch->pOutputName ); Io_ReadPrintErrorMessage( p ); return 1; } return 0;}/**Function************************************************************* Synopsis [Preparses the .res statement.] Description [] SideEffects [] SeeAlso []***********************************************************************/int Io_ReadLinesDotRes( Io_Read_t * p, int Line ){ char * pTemp; // get the latch output name (the last entry on .res line) pTemp = Io_ReadLinesLastEntry( p->pLines[Line] ); if ( pTemp[0] == '-' && pTemp[1] == '>' ) pTemp += 2; // hash latch output names into the beginning line of the reset table if ( p->tLatch2ResLine == NULL ) p->tLatch2ResLine = st_init_table(strcmp, st_strhash); if ( st_insert( p->tLatch2ResLine, pTemp, (char*)Line ) ) { sprintf( p->sError, "Latch \"%s\" has multiple reset lines.", pTemp ); Io_ReadPrintErrorMessage( p ); return 1; } p->nDotReses++; return 0;}/**Function************************************************************* Synopsis [Preparses the .node/.table/.res statement.] Description [] SideEffects [] SeeAlso []***********************************************************************/int Io_ReadLinesDotNode( Io_Read_t * p, Io_Node_t * pIoNode ){ char * pTemp, * pLine, * pLimit; int LineNext, nValues, i; Io_Var_t * pVar; // if the output identifier (->) appears on the .names line, remove it if ( pTemp = strstr( p->pLines[ pIoNode->LineNames ], "->" ) ) { pTemp[0] = ' '; pTemp[1] = ' '; } // get the output name as the last name on the .names line pIoNode->pOutput = Io_ReadLinesLastEntry( p->pLines[ pIoNode->LineNames ] ); // find the line after the .names/.table line pLimit = p->pLines[pIoNode->LineNames] + strlen( p->pLines[pIoNode->LineNames] ); for ( LineNext = pIoNode->LineNames + 1; p->pLines[LineNext] < pLimit; LineNext++ ); pLine = p->pLines[ LineNext ]; // process the .def line if present pIoNode->Default = -1; if ( pLine[0] == '.' && pLine[1] == 'd' && pLine[2] == 'e' && pLine[3] == 'f' ) { assert( p->nDotDefs > 0 ); // read the default value pTemp = strtok( pLine, " \t" ); pTemp = strtok( NULL, " \t" ); // first try to read the symbolic value if ( p->tName2Var && st_lookup( p->tName2Var, pIoNode->pOutput, (char**)&pVar ) ) { // try to find the symbol variable name for ( i = 0; i < pVar->nValues; i++ ) if ( strcmp( pVar->pValueNames[i], pTemp ) == 0 ) { pIoNode->Default = i; break; } if ( i == pVar->nValues ) { p->LineCur = LineNext; sprintf( p->sError, "No symbolic value for \"%s\" in the default line for node \"%s\".", pTemp, pIoNode->pOutput ); Io_ReadPrintErrorMessage( p ); return 1; } } else { if ( pTemp[0] < '0' || pTemp[0] > '9' ) { p->LineCur = LineNext; sprintf( p->sError, "Cannot read numeric value (%s) in the default line for node \"%s\".", pTemp, pIoNode->pOutput ); Io_ReadPrintErrorMessage( p ); return 1; } pIoNode->Default = atoi( pTemp ); if ( pIoNode->Default < 0 || pIoNode->Default > 32000 ) { p->LineCur = LineNext; sprintf( p->sError, "Default value (%s) is not correct.", pTemp ); Io_ReadPrintErrorMessage( p ); return 1; } } // go to the next line pLine = p->pLines[ ++LineNext ]; } // assign the first table line and count the lines pIoNode->LineTable = -1; pIoNode->nLines = 0; for ( ; *pLine != '.'; LineNext++, pLine = p->pLines[LineNext] ) if ( *pLine != '\0' ) { if ( pIoNode->LineTable == -1 ) pIoNode->LineTable = LineNext; pIoNode->nLines++; } // detect the file type if ( p->Type == IO_FILE_NONE ) p->Type = Io_ReadLinesDetectFileType( p, pIoNode ); // get the number of values if ( p->Type == IO_FILE_BLIF ) pIoNode->nValues = 2; else if ( p->Type == IO_FILE_BLIF_MVS ) pIoNode->nValues = strlen( Io_ReadLinesLastEntry( p->pLines[ pIoNode->LineTable ] ) ); else if ( p->Type == IO_FILE_BLIF_MV ) { // get the number of values if present in the table if ( p->tName2Values && st_lookup( p->tName2Values, pIoNode->pOutput, (char **)&nValues ) ) pIoNode->nValues = nValues; else pIoNode->nValues = 2; } else { assert( 0 ); } // update the largest number of values if ( p->nValuesMax < pIoNode->nValues ) p->nValuesMax = pIoNode->nValues; // set the pointer to the parent // this is useful to reduce the number of arguments passed in the procedures// pIoNode->p = p; return 0;}/**Function************************************************************* Synopsis [Returns the pointer to the last entry in the line.] Description [] SideEffects [] SeeAlso []***********************************************************************/char * Io_ReadLinesLastEntry( char * pStr ){ char * pTemp, * pEnd; pEnd = pStr + strlen(pStr) - 1; assert( *pEnd != ' ' && *pEnd != '\t' ); for ( pTemp = pEnd; *pTemp && *pTemp != ' ' && *pTemp != '\t'; pTemp-- ); return pTemp + 1;}/**Function************************************************************* Synopsis [Gracefully treats long lines.] Description [Removes the back slashes at the end of long lines and combines several 0-separated lines into one line, for smooth parsing of name lists.] SideEffects [] SeeAlso []***********************************************************************/void Io_ReadLinesRemoveExtenders( Io_Read_t * p, int Line ){ char * pLine, * pCur; while ( 1 ) { // make sure the next line exists assert( Line < p->nLines - 1 ); // get the next line pLine = p->pLines[ Line + 1 ]; // walk backward till the first non-space char for ( pCur = pLine - 1; *pCur == 0 || *pCur == ' ' || *pCur == '\t'; pCur-- ); // if this char is a backslash, walk forward and overwrite it with spaces if ( *pCur == '\\' ) { *pCur = ' '; for ( pCur++; *pCur == 0 || *pCur == ' ' || *pCur == '\n' || *pCur == '\t'; pCur++ ) *pCur = ' '; } else break; // go to the next line Line++; }}/**Function************************************************************* Synopsis [Adds the number of values to the table.] Description [] SideEffects [] SeeAlso []***********************************************************************/int Io_ReadLinesAddNumValues( Io_Read_t * p, char * pNodeName, int nValues ){ int * pnValuesCur; assert( nValues > 2 ); if ( p->tName2Values == NULL ) p->tName2Values = st_init_table(strcmp, st_strhash); if ( st_find_or_add( p->tName2Values, pNodeName, (char***)&pnValuesCur ) ) { if ( nValues != *pnValuesCur ) { sprintf( p->sError, "Node \"%s\" has with different number of values in different places (%d and %d).", pNodeName, nValues, *pnValuesCur ); Io_ReadPrintErrorMessage( p ); return 1; } } else // set the number of values *pnValuesCur = nValues; return 0;}/**Function************************************************************* Synopsis [Detects the file type using all the available info.] Description [Theoretically, this detector can be wrong if the following three conditions are true: (1) the input file is BLIF-MV (2) it is a binary file without .mv and .default directives (3) the first table of the first node has an output literal composed of several values, for example, {0,1}. I wonder if these three conditions will ever happen at the same time.] SideEffects [] SeeAlso []***********************************************************************/int Io_ReadLinesDetectFileType( Io_Read_t * p, Io_Node_t * pIoNode ){ // it is BLIF-MV if there are some obvious signs (.mv, .def, etc) if ( p->pDotMvs || p->nDotDefs ) return IO_FILE_BLIF_MV; // it is BLIF if the node has no table (and there is no default lines) if ( pIoNode->nLines == 0 ) return IO_FILE_BLIF; // it is BLIF-MVS if the last entry in the first line // of the table has more than one character if ( strlen( Io_ReadLinesLastEntry( p->pLines[ pIoNode->LineTable ] ) ) > 1 ) return IO_FILE_BLIF_MVS; return IO_FILE_BLIF;}/////////////////////////////////////////////////////////////////////////// END OF FILE ///////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -