Modul:Vorlage:CompilerExplorerLink

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

  • 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 Hauptdatei example.c heißen 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.
  • Für den Executor Frame gibt es folgende optionale Parameter, die ebenfalls Schlüssel-Wert-Paare bilden, die ebenfalls durch Pipes voneinander getrennt werden:
    • 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)
    • execCompiler enthält den Namen des verwendeten Compilers (standardmäßig "cg122"):
    • execCompilerOutputShown gibt an, ob der Compiler Output angezeigt wird (standardmäßig true)
    • execArgs enthält die Execution Arguments (standardmäßig ___)
    • 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)
  • Wenn man CMake verwendet, sind die folgenden Optionen wichtig, die auch wieder Schlüssel-Wert-Paare bilden, die durch Pipes voneinander getrennt werden:
    • 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))
  • Folgende Bibliotheken sind dem Compiler Explorer bekannt und können ebenfalls verwendet werden, in dem man aus Schlüssel-Werte-Paare aus den Namen und der Versionsnummer (mögliche Versionen in Klammern angegeben) bildet: cs50 (910), hedley (v12), libuv (1370,1381), lua (535,540), nsimd(22-x86_64,22-arm,22-arm64,310-x86_64,310-arm,310-arm64), openssl (111c,111g), python (359,3610,376,381), simde (trunk), curl(7831), sqlite (3400).


Ein typischer Aufruf dieser Vorlage sieht wie folgt aus:
{{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:!((g:!((h:tree,i:(cmakeArgs:%27%27,compilerLanguageId:___c,customOutputFilename:%27%27,files:!((editorId:1,fileId:1,filename:example.c,g:%27%27,isIncluded:'0',isMainSource:'0',isOpen:'0',langId:%27%27)),isCMakeProject:'1',j:1,newFileId:2),l:'5',n:'0',o:'Tree+%231',t:'0')),header:(),l:'4',m:50,n:'0',o:%27%27,s:0,t:'0'),(g:!((h:executor,i:(argsPanelShown:'1',compilationPanelShown:'0',compiler:cg122,compilerOutShown:'0',execArgs:___,execStdin:%27%27,fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!(),options:%27%27,source:'1',stdinPanelShown:'1',tree:1,wrap:'1'),l:'5',n:'0',o:'Executor+(C,+Tree+%231)',t:'0')),header:(),k:50,l:'4',m:50,n:'0',o:%27%27,s:0,t:'0')),k:50,l:'3',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!


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

-- 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 = "cg122"
	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 = {}
	
	-- falls vorhanden, werden die Optionen und Bibliotheken ausgewertet
	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.execCompiler ~= nil then
		compiler = source.execCompiler
	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.cs50 ~= nil then
		libs[#libs+1] = "(name:cs50,ver:'".. source.cs50 .. "')"
	end
	if source.hedley ~= nil then
		libs[#libs+1] = "(name:hedley,ver:".. source.hedley .. ")"
	end
	if source.libuv ~= nil then
		libs[#libs+1] = "(name:libuv,ver:'".. source.libuv .. "')"
	end
	if source.lua ~= nil then
		libs[#libs+1] = "(name:lua,ver:'".. source.lua .. "')"
	end
	if source.nsimd ~= nil then
		libs[#libs+1] = "(name:nsimd,ver:'".. source.nsimd .. "')"
	end
	if source.openssl ~= nil then
		libs[#libs+1] = "(name:openssl,ver:'".. source.openssl .. "')"
	end
	if source.python ~= nil then
		libs[#libs+1] = "(name:python,ver:'".. source.python .. "')"
	end
	if source.simde ~= nil then
		libs[#libs+1] = "(name:simde,ver:".. source.simde .. ")"
	end
	if source.curl ~= nil then
		libs[#libs+1] = "(name:curl,ver:'".. source.curl .. "')"
	end
	if source.sqlite ~= nil then
		libs[#libs+1] = "(name:sqlite,ver:'".. source.sqlite .. "')"
	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
	
	-- falls kein Dateiname oder Quellcode angegeben wurde,
	-- wird nur eine aus Schema und Host gebildete URL zurückgegeben
	if (#name == 0) or (#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
		name[1] = "example.c"
		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:___c,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:" .. (100/(#name+1)) .. ",l:'4',m:100,n:'0',o:%27%27,s:0,t:'0'),"
	end

	url = url .. "(g:!((g:!((h:tree,i:(cmakeArgs:%27" .. cmakeArgs .. "%27,compilerLanguageId:___c,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+%231',t:'0')),header:(),l:'4',m:50,n:'0',o:%27%27,s:0,t:'0'),(g:!((h:executor,i:(argsPanelShown:'" .. execArgsPanelShown .. "',compilationPanelShown:'" .. compilationPanelShown .. "',compiler:" .. compiler .. ",compilerOutShown:'" .. compilerOutShown .. "',execArgs:"
	if execArgs == "___" then
		url = url .. execArgs
	else
		url = url .. "'" .. transform(execArgs) .. "'"
	end
	url = url .. ",execStdin:%27" .. transform(execStdin) .."%27,fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!("
	if #libs > 0 then 
		for i = 1, #libs, 1 do
			url = url .. libs[i]
			if  i < #libs then
				url = url ..","
			end
		end
	end
	url = url .. "),options:%27" .. transform(options) .. "%27,source:'1',stdinPanelShown:'" .. stdinPanelShown .. "',tree:1,wrap:'" .. wrap .. "'),l:'5',n:'0',o:'Executor+(C,+Tree+%231)',t:'0')),header:(),k:50,l:'4',m:50,n:'0',o:%27%27,s:0,t:'0')),k:" .. (100/(#name+1)) .. ",l:'3',n:'0',o:%27%27,s:0,t:'0')),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
-- Dateinamen und Quellcodes bilden ein Schlüssel-Wert-Paar,
-- wobei Punkte im Dateinamen durch '_' dargestellt werden müssen (so muss z.B. statt "main.c" "main_c" geschrieben werden)
-- Für den Executor Frame gibt es folgende Optionen, die ebenfalls Schlüssel-Wert-Paare bilden, aber angegeben werden müssen:
-- execCompilerOptions wird für die Compiler-Optionen verwendet (standardmäßig "")
-- execArgs enthält die Execution Arguments (standardmäßig ___)
-- execStdin enthät den Stdin (standardmäßig "")
-- execCompiler enthält den Namen des verwendeten Compilers (standardmäßig "cg122")
-- execArgsPanelShown gibt an, ob die Execution Arguments angezeigt werden (standardmäßig "0")
-- execStdinPanelShown gibt an, ob das Stdin angezeigt wird (standardmäßig "0")
-- execLineWrap gibt an, ob es einen automatischen Zeilenumbruch gibt (standardmäßig "0")
-- execCompilerOutputShown gibt an, ob der Compiler Output angezeigt wird (standardmäßig "1")
-- execCompilationPanelShown gibt an, ob der Compiler und die Compiler Options angezeigt werden (standardmäßig "1")
function CompilerExplorerLink.createLink(frame)
	local source = frame:getParent().args
	return tostring(convert(source))
end

return CompilerExplorerLink

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.