mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
356 lines
9.4 KiB
Go
356 lines
9.4 KiB
Go
//Parses perl scripts
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func main() {
|
|
path := "../../../zone/embparser_api.cpp"
|
|
err := readFile(path)
|
|
if err != nil {
|
|
log.Panicf("Failed to read file: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
type API struct {
|
|
Function string
|
|
Arguments []*Argument
|
|
}
|
|
|
|
type Argument struct {
|
|
Name string
|
|
Type string
|
|
API *API
|
|
}
|
|
|
|
func readFile(path string) (err error) {
|
|
inFile, err := os.Open(path)
|
|
if err != nil {
|
|
err = errors.Wrap(err, "Failed to open file")
|
|
}
|
|
defer inFile.Close()
|
|
scanner := bufio.NewScanner(inFile)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
arguments := map[string][]*Argument{}
|
|
functions := []*API{}
|
|
reg, err := regexp.Compile(`\]+|\[+|\?+|[...]+`)
|
|
if err != nil {
|
|
err = errors.Wrap(err, "Failed to compile regex")
|
|
return
|
|
}
|
|
regType, err := regexp.Compile(`(unsigned long|long|int32|bool|uint[0-9]+|int|auto|float|unsigned int|char[ \*]).+([. a-zA-Z]+=)`)
|
|
if err != nil {
|
|
err = errors.Wrap(err, "Failed to compile type regex")
|
|
return
|
|
}
|
|
|
|
lastArguments := []*Argument{}
|
|
lastAPI := &API{}
|
|
lineNum := 0
|
|
for scanner.Scan() {
|
|
lineNum++
|
|
key := ""
|
|
line := scanner.Text()
|
|
if len(line) < 1 {
|
|
continue
|
|
}
|
|
if len(lastArguments) > 0 { //existing args to parse
|
|
for i, argument := range lastArguments {
|
|
key = fmt.Sprintf("ST(%d)", i)
|
|
if strings.Contains(line, key) {
|
|
//We found a definition argument line
|
|
if argument.Type != "" {
|
|
continue
|
|
}
|
|
|
|
match := regType.FindStringSubmatch(line)
|
|
if len(match) < 2 {
|
|
continue
|
|
}
|
|
|
|
//key = `int`
|
|
//function = line[strings.Index(line, key)+len(key):]
|
|
newType := ""
|
|
|
|
switch v := strings.TrimSpace(match[1]); v {
|
|
case "int":
|
|
newType = "int"
|
|
case "int32":
|
|
newType = "int"
|
|
case "float":
|
|
newType = "float"
|
|
case "unsigned int":
|
|
newType = "uint"
|
|
case "uint32":
|
|
newType = "uint"
|
|
case "uint8":
|
|
newType = "uint"
|
|
case "uint":
|
|
newType = "uint"
|
|
case "bool":
|
|
newType = "bool"
|
|
case "uint16":
|
|
newType = "uint"
|
|
case "long":
|
|
newType = "long"
|
|
case "unsigned long":
|
|
newType = "unsigned long"
|
|
case "char":
|
|
newType = "string"
|
|
case "auto":
|
|
//Auto is tricky
|
|
if strings.Contains(line, "glm::vec4") {
|
|
newType = "float"
|
|
}
|
|
|
|
default:
|
|
log.Printf(`Unknown type: "%s" on line %d`, v, lineNum)
|
|
}
|
|
//log.Println("Found arg type", newType, "on index", i, argument.Name)
|
|
lastArguments[i].Type = newType
|
|
}
|
|
}
|
|
}
|
|
|
|
function := ""
|
|
|
|
argLine := ""
|
|
args := []string{}
|
|
//Find line
|
|
key = `Perl_croak(aTHX_ "Usage:`
|
|
if strings.Contains(line, key) {
|
|
function = line[strings.Index(line, key)+len(key):]
|
|
}
|
|
|
|
for _, argument := range lastArguments {
|
|
arguments[argument.Name] = append(arguments[argument.Name], argument)
|
|
}
|
|
|
|
lastArguments = []*Argument{}
|
|
|
|
//Trim off the endings
|
|
key = `");`
|
|
if strings.Contains(function, key) {
|
|
function = function[0:strings.Index(function, key)]
|
|
}
|
|
//Strip out the arguments
|
|
key = `(`
|
|
if strings.Contains(function, key) {
|
|
argLine = function[strings.Index(function, key)+len(key):]
|
|
function = function[0:strings.Index(function, key)]
|
|
key = `)`
|
|
if strings.Contains(argLine, key) {
|
|
argLine = argLine[:strings.Index(argLine, key)]
|
|
}
|
|
key = `=`
|
|
if strings.Contains(argLine, key) {
|
|
argLine = argLine[:strings.Index(argLine, key)]
|
|
}
|
|
argLine = reg.ReplaceAllString(argLine, "")
|
|
}
|
|
key = `,`
|
|
argLine = strings.TrimSpace(argLine)
|
|
|
|
if strings.Contains(argLine, key) {
|
|
args = strings.Split(argLine, key)
|
|
}
|
|
|
|
if len(function) < 1 {
|
|
continue
|
|
}
|
|
|
|
newArgs := []string{}
|
|
for j, _ := range args {
|
|
args[j] = strings.TrimSpace(args[j])
|
|
if len(args[j]) == 0 {
|
|
continue
|
|
}
|
|
newArgs = append(newArgs, args[j])
|
|
}
|
|
|
|
lastAPI = &API{
|
|
Function: function,
|
|
}
|
|
|
|
for _, arg := range newArgs {
|
|
argType, _ := knownTypes[arg]
|
|
argument := &Argument{
|
|
Name: arg,
|
|
Type: argType,
|
|
API: lastAPI,
|
|
}
|
|
lastArguments = append(lastArguments, argument)
|
|
}
|
|
lastAPI.Arguments = lastArguments
|
|
|
|
functions = append(functions, lastAPI)
|
|
}
|
|
|
|
foundCount := 0
|
|
failCount := 0
|
|
for key, val := range arguments {
|
|
isMissing := false
|
|
line := ""
|
|
line = fmt.Sprintf("%s used by %d functions:", key, len(val))
|
|
for _, fnc := range val {
|
|
line += fmt.Sprintf("%s(%s %s), ", fnc.API.Function, fnc.Type, key)
|
|
if fnc.Type == "" {
|
|
isMissing = true
|
|
}
|
|
}
|
|
if isMissing {
|
|
fmt.Println(line)
|
|
failCount++
|
|
} else {
|
|
foundCount++
|
|
}
|
|
}
|
|
log.Println(foundCount, "functions properly identified,", failCount, "have errors")
|
|
|
|
line := ""
|
|
for _, api := range functions {
|
|
line += fmt.Sprintf("void %s(", strings.TrimSpace(api.Function))
|
|
for _, argument := range api.Arguments {
|
|
line += fmt.Sprintf("%s %s, ", argument.Type, argument.Name)
|
|
}
|
|
if len(api.Arguments) > 0 {
|
|
line = line[0 : len(line)-2]
|
|
}
|
|
line += ")\n"
|
|
}
|
|
fmt.Println(line)
|
|
return
|
|
}
|
|
|
|
var knownTypes = map[string]string{
|
|
"activity_id": "uint",
|
|
"alt_mode": "bool",
|
|
"anim_num": "int",
|
|
"best_z": "float",
|
|
"buttons": "int",
|
|
"channel_id": "int",
|
|
"char_id": "int",
|
|
"charges": "int",
|
|
"class_id": "int",
|
|
"client_name": "string",
|
|
"color": "int",
|
|
"color_id": "int",
|
|
"condition_id": "int",
|
|
"copper": "int",
|
|
"count": "int",
|
|
"debug_level": "int",
|
|
"decay_time": "int",
|
|
"dest_heading": "float",
|
|
"dest_x": "float",
|
|
"dest_y": "float",
|
|
"dest_z": "float",
|
|
"distance": "int",
|
|
"door_id": "int",
|
|
"doorid": "uint",
|
|
"duration": "int",
|
|
"effect_id": "int",
|
|
"elite_material_id": "int",
|
|
"enforce_level_requirement": "bool",
|
|
"explore_id": "uint",
|
|
"faction_value": "int",
|
|
"fade_in": "int",
|
|
"fade_out": "int",
|
|
"fadeout": "uint",
|
|
"firstname": "string",
|
|
"from": "string",
|
|
"gender_id": "int",
|
|
"gold": "int",
|
|
"grid_id": "int",
|
|
"guild_rank_id": "int",
|
|
"heading": "float",
|
|
"hero_forge_model_id": "int",
|
|
"ignore_quest_update": "bool",
|
|
"instance_id": "int",
|
|
"int_unused": "int",
|
|
"int_value": "int",
|
|
"is_enabled": "bool",
|
|
"is_strict": "bool",
|
|
"item_id": "int",
|
|
"key": "string",
|
|
"language_id": "int",
|
|
"lastname": "string",
|
|
"leader_name": "string",
|
|
"level": "int",
|
|
"link_name": "string",
|
|
"macro_id": "int",
|
|
"max_level": "int",
|
|
"max_x": "float",
|
|
"max_y": "float",
|
|
"max_z": "float",
|
|
"message": "string",
|
|
"milliseconds": "int",
|
|
"min_level": "int",
|
|
"min_x": "float",
|
|
"min_y": "float",
|
|
"min_z": "float",
|
|
"name": "string",
|
|
"new_hour": "int",
|
|
"new_min": "int",
|
|
"node1": "int",
|
|
"node2": "int",
|
|
"npc_id": "int",
|
|
"npc_type_id": "int",
|
|
"object_type": "int",
|
|
"options": "int",
|
|
"platinum": "int",
|
|
"popup_id": "int",
|
|
"priority": "int",
|
|
"quantity": "int",
|
|
"race_id": "int",
|
|
"remove_item": "bool",
|
|
"requested_id": "int",
|
|
"reset_base": "bool",
|
|
"saveguard": "bool",
|
|
"seconds": "int",
|
|
"send_to_world": "bool",
|
|
"signal_id": "int",
|
|
"silent": "bool",
|
|
"silver": "int",
|
|
"size": "int",
|
|
"stat_id": "int",
|
|
"str_value": "string",
|
|
"subject": "string",
|
|
"target_enum": "string",
|
|
"target_id": "int",
|
|
"task": "int",
|
|
"task_id": "uint",
|
|
"task_id1": "int",
|
|
"task_id10": "int",
|
|
"task_id2": "int",
|
|
"task_set": "int",
|
|
"taskid": "int",
|
|
"taskid1": "int",
|
|
"taskid2": "int",
|
|
"taskid3": "int",
|
|
"taskid4": "int",
|
|
"teleport": "int",
|
|
"temp": "int",
|
|
"texture_id": "int",
|
|
"theme_id": "int",
|
|
"update_world": "int",
|
|
"updated_time_till_repop": "uint",
|
|
"version": "int",
|
|
"wait_ms": "int",
|
|
"window_title": "string",
|
|
"x": "float",
|
|
"y": "float",
|
|
"z": "float",
|
|
"zone_id": "int",
|
|
"zone_short": "string",
|
|
`task_id%i`: "int",
|
|
}
|