예제 #1
0
    /*
    INDEX ::= <project name=${PROJECT_NAME}> PACKAGE* </project>
    PACKAGE ::= <package name=${PACKAGE_NAME}> IMPORTS INCLUDES DEFINITIONS </package>
    IMPORTS ::= <imports> IMPORT* </imports>
    IMPORT ::= <import from.pkg=${PKG_NAME} [ alias=${ALIAS} ] from.tags=${TAGS} to.tags=${TAGS1} />
    INCLUDE ::= <include from.pkg=${PKG_NAME} [ alias=${ALIAS} ] from.tags=${TAGS} to.tags=${TAGS1}/>
    DEFINITIONS ::= <definitions> DEFINITON* </definitions>
    DEFINITION ::= <define var.name=${VAR} tags=${TAGS} />

    For example::

        <project name="Foo">
            <package name="maths=">
                <imports>
                    <import from.pkg="ginger.constants" from.tags="public" to.tags="public" />
                </imports>
                <definitions>
                    <define var.name="pi" tags="public" />
                    <define var.name="e" tags="public" />
                </definitions>
            </package>
        </project>
    */
    void addAllPackages( Ginger::MnxBuilder & b ) {
        FolderScan fscan( this->projectFolder() );
        while ( fscan.nextFolder() ) {
            const string entry = fscan.entryName();
            if ( entry.size() >= 1 && entry[0] == '.' ) continue;

            const string pkg_folder = fscan.folderName() + '/' + entry;

            b.start( "package" );
            b.put( "name", entry );

            b.start( "imports" );
            ifstream imp( pkg_folder + "/imports.gnx" );
            if ( imp ) {
                Ginger::MnxReader reader( imp );
                Ginger::SharedMnx imports = reader.readMnx();
                for ( Ginger::MnxChildIterator kids( imports ); !!kids; ++kids ) {
                    auto k = *kids;
                    if ( ! k->hasName( "import" ) ) continue;
                    if ( ! k->hasAttribute( "from" ) ) continue;
                    if ( ! k->hasAttribute( "match0" ) ) continue;
                    b.start( "import" );
                    b.put( "from.pkg", k->attribute( "from" ) );
                    b.put( "from.tags", k->attribute( "match0" ) );
                    b.end();
                }
            }
            b.end();
            
            this->addPackage( b, pkg_folder );

            b.end();
        }
    }
예제 #2
0
    void addPackage( Ginger::MnxBuilder & b, const string pkg_folder ) {
        FolderScan fscan( pkg_folder );

        b.start( "definitions" );
        
        while ( fscan.nextFolder() ) {
            const string entry = fscan.entryName();

            #ifdef DBG_SEARCH
                cerr << "subfolder: " << entry << endl;
            #endif

            //  Check that -entry- matches *.auto
            if ( entry.find( AUTO_SUFFIX, entry.size() - AUTO_SUFFIX_SIZE ) != string::npos ) {
            
                const string default_tag = entry.substr( 0, entry.size() + 1 - AUTO_SUFFIX_SIZE );
                //cout << "TAG = " << default_tag << endl;
            
                #ifdef DBG_SEARCH
                    cerr << "*.auto: " << entry << endl;
                #endif
                
                FolderScan files( fscan.folderName() + "/" + entry );
                while ( files.nextFile() ) {
                    string fname = files.entryName();
                    #ifdef DBG_SEARCH
                        cerr << "Entry : " << fname << endl;
                    #endif
                    
                    size_t n = fname.rfind( '.' );
                    if ( n == string::npos ) continue;
                    
                    const string root = URLdecode( fname.substr( 0, n ) );
                    const string extn = fname.substr( n + 1 );
                    
                    #ifdef DBG_SEARCH
                        cerr << "Adding " << root << " -> " << ( files.folderName() + "/" + fname ) <<  endl;
                    #endif
                    
                    b.start( "define" );
                    b.put( "name", root );
                    b.put( "tags",default_tag );
                    b.end();
                }
            } else if ( entry == "load" ) {
                //  It doesn't match *.auto but it is a load folder though.
                //const string p( fscan.folderName() + "/" + entry );
                //newc->setLoadFolder( p );
            }
        }   

        b.end();
    }
