#!/usr/bin/env python from subprocess import Popen import urllib.request import urllib.parse import urllib.error import sys, os, re import ssl, json class godbolt(object): ssl._create_default_https_context = ssl._create_unverified_context compiler = {"CC": "", "CXX": "", "CFLAGS": "", "CXXFLAGS": ""} home_url = "https://godbolt.org" headers = { "Content-Type": "application/json;charset=utf-8", "Accept": "application/json;charset=utf-8", "User-Agent": "godbolt", } def languages(self): url = self.home_url + "/api/languages" request = urllib.request.Request(url, headers=self.headers) reponse = urllib.request.urlopen(request) text = reponse.read().decode("UTF-8") sys.stdout.write(text) return 0 def compilers(self, lang): url = self.home_url + "/api/compilers/" + lang request = urllib.request.Request(url, headers=self.headers) reponse = urllib.request.urlopen(request) text = reponse.read().decode("UTF-8") sys.stdout.write(text) return 0 def compile(self, source, output=""): if os.path.splitext(source)[-1] != ".c": option = self.compiler["CXXFLAGS"] compiler = self.compiler["CXX"] else: option = self.compiler["CFLAGS"] compiler = self.compiler["CC"] if not compiler: return False if not output: output = source + ".s" with open(source, "r") as f: source = f.read() data = json.dumps( { "source": source, "options": { "userArguments": option, }, } ).encode("UTF-8") url = self.home_url + "/api/compiler/" + compiler + "/compile" request = urllib.request.Request(url, data=data, headers=self.headers) reponse = urllib.request.urlopen(request) text = reponse.read() with open(output, "wb") as f: f.write(text) text = text.decode("UTF-8") if "" not in text: return True return text.split("Standard error:")[-1] if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("-S") parser.add_argument("-O") parser.add_argument("--cc", default="") parser.add_argument("--cxx", default="") parser.add_argument("--cflags", default="") parser.add_argument("--cxxflags", default="") parser.add_argument("-l", "--lang", default="") args = parser.parse_known_args() if not args[0].O: args[0].O = "build" if not args[0].S: args[0].S = "src" o = godbolt() if args[0].lang: exit(o.compilers(args[0].lang)) args[0].S = os.path.relpath(args[0].S) args[0].O = os.path.relpath(args[0].O) single = os.path.join(os.path.dirname(__file__), "single.py") single = [sys.executable, single, "-Iinclude", "-C", args[0].S] single += ["-O", os.path.join(args[0].O, args[0].S)] Popen(single).wait() os.chdir(args[0].O) o.compiler["CC"] = args[0].cc o.compiler["CFLAGS"] = args[0].cflags o.compiler["CXX"] = args[0].cxx o.compiler["CXXFLAGS"] = args[0].cxxflags for dirpath, dirnames, filenames in os.walk(args[0].S): for filename in filenames: source = os.path.join(dirpath, filename) prefix, suffix = os.path.splitext(source) if suffix in (".c", ".cc", ".cpp", ".cxx"): err = o.compile(source) if err != False: sys.stdout.write(source) if type(err) == type(""): sys.stdout.write(err) # type: ignore if err != False: sys.stdout.write("\n")