Files
allwpilib/gen/wpilibj_frcnetcomm.py
2018-07-21 23:50:40 -07:00

185 lines
6.6 KiB
Python
Executable File

#!/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 <b>FRC_NetworkCommunication</b><br>.
*/
@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()