#!/usr/bin/env python3 # This script generates the network communication interface for wpilibj. # # This script takes no arguments and should be invoked from either the gen # directory or the root directory of the project. from datetime import date import os import re import subprocess # Check that the current directory is part of a Git repository def in_git_repo(directory): return subprocess.run(["git", "rev-parse"]).returncode == 0 def main(): if not in_git_repo("."): print("Error: not invoked within a Git repository", file=sys.stderr) sys.exit(1) # Handle running in either the root or gen directories config_path = "." if os.getcwd().rpartition(os.sep)[2] == "gen": config_path = ".." output_name = config_path + \ "/hal/src/generated/java/edu/wpi/first/wpilibj/hal/FRCNetComm.java" # Set initial copyright year and get current year year = "2016" current_year = str(date.today().year) # Start writing output file with open(output_name + ".tmp", "w") as temp: # Write first line of comment temp.write("/*") for i in range(0, 76): temp.write("-") print("*/", file=temp) # Write second line of comment temp.write("/* Copyright (c) ") if year != current_year: temp.write(year) temp.write("-") temp.write(current_year) temp.write(" FIRST. All Rights Reserved.") for i in range(0, 24): temp.write(" ") if year == current_year: for i in range(0, 5): temp.write(" ") print("*/", file=temp) # Write rest of lines of comment temp.write("""\ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ /*""") for i in range(0, 76): temp.write("-") print("*/", file=temp) # Write preamble temp.write(""" // Autogenerated by wpilibj_frcnetcomm.py. Do not manually edit this file. package edu.wpi.first.wpilibj.hal; /** * JNI wrapper for library FRC_NetworkCommunication
. */ @SuppressWarnings({\"MethodName\", \"LineLength\"}) public class FRCNetComm extends JNIWrapper { """) # Read enums from C++ source files first_enum = True files = [ "/ni-libraries/include/FRC_NetworkCommunication/LoadOut.h", "/hal/src/main/native/include/hal/UsageReporting.h" ] for file_name in files: with open(config_path + file_name, "r") as cpp_source: while True: # Read until an enum is encountered line = "" pos = -1 while "enum" not in line: line = cpp_source.readline() if line == "": break if line == "": break # If "{" is on next line, read next line if "{" not in line: line = cpp_source.readline() # Write enum to output file as interface values = [] line = cpp_source.readline() while "}" not in line: if line == os.linesep: values.append("") elif line[0] != "#": try: values.append( re.search("[^,]+", line.strip()).group()) except AttributeError: # Ignore lines that don't match value regex pass line = cpp_source.readline() # Extract enum name name_start = 0 for i, c in enumerate(line): if c != " " and c != "}": name_start = i break enum_name = line[name_start:len(line) - 2] # Write comment for interface name # Only add newline if not the first enum if first_enum == True: first_enum = False else: temp.write(os.linesep) temp.write(" /**" + os.linesep + " * ") # Splits camelcase string into words enum_camel = re.findall( r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', enum_name) temp.write(enum_camel[0] + " ") for i in range(1, len(enum_camel)): temp.write(enum_camel[i][0].lower() + \ enum_camel[i][1:len(enum_camel[i])] + " ") temp.write( "from " + os.path.basename(file_name) + os.linesep + " */" + os.linesep + " @SuppressWarnings({\"TypeName\", \"PMD.ConstantsInInterface\"})" + os.linesep + \ " public static final class " + enum_name + " {" + os.linesep + \ " private " + enum_name + "() {" + os.linesep + " }" + os.linesep + os.linesep) # Write enum values count = 0 for value in values: # Pass through empty lines if value == "": temp.write(os.linesep) continue if "=" not in value: value = value + " = " + str(count) count += 1 # Add scoping for values from a different enum if enum_name != "tModuleType" and "kModuleType" in value: value = value.replace("kModuleType", "tModuleType.kModuleType") temp.write(" public static final int " + value[0:len(value)] + ";" + os.linesep) # Write end of enum print(" }", file=temp) # Write closing brace for file print("}", file=temp) # Replace old output file try: os.remove(output_name) except OSError: pass os.rename(output_name + ".tmp", output_name) if __name__ == "__main__": main()