Modul:Programmieren in C/C++:Vorlage:CompilerExplorerLink

Aus Wikibooks

Informationen zu dieser Dokumentation
Modul Programmieren in C

Modulbeschreibung

Diese Vorlage erzeugt die URL für einen Link zum Compiler Explorer.

Zur Vermeidung von

  • doppelter Datenhaltung, d.h. Code sowohl im Buch als auch im CompilerExplorer (mittels KurzLinks) zu pflegen
  • 'unnötigen' Code (wie z.B. Include-Anweisungen, Funktionsrumpf, ..) im Buch zu vermeiden und damit den Blick aufs wesentliche zu lenken.

ist hier ein LUA Modul vorhanden, bei welchen über die Übergabeparameter beim Funktionsaufruf der vollständige auszuführende Code übergeben wird. Das Modul erzeugt aus diesen Übergabeparameter eine URL zum Aufruf des CompilerExplorers. Dies ermöglicht es, sowohl den Beispielcode als auch den vollständigen Code im Buch zu pflegen. Ergänzend können über den Funktionsaufruf auch Compilerschalter, der Compiler selbst und mehrere Source-Dateien übergeben werden.

Ein typischer Aufruf dieser Vorlage sieht wie folgt aus:
{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|main_c=#include <stdio.h>
void main(){
    printf("Hello World!");
} }}
Und erzeugt folgenden HTML-Code:
https://www.godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:example.c,fontScale:14,fontUsePx:'0',j:1,lang:___c,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:'%23include+%3Cstdio%2Eh%3E%0Avoid+main%28%29%7B%0A++++printf%28%22Hello+World!!%22%29%3B%0A%7D'),l:'5',n:'0',o:example.c,t:'0')),header:(),k:50,l:'4',m:100,n:'0',o:%27%27,s:0,t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:cgsnapshot,compilerOutShown:'0',execArgs:%27%27,execStdin:%27%27,fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!(),options:%27%27,overrides:!(),runtimeTools:!(),source:'1',stdinPanelShown:'1',wrap:'1'),l:'5',n:'0',o:'Executor',t:'0')),header:(),k:50,l:'4',m:100,n:'0',o:%27%27,s:0,t:'0')),l:'2',n:'0',o:%27%27,t:'0')),version:4
Diese URL kann man dann in einem Link einfügen: Hello World!

