Back to index

lightning-sunbird  0.9+nobinonly
mac_xpidl.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038        mac_xpidl.cpp
00039        
00040        Metrowerks Codewarrior IDL plugin.
00041        
00042        by Patrick C. Beard.
00043  */
00044 
00045 /* standard headers */
00046 #include <ctype.h>
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <stdlib.h>
00050 #include <new.h>
00051 #include <setjmp.h>
00052 
00053 /* system headers */
00054 #include <Files.h>
00055 #include <Errors.h>
00056 #include <Strings.h>
00057 
00058 #include "FullPath.h"
00059 #include "MoreFilesExtras.h"
00060 
00061 /* compiler headers */
00062 #include "DropInCompilerLinker.h"
00063 #include "CompilerMapping.h"
00064 #include "CWPluginErrors.h"
00065 
00066 /* local headers. */
00067 #include "mac_xpidl.h"
00068 #include "mac_console.h"
00069 #include "mac_strings.h"
00070 #include "mac_xpidl_panel.h"
00071 
00072 /* prototypes of local functions */
00073 static CWResult      Compile(CWPluginContext context);
00074 static CWResult      Disassemble(CWPluginContext context);
00075 static CWResult      LocateFile(CWPluginContext context, const char* filename, FSSpec& file);
00076 
00077 /* external variables */
00078 extern jmp_buf exit_jump;
00079 extern int exit_status;
00080 
00081 /* global variables */
00082 CWPluginContext gPluginContext;
00083 
00084 /* local variables */
00085 static CWFileSpec gSourceFile;
00086 static char* gSourcePath = NULL;
00087 static CWFileSpec gOutputFile;
00088 
00089 extern "C" {
00090 pascal short xpidl_compiler(CWPluginContext context);
00091 int xpidl_main(int argc, char* argv[]);
00092 int xptdump_main(int argc, char* argv[]);
00093 
00094 FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
00095 }
00096 
00097 pascal short xpidl_compiler(CWPluginContext context)
00098 {
00099        long request;
00100        if (CWGetPluginRequest(context, &request) != cwNoErr)
00101               return cwErrRequestFailed;
00102        
00103        gPluginContext = context;
00104        short result = cwNoErr;
00105        
00106        /* dispatch on compiler request */
00107        switch (request) {
00108        case reqInitCompiler:
00109               /* compiler has just been loaded into memory */
00110               break;
00111               
00112        case reqTermCompiler:
00113               /* compiler is about to be unloaded from memory */
00114               break;
00115               
00116        case reqCompile:
00117               /* compile a source file */
00118               result = Compile(context);
00119               break;
00120        
00121        case reqCompDisassemble:
00122               /* disassemble a source file */
00123               result = Disassemble(context);
00124               break;
00125        
00126        default:
00127               result = cwErrRequestFailed;
00128               break;
00129        }
00130        
00131        /* is this necessary? */
00132        CWDonePluginRequest(context, result);
00133        
00134        /* return result code */
00135        return (result);
00136 }
00137 
00138 static char* full_path_to(const FSSpec& file)
00139 {
00140        short len = 0;
00141        Handle fullPath = NULL;
00142        if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
00143               char* path = new char[1 + len];
00144               if (path != NULL) {
00145                      BlockMoveData(*fullPath, path, len);
00146                      path[len] = '\0';
00147               }
00148               DisposeHandle(fullPath);
00149               return path;
00150        }
00151        return NULL;
00152 }
00153 
00154 static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
00155 {
00156        CWMemHandle   settingsHand;
00157        CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
00158        if (!CWSUCCESS(err))
00159               return (err);
00160        
00161        XPIDLSettings* settingsPtr = NULL;
00162        err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
00163        if (!CWSUCCESS(err))
00164               return (err);
00165        
00166        settings = *settingsPtr;
00167        
00168        err = CWUnlockMemHandle(context, settingsHand);
00169        if (!CWSUCCESS(err))
00170               return (err);
00171 
00172        return noErr;
00173 }
00174 
00175 static CWResult      Compile(CWPluginContext context)
00176 {
00177        CWResult err = CWGetMainFileSpec(context, &gSourceFile);
00178        if (!CWSUCCESS(err))
00179               return (err);
00180 
00181        long fileNum;
00182        err = CWGetMainFileNumber(context, &fileNum);
00183        if (!CWSUCCESS(err))
00184               return (err);
00185 
00186        // get the name of the source file to compile.
00187        gSourcePath = p2c_strdup(gSourceFile.name);
00188        if (gSourcePath == NULL)
00189               return cwErrOutOfMemory;
00190        
00191        // build an argument list and call the compiler.
00192        XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeHeader, false, false };
00193        GetSettings(context, settings);
00194 
00195 #if 0  
00196        // if generating .xpt files, let the IDE tell us where to put the output file.
00197        // otherwise, put them in the project's output directory.
00198        if (settings.mode == kXPIDLModeTypelib)
00199               err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
00200        else
00201               err = CWGetOutputFileDirectory(gPluginContext, &gOutputFile);
00202 #else
00203        // always generate the output file into the project target's data directory.
00204        err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
00205 #endif
00206        if (!CWSUCCESS(err))
00207               return (err);
00208        
00209        int argc = 3;
00210        char* modes[] = { "header", "java", "typelib", "doc" };
00211        char* argv[] = { "xpidl", "-m", modes[settings.mode - 1], NULL, NULL, NULL, NULL, };
00212        if (settings.warnings) argv[argc++] = "-w";
00213        if (settings.verbose) argv[argc++] = "-v";
00214        argv[argc++] = gSourcePath;
00215        
00216        if (setjmp(exit_jump) == 0) {
00217               if (xpidl_main(argc, argv) != 0)
00218                      err = cwErrRequestFailed;
00219        } else {
00220               // evidently the good old exit function got called.
00221               if (exit_status != 0)
00222                      err = cwErrRequestFailed;
00223        }
00224 
00225        // if the compilation succeeded, tell CodeWarrior about the output file.
00226        // this ensures several things:  1. if the output file is deleted by the user,
00227        // then the IDE will know to recompile it, which is good for dirty builds,
00228        // where the output files may be hand deleted; 2. if the user elects to remove
00229        // objects, the output files are deleted. Thanks to robv@metrowerks.com for
00230        // pointing this new CWPro4 API out.
00231        if (err == cwNoErr) {
00232               CWObjectData objectData;
00233               BlockZero(&objectData, sizeof(objectData));
00234               
00235               // for fun, show how large the output file is in the data area.
00236               long dataSize, rsrcSize;
00237               if (FSpGetFileSize(&gOutputFile, &dataSize, &rsrcSize) == noErr)
00238                      objectData.idatasize = dataSize;
00239               
00240               // tell the IDE that this file was generated by the compiler.
00241               objectData.objectfile = &gOutputFile;
00242               
00243               err = CWStoreObjectData(context, fileNum, &objectData);
00244        } else {
00245               // an error occured, delete the output file, which might be a partial file.
00246               if (gOutputFile.name[0] != 0) {
00247                      ::FSpDelete(&gOutputFile);
00248               }
00249        }
00250 
00251        delete[] gSourcePath;
00252        gSourcePath = NULL;
00253 
00254        return (err);
00255 }
00256 
00257 static CWResult      Disassemble(CWPluginContext context)
00258 {
00259        // the disassembly code has moved to the linker.
00260        return noErr;
00261 }
00262 
00263 static CWResult      LocateFile(CWPluginContext context, const char* filename, FSSpec& file)
00264 {
00265        /* prefill the CWFileInfo struct */
00266        CWFileInfo fileinfo;
00267        BlockZero(&fileinfo, sizeof(fileinfo));
00268        // memset(&fileinfo, 0, sizeof(fileinfo));
00269        fileinfo.fullsearch = true;
00270        fileinfo.suppressload = true;
00271        fileinfo.dependencyType = cwNormalDependency;
00272        fileinfo.isdependentoffile = kCurrentCompiledFile;
00273 
00274        /* locate the file name using the project's access paths */
00275        CWResult err = CWFindAndLoadFile(context, filename, &fileinfo);
00276        if (err == cwNoErr) {
00277               file = fileinfo.filespec;
00278        } else if (err == cwErrFileNotFound) {
00279               char errmsg[200];
00280               sprintf(errmsg, "Can't locate file \"%s\".", filename);
00281               CWResult callbackResult = CWReportMessage(context, 0, errmsg, 0, messagetypeError, 0);
00282        }
00283        
00284        return (err);
00285 }
00286 
00294 FILE* std::fopen(const char* filename, const char *mode)
00295 {
00296        FSSpec filespec;
00297        CWResult err = noErr;
00298        do {
00299               if (filename == gSourcePath || strcmp(filename, gSourcePath) == 0) {
00300                      // opening the main source file.
00301                      filespec = gSourceFile;
00302               } else if (mode[0] == 'w') {
00303                      // if an output file, open it in the current compilation's output directory.
00304                      c2p_strcpy(filespec.name, filename);
00305                      filespec.vRefNum = gOutputFile.vRefNum;
00306                      filespec.parID = gOutputFile.parID;
00307                      c2p_strcpy(gOutputFile.name, filename);
00308               } else {
00309                      // an input file, use CodeWarrior's search paths to find the named source file.
00310                      err = LocateFile(gPluginContext, filename, filespec);
00311               }
00312        } while (0);
00313        // if all went well, we have a file to open.
00314        return (err == noErr ? FSp_fopen(&filespec, mode) : NULL);
00315 }
00316 
00321 size_t mac_get_file_length(const char* filename)
00322 {
00323        long dataSize= 0, rsrcSize = 0;
00324        FSSpec filespec;
00325        if (CWGetOutputFileDirectory(gPluginContext, &filespec) != noErr)
00326               return 0;
00327        c2p_strcpy(filespec.name, filename);
00328        if (FSpGetFileSize(&filespec, &dataSize, &rsrcSize) != noErr)
00329               return 0;
00330        return dataSize;
00331 }
00332 
00333 void mac_warning(const char* warning_message)
00334 {
00335        CWReportMessage(gPluginContext, 0, warning_message, 0, messagetypeWarning, 0);
00336 }
00337 
00338 void mac_error(const char* error_message)
00339 {
00340        CWReportMessage(gPluginContext, 0, error_message, 0, messagetypeError, 0);
00341 }
00342 
00343 // plugin compiler exports.
00344 
00345 #if CW_USE_PRAGMA_EXPORT
00346 #pragma export on
00347 #endif
00348 
00349 CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
00350 {
00351        static const DropInFlags sFlags = {
00352               kCurrentDropInFlagsVersion,
00353               CWDROPINCOMPILERTYPE,
00354               DROPINCOMPILERLINKERAPIVERSION,
00355               (kGeneratescode | /* kCandisassemble | */ kCompMultiTargAware | kCompAlwaysReload),
00356               Lang_MISC,
00357               DROPINCOMPILERLINKERAPIVERSION
00358        };
00359        
00360        *flags = &sFlags;
00361        *flagsSize = sizeof(sFlags);
00362        
00363        return cwNoErr;
00364 }
00365 
00366 CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
00367 {
00368        static const char* sDropInName = "xpidl";
00369        
00370        *dropinName = sDropInName;
00371        
00372        return cwNoErr;
00373 }
00374 
00375 CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
00376 {
00377        static const char* sDisplayName = "xpidl";
00378        
00379        *displayName = sDisplayName;
00380        
00381        return cwNoErr;
00382 }
00383 
00384 CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
00385 {
00386        static const char* sPanelName = kXPIDLPanelName;
00387        static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
00388        
00389        *panelList = &sPanelList;
00390        
00391        return cwNoErr;
00392 }
00393 
00394 CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
00395 {
00396        static CWDataType sCPU = '****';
00397        static CWDataType sOS = '****';
00398        static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
00399        
00400        *targetList = &sTargetList;
00401        
00402        return cwNoErr;
00403 }
00404 
00405 CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
00406 {
00407        static CWExtensionMapping sExtension = { 'TEXT', ".idl", 0 };
00408        static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
00409        
00410        *defaultMappingList = &sExtensionMapList;
00411        
00412        return cwNoErr;
00413 }
00414 
00415 #if CW_USE_PRAGMA_EXPORT
00416 #pragma export off
00417 #endif