mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-25 01:41:43 +00:00
185 lines
6.6 KiB
Python
Executable File
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()
|