1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Netscape Public License
5
* Version 1.1 (the "License"); you may not use this file except in
6
* compliance with the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/NPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is mozilla.org code.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1998
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the NPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the NPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
40
Metrowerks Codewarrior IDL plugin.
45
/* standard headers */
59
#include "MoreFilesExtras.h"
61
/* compiler headers */
62
#include "DropInCompilerLinker.h"
63
#include "CompilerMapping.h"
64
#include "CWPluginErrors.h"
67
#include "mac_xpidl.h"
68
#include "mac_console.h"
69
#include "mac_strings.h"
70
#include "mac_xpidl_panel.h"
72
/* prototypes of local functions */
73
static CWResult Compile(CWPluginContext context);
74
static CWResult Disassemble(CWPluginContext context);
75
static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file);
77
/* external variables */
78
extern jmp_buf exit_jump;
79
extern int exit_status;
81
/* global variables */
82
CWPluginContext gPluginContext;
85
static CWFileSpec gSourceFile;
86
static char* gSourcePath = NULL;
87
static CWFileSpec gOutputFile;
90
pascal short xpidl_compiler(CWPluginContext context);
91
int xpidl_main(int argc, char* argv[]);
92
int xptdump_main(int argc, char* argv[]);
94
FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
97
pascal short xpidl_compiler(CWPluginContext context)
100
if (CWGetPluginRequest(context, &request) != cwNoErr)
101
return cwErrRequestFailed;
103
gPluginContext = context;
104
short result = cwNoErr;
106
/* dispatch on compiler request */
108
case reqInitCompiler:
109
/* compiler has just been loaded into memory */
112
case reqTermCompiler:
113
/* compiler is about to be unloaded from memory */
117
/* compile a source file */
118
result = Compile(context);
121
case reqCompDisassemble:
122
/* disassemble a source file */
123
result = Disassemble(context);
127
result = cwErrRequestFailed;
131
/* is this necessary? */
132
CWDonePluginRequest(context, result);
134
/* return result code */
138
static char* full_path_to(const FSSpec& file)
141
Handle fullPath = NULL;
142
if (FSpGetFullPath(&file, &len, &fullPath) == noErr && fullPath != NULL) {
143
char* path = new char[1 + len];
145
BlockMoveData(*fullPath, path, len);
148
DisposeHandle(fullPath);
154
static CWResult GetSettings(CWPluginContext context, XPIDLSettings& settings)
156
CWMemHandle settingsHand;
157
CWResult err = CWGetNamedPreferences(context, kXPIDLPanelName, &settingsHand);
161
XPIDLSettings* settingsPtr = NULL;
162
err = CWLockMemHandle(context, settingsHand, false, (void**)&settingsPtr);
166
settings = *settingsPtr;
168
err = CWUnlockMemHandle(context, settingsHand);
175
static CWResult Compile(CWPluginContext context)
177
CWResult err = CWGetMainFileSpec(context, &gSourceFile);
182
err = CWGetMainFileNumber(context, &fileNum);
186
// get the name of the source file to compile.
187
gSourcePath = p2c_strdup(gSourceFile.name);
188
if (gSourcePath == NULL)
189
return cwErrOutOfMemory;
191
// build an argument list and call the compiler.
192
XPIDLSettings settings = { kXPIDLSettingsVersion, kXPIDLModeHeader, false, false };
193
GetSettings(context, settings);
196
// if generating .xpt files, let the IDE tell us where to put the output file.
197
// otherwise, put them in the project's output directory.
198
if (settings.mode == kXPIDLModeTypelib)
199
err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
201
err = CWGetOutputFileDirectory(gPluginContext, &gOutputFile);
203
// always generate the output file into the project target's data directory.
204
err = CWGetSuggestedObjectFileSpec(context, fileNum, &gOutputFile);
210
char* modes[] = { "header", "java", "typelib", "doc" };
211
char* argv[] = { "xpidl", "-m", modes[settings.mode - 1], NULL, NULL, NULL, NULL, };
212
if (settings.warnings) argv[argc++] = "-w";
213
if (settings.verbose) argv[argc++] = "-v";
214
argv[argc++] = gSourcePath;
216
if (setjmp(exit_jump) == 0) {
217
if (xpidl_main(argc, argv) != 0)
218
err = cwErrRequestFailed;
220
// evidently the good old exit function got called.
221
if (exit_status != 0)
222
err = cwErrRequestFailed;
225
// if the compilation succeeded, tell CodeWarrior about the output file.
226
// this ensures several things: 1. if the output file is deleted by the user,
227
// then the IDE will know to recompile it, which is good for dirty builds,
228
// where the output files may be hand deleted; 2. if the user elects to remove
229
// objects, the output files are deleted. Thanks to robv@metrowerks.com for
230
// pointing this new CWPro4 API out.
231
if (err == cwNoErr) {
232
CWObjectData objectData;
233
BlockZero(&objectData, sizeof(objectData));
235
// for fun, show how large the output file is in the data area.
236
long dataSize, rsrcSize;
237
if (FSpGetFileSize(&gOutputFile, &dataSize, &rsrcSize) == noErr)
238
objectData.idatasize = dataSize;
240
// tell the IDE that this file was generated by the compiler.
241
objectData.objectfile = &gOutputFile;
243
err = CWStoreObjectData(context, fileNum, &objectData);
245
// an error occured, delete the output file, which might be a partial file.
246
if (gOutputFile.name[0] != 0) {
247
::FSpDelete(&gOutputFile);
251
delete[] gSourcePath;
257
static CWResult Disassemble(CWPluginContext context)
259
// the disassembly code has moved to the linker.
263
static CWResult LocateFile(CWPluginContext context, const char* filename, FSSpec& file)
265
/* prefill the CWFileInfo struct */
267
BlockZero(&fileinfo, sizeof(fileinfo));
268
// memset(&fileinfo, 0, sizeof(fileinfo));
269
fileinfo.fullsearch = true;
270
fileinfo.suppressload = true;
271
fileinfo.dependencyType = cwNormalDependency;
272
fileinfo.isdependentoffile = kCurrentCompiledFile;
274
/* locate the file name using the project's access paths */
275
CWResult err = CWFindAndLoadFile(context, filename, &fileinfo);
276
if (err == cwNoErr) {
277
file = fileinfo.filespec;
278
} else if (err == cwErrFileNotFound) {
280
sprintf(errmsg, "Can't locate file \"%s\".", filename);
281
CWResult callbackResult = CWReportMessage(context, 0, errmsg, 0, messagetypeError, 0);
288
* Substitute for standard fopen, treats certain filenames specially,
289
* and also considers the mode argument. If a file is being opened
290
* for reading, the file is assumed to be locateable using CodeWarrior's
291
* standard access paths. If it's for writing, the file is opened in
292
* the current project's output directory.
294
FILE* std::fopen(const char* filename, const char *mode)
297
CWResult err = noErr;
299
if (filename == gSourcePath || strcmp(filename, gSourcePath) == 0) {
300
// opening the main source file.
301
filespec = gSourceFile;
302
} else if (mode[0] == 'w') {
303
// if an output file, open it in the current compilation's output directory.
304
c2p_strcpy(filespec.name, filename);
305
filespec.vRefNum = gOutputFile.vRefNum;
306
filespec.parID = gOutputFile.parID;
307
c2p_strcpy(gOutputFile.name, filename);
309
// an input file, use CodeWarrior's search paths to find the named source file.
310
err = LocateFile(gPluginContext, filename, filespec);
313
// if all went well, we have a file to open.
314
return (err == noErr ? FSp_fopen(&filespec, mode) : NULL);
318
* Returns the length of a file, assuming it is always located in the
319
* project's output directory.
321
size_t mac_get_file_length(const char* filename)
323
long dataSize= 0, rsrcSize = 0;
325
if (CWGetOutputFileDirectory(gPluginContext, &filespec) != noErr)
327
c2p_strcpy(filespec.name, filename);
328
if (FSpGetFileSize(&filespec, &dataSize, &rsrcSize) != noErr)
333
void mac_warning(const char* warning_message)
335
CWReportMessage(gPluginContext, 0, warning_message, 0, messagetypeWarning, 0);
338
void mac_error(const char* error_message)
340
CWReportMessage(gPluginContext, 0, error_message, 0, messagetypeError, 0);
343
// plugin compiler exports.
345
#if CW_USE_PRAGMA_EXPORT
349
CWPLUGIN_ENTRY(CWPlugin_GetDropInFlags)(const DropInFlags** flags, long* flagsSize)
351
static const DropInFlags sFlags = {
352
kCurrentDropInFlagsVersion,
353
CWDROPINCOMPILERTYPE,
354
DROPINCOMPILERLINKERAPIVERSION,
355
(kGeneratescode | /* kCandisassemble | */ kCompMultiTargAware | kCompAlwaysReload),
357
DROPINCOMPILERLINKERAPIVERSION
361
*flagsSize = sizeof(sFlags);
366
CWPLUGIN_ENTRY(CWPlugin_GetDropInName)(const char** dropinName)
368
static const char* sDropInName = "xpidl";
370
*dropinName = sDropInName;
375
CWPLUGIN_ENTRY(CWPlugin_GetDisplayName)(const char** displayName)
377
static const char* sDisplayName = "xpidl";
379
*displayName = sDisplayName;
384
CWPLUGIN_ENTRY(CWPlugin_GetPanelList)(const CWPanelList** panelList)
386
static const char* sPanelName = kXPIDLPanelName;
387
static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 1, &sPanelName };
389
*panelList = &sPanelList;
394
CWPLUGIN_ENTRY(CWPlugin_GetTargetList)(const CWTargetList** targetList)
396
static CWDataType sCPU = '****';
397
static CWDataType sOS = '****';
398
static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS };
400
*targetList = &sTargetList;
405
CWPLUGIN_ENTRY(CWPlugin_GetDefaultMappingList)(const CWExtMapList** defaultMappingList)
407
static CWExtensionMapping sExtension = { 'TEXT', ".idl", 0 };
408
static CWExtMapList sExtensionMapList = { kCurrentCWExtMapListVersion, 1, &sExtension };
410
*defaultMappingList = &sExtensionMapList;
415
#if CW_USE_PRAGMA_EXPORT