예제 #3
0
 void fetchIndex() {
     #ifdef DBG_GPROJLIBTOOL
         cerr << "COMMAND: " << "fetchIndex" << endl;
         cerr << "FOLDER:  " << this->projectFolder() << endl;
         cerr << "Name:    " << this->projectName() << endl;
     #endif
     Ginger::MnxBuilder b;
     b.start( "project" );
     b.put( "name", this->projectName() );
     this->addAllPackages( b );
     b.end();
     b.build()->render();
     cout << endl;
 }
예제 #4
0
Valof * OrdinaryPackage::absoluteAutoload( const std::string & c ) {
	syslog( LOG_INFO, "Autoloading is_absolute_ref %s", c.c_str() );
	
	Ginger::Command cmd( FETCHGNX );
	cmd.addArg( "-X" );
	{
		list< string > & folders = this->getMachine()->getAppContext().getProjectFolderList();
		for ( 
			list< string >::iterator it = folders.begin();
			it != folders.end();
			++it
		) {
			cmd.addArg( "-j" );
			cmd.addArg( *it );
		}
	}
	
	#ifdef DBG_PACKAGE_AUTOLOAD
		cerr << "Autoloading" << endl;
		cerr << "  Package 	: " << this->title << endl;
		cerr << "  Variable : " << c << endl;
		list< string > & folders = this->getMachine()->getAppContext().getProjectFolderList();
		for ( 
			list< string >::iterator it = folders.begin();
			it != folders.end();
			++it
		) {
			cerr << "  Folder  : " << *it << endl;
		}
		cerr << "  Command  : " << cmd.asPrintString() << endl;
	#endif

	Ginger::MnxBuilder qb;
	qb.start( "fetch.definition" );
	qb.put( "pkg.name", this->title );
	qb.put( "var.name", c );
	qb.end();
	shared< Ginger::Mnx > query( qb.build() );

	#ifdef DBG_PACKAGE_AUTOLOAD
		cerr << "appginger asking for definition, using fetchgnx -X" << endl;
		cerr << "  [[";
		query->render( cerr );
		cerr << "]]" << endl;
	#endif	

	cmd.runWithInputAndOutput();
	int fd = cmd.getInputFD();   
	FILE * foutd = fdopen( cmd.getOutputFD(), "w" );
	fRenderMnx( foutd, query );
	
	stringstream prog;
	for (;;) {
		static char buffer[ 1024 ];
		int n = read( fd, buffer, sizeof( buffer ) );
		if ( n == 0 ) break;
		if ( n == -1 ) {
			if ( errno != EINTR ) {
				perror( "PACKAGE AUTOLOAD" );
				throw Ginger::Mishap( "Failed to read" );
			}
		} else if ( n > 0 ) {
			prog.write( buffer, n );
		}
	}
		
	fclose( foutd );
	
	#ifdef DBG_PACKAGE_AUTOLOAD
		cerr << "appginger/package autoloading, reply from fetchgnx -X" << endl;
		cerr << "  [[" << prog.str() << "]]" << endl;
		cerr << "ok" << endl;
	#endif
	
		
	//	Now we establish a forward declaration - to be justified by the success.
	#ifdef DBG_PACKAGE_AUTOLOAD
		cerr << "appginger/package doing a forward declaration" << endl;
	#endif
	Valof * id = this->forwardDeclare( c );

	try {
		//	And we load the stream.
		RCEP rcep( this );
		rcep.setPrinting( false );	//	Turn off result printing.
		#ifdef DBG_PACKAGE_AUTOLOAD
			cerr << "appginger/package loading into RCEP" << endl;
			cerr << "  [[" << prog.str() << "]]" << endl;
		#endif	
		rcep.unsafe_read_comp_exec_print( prog, cout );		
		return id;		
	} catch ( Ginger::Mishap & e ) {
		//	Undo the forward declaration.
		if ( id->valof == SYS_UNASSIGNED ) {
			//	The autoloading failed. Undo the declaration.
			this->retractForwardDeclare( c );
		}
		syslog( LOG_ERR, "Autoloading %s failed due to an exception", c.c_str() );
		throw Ginger::Mishap( "Autoloading failed (rethrowing)" ).culprit( "Name", c ).cause( e );
	}
	
	//	No autoloading implemented yet - just fail.
	return NULL;
}