#! /usr/bin/python3 import fileinput import sys import re import os from enum import Enum class Section(Enum): PREAMBLE = 1 EXP_TYPE = 2 EXP_VALUE = 3 STATIC = 4 UNKNOWN = 5 class ValueSubsection(Enum): FUNCTION = 1 VARIABLE = 2 NA = 3 outfile = sys.argv[1] outfile_local = os.path.basename(outfile) parts = re.match(r"(?P.*)\.(?P[^\.]*)\.[hc]$", outfile_local) module = parts.group('module') outtype = parts.group('mode') srcfile = os.path.join(os.path.dirname(outfile), module) + ".src.c" circImpVar = "__{mod}_{ty}_IMPORTING__".format(mod=module.upper(), ty=outtype.upper()) sys.stdout = open(outfile, 'w') # data about the current //#-delimited chunk of file section = Section.PREAMBLE valueSubsection = ValueSubsection.NA lines = [] def declOnly(): if valueSubsection == ValueSubsection.VARIABLE: eqpos = lines[0].find('=') lines[0] = lines[0][0:eqpos] print( 'extern', lines[0], ';' ) else: if lines[0].endswith("{"): lines[0] = lines[0][0:len(lines[0])-2].rstrip() print( lines[0], ';' ) def fulldump(): for line in lines: print(line) def flush(): global lines # print("\t// flush", outtype, section) if (section == Section.PREAMBLE): postpreamble() elif (len(lines) == 0): return elif (outtype == 'tdcl') & (section == Section.EXP_TYPE): declOnly() elif (outtype == 'defn') & (section == Section.EXP_TYPE): fulldump() elif (outtype == 'defn') & (section == Section.EXP_VALUE): declOnly() elif (outtype == 'impl') & (section == Section.EXP_VALUE): fulldump() elif (outtype == 'impl') & (section == Section.STATIC): fulldump() else: for line in lines: pass #print("//", line) lines = [] class ImportStyle(Enum): NO_EXPORT = 1 EXPORT_INCOMPLETE = 2 EXPORT_COMPLETE = 3 def emitInclude(imodule, iftype): print('#include "{mod}.{typ}.h"'.format(mod=imodule, typ=iftype)) def import_(cmd): if section == Section.PREAMBLE: if cmd.startswith("auto"): cmd = cmd.replace("auto","").lstrip() if cmd.startswith("&"): cmd = cmd.replace("&","").lstrip() style = ImportStyle.EXPORT_INCOMPLETE else: style = ImportStyle.EXPORT_COMPLETE elif cmd.startswith("static"): cmd = cmd.replace("static","").lstrip() style = ImportStyle.NO_EXPORT else: print("#error import not understood:", cmd) style = ImportStyle.NO_EXPORT imodule = cmd if( style != ImportStyle.EXPORT_COMPLETE) & (outtype == "impl"): emitInclude(imodule, "defn") if (style == ImportStyle.EXPORT_COMPLETE) & (outtype == "defn"): emitInclude(imodule, "defn") if (style != ImportStyle.NO_EXPORT) & (outtype == "tdcl"): emitInclude(imodule, outtype) else: print("#error illegal place for: import ", cmd) def beginunit(): print("//", outfile_local) if (outtype == "tdcl"): print("#pragma once") elif outtype == "defn": print("#ifdef", circImpVar) print("#error Illegal circularity detected") print("#else") print("#define", circImpVar) if outtype == "defn": emitInclude(module, "tdcl") elif outtype == "impl": emitInclude(module, "defn") def postpreamble(): if outtype == "defn": print("#undef", circImpVar) print("#pragma once") def endunit(): if outtype == "defn": print("#endif // ", circImpVar) try: with open(srcfile, "r") as file: beginunit() for line in file: line = line.rstrip() if ( line.startswith("#import") ): line = line.replace("#import", "").lstrip() import_(line) elif ( line.startswith("//#") ): flush() line = line.replace("//#", "").lstrip() if line[0] == '@': section = Section.EXP_TYPE valueSubsection = ValueSubsection.NA elif line[0] == '$': section = Section.EXP_VALUE valueSubsection = ValueSubsection.NA # print("\t// object decl:{name}, with deps:{decldeps}".format( # name=name, decldeps=decldeps)) line = line[1:] if line[0] == 'f': valueSubsection = ValueSubsection.FUNCTION elif line[0] == 'v': valueSubsection = ValueSubsection.VARIABLE else: print("#error $-subdirective not understood: ", line) valueSubsection = ValueSubsection.NA elif line[0] == '-': section = Section.STATIC valueSubsection = ValueSubsection.NA else: print("#error directive not understood:", line) section = Section.UNKNOWN valueSubsection = ValueSubsection.NA line = line[1:] else: line = line.split("//")[0].rstrip() if (line): lines.append(line) flush() endunit() except FileNotFoundError: print("Error: The file '" + srcfile + "' was not found.")