def get_files_to_search(sig, jamaicaoutputdir): """ When performing flow analysis, the search order of files will hugely affect the execution time because almost all referenced functions will be in the current file (i.e. Java package), the FPGA porting layer, or the java.lang package or similar. This function returns a list containing all of the files in the Jamaica output directory and the porting layer. However it orders it based on heuristics to try to ensure that resolutions are faster. """ filestosearch = [] #First, put the originating file as this is the most likely source filestosearch.append(c_filename_of_java_method_sig(sig, jamaicaoutputdir)) #Then the FPGA porting layer filestosearch.append(project_path("projectfiles", "src", "fpgaporting.c")) #Then the java.lang package filestosearch.append(deglob_file(os.path.join(jamaicaoutputdir, "PKG_java_lang_V*__.c"))) #Then the other output C files for f in os.listdir(jamaicaoutputdir): ffullpath = os.path.join(jamaicaoutputdir, f) if ffullpath.endswith(".c") and (not ffullpath.endswith("Main__.c")) and not ffullpath in filestosearch: filestosearch.append(ffullpath) return filestosearch
def parse_jamaica_output(filename, includepath = None): """ Use pycparser to parse a Jamaica output file. Because Jamaica's output is pretty complex, cpp is required, and even still some features have to be removed because it uses GCC extensions unsupported by pycparser. Returns a pycparser.c_ast or throws ParseError If includepath is None then the project include files are used for parsing. Else, an absolute path to alternate includes can be provided. """ if '*' in filename: filename = deglob_file(filename) cppargs = ['-E', '-DNDEBUG', #Disable Jamaica debug support '-U__GNUC__', #Prevents use of __attribute__, will cause an "unsupported compiler" #warning #'-W#warnings', #And this hides that warning '-DJAMAICA_NATIVE_TIME_GET_HIGH_RESOLUTION_TIMESTAMP', #These use volatile asm() which is not supported by pycparser '-DJAMAICA_NATIVE_THREAD_COMPARE_AND_SWAP', '-D__CAICOS__', #So we can tell if we are being parsed by caicos r'-I' + project_path("stdlibheaders"), #Override stdlib headers with blank versions (Jamaica builder doesn't use them, but includes them) ] if includepath == None: cppargs.append(r'-I' + project_path("projectfiles", "include")) else: cppargs.append(r'-I' + str(includepath)) return pycparser.parse_file(filename, use_cpp=True, cpp_path="gcc", cpp_args=cppargs)
def c_filename_of_javaclass(classname, c_output_base, classdelimiter='.'): """ The C file containing a given Java class is only semi-predictable, we need to glob for it. Java class format x.y.classname is translated to an absolute file pathname. Jamaica translates on a per-package basis, so many classes may be in the same C file. """ parts = classname.strip().split(classdelimiter) if not os.path.exists(c_output_base): return None if len(parts) < 2: raise CaicosError("Class name " + str(classname) + " appears to reference an unpackaged class, which is not supported by JamaicaBuilder or modern Java.") name = "PKG_" for part in parts[:-1]: name = name + part + "_" name = name + "V*__.c" try: matches = utils.deglob_file(os.path.join(c_output_base, name)) except CaicosError, _: raise CaicosError("No source file was found for class '" + str(classname) + "'. Are the bindings in the config file correct?")