Folgendes gilt es zu beachten:

  • Dateinamen und Inhalt jeder einzelnen verwendeten Datei bilden ein Schlüssel-Wert-Paar, wobei der Dateiname der Schüssel und der Dateiinhalt der Wert ist. Dabei ist zu beachten, dass Punkte in den Dateinamen durch Unterstriche (_) zu ersetzen sind, da es sonst zu einer Fehlermeldung kommt. Pipes (|) trennen die einzelnen Dateien voneinader. Wichtig: Bei mehr als einer Datei muss die erste Datei example.<dateiendung> heißen (wobei <dateiendung> je nach Sprache durch c, cpp oder java zu ersetzen ist) bzw. CMakeLists.txt, wenn es sich im ein CMake-Projekt handelt.
  • Doppelte geschweifte Klammern ({{ und }}) sind innerhalb des Quellcodes nicht gestattet und müssen immer durch ein Leerzeichen voneinander getrennt werden ({ { bzw. } }), da sie sonst als Anfang oder Ende einer Wiki-Vorlage interpretiert werden. Deshalb muss auch nach eine schließenden geschweiften Klammer am Ende einer Datei ein Leerzeichen oder Zeilenumbruch gesetzt werden.
  • Pipes (|) müssen im Quellcode durch {{!}} ersetzt werden, da sie sonst als Feldtrenner interpertiert werden.
  • Es gibt folgende optionale Parameter, die ebenfalls Schlüssel-Wert-Paare bilden und ebenfalls durch Pipes voneinander getrennt werden:
    • lang gibt die verwendete Programmiersprache an, wobei bisher nur C, C++ und Java sowohl groß als auch klein geschrieben möglich sind (standardmäßig C)
    • compiler enthält den Namen des verwendeten Compilers bzw. JDK-Version (standardmäßig "gsnapshot" für C bzw. "cgsnapshot" für C++ bzw. "java1601"):
    • Wenn man CMake verwendet, sind die folgenden Optionen wichtig:
      • isCMakeProject gibt an, ob es sich im ein CMake-Projekt handelt (standardmäßig false)
      • CMakeArgs enhält die CMake Arguments (standardmäßig "" (ein leerer String))
      • CMakeCustomOutputFilename enthält den Namen der Ausgabedatei (standardmäßig "" (ein leerer String))
    • libs enthält eingebundene C- und C++-Bibliotheken. Jede Bibliothek wird nach folgendem Schema eingebunden: (name:<name>,ver:'<versionsnummer'). Dabei steht <name> für den Compiler Explorer-internen Namen der Bibliothek und <versionsnummer> für deren Compiler Explorer-interne Versionsnummer. Kommata trennen die einzelnen Bibiliotheken voneinander. Eine vollständige Liste mit anderen möglichen C-Compilern kann man den Dateien c.amazon.properties (für C-Bibliotheken) und c++.amazon.properties (für C++-Bibliotheken) im GitHub Repositiory des Compiler Explorers entnehmen. (standardmäßig "" (ein leerer String))
    • Über h lässt sich einstellen, ob ein Executor-Fenster (e), ein Compiler-Fenster (c), ein Compiler-Fenster mit GCC Tree/RTL Viewer (g) oder ein Compiler-Fenster mit Präprozessor-Ausgabe (p) angezeigt werden soll (standardmäßig e)
      • Folgende Optionen gibt es für das Executor-Fenster:
        • execArgsPanelShown gibt an, ob die Execution Arguments angezeigt werden (standardmäßig false)
        • execCompilationPanelShown gibt an, ob der Compiler und die Compiler Options angezeigt werden (standardmäßig true)
        • execCompilerOutputShown gibt an, ob der Compiler Output angezeigt wird (standardmäßig true)
        • execArgs enthält die Execution Arguments (standardmäßig "" (ein leerer String))
        • execStdin enthät den Stdin (standardmäßig "" (ein leerer String))
        • execCompilerOptions wird für die Compiler-Optionen verwendet (standardmäßig "" (ein leerer String))
        • execStdinPanelShown gibt an, ob das Stdin angezeigt wird (standardmäßig false)
        • execLineWrap gibt an, ob es einen automatischen Zeilenumbruch gibt (standardmäßig false)
        • execEnv enthält Umgebungsvariablen, die als durch Semikolons getrennte Schlüssel-Wert-Paare eingetragen werden (standardmäßig "" (ein leerer String))
      • Für das Compiler-Fenster gibt es folgende Filter:
        • comFilterB gibt an, ob der Filter 'unused labels' angeschaltet werden soll (standardmäßig true)
        • comBinary gibt an, die Ausgabeoption 'Link to binary and disassemble the output' angeschaltet werden soll (standardmäßig false)
        • comBinaryObject gibt an, ob die Ausgabeoption 'Compare to binary object and disassemble the output' angeschaltet werden soll (standardmäßig false)
        • comFilterCommentOnly gibt an, ob der Filter 'comments' angeschaltet werden soll (standardmäßig true)
        • comDemangle gibt an, ob die Ausgabeoption 'Demangle output' angeschaltet werden soll (standardmäßig true)
        • comFilterDirectives gibt an, ob der Filter 'directives' angeschaltet werden soll (standardmäßig true)
        • comExecute gibt an, ob die Ausgabeoption 'Execute the code and show its output' angeschaltet werden soll (standardmäßig false)
        • comIntel gibt an, ob die Ausgabeoption 'Output disassembly in Intel syntax' angeschaltet werden soll (standardmäßig true)
        • comFilterLibraryCode gibt an, ob der Filter 'library functions' angeschaltet werden soll (standardmäßig true)
        • comFilterTrim gibt an, ob der Filter 'horizontal whitespace' angeschaltet werden soll (standardmäßig false)
      • Obwohl es für GCC Tree/RTL Viewer verschiedene Optionen und Einstellungen gibt, sind hier alle Optionen deaktiviert, alle Filter aktiviert und es wurde original (tree) als pass ausgewählt. Diese Einstellungen lassen durch dieses Script nicht ändern.
      • Für die Präprozessor-Ausgabe gibt es folgende Optionen:
        • preClangFormat gibt an, ob die Ausgabe im Clang-Format erfolgen soll (standardmäßig false)
        • preFilterHeaders gibt an, ob die Header herausgefiltert (d.h. nicht angezeigt) werden sollen (standardmäßig true)

