From 306b80c1cf9ab490a83b36d3e7cf07e09f9e5d68 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sat, 15 May 2010 07:44:10 +0000 Subject: mkunit.sh was a little dumb, it didn't handle a number of things correctly. I've written a new program that basically does the same thing, only it's much more clever, and does many more of the translations and conversions better, including the #line directives. Also, I dropped nids, we don't need it anymore. But now I'm ready to write some serious tests for myriad. --- src/tools/mkunit.cpp | 547 +++++++++++++++++++++++++++++++++++++++++++++++++ src/tools/nidstool.cpp | 248 ---------------------- 2 files changed, 547 insertions(+), 248 deletions(-) create mode 100644 src/tools/mkunit.cpp delete mode 100644 src/tools/nidstool.cpp (limited to 'src/tools') diff --git a/src/tools/mkunit.cpp b/src/tools/mkunit.cpp new file mode 100644 index 0000000..43fab38 --- /dev/null +++ b/src/tools/mkunit.cpp @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#include +#include + +using namespace Bu; + +class Test +{ +public: + Test() : + bExpectPass( true ) + { + } + + Bu::FString sName; + bool bExpectPass; +}; +typedef Bu::List TestList; + +class Suite +{ +public: + Bu::FString sName; + TestList lTest; +}; +//typedef Bu::List SuiteList; + +enum TokType +{ + tokFluff, + tokSuite, + tokTest, + tokChar, + tokBlock, + tokEof +}; + +Bu::Formatter &operator<<( Bu::Formatter &f, TokType t ) +{ + switch( t ) + { + case tokFluff: return f << "tokFluff"; + case tokSuite: return f << "tokSuite"; + case tokTest: return f << "tokTest"; + case tokChar: return f << "tokChar"; + case tokBlock: return f << "tokBlock"; + case tokEof: return f << "tokEof"; + } + + return f; +} + +Bu::Formatter &operator<<( Bu::Formatter &f, const Test &t ) +{ + return f << "{" << t.sName << ", bExpectPass=" << t.bExpectPass << "}"; +} + +Bu::Formatter &operator<<( Bu::Formatter &f, const Suite &s ) +{ + return f << "Suite[" << s.sName << "] = " << s.lTest << f.nl; +} + +class Parser +{ +public: + Parser( const Bu::FString &sFile ) : + fIn( sFile, File::Read ), + bIn( fIn ), + cBuf( 0 ), + bAvail( false ), + eMode( mRoot ), + iLine( 1 ), + iChar( 0 ), + iDepth( 0 ) + { + } + + char nextChar() + { + if( bAvail ) + return cBuf; + + if( bIn.read( &cBuf, 1 ) < 1 ) + throw Bu::ExceptionBase("End of stream"); + bAvail = true; + + if( cBuf == '\n' ) + { + iLine++; + iChar = 0; + } + else + iChar++; + + return cBuf; + } + + TokType nextToken( Variant &v, Bu::FString &sWsOut, int &iLineStart, + int &iCharStart ) + { + Bu::FString sTok, sWs; + + char buf; + try + { + buf = nextChar(); + } + catch(...) + { + return tokEof; + } + + for(;;) + { + if( buf == ' ' || buf == '\t' || buf == '\n' || buf == '\r' ) + { + sWs += buf; + bAvail = false; + } + else + break; + + try + { + buf = nextChar(); + } + catch(...) + { + sWsOut = sWs; + return tokEof; + } + } + + sWsOut = sWs; + + iLineStart = iLine; + iCharStart = iChar; + bool bInStr = false; + bool bDblStr; + + for(;;) + { + switch( eMode ) + { + case mRoot: + if( buf == ' ' || buf == '\t' || buf == '\n' + || buf == '\r' ) + { + if( sTok == "suite" ) + return tokSuite; + else + { + v = sTok; + return tokFluff; + } + } + else if( buf == '(' || buf == ')' || buf == '{' + || buf == '}' || buf == ';' ) + { + if( sTok.getSize() == 0 ) + { + bAvail = false; + v = buf; + return tokChar; + } + else + { + v = sTok; + return tokFluff; + } + } + else + { + sTok += buf; + bAvail = false; + } + break; + + case mSuite: + if( buf == ' ' || buf == '\t' || buf == '\n' + || buf == '\r' ) + { + if( sTok == "test" ) + return tokTest; + else + { + v = sTok; + return tokFluff; + } + } + else if( buf == '(' || buf == ')' + || buf == '}' || buf == ';' ) + { + if( sTok.getSize() == 0 ) + { + bAvail = false; + v = buf; + return tokChar; + } + else + { + v = sTok; + return tokFluff; + } + } + else if( buf == '{' ) + { + if( sTok.getSize() > 0 ) + { + v = sTok; + return tokFluff; + } + else + { + sTok += buf; + bAvail = false; + eMode = mBlock; + iDepth = 1; + } + } + else + { + sTok += buf; + bAvail = false; + } + break; + + case mBlock: + if( bInStr ) + { + if( buf == '\\' ) + { + sTok += buf; + bAvail = false; + sTok += nextChar(); + bAvail = false; + } + else if( bDblStr == true && buf == '\"' ) + { + sTok += buf; + bAvail = false; + bInStr = false; + } + else if( bDblStr == false && buf == '\'' ) + { + sTok += buf; + bAvail = false; + bInStr = false; + } + else + { + sTok += buf; + bAvail = false; + } + } + else + { + if( buf == '\"' ) + { + bInStr = true; + bDblStr = true; + sTok += buf; + bAvail = false; + } + else if( buf == '\'' ) + { + bInStr = true; + bDblStr = false; + sTok += buf; + bAvail = false; + } + else if( buf == '}' ) + { + sTok += buf; + bAvail = false; + iDepth--; + if( iDepth == 0 ) + { + v = sTok; + eMode = mSuite; + return tokBlock; + } + } + else if( buf == '{' ) + { + sTok += buf; + bAvail = false; + iDepth++; + } + else + { + sTok += buf; + bAvail = false; + } + } + break; + } + + buf = nextChar(); + } + } + + void firstPass() + { + Variant v; + Bu::FString sWs; + int iL, iC; + for(;;) + { + TokType t = nextToken( v, sWs, iL, iC ); + if( t == tokEof ) + return; + switch( eMode ) + { + case mRoot: + if( t == tokSuite ) + { + if( nextToken( v, sWs, iL, iC ) != tokFluff ) + throw Bu::ExceptionBase("%d:%d: Expected string " + "following suite.", iL, iC ); + s.sName = v.get(); + if( nextToken( v, sWs, iL, iC ) != tokChar || + v.get() != '{' ) + throw Bu::ExceptionBase("%d:%d: Expected {, got " + "'%s'", iL, iC, v.toString().getStr() ); + eMode = mSuite; + } + break; + + case mSuite: + switch( t ) + { + case tokFluff: + break; + + case tokBlock: + break; + + case tokTest: + { + if( nextToken( v, sWs, iL, iC ) != tokFluff ) + throw Bu::ExceptionBase("%d:%d: Expected " + "string following test.", iL, iC ); + Test t; + t.sName = v.get(); + if( nextToken( v, sWs, iL, iC ) != tokBlock ) + throw Bu::ExceptionBase("%d:%d: Expected " + "{...} block.", + iL, iC ); + s.lTest.append( t ); + } + break; + + case tokChar: + if( v.get() == '}' ) + { + eMode = mRoot; + } + else + { + } + break; + + default: + sio << iL << ":" << iC << ": Unexpected " + << t << " found." << sio.nl; + return; + break; + } + break; + + default: + sio << "???" << sio.nl; + break; + } + } + } + + void secondPass( const Bu::FString &sOut ) + { + File fOut( sOut, File::WriteNew ); + Formatter f( fOut ); + fIn.setPos( 0 ); + bIn.stop(); + bIn.start(); + bAvail = false; + eMode = mRoot; + iLine = 1; + iChar = 0; + bool bHasIncluded = false; + + Bu::FString sWs; + Variant v; + int iL, iC; + for(;;) + { + TokType t = nextToken( v, sWs, iL, iC ); + switch( eMode ) + { + case mRoot: + if( t == tokSuite ) + { + fOut.write( sWs ); + if( nextToken( v, sWs, iL, iC ) != tokFluff ) + throw Bu::ExceptionBase("%d:%d: Expected string " + "following suite.", iL, iC ); + s.sName = v.get(); + if( nextToken( v, sWs, iL, iC ) != tokChar || + v.get() != '{' ) + throw Bu::ExceptionBase("%d:%d: Expected {", + iL, iC ); + eMode = mSuite; + + if( bHasIncluded == false ) + { + fOut.write("#include \n"); + bHasIncluded = true; + } + + Bu::FString sClass = "_UnitSuite_" + s.sName; + f << "class " << sClass + << " : public Bu::UnitSuite" << f.nl + << "{" << f.nl << "public:" << f.nl + << "\t" << sClass << "()" << f.nl + << "\t{" << f.nl + << "\t\tsetName(\"" << s.sName << "\");" << f.nl; + for( TestList::iterator i = s.lTest.begin(); i; i++ ) + { + f << "\t\tadd( static_cast(" + "&" << sClass << "::" << (*i).sName << "), \"" + << (*i).sName << "\", Bu::UnitSuite::" + "expectPass );" << f.nl; + } + f << "\t}" << f.nl << f.nl + << "\tvirtual ~" << sClass << "() { }" << f.nl + << f.nl; + } + else if( t == tokEof ) + { + Bu::FString sClass = "_UnitSuite_" + s.sName; + f << sWs << f.nl << "int main( int argc, char *argv[] )" + << f.nl << "{" << f.nl << "\treturn " << sClass + << "().run( argc, argv );" << f.nl << "}" << f.nl; + } + else + { + fOut.write( sWs ); + f << v; + } + break; + + case mSuite: + switch( t ) + { + case tokFluff: + fOut.write( sWs ); + fOut.write( v.get() ); + break; + + case tokTest: + { + fOut.write( sWs ); + if( nextToken( v, sWs, iL, iC ) != tokFluff ) + throw Bu::ExceptionBase("%d:%d: Expected " + "string following test.", iL, iC ); + Test t; + t.sName = v.get(); + if( nextToken( v, sWs, iL, iC ) != tokBlock ) + throw Bu::ExceptionBase("%d:%d: Expected " + "{...} block.", + iL, iC ); + + f << "\tvoid " << t.sName << "()" + << f.nl << "#line " << iL + << " \"" << sOut << "\"" << f.nl + << v << f.nl; + } + break; + + case tokChar: + if( v.get() == '}' ) + { + f << "};" << f.nl << f.nl; + eMode = mRoot; + } + else + { + char buf = v.get(); + fOut.write( sWs ); + fOut.write( &buf, 1 ); + } + break; + + case tokBlock: + fOut.write( sWs ); + f << f.nl << "#line " << iL << " \"" << sOut + << "\"" << f.nl; + fOut.write( v.get() ); + + break; + + default: + sio << iL << ":" << iC << ": Unexpected " + << t << " found." << sio.nl; + return; + break; + } + break; + + default: + sio << "???" << sio.nl; + break; + } + if( t == tokEof ) + return; + } + } + +private: + File fIn; + Buffer bIn; + char cBuf; + bool bAvail; + enum Mode + { + mRoot, + mSuite, + mBlock + }; + Mode eMode; + int iLine, iChar; + int iDepth; + Suite s; +}; + +int main( int argc, char *argv[] ) +{ + Parser p( argv[1] ); + + p.firstPass(); + + p.secondPass( argv[2] ); +} + diff --git a/src/tools/nidstool.cpp b/src/tools/nidstool.cpp deleted file mode 100644 index 41179f9..0000000 --- a/src/tools/nidstool.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2007-2010 Xagasoft, All rights reserved. - * - * This file is part of the libbu++ library and is released under the - * terms of the license contained in the file LICENSE. - */ - -#include "bu/file.h" -#include "bu/nids.h" -#include "bu/nidsstream.h" -#include "bu/paramproc.h" - -#include - -typedef struct Block -{ - uint32_t uFirstBlock; - uint32_t uNextBlock; - uint32_t uBytesUsed; -} Block; - -class Param : public Bu::ParamProc -{ -public: - Param( int argc, char *argv[] ) - { - addHelpBanner("nidstool - Do stuff with nids files.\n\n"); - addParam("info", 'i', mkproc(Param::procInfo), - "Print some info about the file."); - addParam("dump", 'd', mkproc(Param::procDump), - "Dump a stream to a file."); - addParam("analyze", 'a', mkproc(Param::procAnalyze), - "Analyze a nids file."); - addParam("copy", 'c', mkproc(Param::procCopy), - "Copy a nids file, changing settings."); - addParam("help", 'h', mkproc(Bu::ParamProc::help), "This help."); - process( argc, argv ); - } - - virtual ~Param() - { - } - - void printInfo( Bu::Nids &n ) - { - printf("File info:\n"); - printf(" Header overhead: %db\n", n.getBlockStart() ); - printf(" Block size: %db\n", n.getBlockSize() ); - printf(" Block count: %d\n", n.getNumBlocks() ); - printf(" Blocks used: %d (%d%%)\n", n.getNumUsedBlocks(), - n.getNumUsedBlocks()*100/n.getNumBlocks() ); - printf(" Block overhead: %db\n", n.getBlockOverhead() ); - printf(" Block storage: %db (%d%%)\n", - n.getBlockSize()-n.getBlockOverhead(), - (n.getBlockSize()-n.getBlockOverhead())*100/n.getBlockSize() ); - } - - int procInfo( int argc, char *argv[] ) - { - if( argc < 1 ) - { - printf("You must provide a file name.\n"); - exit( 1 ); - } - - Bu::File fIn( argv[0], Bu::File::Read ); - Bu::Nids n( fIn ); - n.initialize(); - - printInfo( n ); - - if( argc >= 2 ) - { - uint32_t uStream = strtoul( argv[1], NULL, 0 ); - uint32_t uBlock = uStream; - - Block b; - - for(;;) - { - fIn.setPos( n.getBlockStart()+n.getBlockSize()*uBlock ); - fIn.read( &b, sizeof(Block) ); - printf("Stream %u: block %u, next %u, %ub used.\n", - uStream, uBlock, b.uNextBlock, b.uBytesUsed - ); - if( b.uNextBlock == 0xFFFFFFFFUL ) - break; - uBlock = b.uNextBlock; - } - printf("Stream End.\n"); - - return 2; - } - - return 1; - } - - int procDump( int argc, char *argv[] ) - { - if( argc < 3 ) - { - printf("You must provide a nids file, a stream id, and an output " - "file.\n"); - exit( 1 ); - } - - Bu::File fIn( argv[0], Bu::File::Read ); - Bu::Nids n( fIn ); - n.initialize(); - - int iStream = strtol( argv[1], NULL, 0 ); - Bu::NidsStream sIn = n.openStream( iStream ); - - Bu::File fOut( argv[2], Bu::File::Write|Bu::File::Create ); - int iTotal = 0; - char buf[100]; - for(;;) - { - int iRead = sIn.read( buf, 100 ); - iTotal += fOut.write( buf, iRead ); - if( iRead < 100 ) - break; - } - - printf("Wrote %db from stream %d in %s to %s.\n", - iTotal, iStream, argv[0], argv[2] ); - return 3; - } - - int procAnalyze( int argc, char *argv[] ) - { - if( argc < 1 ) - { - printf("You must provide a file name.\n"); - exit( 1 ); - } - - Bu::File fIn( argv[0], Bu::File::Read ); - Bu::Nids n( fIn ); - n.initialize(); - - printInfo( n ); - - int iStreamCnt = 0; - int iStreamTotal = 0; - int iOneBlock = 0; - uint32_t iLargest = 0; - uint32_t iSmallest = 0; - int iWaste = 0; - int iUsable = n.getBlockSize()-n.getBlockOverhead(); - Block b; - for( int j = 0; j < n.getNumBlocks(); j++ ) - { - fIn.setPos( n.getBlockStart()+n.getBlockSize()*j ); - fIn.read( &b, sizeof(Block) ); - if( b.uFirstBlock != (uint32_t)j ) - continue; - - iStreamCnt++; - iStreamTotal += b.uBytesUsed; - - if( b.uNextBlock == 0xFFFFFFFFUL ) - { - iOneBlock++; - iWaste += iUsable - b.uBytesUsed; - } - else - { - iWaste += iUsable - (b.uBytesUsed%iUsable); - } - - if( j == 0 ) - { - iSmallest = iLargest = b.uBytesUsed; - } - else - { - if( iLargest < b.uBytesUsed ) - iLargest = b.uBytesUsed; - if( iSmallest > b.uBytesUsed ) - iSmallest = b.uBytesUsed; - } - } - printf("Steam analysis:\n"); - printf(" Stream count: %d\n", iStreamCnt ); - printf(" Stream size: %db/%db/%db (min/avr/max)\n", - iSmallest, iStreamTotal/iStreamCnt, iLargest ); - printf(" One-block streams: %d (%d%%)\n", - iOneBlock, iOneBlock*100/iStreamCnt ); - printf(" Total wasted space: %db (%d%%)\n", - iWaste, iWaste*100/iStreamTotal ); - printf(" Avr blocks-per-stream: %f%%\n", - (float)n.getNumBlocks()/(float)iStreamCnt ); - - return 1; - } - - int procCopy( int argc, char *argv[] ) - { - if( argc < 3 ) - { - printf("You must provide source stream, blocksize, destination.\n"); - exit( 1 ); - } - - Bu::File fIn( argv[0], Bu::File::Read ); - Bu::Nids nIn( fIn ); - nIn.initialize(); - - Bu::File fOut( argv[2], Bu::File::Read|Bu::File::Write|Bu::File::Create| - Bu::File::Truncate ); - Bu::Nids nOut( fOut ); - nOut.initialize( strtol( argv[1], 0, NULL ) ); - - Block b; - for( int j = 0; j < nIn.getNumBlocks(); j++ ) - { - fIn.setPos( nIn.getBlockStart()+nIn.getBlockSize()*j ); - fIn.read( &b, sizeof(Block) ); - if( b.uFirstBlock != (uint32_t)j ) - continue; - - Bu::NidsStream sIn = nIn.openStream( j ); - int iNew = nOut.createStream(); - Bu::NidsStream sOut = nOut.openStream( iNew ); - - char buf[1024]; - for(;;) - { - int iRead = sIn.read( buf, 1024 ); - sOut.write( buf, iRead ); - if( iRead < 1024 ) - break; - } - } - - return 3; - } -}; - - -int main( int argc, char *argv[] ) -{ - Param p( argc, argv ); - - return 0; -} - -- cgit v1.2.3