Changeset 239
- Timestamp:
- 07/15/07 10:23:13 (1 year ago)
- Files:
-
- trunk/cocoa/mogenerator (modified) (1 prop)
- trunk/cocoa/mogenerator/ddcli (added)
- trunk/cocoa/mogenerator/ddcli/DDCliApplication.h (added)
- trunk/cocoa/mogenerator/ddcli/DDCliApplication.m (added)
- trunk/cocoa/mogenerator/ddcli/DDCliParseException.h (added)
- trunk/cocoa/mogenerator/ddcli/DDCliParseException.m (added)
- trunk/cocoa/mogenerator/ddcli/DDCliUtil.h (added)
- trunk/cocoa/mogenerator/ddcli/DDCliUtil.m (added)
- trunk/cocoa/mogenerator/ddcli/DDCommandLineInterface.h (added)
- trunk/cocoa/mogenerator/ddcli/DDGetoptLongParser.h (added)
- trunk/cocoa/mogenerator/ddcli/DDGetoptLongParser.m (added)
- trunk/cocoa/mogenerator/mogenerator.m (modified) (10 diffs)
- trunk/cocoa/mogenerator/mogenerator.xcodeproj/project.pbxproj (modified) (7 diffs)
- trunk/cocoa/mogenerator/mogeneratorTestMule (modified) (1 prop)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cocoa/mogenerator
- Property svn:ignore set to
build
scratch
- Property svn:ignore set to
trunk/cocoa/mogenerator/mogenerator.m
r236 r239 15 15 #import "nsenumerate.h" 16 16 #import "NSString+MiscAdditions.h" 17 18 #include <getopt.h> 17 #import "DDCommandLineInterface.h" 19 18 20 19 NSString *gCustomBaseClass; … … 165 164 166 165 NSLog(@"appSupportFileNamed(@\"%@\"): file not found", fileName_); 167 exit( 1);166 exit(EXIT_FAILURE); 168 167 return nil; 169 168 } 170 169 171 #define DEOPT_(OPTION_NAME) OPTION_NAME+(sizeof("opt_")-1) 172 #define LONG_OPT(OPTION_NAME, HAS_ARG) {DEOPT_(#OPTION_NAME), HAS_ARG, NULL, OPTION_NAME} 173 #define LONG_OPT_LAST { NULL,0,NULL,0 } 174 175 enum { 176 opt_help = 1, 177 opt_version, 178 opt_model, 179 opt_baseClass, 180 opt_includem, 181 opt_templatePath 182 }; 183 184 int main (int argc, const char * argv[]) { 185 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 186 187 NSManagedObjectModel *model = nil; 188 NSString *tempMOMPath = nil; 189 NSString *mfilePath = nil; 190 NSMutableString *mfileContent = [NSMutableString stringWithString:@""]; 191 192 static struct option longopts[] = { 193 LONG_OPT(opt_help, no_argument), 194 LONG_OPT(opt_version, no_argument), 195 LONG_OPT(opt_model, required_argument), 196 LONG_OPT(opt_baseClass, required_argument), 197 LONG_OPT(opt_includem, required_argument), 198 LONG_OPT(opt_templatePath, required_argument), 199 LONG_OPT_LAST 200 }; 201 int opt_code; 202 while ((opt_code = getopt_long_only(argc, (char* const*)argv, "m:", longopts, NULL)) != -1) { 203 switch (opt_code) { 204 case opt_model: 205 assert(!model); // Currently we only can load one model. 206 NSString *path = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:optarg length:strlen(optarg)]; 207 208 if( ![[NSFileManager defaultManager] fileExistsAtPath:path]){ 209 fprintf(stderr, "mogenerator: error loading file at %s: no such file exists.\n", optarg); 210 return ENOENT; 211 } 212 213 if ([[path pathExtension] isEqualToString:@"xcdatamodel"]) { 214 // We've been handed a .xcdatamodel data model, transparently compile it into a .mom managed object model. 215 NSString *momc = [[NSFileManager defaultManager] fileExistsAtPath:@"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"] 216 ? @"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc" 217 : @"/Developer/Library/Xcode/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"; 218 219 tempMOMPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[(id)CFUUIDCreateString(kCFAllocatorDefault, CFUUIDCreate(kCFAllocatorDefault)) autorelease]] stringByAppendingPathExtension:@"mom"]; 220 system([[NSString stringWithFormat:@"\"%@\" %@ %@", momc, path, tempMOMPath] UTF8String]); // Ignored system's result -- momc doesn't return any relevent error codes. 221 path = tempMOMPath; 222 } 223 model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]] autorelease]; 224 assert(model); 225 break; 226 case opt_baseClass: 227 gCustomBaseClass = [NSString stringWithUTF8String:optarg]; 228 break; 229 case opt_includem: 230 assert(!mfilePath); 231 mfilePath = [NSString stringWithUTF8String:optarg]; 232 assert(mfilePath); 233 assert([mfilePath length]); 234 break; 235 case opt_version: 236 printf("mogenerator 1.3. By Jonathan 'Wolf' Rentzsch + friends.\n"); 237 break; 238 case opt_templatePath: 239 gTemplatePath = [NSString stringWithUTF8String:optarg]; 240 break; 241 case opt_help: 242 default: 243 printf("mogenerator [-model /path/to/file.xcdatamodel] [-baseClass MyBaseClassMO] [-includem include.m] [-version] [-templatePath] [-help]\n"); 244 printf("Implements generation gap codegen pattern for Core Data. Inspired by eogenerator.\n"); 245 } 246 } 247 argc -= optind; 248 argv += optind; 249 170 @interface MOGeneratorApp : NSObject <DDCliApplicationDelegate> 171 { 172 NSString * tempMOMPath; 173 NSManagedObjectModel * model; 174 NSString * baseClass; 175 NSString * includem; 176 NSString * templatePath; 177 NSString * outputDir; 178 NSString * machineDir; 179 NSString * humanDir; 180 BOOL _help; 181 BOOL _version; 182 } 183 184 @end 185 186 @implementation MOGeneratorApp 187 188 - (void) application: (DDCliApplication *) app 189 willParseOptions: (DDGetoptLongParser *) optionsParser; 190 { 191 [optionsParser setGetoptLongOnly: YES]; 192 DDGetoptOption optionTable[] = 193 { 194 // Long Short Argument options 195 {@"model", 'm', DDGetoptRequiredArgument}, 196 {@"base-class", 0, DDGetoptRequiredArgument}, 197 // For compatibility: 198 {@"baseClass", 0, DDGetoptRequiredArgument}, 199 {@"includem", 0, DDGetoptRequiredArgument}, 200 {@"template-path", 0, DDGetoptRequiredArgument}, 201 // For compatibility: 202 {@"templatePath", 0, DDGetoptRequiredArgument}, 203 {@"output-dir", 'O', DDGetoptRequiredArgument}, 204 {@"machine-dir", 'M', DDGetoptRequiredArgument}, 205 {@"human-dir", 'H', DDGetoptRequiredArgument}, 206 207 {@"help", 'h', DDGetoptNoArgument}, 208 {@"version", 0, DDGetoptNoArgument}, 209 {nil, 0, 0}, 210 }; 211 [optionsParser addOptionsFromTable: optionTable]; 212 } 213 214 - (void) printUsage; 215 { 216 ddprintf(@"%@: Usage [OPTIONS] <argument> [...]\n", DDCliApp); 217 printf("\n" 218 " -m, --model MODEL Path to model\n" 219 " --base-class CLASS Custom base class\n" 220 " --includem FILE Generate aggregate include file\n" 221 " --template-path PATH Path to templates\n" 222 " -O, --output-dir DIR Output directory\n" 223 " -M, --machine-dir DIR Output directory for machine files\n" 224 " -H, --human-dir DIR Output director for human files\n" 225 " --version Display version and exit\n" 226 " -h, --help Display this help and exit\n" 227 "\n" 228 "Implements generation gap codegen pattern for Core Data.\n" 229 "Inspired by eogenerator.\n"); 230 } 231 232 - (void) setModel: (NSString *) path; 233 { 234 assert(!model); // Currently we only can load one model. 235 236 if( ![[NSFileManager defaultManager] fileExistsAtPath:path]){ 237 NSString * reason = [NSString stringWithFormat: @"error loading file at %@: no such file exists", path]; 238 DDCliParseException * e = [DDCliParseException parseExceptionWithReason: reason 239 exitCode: EX_NOINPUT]; 240 @throw e; 241 } 242 243 if ([[path pathExtension] isEqualToString:@"xcdatamodel"]) { 244 // We've been handed a .xcdatamodel data model, transparently compile it into a .mom managed object model. 245 NSString *momc = [[NSFileManager defaultManager] fileExistsAtPath:@"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"] 246 ? @"/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc" 247 : @"/Developer/Library/Xcode/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc"; 248 249 tempMOMPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[(id)CFUUIDCreateString(kCFAllocatorDefault, CFUUIDCreate(kCFAllocatorDefault)) autorelease]] stringByAppendingPathExtension:@"mom"]; 250 system([[NSString stringWithFormat:@"\"%@\" %@ %@", momc, path, tempMOMPath] UTF8String]); // Ignored system's result -- momc doesn't return any relevent error codes. 251 path = tempMOMPath; 252 } 253 model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]] autorelease]; 254 assert(model); 255 } 256 257 - (int) application: (DDCliApplication *) app 258 runWithArguments: (NSArray *) arguments; 259 { 260 if (_help) 261 { 262 [self printUsage]; 263 return EXIT_SUCCESS; 264 } 265 266 if (_version) 267 { 268 printf("mogenerator 1.4. By Jonathan 'Wolf' Rentzsch + friends.\n"); 269 return EXIT_SUCCESS; 270 } 271 272 gCustomBaseClass = [baseClass retain]; 273 gTemplatePath = templatePath; 274 NSString * mfilePath = includem; 275 NSMutableString * mfileContent = [NSMutableString stringWithString:@""]; 276 if (outputDir == nil) 277 outputDir = @""; 278 if (machineDir == nil) 279 machineDir = outputDir; 280 if (humanDir == nil) 281 humanDir = outputDir; 282 250 283 NSFileManager *fm = [NSFileManager defaultManager]; 251 284 252 285 int machineFilesGenerated = 0; 253 286 int humanFilesGenerated = 0; … … 262 295 MiscMergeEngine *humanM = engineWithTemplatePath(appSupportFileNamed(@"human.m.motemplate")); 263 296 assert(humanM); 264 297 265 298 int entityCount = [[model entities] count]; 266 299 267 300 if(entityCount == 0){ 268 301 printf("No entities found in model. No files will be generated.\n"); … … 272 305 nsenumerate ([model entities], NSEntityDescription, entity) { 273 306 NSString *entityClassName = [entity managedObjectClassName]; 274 307 275 308 if ([entityClassName isEqualToString:@"NSManagedObject"] || 276 309 [entityClassName isEqualToString:gCustomBaseClass]){ 277 printf("skipping entity %sbecause it doesn't use a custom subclass.\n",278 [entityClassName cStringUsingEncoding:NSUTF8StringEncoding]);310 ddprintf(@"skipping entity %@ because it doesn't use a custom subclass.\n", 311 entityClassName); 279 312 continue; 280 313 } … … 287 320 BOOL machineDirtied = NO; 288 321 289 NSString *machineHFileName = [NSString stringWithFormat:@"_%@.h", entityClassName]; 322 NSString *machineHFileName = [machineDir stringByAppendingPathComponent: 323 [NSString stringWithFormat:@"_%@.h", entityClassName]]; 290 324 if (![fm regularFileExistsAtPath:machineHFileName] || ![generatedMachineH isEqualToString:[NSString stringWithContentsOfFile:machineHFileName]]) { 291 325 // If the file doesn't exist or is different than what we just generated, write it out. … … 294 328 machineFilesGenerated++; 295 329 } 296 NSString *machineMFileName = [NSString stringWithFormat:@"_%@.m", entityClassName]; 330 NSString *machineMFileName = [machineDir stringByAppendingPathComponent: 331 [NSString stringWithFormat:@"_%@.m", entityClassName]]; 297 332 if (![fm regularFileExistsAtPath:machineMFileName] || ![generatedMachineM isEqualToString:[NSString stringWithContentsOfFile:machineMFileName]]) { 298 333 // If the file doesn't exist or is different than what we just generated, write it out. … … 301 336 machineFilesGenerated++; 302 337 } 303 NSString *humanHFileName = [NSString stringWithFormat:@"%@.h", entityClassName]; 338 NSString *humanHFileName = [humanDir stringByAppendingPathComponent: 339 [NSString stringWithFormat:@"%@.h", entityClassName]]; 304 340 if ([fm regularFileExistsAtPath:humanHFileName]) { 305 341 if (machineDirtied) … … 309 345 humanFilesGenerated++; 310 346 } 311 NSString *humanMFileName = [NSString stringWithFormat:@"%@.m", entityClassName]; 312 NSString *humanMMFileName = [NSString stringWithFormat:@"%@.mm", entityClassName]; 347 NSString *humanMFileName = [humanDir stringByAppendingPathComponent: 348 [NSString stringWithFormat:@"%@.m", entityClassName]]; 349 NSString *humanMMFileName = [humanDir stringByAppendingPathComponent: 350 [NSString stringWithFormat:@"%@.mm", entityClassName]]; 313 351 if (![fm regularFileExistsAtPath:humanMFileName] && [fm regularFileExistsAtPath:humanMMFileName]) { 314 352 // Allow .mm human files as well as .m files. … … 324 362 } 325 363 326 [mfileContent appendFormat:@"#include \"%@\"\n#include \"%@\"\n", humanMFileName, machineMFileName]; 364 [mfileContent appendFormat:@"#include \"%@\"\n#include \"%@\"\n", 365 [humanMFileName lastPathComponent], [machineMFileName lastPathComponent]]; 327 366 } 328 367 } … … 339 378 printf("%d machine files%s %d human files%s generated.\n", machineFilesGenerated, 340 379 (mfileGenerated ? "," : " and"), humanFilesGenerated, (mfileGenerated ? " and one include.m file" : "")); 341 342 [pool release]; 343 return 0; 344 } 380 381 return EXIT_SUCCESS; 382 } 383 384 @end 385 386 int main (int argc, char * const * argv) 387 { 388 return DDCliAppRunWithClass([MOGeneratorApp class]); 389 } 390 trunk/cocoa/mogenerator/mogenerator.xcodeproj/project.pbxproj
r228 r239 8 8 9 9 /* Begin PBXBuildFile section */ 10 55200E960C49FEEA00018A42 /* DDCliApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E900C49FEEA00018A42 /* DDCliApplication.m */; }; 11 55200E970C49FEEA00018A42 /* DDCliUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E920C49FEEA00018A42 /* DDCliUtil.m */; }; 12 55200E980C49FEEA00018A42 /* DDGetoptLongParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */; }; 13 55200F9D0C4A2CA800018A42 /* DDCliParseException.m in Sources */ = {isa = PBXBuildFile; fileRef = 55200F9C0C4A2CA800018A42 /* DDCliParseException.m */; }; 10 14 79D2BF3F0ACFB25B00F3F141 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79D2BF3E0ACFB25B00F3F141 /* CoreData.framework */; }; 11 15 79D2BFA20ACFB51A00F3F141 /* _MiscMergeBreakCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 79D2BF530ACFB51A00F3F141 /* _MiscMergeBreakCommand.m */; }; … … 57 61 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 58 62 32A70AAB03705E1F00C91783 /* mogenerator_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mogenerator_Prefix.pch; sourceTree = "<group>"; }; 63 55200E8F0C49FEEA00018A42 /* DDCliApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliApplication.h; sourceTree = "<group>"; }; 64 55200E900C49FEEA00018A42 /* DDCliApplication.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliApplication.m; sourceTree = "<group>"; }; 65 55200E910C49FEEA00018A42 /* DDCliUtil.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliUtil.h; sourceTree = "<group>"; }; 66 55200E920C49FEEA00018A42 /* DDCliUtil.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliUtil.m; sourceTree = "<group>"; }; 67 55200E930C49FEEA00018A42 /* DDCommandLineInterface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCommandLineInterface.h; sourceTree = "<group>"; }; 68 55200E940C49FEEA00018A42 /* DDGetoptLongParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDGetoptLongParser.h; sourceTree = "<group>"; }; 69 55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDGetoptLongParser.m; sourceTree = "<group>"; }; 70 55200F9B0C4A2CA800018A42 /* DDCliParseException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DDCliParseException.h; sourceTree = "<group>"; }; 71 55200F9C0C4A2CA800018A42 /* DDCliParseException.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DDCliParseException.m; sourceTree = "<group>"; }; 59 72 79D2BF3E0ACFB25B00F3F141 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; }; 60 73 79D2BF520ACFB51A00F3F141 /* _MiscMergeBreakCommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = _MiscMergeBreakCommand.h; path = ../MiscMerge/_MiscMergeBreakCommand.h; sourceTree = "<group>"; }; … … 161 174 08FB7795FE84155DC02AAC07 /* Source */, 162 175 79D2BF510ACFB51000F3F141 /* MiscMerge */, 176 55200E8E0C49FEEA00018A42 /* ddcli */, 163 177 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */, 164 178 1AB674ADFE9D54B511CA2CBB /* Products */, … … 194 208 ); 195 209 name = Products; 210 sourceTree = "<group>"; 211 }; 212 55200E8E0C49FEEA00018A42 /* ddcli */ = { 213 isa = PBXGroup; 214 children = ( 215 55200F9B0C4A2CA800018A42 /* DDCliParseException.h */, 216 55200F9C0C4A2CA800018A42 /* DDCliParseException.m */, 217 55200E8F0C49FEEA00018A42 /* DDCliApplication.h */, 218 55200E900C49FEEA00018A42 /* DDCliApplication.m */, 219 55200E910C49FEEA00018A42 /* DDCliUtil.h */, 220 55200E920C49FEEA00018A42 /* DDCliUtil.m */, 221 55200E930C49FEEA00018A42 /* DDCommandLineInterface.h */, 222 55200E940C49FEEA00018A42 /* DDGetoptLongParser.h */, 223 55200E950C49FEEA00018A42 /* DDGetoptLongParser.m */, 224 ); 225 path = ddcli; 196 226 sourceTree = "<group>"; 197 227 }; … … 364 394 79D2BFEF0ACFB51A00F3F141 /* NSString+MiscAdditions.m in Sources */, 365 395 79D2C05A0ACFBCB500F3F141 /* FoundationAdditions.m in Sources */, 396 55200E960C49FEEA00018A42 /* DDCliApplication.m in Sources */, 397 55200E970C49FEEA00018A42 /* DDCliUtil.m in Sources */, 398 55200E980C49FEEA00018A42 /* DDGetoptLongParser.m in Sources */, 399 55200F9D0C4A2CA800018A42 /* DDCliParseException.m in Sources */, 366 400 ); 367 401 runOnlyForDeploymentPostprocessing = 0; … … 409 443 buildSettings = { 410 444 GCC_C_LANGUAGE_STANDARD = c99; 445 GCC_ENABLE_OBJC_EXCEPTIONS = YES; 411 446 GCC_WARN_ABOUT_RETURN_TYPE = YES; 412 447 GCC_WARN_UNUSED_VARIABLE = YES; … … 420 455 buildSettings = { 421 456 GCC_C_LANGUAGE_STANDARD = c99; 457 GCC_ENABLE_OBJC_EXCEPTIONS = YES; 422 458 GCC_WARN_ABOUT_RETURN_TYPE = YES; 423 459 GCC_WARN_UNUSED_VARIABLE = YES; trunk/cocoa/mogenerator/mogeneratorTestMule
- Property svn:ignore set to
build
- Property svn:ignore set to