Information


--- Diese Vorlage erzeugt die URL für einen Link zum [https://www.godbolt.org/ Compiler Explorer].
-- 
-- Zur Vermeidung von
-- * doppelter Datenhaltung, d.h. Code sowohl im Buch als auch im CompilerExplorer (mittels KurzLinks) zu pflegen
-- * 'unnötigen' Code (wie z.B. Include-Anweisungen, Funktionsrumpf, ..) im Buch zu vermeiden und damit den Blick aufs wesentliche zu lenken.
-- ist hier ein LUA Modul vorhanden, bei welchen über die Übergabeparameter beim Funktionsaufruf der vollständige auszuführende Code übergeben wird. Das Modul erzeugt aus diesen Übergabeparameter eine URL zum Aufruf des CompilerExplorers. Dies ermöglicht es, sowohl den Beispielcode als auch den vollständigen Code im Buch zu pflegen. Ergänzend können über den Funktionsaufruf auch Compilerschalter, der Compiler selbst und mehrere Source-Dateien übergeben werden. 
--
-- Ein typischer Aufruf dieser Vorlage sieht wie folgt aus:<br>
-- '''<nowiki>{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|main_c=#include <stdio.h></nowiki>'''<br>
-- '''<nowiki>void main(){</nowiki>'''<br>
-- '''<nowiki>&nbsp;&nbsp;&nbsp;&nbsp;printf("Hello World!");</nowiki>'''<br>
-- '''<nowiki>} }}</nowiki>'''<br>
-- Und erzeugt folgenden HTML-Code:<br>
-- '''{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|main_c=#include <stdio.h>
-- void main(){
--     printf("Hello World!");
-- } }}'''<br>
-- Diese URL kann man dann in einem Link einfügen: '''[{{:Programmieren in C/C++:Vorlage:CompilerExplorerLink|main_c=#include <stdio.h>
-- void main(){
--     printf("Hello World!");
-- } }} Hello World!]'''
--
-- Folgendes gilt es zu beachten:
-- * Dateinamen und Inhalt jeder einzelnen verwendeten Datei bilden ein Schlüssel-Wert-Paar, wobei der Dateiname der Schüssel und der Dateiinhalt der Wert ist. Dabei ist zu beachten, dass Punkte in den Dateinamen durch Unterstriche ('''_''') zu ersetzen sind, da es sonst zu einer Fehlermeldung kommt. Pipes ('''|''') trennen die einzelnen Dateien voneinader. '''Wichtig''': Bei mehr als einer Datei muss die erste Datei ''example.<dateiendung>'' heißen (wobei <dateiendung> je nach Sprache durch ''c'', ''cpp'' oder ''java'' zu ersetzen ist) bzw. ''CMakeLists.txt'', wenn es sich im ein CMake-Projekt handelt.
-- * Doppelte geschweifte Klammern ('''<nowiki>{{</nowiki>''' und '''<nowiki>}}</nowiki>''') sind innerhalb des Quellcodes nicht gestattet und müssen immer durch ein Leerzeichen voneinander getrennt werden ('''{ {''' bzw. '''} }'''), da sie sonst als Anfang oder Ende einer Wiki-Vorlage interpretiert werden. Deshalb muss auch nach eine schließenden geschweiften Klammer am Ende einer Datei ein Leerzeichen oder Zeilenumbruch gesetzt werden.
-- * Pipes ('''|''') müssen im Quellcode durch '''<nowiki>{{!}}</nowiki>''' ersetzt werden, da sie sonst als Feldtrenner interpertiert werden.
-- * Es gibt folgende optionale Parameter, die ebenfalls Schlüssel-Wert-Paare bilden und ebenfalls durch Pipes voneinander getrennt werden:
-- ** ''lang'' gibt die verwendete Programmiersprache an, wobei bisher nur ''C'', ''C++'' und ''Java'' sowohl groß als auch klein geschrieben möglich sind (standardmäßig '''C''')
-- ** ''compiler'' enthält den Namen des verwendeten Compilers bzw. JDK-Version (standardmäßig '''"gsnapshot"''' für C bzw. '''"cgsnapshot"''' für C++ bzw. '''"java1601"'''):
-- *** Für GCC-Compiler beginnt der Name mit cg gefolgt von der Versionsnummer ohne Punkte (also steht cg132 für GCC 13.2). Eine vollständige Liste mit anderen möglichen C-Compilern kann man den Dateien [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c.amazon.properties c.amazon.properties] und [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c.defaults.properties c.default.properties] im [https://github.com/compiler-explorer GitHub Repositiory] des [https://www.godbolt.org Compiler Explorers] entnehmen.
-- *** Für G++-Compiler beginnt der Name mit g gefolgt von der Versionsnummer ohne Punkte (also steht g132 für G++ 13.2). Eine vollständige Liste mit anderen möglichen C++-Compilern kann man den Dateien [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c++.amazon.properties c++.amazon.properties] und [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c++.defaults.properties c++.default.properties] im [https://github.com/compiler-explorer GitHub Repositiory] des [https://www.godbolt.org Compiler Explorers] entnehmen.
-- *** Für die JDK-Version beginnt der Name mit java gefolgt von der Versionsnummer ohne Punkte (also steht java1601 für JDK 16.0.1). Eine Übersicht der implementierten JDK-Versionen kann man der Datei [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/java.amazon.properties java.amazon.properties] im [https://github.com/compiler-explorer GitHub Repositiory] des [https://www.godbolt.org Compiler Explorers] entnehmen.
-- ** Wenn man CMake verwendet, sind die folgenden Optionen wichtig:
-- *** ''isCMakeProject'' gibt an, ob es sich im ein CMake-Projekt handelt (standardmäßig '''false''')
-- *** ''CMakeArgs'' enhält die CMake Arguments (standardmäßig '''""''' (ein leerer String))
-- *** ''CMakeCustomOutputFilename'' enthält den Namen der Ausgabedatei (standardmäßig '''""''' (ein leerer String))
-- ** ''libs'' enthält eingebundene C- und C++-Bibliotheken. Jede Bibliothek wird nach folgendem Schema eingebunden: ''(name:<name>,ver:'<versionsnummer')''. Dabei steht <name> für den Compiler Explorer-internen Namen der Bibliothek und <versionsnummer> für deren Compiler Explorer-interne Versionsnummer. Kommata trennen die einzelnen Bibiliotheken voneinander. Eine vollständige Liste mit anderen möglichen C-Compilern kann man den Dateien [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c.amazon.properties c.amazon.properties] (für C-Bibliotheken) und [https://github.com/compiler-explorer/compiler-explorer/blob/e861f94a0d32622395536175c5f3df5880bc8744/etc/config/c++.amazon.properties c++.amazon.properties] (für C++-Bibliotheken) im [https://github.com/compiler-explorer GitHub Repositiory] des [https://www.godbolt.org Compiler Explorers] entnehmen. (standardmäßig '''""''' (ein leerer String))
-- ** Über ''h'' lässt sich einstellen, ob ein Executor-Fenster (''e''), ein Compiler-Fenster (''c''), ein Compiler-Fenster mit GCC Tree/RTL Viewer (''g'') oder ein Compiler-Fenster mit Präprozessor-Ausgabe (''p'') angezeigt werden soll (standardmäßig '''e''')
-- *** Folgende Optionen gibt es für das Executor-Fenster:
-- **** ''execArgsPanelShown'' gibt an, ob die Execution Arguments angezeigt werden (standardmäßig '''false''')
-- **** ''execCompilationPanelShown'' gibt an, ob der Compiler und die Compiler Options angezeigt werden (standardmäßig '''true''')
-- **** ''execCompilerOutputShown'' gibt an, ob der Compiler Output angezeigt wird (standardmäßig '''true''')
-- **** ''execArgs'' enthält die Execution Arguments (standardmäßig '''""''' (ein leerer String))
-- **** ''execStdin'' enthät den Stdin (standardmäßig '''""''' (ein leerer String))
-- **** ''execCompilerOptions'' wird für die Compiler-Optionen verwendet (standardmäßig '''""''' (ein leerer String))
-- **** ''execStdinPanelShown'' gibt an, ob das Stdin angezeigt wird (standardmäßig '''false''')
-- **** ''execLineWrap'' gibt an, ob es einen automatischen Zeilenumbruch gibt (standardmäßig '''false''')
-- **** ''execEnv'' enthält Umgebungsvariablen, die als durch Semikolons getrennte Schlüssel-Wert-Paare eingetragen werden (standardmäßig '''""''' (ein leerer String))
-- *** Für das Compiler-Fenster gibt es folgende Filter:
-- **** ''comFilterB'' gibt an, ob der Filter 'unused labels' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comBinary'' gibt an, die Ausgabeoption 'Link to binary and disassemble the output' angeschaltet werden soll (standardmäßig '''false''')
-- **** ''comBinaryObject'' gibt an, ob die Ausgabeoption 'Compare to binary object and disassemble the output' angeschaltet werden soll (standardmäßig '''false''')
-- **** ''comFilterCommentOnly'' gibt an, ob der Filter 'comments' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comDemangle'' gibt an, ob die Ausgabeoption 'Demangle output' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comFilterDirectives'' gibt an, ob der Filter 'directives' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comExecute'' gibt an, ob die Ausgabeoption 'Execute the code and show its output' angeschaltet werden soll (standardmäßig '''false''')
-- **** ''comIntel'' gibt an, ob die Ausgabeoption 'Output disassembly in Intel syntax' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comFilterLibraryCode'' gibt an, ob der Filter 'library functions' angeschaltet werden soll (standardmäßig '''true''')
-- **** ''comFilterTrim'' gibt an, ob der Filter 'horizontal whitespace' angeschaltet werden soll (standardmäßig '''false''')
-- *** Obwohl es für GCC Tree/RTL Viewer verschiedene Optionen und Einstellungen gibt, sind hier alle Optionen deaktiviert, alle Filter aktiviert und es wurde ''original (tree)'' als ''pass'' ausgewählt. Diese Einstellungen lassen durch dieses Script nicht ändern.
-- *** Für die Präprozessor-Ausgabe gibt es folgende Optionen:
-- **** ''preClangFormat'' gibt an, ob die Ausgabe im Clang-Format erfolgen soll (standardmäßig '''false''')
-- **** ''preFilterHeaders'' gibt an, ob die Header herausgefiltert (d.h. nicht angezeigt) werden sollen (standardmäßig '''true''')

local CompilerExplorerLink = {}

-- Konvertiert Dezimal-Integer in Hexadezimal-Integer
local function hex(dec)
	local hb = math.floor(dec/16)
	local lb = dec%16
	if lb > 9 then
		lb = string.char(lb +55)
	end
	if hb > 9 then
		hb = string.char(hb +55)
	end
	return hb .. lb
end

-- Wandelt einen String so um, dass er innerhalb einer URL verwendet werden kann
-- Dabei werden Leerzeichen durch + ersetzt, andere Sonderzeichen durch ihren Hex-Code und
-- einfachen Anführungszeichen(') und Ausrufezeichen(!) ein Ausrufungszeichen vorgestellt
local function transform(code)
	local codestring = ""
	if code == nil then
		return "";
	end
	for i = 1, #code, 1 do
		local zeichen = code:byte(i)
		if (((zeichen >= 48) and (zeichen <=57)) or ((zeichen >= 65) and (zeichen <=90)) or ((zeichen >= 97) and (zeichen <=122))) then
			codestring = codestring .. string.char(zeichen)
		elseif zeichen == 39 then
			codestring = codestring .. "!'"
		elseif zeichen == 33 then
			codestring = codestring .. "!!"
		elseif zeichen == 95 then
			codestring = codestring .. "_"
		elseif zeichen == 32 then
			codestring = codestring .. "+"
		else
			codestring = codestring .. "%" .. hex(zeichen)
		end
	end
	return codestring
end

-- Wandelt eine 1 in eine 0 um und umgekehrt
-- Dies ist notwendig, da der Compiler Optionen eine 0 in der URL als true und eine 1 als false interpretiert
local function invert(a)
	if a == "true" then
		return "0"
	elseif a == "false" then
		return "1"
	else
		return nil
	end
end

-- Dies Funktion
local function divEnv(source)
	local div = string.find(source,"=")
    local name = string.sub(source,1,div-1)
    local value = string.sub(source,div+1)
    if #name == 1 then
    	name = "___" .. name
	end
    if #value == 1 then
	   	value = "___" .. value
	else
    	value = "'" .. value .. "'"
	end
	return "(name:" .. name .. ",value:" .. value .. ")"
end

-- Diese Funktion konvertiert den String mit den Umgebungsvariablen in das vom Compiler Explorer verlangte Format
local function convEnv(source)
	local overrides = ""
	local ende = 1
	while ende ~= nil do
		ende = string.find(source,";")
		if ende ~= nil then
			overrides = overrides .. divEnv(string.sub(source,1, ende-1)) ..","
			source = string.sub(source,ende+1)
		end
	end
	return overrides .. divEnv(source)
end

-- Erzeugt eine URL zum Compiler Explorer
-- für jede "Datei" wird ein Eintrag in den Arrays "code" (der Inhalt der Datei)
-- und "filename" (der Name der Datei) benötigt.
-- Optionen können weggelassen werden. in diesem fall werden Standardwerte benutzt.
local function convert(source)
	-- Die Standardwerte der Optionen werden festgelegt
	local options = ""
	local compiler = "cgsnapshot"
	local execArgsPanelShown = "1"
	local execStdin = ""
	local execArgs = ""
	local stdinPanelShown = "1"
	local wrap = "1"
	local compilerOutShown = "0"
	local compilationPanelShown = "0"
	local isCMakeProject = "1"
	local cmakeArgs = ""
	local customOutputFilename = ""
	local libs = ""
	local lang = "___c"
	local h = "e"
	local b = "0"
	local binary = "1"
	local binaryObject = "1"
	local commentOnly = "0"
	local demangle = "0"
	local directives = "0"
	local execute = "1"
	local intel = "0"
	local libraryCode = "0"
	local trim = "1"
	local runtimeTools = ""
	local clangformat = "1"
	local filterheaders = "0" 
	
	-- falls vorhanden, werden die Optionen und Bibliotheken ausgewertet
	if source.lang ~= nil then
		lang = string.lower(source.lang)
		if lang == "c++" then
			compiler = "gsnapshot"
		elseif lang == "java" then
			compiler = "java1601"
		elseif lang == "c" then
			lang = "___c"
		end
	end
	if (source.execArgsPanelShown == "true") or (source.execArgsPanelShown == "false") then
		execArgsPanelShown = invert(source.execArgsPanelShown)
	end
	if (source.execCompilationPanelShown == "true") or (source.execCompilationPanelShown == "false") then
		compilationPanelShown = invert(source.execCompilationPanelShown)
	end
	if source.compiler ~= nil then
		compiler = compiler
	end
	if (source.execCompilerOutputShown == "true") or (source.execCompilerOutputShown == "false") then
		compilerOutShown = invert(source.execCompilerOutputShown)
	end
	if source.execArgs ~= nil then
		execArgs = source.execArgs
	end
	if source.execStdin ~= nil then
		execStdin = source.execStdin
	end
	if source.execCompilerOptions ~= nil then
		options = source.execCompilerOptions
	end
	if (source.execStdinPanelShown == "true") or (source.execStdinPanelShown == "false") then
		stdinPanelShown = invert(source.execStdinPanelShown)
	end
	if (source.execLineWrap == "true") or (source.execLineWrap == "false") then
		wrap = invert(source.execLineWrap)
	end
	if (source.isCMakeProject == "true") or (source.isCMakeProject == "false") then
		isCMakeProject = invert(source.isCMakeProject)
	end
	if source.CMakeArgs ~= nil then
		cmakeArgs = source.CMakeArgs
	end
	if source.CMakeCustomOutputFilename ~= nil then
		customOutputFilename = source.CMakeCustomOutputFilename
	end
	if source.libs ~= nil then
		libs = source.libs
	end
	if source.h ~= nil then
		h = source.h
	end
	if (source.comFilterB == "true") or (source.comFilterB == "false") then
		b = invert(source.b)
	end
	if ((source.comBinary == "true") and (source.comBinaryObject == "false")) or (source.comBinary == "false") then
		binary = invert(source.binary)
	end
	if ((source.comBinary == "false") and (source.comBinaryObject == "true")) or (source.comBinaryObject == "false") then
		binaryObject = invert(source.binaryObject)
	end
	if (source.comFilterCommentOnly == "true") or (source.comFilterCommentOnly == "false") then
		commentOnly = invert(source.commentOnly)
	end
	if (source.comDemangle == "true") or (source.comDemangle == "false") then
		demangle = invert(source.demangle)
	end
	if (source.comFilterDirectives == "true") or (source.comFilterDirectives == "false") then
		directives = invert(source.directives)
	end
	if (source.comExecute == "true") or (source.comExecute == "false") then
		execute = invert(source.execute)
	end
	if (source.comIntel == "true") or (source.comIntel == "false") then
		intel = invert(source.intel)
	end
	if (source.comFilterLibraryCode == "true") or (source.comFilterLibraryCode == "false") then
		libraryCode = invert(source.libraryCode)
	end
	if (source.comFilterTrim == "true") or (source.comFilterTrim == "false") then
		trim = invert(source.trim)
	end
	if (source.preClangFormat == "true") or (source.preClangFormat == "false") then
		clangformat = invert(source.preClangFormat)
	end
	if (source.preFilterHeaders == "true") or (source.preFilterHeaders == "false") then
		filterheaders = invert(source.preFilterHeaders)
	end
	if source.execEnv ~= nil then
		runtimeTools = "(name:env,options:!(" .. convEnv(source.execEnv) .. "))"	
	end
	
	local name = {}
	local code = {}
	for key,value in pairs(source) do
		if key:find('_') ~= nil then
			key = string.gsub(key,'_','.')
			name[#name+1] = key
			code[#code+1] = value
		end
	end
	
	local breite = 100
	local hoehe = 100
	
	if #name > 1 then
		hoehe = 50
	end
	
	if (h == g) or (h == p) then
		breite = 100/(#name+2)
	else
		breite = 100/(#name+1)
	end
	
	-- falls kein Dateiname oder Quellcode angegeben wurde,
	-- wird nur eine aus Schema und Host gebildete URL zurückgegeben
	if (#name == 0) and (#code ==0) then
		return "https://www.godbolt.org/"
	end

	-- Der Fragment-Teil der URL wird erzeugt
	local url = "g:!((g:!("
	
	-- da der Compiler Explorer verlangt, dass die Hauptdatei einen bestimmten Namen hat, wird dies hier sicher gestellt
	if #name == 1 then
		if lang == "c++" then
			name[1] = "example.cpp"
		elseif lang == "java" then
			name[1] = "example.java"
		else
			name[1] = "example.c"
		end
		isCMakeProject = "1"
	end
	for i = 1, #name, 1 do
		url = url .. "(g:!((h:codeEditor,i:(filename:" .. name[i] .. ",fontScale:14,fontUsePx:'0',j:" .. i .. ",lang:" .. transform(lang) .. ",selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:'" .. transform(code[i]) .. "'),l:'5',n:'0',o:" .. name[i] .. ",t:'0')),header:(),k:" .. breite .. ",l:'4',m:100,n:'0',o:%27%27,s:0,t:'0'),"
	end

	url = url .. "(g:!(("
	if #name > 1 then
		url = url .. "g:!((h:tree,i:(cmakeArgs:%27" .. cmakeArgs .. "%27,compilerLanguageId:" .. transform(lang) .. ",customOutputFilename:%27" .. customOutputFilename .. "%27,files:!("
	
		for i = 1, #name, 1 do
		
			url = url .. "(editorId:" .. i .. ",fileId:" .. i .. ",filename:" .. name[i] .. ",g:%27%27,isIncluded:'0',isMainSource:'"
		
			if isCMakeProject == "0" then
				if 	name[i] == "CMakeLists.txt" then 
					url = url .. "0"
				else
					url = url .."1"
				end
			else
				if 	name[i] == "example.c" then 
					url = url .. "0"
				else
					url = url .."1"
				end
			end
		
			url = url .. "',isOpen:'0',langId:%27%27)"
		
			if i < #name then
				url = url .. ","
			end
		end
	
		url = url .. "),isCMakeProject:'".. isCMakeProject .. "',j:1,newFileId:" .. (#name+1) .. "),l:'5',n:'0',o:'Tree',t:'0')),header:(),l:'4',m:" .. hoehe .. ",n:'0',o:%27%27,s:0,t:'0'),(g:!(("
	end
	if h == "e" then
		url = url .. "h:executor,i:(argsPanelShown:'" .. execArgsPanelShown .. "',compilationPanelShown:'" .. compilationPanelShown .. "',compiler:" .. compiler .. ",compilerOutShown:'" .. compilerOutShown .. "',execArgs:"
		if execArgs == "___" then
			url = url .. execArgs
		else
			url = url .. "%27" .. transform(execArgs) .. "%27"
		end
		url = url .. ",execStdin:%27" .. transform(execStdin) .."%27,fontScale:14,fontUsePx:'0',j:1,lang:" .. transform(lang) .. ",libs:!(" .. libs .. "),options:%27" .. transform(options) .. "%27,overrides:!(),runtimeTools:!(" .. runtimeTools .. "),source:'1',stdinPanelShown:'" .. stdinPanelShown .. "',"
		if #name > 1 then
			url = url .. "tree:1,"
		end
		url = url .. "wrap:'" .. wrap .. "'),l:'5',n:'0',o:'Executor',t:'0'"
	else
		url = url .. "h:compiler,i:(compiler:" .. compiler .. ",filters:(b:'" .. b .. "',binary:'" .. binary .. "',binaryObject:'" .. binaryObject .. "',commentOnly:'" .. commentOnly .. "',debugCalls:'1',demangle:'" .. demangle .. "',directives:'" .. directives .. "',execute:'" .. execute .. "',intel:'" .. intel .. "',libraryCode:'" .. libraryCode .. "',trim:'" .. trim .. "'),"
		url = url .. "flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:" .. lang .. ",libs:!(" .. libs .. "),options:%27" .. transform(options) .. "%27,overrides:!(),"
		url = url .. "selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),"
		if #name > 1 then
			url = url .. "tree:1,"
		end
		url = url .. "source:'1'),l:'5',n:'0',o:'compiler',t:'0'"
	end
	url = url ..")),header:(),k:" .. breite .. ",l:'4',m:" .. hoehe .. ",n:'0',o:%27%27,s:0,t:'0')"
	if #name > 1 then
		url = url .. "),k:" .. breite .. ",l:'3',n:'0',o:%27%27,s:0,t:'0')"
	end
	if h == "g" then
		url = url ..",(g:!((h:gccdump,i:(addressOption:'1',allOption:'1',blocksOption:'1',command_prefix:(),compilerName:%27%27,detailsOption:'1',editorid:1,filename_suffix:t.original,fontScale:14,fontUsePx:'0',gimpleFeOption:'1',ipaDump:'0',j:1,linenoOption:'1',name:(),rawOption:'1',rtlDump:'0',selectedPass:t.original,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),slimOption:'1',statsOption:'1',treeDump:'0',treeid:0,uidOption:'1',vopsOption:'1'),l:'5',n:'0',o:'GCC+Tree/RTL+Viewer',t:'0')),k:" .. breite .. ",l:'4',n:'0',o:%27%27,s:0,t:'0')),"
	elseif h == "p" then
		url = url ..",(g:!((h:pp,i:(clang-format:'" .. clangformat .. "',editorid:1,filter-headers:'" .. filterheaders .. "',fontScale:14,fontUsePx:'0',j:1,treeid:0),l:'5',n:'0',o:'Preprocessor+Output',t:'0')),k:" .. breite .. ",l:'4',n:'0',o:%27%27,s:0,t:'0')),"
	else 
		url = url .. "),"
	end
	url = url .. "l:'2',n:'0',o:%27%27,t:'0')),version:4"

	-- Die vollständieg URL (Schema + Host + Fragment) wird zurückgegeben
	return "https://www.godbolt.org/#" .. url
end

-- Hauptprogramm: Erzeugt einen Link zum Compiler Explorer
function CompilerExplorerLink.createLink(frame)
	local source = frame:getParent().args
	return tostring(convert(source))
end

return CompilerExplorerLink