Facepunch.Steamworks/Generator/CodeParser/CodeParser.cs

175 lines
5.4 KiB
C#
Raw Normal View History

2016-10-29 22:28:16 +03:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Generator
{
2019-04-12 17:41:40 +03:00
public partial class CodeParser
2016-10-29 22:28:16 +03:00
{
public string Content;
public CodeParser( string folder )
{
foreach ( var file in System.IO.Directory.GetFiles( folder, "*.h", System.IO.SearchOption.AllDirectories ) )
{
Content += System.IO.File.ReadAllText( file );
}
Content = Content.Replace( "\r\n", "\n" );
Content = Content.Replace( "\n\r", "\n" );
}
internal void ExtendDefinition( SteamApiDefinition def )
{
2016-10-31 12:00:47 +03:00
//
// Get a list of CallbackIds
//
2016-10-29 22:28:16 +03:00
def.CallbackIds = new Dictionary<string, int>();
2019-04-11 19:00:44 +03:00
//v1
2016-10-29 22:28:16 +03:00
{
2018-03-21 13:42:55 +03:00
var r = new Regex( @"enum { (k_[i|I](?:.+)) = ([0-9]+) };" );
2016-10-29 22:28:16 +03:00
var ma = r.Matches( Content );
foreach ( Match m in ma )
{
2018-03-21 13:42:55 +03:00
def.CallbackIds.Add( m.Groups[1].Value.Substring( 3 ).Replace( "Callbacks", "" ), int.Parse( m.Groups[2].Value ) );
2016-10-29 22:28:16 +03:00
}
}
2019-04-11 19:00:44 +03:00
//
// Associate callbackIds with structs
//
foreach ( var t in def.structs )
2016-10-29 22:28:16 +03:00
{
2016-11-03 13:52:52 +03:00
if ( !string.IsNullOrEmpty( t.CallbackId ) ) continue;
2016-10-31 14:46:53 +03:00
// Standard style
{
var r = new Regex( @"struct "+t.Name+@"\n{ ?\n(?:.)+enum { k_iCallback = (?:(.+) \+ ([0-9]+)|(.+)) };", RegexOptions.Multiline | RegexOptions.IgnoreCase );
var m = r.Match( Content );
if ( m.Success )
{
var kName = m.Groups[1].Value;
var num = m.Groups[2].Value;
if ( string.IsNullOrEmpty( kName ) )
{
kName = m.Groups[3].Value;
num = "0";
}
2018-03-21 13:42:55 +03:00
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
2016-10-31 14:46:53 +03:00
t.CallbackId = $"{kName} + {num}";
}
}
// New style
2016-10-29 22:28:16 +03:00
{
2016-10-31 14:46:53 +03:00
var r = new Regex( @"DEFINE_CALLBACK\( "+t.Name+@", (.+) \+ ([0-9]+) \)" );
var m = r.Match( Content );
if ( m.Success )
{
var kName = m.Groups[1].Value;
var num = m.Groups[2].Value;
2016-10-29 22:28:16 +03:00
2018-03-21 13:42:55 +03:00
//kName = kName.Replace( "k_i", "CallbackIdentifiers." ).Replace( "Callbacks", "" );
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
2016-10-29 22:28:16 +03:00
2016-10-31 14:46:53 +03:00
t.CallbackId = $"{kName} + {num}";
}
2016-10-29 22:28:16 +03:00
}
2019-04-11 19:00:44 +03:00
// Even Newer Style
{
var r = new Regex( @"STEAM_CALLBACK_BEGIN\( " + t.Name + @", (.+) \+ ([0-9]+) \)" );
var m = r.Match( Content );
if ( m.Success )
{
var kName = m.Groups[1].Value;
var num = m.Groups[2].Value;
//kName = kName.Replace( "k_i", "CallbackIdentifiers." ).Replace( "Callbacks", "" );
kName = "CallbackIdentifiers." + kName.Substring( 3 ).Replace( "Callbacks", "" );
t.CallbackId = $"{kName} + {num}";
}
}
}
2016-10-29 22:28:16 +03:00
2016-10-31 12:00:47 +03:00
//
// Find defines
//
2016-10-29 23:05:48 +03:00
def.Defines = new Dictionary<string, string>();
{
var r = new Regex( @"#define ([a-zA-Z_]+) ""(.+)""" );
var ma = r.Matches( Content );
foreach ( Match m in ma )
{
def.Defines.Add( m.Groups[1].Value.Replace( "Callbacks", "" ), m.Groups[2].Value );
}
}
2016-10-31 14:46:53 +03:00
//
// Find CALL_RESULTs
//
{
var r = new Regex( @"CALL_RESULT\( (.+) \)(?:.+)?\n(?:.+)virtual\s+SteamAPICall_t\s+(\w+)\(" );
var ma = r.Matches( Content );
foreach ( Match m in ma )
{
var s = def.structs.Single( x => x.Name == m.Groups[1].Value );
s.IsCallResult = true;
foreach ( var t in def.methods.Where( x => x.Name == m.Groups[2].Value ) )
{
2016-11-03 13:52:52 +03:00
if ( !string.IsNullOrEmpty( t.CallResult ) ) continue;
2016-10-31 14:46:53 +03:00
t.CallResult = s.Name;
}
}
}
2018-03-21 13:42:55 +03:00
//
// Find missing structs
//
{
var r = new Regex( @"struct ([a-zA-Z]+_t)" );
var ma = r.Matches( Content );
foreach ( Match m in ma )
{
var s = def.structs.SingleOrDefault( x => x.Name == m.Groups[1].Value );
if ( s == null )
{
Console.WriteLine( "Missing Struct: " + m.Groups[1].Value );
}
}
//Console.ReadKey();
}
//
// Change all struct bool fields to bytes (they're technically bytes anyway, and it helps with marshalling)
//
{
foreach ( var s in def.structs )
{
foreach ( var f in s.Fields )
{
if ( f.Type == "bool" )
f.Type = "byte";
}
}
}
}
2016-10-29 22:28:16 +03:00
}
}