Index: generators/library/LibraryGenerator.m ================================================================== --- generators/library/LibraryGenerator.m +++ generators/library/LibraryGenerator.m @@ -16,209 +16,40 @@ */ #include "config.h" #import "OFApplication.h" -#import "OFArray.h" #import "OFFile.h" -#import "OFXMLAttribute.h" +#import "OFFileManager.h" +#import "OFURL.h" #import "OFXMLElement.h" -#import "OFInvalidFormatException.h" -#import "OFUnsupportedVersionException.h" - -#import "copyright.h" +#import "LinkLibGenerator.h" @interface LibraryGenerator: OFObject @end OF_APPLICATION_DELEGATE(LibraryGenerator) @implementation LibraryGenerator -- (void)generateLinkLibInDirectory: (OFString *)directory -{ - OFXMLElement *library = [OFXMLElement elementWithFile: - [directory stringByAppendingPathComponent: @"library.xml"]]; - OFString *linklibPath = [[directory - stringByAppendingPathComponent: @"linklib"] - stringByAppendingPathComponent: @"linklib.m"]; - OFFile *linklib = [OFFile fileWithPath: linklibPath - mode: @"w"]; - OFArray OF_GENERIC(OFXMLElement *) *functions; - size_t funcIndex = 0; - OFString *libBase; - - if (![library.name isEqual: @"amiga-library"] || - library.namespace != nil) - @throw [OFInvalidFormatException exception]; - - OFXMLAttribute *version = [library attributeForName: @"version"]; - if (version == nil) - @throw [OFInvalidFormatException exception]; - - if (![version.stringValue isEqual: @"1.0"]) - @throw [OFUnsupportedVersionException - exceptionWithVersion: version.stringValue]; - - libBase = [library attributeForName: @"base"].stringValue; - - [linklib writeString: COPYRIGHT]; - [linklib writeString: - @"/* This file is automatically generated from library.xml */\n" - @"\n" - @"#include \"config.h\"\n" - @"\n"]; - - for (OFXMLElement *include in [library elementsForName: @"include"]) - [linklib writeFormat: @"#import \"%@\"\n", include.stringValue]; - - [linklib writeFormat: @"\n" - @"extern struct Library *%@;\n" - @"\n", - libBase]; - - functions = [library elementsForName: @"function"]; - for (OFXMLElement *function in functions) { - OFString *name = - [function attributeForName: @"name"].stringValue; - OFString *returnType = - [function attributeForName: @"return-type"].stringValue; - OFArray OF_GENERIC(OFXMLElement *) *arguments = - [function elementsForName: @"argument"]; - size_t argumentIndex; - - if (returnType == nil) - returnType = @"void"; - - [linklib writeFormat: @"%@\n%@(", returnType, name]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - OFString *argType = - [argument attributeForName: @"type"].stringValue; - - if (argumentIndex++ > 0) - [linklib writeString: @", "]; - - [linklib writeString: argType]; - if (![argType hasSuffix: @"*"]) - [linklib writeString: @" "]; - [linklib writeString: argName]; - } - - [linklib writeFormat: - @")\n" - @"{\n" - @"#if defined(OF_AMIGAOS_M68K)\n" - @"\tregister struct Library *a6 __asm__(\"a6\") = %@;\n" - @"\t(void)a6;\n" - @"\t", libBase]; - - if (![returnType isEqual: @"void"]) - [linklib writeString: @"return "]; - - [linklib writeString: @"(("]; - [linklib writeString: returnType]; - if (![returnType hasSuffix: @"*"]) - [linklib writeString: @" "]; - [linklib writeString: @"(*)("]; - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argType = - [argument attributeForName: @"type"].stringValue; - OFString *m68kReg = [argument - attributeForName: @"m68k-reg"].stringValue; - - if (argumentIndex++ > 0) - [linklib writeString: @", "]; - - [linklib writeString: argType]; - if (![argType hasSuffix: @"*"]) - [linklib writeString: @" "]; - [linklib writeFormat: @"__asm__(\"%@\")", m68kReg]; - } - - [linklib writeFormat: @"))(((uintptr_t)%@) - %zu))(", - libBase, 30 + funcIndex * 6]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - - if (argumentIndex++ > 0) - [linklib writeString: @", "]; - - [linklib writeString: argName]; - } - - [linklib writeFormat: - @");\n" - @"#elif defined(OF_MORPHOS)\n" - @"\t__asm__ __volatile__ (\n" - @"\t \"mr\t\t%%%%r12, %%0\"\n" - @"\t :: \"r\"(%@) : \"r12\"\n" - @"\t);\n" - @"\n" - @"\t", - libBase, libBase]; - - if (![returnType isEqual: @"void"]) - [linklib writeString: @"return "]; - - [linklib writeString: @"__extension__ (("]; - [linklib writeString: returnType]; - if (![returnType hasSuffix: @"*"]) - [linklib writeString: @" "]; - [linklib writeString: @"(*)("]; - - argumentIndex = 0; - for (OFXMLElement *argument in arguments) { - OFString *argType = - [argument attributeForName: @"type"].stringValue; - - if (argumentIndex++ > 0) - [linklib writeString: @", "]; - - [linklib writeString: argType]; - } - - [linklib writeFormat: @"))*(void **)(((uintptr_t)%@) - %zu))(", - libBase, 28 + funcIndex * 6]; - - argumentIndex = 0; - for (OFXMLElement *argument in - [function elementsForName: @"argument"]) { - OFString *argName = - [argument attributeForName: @"name"].stringValue; - - if (argumentIndex++ > 0) - [linklib writeString: @", "]; - - [linklib writeString: argName]; - } - - [linklib writeString: @");\n" - @"#endif\n"]; - - if ([function attributeForName: @"noreturn"] != nil) - [linklib writeString: @"\n\tOF_UNREACHABLE\n"]; - - [linklib writeString: @"}\n"]; - - if (++funcIndex < functions.count) - [linklib writeString: @"\n"]; - } -} - - (void)applicationDidFinishLaunching { - [self generateLinkLibInDirectory: @"../../src/runtime"]; + OFURL *sourcesURL = [[OFFileManager defaultManager].currentDirectoryURL + URLByAppendingPathComponent: @"../../src"]; + OFURL *runtimeLibraryPath = [sourcesURL + URLByAppendingPathComponent: @"runtime/library.xml"]; + OFURL *runtimeLinkLibPath = [sourcesURL + URLByAppendingPathComponent: @"runtime/linklib/linklib.m"]; + OFXMLElement *runtimeLibrary = [OFXMLElement elementWithStream: + [OFFile fileWithURL: runtimeLibraryPath + mode: @"r"]]; + OFFile *runtimeLinkLib = [OFFile fileWithURL: runtimeLinkLibPath + mode: @"w"]; + LinkLibGenerator *runtimeLinkLibGenerator = [[[LinkLibGenerator alloc] + initWithLibrary: runtimeLibrary + outputStream: runtimeLinkLib] autorelease]; + + [runtimeLinkLibGenerator generate]; [OFApplication terminate]; } @end ADDED generators/library/LinkLibGenerator.h Index: generators/library/LinkLibGenerator.h ================================================================== --- /dev/null +++ generators/library/LinkLibGenerator.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" +#import "OFStream.h" +#import "OFXMLElement.h" + +@interface LinkLibGenerator: OFObject +{ + OFXMLElement *_library; + OFStream *_outputStream; +} + +- (instancetype)initWithLibrary: (OFXMLElement *)library + outputStream: (OFStream *)outputStream; +- (void)generate; +@end ADDED generators/library/LinkLibGenerator.m Index: generators/library/LinkLibGenerator.m ================================================================== --- /dev/null +++ generators/library/LinkLibGenerator.m @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFArray.h" +#import "OFXMLAttribute.h" + +#import "LinkLibGenerator.h" + +#import "OFInvalidFormatException.h" +#import "OFUnsupportedVersionException.h" + +#import "copyright.h" + +@implementation LinkLibGenerator +- (instancetype)initWithLibrary: (OFXMLElement *)library + outputStream: (OFStream *)outputStream +{ + self = [super init]; + + @try { + OFXMLAttribute *version; + + if (![library.name isEqual: @"amiga-library"] || + library.namespace != nil) + @throw [OFInvalidFormatException exception]; + + if ((version = [library attributeForName: @"version"]) == nil) + @throw [OFInvalidFormatException exception]; + + if (![version.stringValue isEqual: @"1.0"]) + @throw [OFUnsupportedVersionException + exceptionWithVersion: version.stringValue]; + + _library = [library retain]; + _outputStream = [outputStream retain]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_library release]; + [_outputStream release]; + + [super dealloc]; +} + +- (void)generate +{ + OFString *libBase = [_library attributeForName: @"base"].stringValue; + OFArray OF_GENERIC(OFXMLElement *) *functions; + size_t funcIndex = 0; + + [_outputStream writeString: COPYRIGHT]; + [_outputStream writeString: + @"/* This file is automatically generated from library.xml */\n" + @"\n" + @"#include \"config.h\"\n" + @"\n"]; + + for (OFXMLElement *include in [_library elementsForName: @"include"]) + [_outputStream writeFormat: @"#import \"%@\"\n", + include.stringValue]; + + [_outputStream writeFormat: @"\n" + @"extern struct Library *%@;\n" + @"\n", + libBase]; + + functions = [_library elementsForName: @"function"]; + for (OFXMLElement *function in functions) { + OFString *name = + [function attributeForName: @"name"].stringValue; + OFString *returnType = + [function attributeForName: @"return-type"].stringValue; + OFArray OF_GENERIC(OFXMLElement *) *arguments = + [function elementsForName: @"argument"]; + size_t argumentIndex; + + if (returnType == nil) + returnType = @"void"; + + [_outputStream writeFormat: @"%@\n%@(", returnType, name]; + + argumentIndex = 0; + for (OFXMLElement *argument in + [function elementsForName: @"argument"]) { + OFString *argName = + [argument attributeForName: @"name"].stringValue; + OFString *argType = + [argument attributeForName: @"type"].stringValue; + + if (argumentIndex++ > 0) + [_outputStream writeString: @", "]; + + [_outputStream writeString: argType]; + if (![argType hasSuffix: @"*"]) + [_outputStream writeString: @" "]; + [_outputStream writeString: argName]; + } + + [_outputStream writeFormat: + @")\n" + @"{\n" + @"#if defined(OF_AMIGAOS_M68K)\n" + @"\tregister struct Library *a6 __asm__(\"a6\") = %@;\n" + @"\t(void)a6;\n" + @"\t", libBase]; + + if (![returnType isEqual: @"void"]) + [_outputStream writeString: @"return "]; + + [_outputStream writeString: @"(("]; + [_outputStream writeString: returnType]; + if (![returnType hasSuffix: @"*"]) + [_outputStream writeString: @" "]; + [_outputStream writeString: @"(*)("]; + + argumentIndex = 0; + for (OFXMLElement *argument in arguments) { + OFString *argType = + [argument attributeForName: @"type"].stringValue; + OFString *m68kReg = [argument + attributeForName: @"m68k-reg"].stringValue; + + if (argumentIndex++ > 0) + [_outputStream writeString: @", "]; + + [_outputStream writeString: argType]; + if (![argType hasSuffix: @"*"]) + [_outputStream writeString: @" "]; + [_outputStream writeFormat: @"__asm__(\"%@\")", + m68kReg]; + } + + [_outputStream writeFormat: @"))(((uintptr_t)%@) - %zu))(", + libBase, 30 + funcIndex * 6]; + + argumentIndex = 0; + for (OFXMLElement *argument in + [function elementsForName: @"argument"]) { + OFString *argName = + [argument attributeForName: @"name"].stringValue; + + if (argumentIndex++ > 0) + [_outputStream writeString: @", "]; + + [_outputStream writeString: argName]; + } + + [_outputStream writeFormat: + @");\n" + @"#elif defined(OF_MORPHOS)\n" + @"\t__asm__ __volatile__ (\n" + @"\t \"mr\t\t%%%%r12, %%0\"\n" + @"\t :: \"r\"(%@) : \"r12\"\n" + @"\t);\n" + @"\n" + @"\t", + libBase, libBase]; + + if (![returnType isEqual: @"void"]) + [_outputStream writeString: @"return "]; + + [_outputStream writeString: @"__extension__ (("]; + [_outputStream writeString: returnType]; + if (![returnType hasSuffix: @"*"]) + [_outputStream writeString: @" "]; + [_outputStream writeString: @"(*)("]; + + argumentIndex = 0; + for (OFXMLElement *argument in arguments) { + OFString *argType = + [argument attributeForName: @"type"].stringValue; + + if (argumentIndex++ > 0) + [_outputStream writeString: @", "]; + + [_outputStream writeString: argType]; + } + + [_outputStream writeFormat: + @"))*(void **)(((uintptr_t)%@) - %zu))(", + libBase, 28 + funcIndex * 6]; + + argumentIndex = 0; + for (OFXMLElement *argument in + [function elementsForName: @"argument"]) { + OFString *argName = + [argument attributeForName: @"name"].stringValue; + + if (argumentIndex++ > 0) + [_outputStream writeString: @", "]; + + [_outputStream writeString: argName]; + } + + [_outputStream writeString: @");\n" + @"#endif\n"]; + + if ([function attributeForName: @"noreturn"] != nil) + [_outputStream writeString: @"\n\tOF_UNREACHABLE\n"]; + + [_outputStream writeString: @"}\n"]; + + if (++funcIndex < functions.count) + [_outputStream writeString: @"\n"]; + } +} +@end Index: generators/library/Makefile ================================================================== --- generators/library/Makefile +++ generators/library/Makefile @@ -1,9 +1,10 @@ include ../../extra.mk PROG_NOINST = gen_libraries${PROG_SUFFIX} -SRCS = LibraryGenerator.m +SRCS = LibraryGenerator.m \ + LinkLibGenerator.m .PHONY: run run: all rm -f libobjfw.so.${OBJFW_LIB_MAJOR} rm -f libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} @@ -19,14 +20,14 @@ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi if test -f ../../src/objfw.dll; then \ - ${LN_S} ../src/objfw.dll objfw.dll; \ + ${LN_S} ../../src/objfw.dll objfw.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ - ${LN_S} ../src/libobjfw.dylib \ + ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi if test -f ../../src/runtime/libobjfwrt.so; then \ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \ Index: generators/unicode/Makefile ================================================================== --- generators/unicode/Makefile +++ generators/unicode/Makefile @@ -19,14 +19,14 @@ elif test -f ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; then \ ${LN_S} ../../src/libobjfw.so.${OBJFW_LIB_MAJOR_MINOR} \ libobjfw.so.${OBJFW_LIB_MAJOR_MINOR}; \ fi if test -f ../../src/objfw.dll; then \ - ${LN_S} ../src/objfw.dll objfw.dll; \ + ${LN_S} ../../src/objfw.dll objfw.dll; \ fi if test -f ../../src/libobjfw.dylib; then \ - ${LN_S} ../src/libobjfw.dylib \ + ${LN_S} ../../src/libobjfw.dylib \ libobjfw.${OBJFW_LIB_MAJOR}.dylib; \ fi if test -f ../../src/runtime/libobjfwrt.so; then \ ${LN_S} ../../src/runtime/libobjfwrt.so \ libobjfwrt.so.${OBJFWRT_LIB_MAJOR}; \