/** * File: mac_makeconv.cpp * * Mac Codewarrior plugin version of makeconv. * * Sean K. Todd (stodd@broadjump.com) * Marty Saxton (msaxton@broadjump.com) */ // local headers #include "mac_utils.h" //#include "cmemory.h" //#include "utypes.h" // Toolbox headers #include "TextUtils.h" //#include // global variables CWPluginContext gPluginContext; extern "C" { int main( int argc, char* argv[]); //pascal OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath); } // plugin compiler exports. #if CW_USE_PRAGMA_EXPORT #pragma export on #endif // define what file types are handled CWPLUGIN_ENTRY( CWPlugin_GetDefaultMappingList)( const CWExtMapList** defaultMappingList) { static CWExtensionMapping sExtension = { 'TEXT', ".ucm", 0 }; static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension }; *defaultMappingList = &sExtensionMapList; return cwNoErr; } // define what operations this plugin handles CWPLUGIN_ENTRY( CWPlugin_GetDropInFlags)( const DropInFlags** flags, long* flagsSize) { static const DropInFlags sFlags = { kCurrentDropInFlagsVersion, CWDROPINCOMPILERTYPE, DROPINCOMPILERLINKERAPIVERSION, ( kGeneratescode | kCompMultiTargAware | kCompAlwaysReload), Lang_MISC, DROPINCOMPILERLINKERAPIVERSION }; *flags = &sFlags; *flagsSize = sizeof(sFlags); return cwNoErr; } // define what platforms are supported by this plugin // // '****' - specifies any type CWPLUGIN_ENTRY( CWPlugin_GetTargetList)( const CWTargetList** targetList) { static CWDataType sCPU = '****'; static CWDataType sOS = '****'; static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS }; *targetList = &sTargetList; return cwNoErr; } // define the plugin's onscreen name CWPLUGIN_ENTRY( CWPlugin_GetDropInName)( const char** dropinName) { static const char* sDropInName = "makeconv"; *dropinName = sDropInName; return cwNoErr; } #if CW_USE_PRAGMA_EXPORT #pragma export off #endif static CWResult Compile( CWPluginContext context) { // get the FileSpec of the file being processed CWResult err = CWGetMainFileSpec( context, &gSourceFile); if (!CWSUCCESS(err)) return (err); // get the index of the file to process, from the target link order long fileNum; err = CWGetMainFileNumber( context, &fileNum); if (!CWSUCCESS(err)) return (err); // get the name of the source file to compile gSourceFileName = p2c_strdup( gSourceFile.name); if ( gSourceFileName == NULL) return cwErrOutOfMemory; // get the user specified directory from the Target Settings panel (if one exists) err = CWGetOutputFileDirectory( gPluginContext, &gOutputFile); if (!CWSUCCESS(err)) { // else generate the output file into the project target's data directory err = CWGetSuggestedObjectFileSpec( context, fileNum, &gOutputFile); if (!CWSUCCESS(err)) return (err); } /* // set the destination directory Handle destH = 0; short len = 0; OSErr theErr = FSpGetFullPath( &gOutputFile, &len, &destH ); char* theDestPath; char pathBuffer[1024]; if( destH ) { ::HLock(destH); uprv_memcpy(pathBuffer, ((char*)(*destH)), len); pathBuffer[len] = 0; theDestPath = pathBuffer; ::DisposeHandle(destH); destH = 0; } // get the source directory Handle srcH = 0; len = 0; theErr = FSpGetFullPath( &gSourceFile, &len, &srcH ); char* theSrcPath; char srcBuffer[1024]; if( srcH ) { ::HLock(srcH); uprv_memcpy(srcBuffer, ((char*)(*srcH)), len); srcBuffer[len] = 0; theSrcPath = srcBuffer; ::DisposeHandle(srcH); srcH = 0; // truncate file name from full path string // std::string str = theSrcPath; // str = str.substr( 0, str.find_last_of( ":" ) + 1); // std::strcpy(theSrcPath, str.c_str()); } */ // set the destination directory char* theDestPath = ""; char pathBuffer[1024]; get_path_string( &theDestPath, pathBuffer, &gOutputFile, false); // set the source directory char* theSrcPath = ""; char srcBuffer[1024]; get_path_string( &theSrcPath, srcBuffer, &gSourceFile, false); int argc = 4; char* argv[] = { "makeconv", "-d", theDestPath, theSrcPath }; if ( setjmp( exit_jump) == 0) { // Need to test that we can locate our file here so we don't // have to in fopen(). That way, we won't get error messages // from makeconv.c when .dat files (that we don't care about) // aren't found. // err = LocateFile(gPluginContext, gSourceFileName, gSourceFile); if ( main( argc, argv) != 0) err = cwErrRequestFailed; } else { // evidently the good old exit function got called. if ( exit_status != 0) err = cwErrRequestFailed; } // if the compilation succeeded, tell CodeWarrior about the output file. // this ensures several things: 1. if the output file is deleted by the user, // then the IDE will know to recompile it, which is good for dirty builds, // where the output files may be hand deleted; 2. if the user elects to remove // objects, the output files are deleted. Thanks to robv@metrowerks.com for // pointing this new CWPro4 API out. if (err == cwNoErr) { CWObjectData objectData; ::BlockZero(&objectData, sizeof( objectData)); // for fun, show how large the output file is in the data area. long dataSize, rsrcSize; if ( FSpGetFileSize( &gOutputFile, &dataSize, &rsrcSize) == noErr) objectData.idatasize = dataSize; // tell the IDE that this file was generated by the compiler. objectData.objectfile = &gOutputFile; err = CWStoreObjectData( context, fileNum, &objectData); } else { // an error occured, delete the output file, which might be a partial file. if ( gOutputFile.name[0] != 0) { ::FSpDelete( &gOutputFile); } } delete[] gSourceFileName; gSourceFileName = NULL; return (err); } // main entry-point for makeconv compiler plugin pascal short makeconv_compiler( CWPluginContext context) { short result = cwNoErr; long request; // Get the value indicating the task the IDE is currently asking the // plugin to perform and make sure no error was evoked. if ( CWGetPluginRequest( context, &request) != cwNoErr) return cwErrRequestFailed; gPluginContext = context; result = cwNoErr; // dispatch on compiler request switch (request) { case reqInitCompiler: break; // compiler has just been loaded into memory case reqTermCompiler: break; // compiler is about to be unloaded from memory case reqCompile: /* compile a source file */ result = Compile( context); break; default: result = cwErrRequestFailed; break; } gPluginContext = 0; return (result); }