Skip to content

Instantly share code, notes, and snippets.

@stucotso
Last active February 1, 2023 21:02
Show Gist options
  • Save stucotso/76f602a267be052ec19686c38a783f65 to your computer and use it in GitHub Desktop.
Save stucotso/76f602a267be052ec19686c38a783f65 to your computer and use it in GitHub Desktop.
Raylib header preprocessor
from pycparser import parse_file, c_ast
import os
class ast:
def __init__(self, children=[], params=[], line=0):
self.children = children
self.params = params
self.line = line
def expand(self, flags, nest):
return "".join([i.expand(flags, nest+1) for i in self.children])
def dump(self, nest=0):
ret = ("\t"* nest) + self.__class__.__name__ + "\n"
for i in self.children:
ret += i.dump(nest+1)
return ret
class ifdef(ast):
def evaluate(self, flags):
func = self.params[0].strip()
negate = False
if func == "#ifndef": negate=True
key = self.params[1].strip()
test = key in flags.keys() and flags[key] != ""
if negate: return not test
return test
def expand(self, flags, nest):
result = ""
if self.evaluate(flags):#
for i in self.children:
child = i.expand(flags, nest+1)
if child.strip().split(" ")[0].strip() != "#endif":
result += child
return result
class text(ast):
def expand(self, flags, nest): return self.params[0]
class Preprocessor():
def __init__(self, flags):
self.index = 0
self.flags = flags
def preprocessLine(self, lines, parent):
if self.index >= len(lines):
self.index = -1
return text(line=-1, params=[""])
line = lines[self.index]
directive = None
if line.strip().startswith("#"):
directive = line.strip().split(" ")
if directive[0].strip() in ["#ifdef", "#ifndef", "#if"]:
self.index += 1
newparent = ifdef(params=directive, line=self.index, children=[])
parent.children.append(newparent)
self.preprocessLines(lines, newparent)
return newparent
self.index += 1
result = text(line=self.index, params=[line])
parent.children.append(result)
return result
def preprocessLines(self, lines, parent):
while self.index >= 0:
item = self.preprocessLine(lines, parent)
if item.line == -1 or item.params[0].strip() == "#endif" or item.params[0].split(" ")[0] == "#endif":
return
def preprocessFile(self, f):
print ("Preproccessing file:", f)
file = open(f, 'r')
lines = file.readlines()
self.index = 0
result = ast(children=[])
self.preprocessLines(lines, result)
if self.index < len(lines) and self.index >=0: raise Exception("error parsing, failed at: " + str(self.index))
return result.expand(self.flags, 0)#self.expand(result.children)
headers = [
"../../deps/raylib/src/raylib.h",
"../../deps/raylib/src/raymath.h",
"../../deps/raygui/src/raygui.h"
]
params = [
"-d RLAPI",
"-d RMAPI",
"-d RAYGUIAPI"
]
def preprocess():
os.system("mkdir tmp")
for i in headers:
fname = i.split("/")[-1]
output = Preprocessor({}).preprocessFile(i)
print (output)
outHeader = "tmp/" + fname + ".preprocessed"
open(outHeader, "w").write(output)
def runparser():
os.system("gcc ../../deps/raylib/parser/raylib_parser.c")
idx = 0
for i in headers:
fname = i.split("/")[-1]
os.system("a.exe --input ./tmp/{}.preprocessed --output ./tmp/{}.json --format JSON {}".format(fname, fname, params[idx]))
idx += 1
preprocess()
runparser()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment