/**************************************************************************** PROJECT: MusixTeX PreProcessor FILE : macro.cc AUTHOR : J. C. Nieuwenhuizen copyright (c) FlowerSoft 1995 --*/ #include // atoi #include #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #include "strlist.h" #include "macro.h" #include "imacro.h" #include "init.h" #include "staff.h" #include "mpp.h" /**************************************************************************** class Comment --*/ Comment::Comment( Staff& staff ) : Macro( "" ) { staff.expect( '%' ); getFrom( *staff.is ); staff.line++; } Comment::~Comment() { } int Comment::getFrom( istream& is ) { char c = is.get(); char secondChar = is.peek(); char buf[ LINE_MAX + 1 ]; is.get( buf, LINE_MAX, '\n' ); is.get( c ); // get the \n if ( secondChar == '%' ) // only copy double comments %% { substitute = buf; substitute += '\n'; } return 0; } //-- class Comment // /**************************************************************************** class DefaultDuration --*/ DefaultDuration::DefaultDuration( const char* s, const int p ) : Macro( s, "", p ) { } DefaultDuration::~DefaultDuration() { } void DefaultDuration::execute( StringList& parameterList, Staff& staff ) { ;// monitor << "DefaultDuration::execute: " << parameterList.top() << endl; int newxDuration = atoi( (const char*)parameterList.top() ); if ( ( newxDuration != 1 ) && ( newxDuration != 2 ) && ( newxDuration != 4 ) && ( newxDuration != 8 ) && ( newxDuration != 16 ) && ( newxDuration != 32 ) && ( newxDuration != 64 ) ) staff.warning( String( "invalid duration:" ) + String( newxDuration ) ); else staff.xDuration = newxDuration; } //-- class DefaultDuration // /**************************************************************************** class Macro --*/ Macro::Macro( const char* name, const char* sub, const int parameterCount ) : baseSubstitute( sub ), substitute( sub ), Token( name, parameterCount ) { // if ( !substitute.len() ) // baseSubstitute = name; } Macro::Macro( Staff& staff, const char* sub, const int parameterCount ) : baseSubstitute( sub ), substitute( sub ), Token ( "", parameterCount ) { getFrom( staff ); } Macro& Macro::getMacro( Staff& staff ) { istream& is = *staff.is; WhiteSpace ws( staff ); char c = is.peek(); switch( c ) { case '%' : // comment return *new Comment( staff ); case '\\' : return *new Macro( staff ); // case (char)EOF: // staff.warning( "unexpected end of file" ); // return NOMACRO; default: // staff.error( quoteChar( "invalid macro:", c ) ); return NOMACRO; } } Macro::~Macro() { } #if 0 Macro::operator const char *() const { return (const char*)substitute; } #endif void Macro::execute( StringList& parameterList, Staff& ) { substitute = baseSubstitute; // substitute = name; StringListIterator parameters( parameterList ); while( parameters ) { substitute += "{"; if ( isalpha( parameters()[0] ) ) substitute += "\\"; substitute += parameters++; substitute += "}"; } } /* read a (already defined) macro from infile, with params */ int Macro::getFrom( Staff& staff ) { ;// monitor << "Macro::getFrom" << endl; istream& is = *staff.is; char c = staff.is->peek(); if ( c == '\\' ) is.get( c ); String s; s = Token::_getFrom( is ); // get from stream Macro* macro; // search global macrolist for this string if ( (macro = &(Macro&)macroList.firstMacro( Token::compare, (void*)(const char*)s ) ) == ZERO ) { if ( !s.len() ) staff.error( quoteString( "macro not found", name ) ); else staff.error( quoteString( "macro not found", (const char*) s ) ); } name = macro->name; parameterCount = macro->parameterCount; StringList parameterList; for ( int i= 0; i < parameterCount; i++ ) { Parameter parameter( staff ); parameterList.put( *new String( (const char*)parameter.substitute ) ); } if ( parameterList.count() < parameterCount ) staff.error( "parameter expected" ); // do it. macro->execute( parameterList, staff ); // if ( !substitute.len() ) substitute = macro->substitute; ;// monitor << "substitute:" << name << ',' << macro->name << endl; return 0; } void Macro::printOn( ostream& os ) const { ;// monitor << "Macro::printOn" << endl; os << substitute; } int Macro::validCharacter( const char c ) const { return ( Token::validCharacter( c ) && isalpha( c ) ); } //-- class Macro // /**************************************************************************** class Parameter --*/ Parameter::Parameter( Staff& staff ) { WhiteSpace ws( staff ); getFrom( staff ); } Parameter::~Parameter() { } Parameter::operator const char *() const { return (const char*)substitute; } String Parameter::_getFrom( istream& is ) { char c = is.peek(); String& s = *new String; if ( c == '\\' ) { is.get( c ); s = Token::_getFrom( is ); } else if ( c == '{' ) { int nest = 1; is.get( c ); c = is.peek(); while ( nest && Token::validCharacter( c ) ) // \{ \} won't work { is.get( c ); if ( c == '{' ) nest++; else if ( c == '}' ) nest--; s += c; c = is.peek(); } // strip braces // s = s.mid( 2, s.len() - 2 ); s = s.left( s.len() - 1 ); } else { is.get( c ); ;// monitor << c << ':'; s = String( c ); ;// monitor << s << endl; } return s; } int Parameter::getFrom( Staff& staff ) { // String& s = _getFrom( is ); // substitute = s; // delete &s; ;// monitor << "Parameter::getFrom" << endl; substitute = _getFrom( *staff.is ); return 0; } int Parameter::validCharacter( const char c ) const { return ( Token::validCharacter( c ) && isalpha( c ) ); } //-- class Parameter //