/* 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(); } }
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(); }
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; }
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; }