Last active
May 6, 2019 23:55
-
-
Save TheVice/421cb7df499b7515e6f5e278e4335b87 to your computer and use it in GitHub Desktop.
glew_generator - tool that take path to glew and glfixes repositories and generate glew snapshot. More described here https://github.com/nigels-com/glew/issues/13#issuecomment-260712955
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.vs/ | |
Debug/ | |
Release/ | |
x64/ | |
build/ | |
include/ | |
src/ | |
googletest-release-*/ | |
pugixml-*/ | |
Visual_Studio_*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "blacklist.h" | |
#include "input_output.h" | |
#include "common.h" | |
void read_black_list(const std::string& black_list_file, std::list<std::string>& black_list) | |
{ | |
std::string content; | |
read_from_file(black_list_file, content); | |
black_list = split(content, '\n', true); | |
} | |
void apply_black_list(const std::list<std::string>& black_list, std::list<std::string>& extension_list) | |
{ | |
for (const auto& path : black_list) | |
{ | |
extension_list.remove_if([&path](const std::string & ext) | |
{ | |
return ends_with(ext, path); | |
}); | |
} | |
} | |
void apply_black_list(const std::string& black_list_file, std::list<std::string>& extension_list) | |
{ | |
std::list<std::string> lines; | |
read_black_list(black_list_file, lines); | |
apply_black_list(lines, extension_list); | |
} | |
void apply_black_list(std::istream& black_list_stream, std::list<std::string>& extension_list) | |
{ | |
//TODO: change return of function to bool type and monitor if command was apply. | |
for (std::string line; std::getline(black_list_stream, line);) | |
{ | |
extension_list.remove_if([&line](const std::string & ext) | |
{ | |
return ends_with(ext, line); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _BLACK_LIST_H_ | |
#define _BLACK_LIST_H_ | |
#include <list> | |
#include <string> | |
#include <istream> | |
void read_black_list(const std::string& black_list_file, std::list<std::string>& black_list); | |
void apply_black_list(const std::list<std::string>& black_list, std::list<std::string>& extension_list); | |
void apply_black_list(const std::string& black_list_file, std::list<std::string>& extension_list); | |
void apply_black_list(std::istream& black_list_stream, std::list<std::string>& extension_list); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#tool nuget:?package=CMake&version=3.5.2 | |
#addin nuget:?package=Cake.Git&version=0.19.0 | |
#addin nuget:?package=Cake.CMake&version=0.2.2 | |
#addin nuget:?package=ClangSharp&version=3.8.0 | |
////////////////////////////////////////////////////////////////////// | |
// ARGUMENTS | |
////////////////////////////////////////////////////////////////////// | |
var target = Argument("target", "Default"); | |
var gitUserName = Argument("GitUserName", string.Empty); | |
var gitUserPassword = Argument("GitUserPassword", string.Empty); | |
var generator = Argument("generator", string.Empty); | |
var platforms = Argument("platforms", "Win32"); | |
var configs = Argument("configs", "Debug, Release"); | |
var targets = Argument("targets", "glew_generator_app, tests_xml, tests_xml_by_version, tests_parse_xml, tests_parse_xml_alternative"); | |
var versions = Argument("versions", "1.13"); | |
var test_filter = Argument("test_filter", string.Empty); | |
var glew_url = Argument("glew_url", "https://github.com/nigels-com/glew.git"); | |
var glfixes_url = Argument("glfixes_url", "https://github.com/nigels-com/glfixes.git"); | |
var open_gl_registry_url = Argument("open_gl_registry_url", "https://github.com/KhronosGroup/OpenGL-Registry.git"); | |
var egl_registry_url = Argument("egl_registry_url", "https://github.com/KhronosGroup/EGL-Registry.git"); | |
var pugixml_url = Argument("pugixml_url", "https://github.com/zeux/pugixml.git"); | |
var gtest_url = Argument("gtest_url", "https://github.com/google/googletest.git"); | |
////////////////////////////////////////////////////////////////////// | |
// CLASSES | |
////////////////////////////////////////////////////////////////////// | |
using System.Runtime.InteropServices; | |
using System.Reflection; | |
using LibGit2Sharp; | |
using ClangSharp; | |
public static class Misc | |
{ | |
public static char[] SplitSeparator { private set { } get { return new char[] { ',', ' ', ';', '\t', '\n' }; } } | |
} | |
public static class Versions | |
{ | |
public static ISet<System.Version> FromArgumentToArray(string argument) | |
{ | |
var str_versions = argument.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries); | |
var versions = new SortedSet<System.Version>(); | |
for (var i = 0; i < str_versions.Length; ++i) | |
{ | |
versions.Add(new System.Version(str_versions[i])); | |
} | |
return versions; | |
} | |
public static System.Version ver_1_13 { private set { } get { return new System.Version(1, 13); } } | |
public static System.Version ver_2_1 { private set { } get { return new System.Version(2, 1); } } | |
public static System.Version ver_2_2 { private set { } get { return new System.Version(2, 2); } } | |
public static System.Version GetHighestVersion(IEnumerable<System.Version> versions) | |
{ | |
var highest_version = new System.Version(); | |
foreach (var version in versions) | |
{ | |
if (highest_version < version) | |
{ | |
highest_version = version; | |
} | |
} | |
return highest_version; | |
} | |
public static string ToString(System.Version version) | |
{ | |
return $"{version}".Replace(".", "_"); | |
} | |
} | |
public static class Hashes | |
{ | |
public static string pugixml_hash { private set { } get { return "8436f2a69b9331f8e99a52772e93ba0dbb68dafe"; } } | |
public static string gtest_hash { private set { } get { return "2fe3bd994b3189899d93f1d5a881e725e046fdc2"; } } | |
// | |
public static string open_gl_registry_hash_2_2 { private set { } get { return "7457d2c708a49bd92d9c0b121740dec10bf7b5b6"; } } | |
public static string egl_registry_hash_2_2 { private set { } get { return "0555f6db15b61a99e5091d6826fb6fb67d9661c8"; } } | |
// | |
public static string glew_1_10 { private set { } get { return "a6c3e7dad0d1ae34e8016cf086ba6109d6fb4e4a"; } } | |
public static string glew_1_11 { private set { } get { return "83a2bae026289a8d4cdce0061b1c52595b3c9338"; } } | |
public static string glew_1_12 { private set { } get { return "9fedd9e053c973ef85cfc830c74a26d0cdd8c99a"; } } | |
public static string glew_1_13 { private set { } get { return "f0067bb1151d36b37bd43948ce5a399844afb313"; } } | |
public static string glew_2_0 { private set { } get { return "7d72257b0ff2aadab92d9b627beb44c36b072e52"; } } | |
public static string glew_2_1 { private set { } get { return "3a8eff77da3658c13fbd3634c943d5251d76322c"; } } | |
public static string glew_2_2 { private set { } get { return "61d167422c86735514e713eeea70e0477a979b26"; } } | |
// | |
public static string glfixes_1_10 { private set { } get { return "909400fa310f1eee70fcfd444630518cbfdce6f3"; } } | |
public static string glfixes_1_11 { private set { } get { return "c948e0dcdbb4aeb617da351c70887a79b94cdded"; } } | |
public static string glfixes_1_12 { private set { } get { return "d3ae5b802bf057e06f94d9c30b92e192e2316d7f"; } } | |
public static string glfixes_1_13 { private set { } get { return "6482cec77a49f12c20b2be0b17e0a537c043b64e"; } } | |
public static string glfixes_2_0 { private set { } get { return "c0e1bb4f7c49ffa844d930091d3ccb197feb42ee"; } } | |
public static string glfixes_2_1 { private set { } get { return "970b8145acd42ebd86ff025e1eb8c8cbcd1fc6a2"; } } | |
// | |
public static string get_property_value_by_name(string name) | |
{ | |
var props = typeof(Hashes).GetProperties(BindingFlags.Public | BindingFlags.Static); | |
foreach (var prop in props) | |
{ | |
if (prop.Name == name) | |
{ | |
return (string)prop.GetValue(null, null); | |
} | |
} | |
throw new ArgumentException($"Can not find property with name '{name}'."); | |
} | |
} | |
public class PathComparer : IComparer<Cake.Core.IO.Path> | |
{ | |
public int Compare(Cake.Core.IO.Path x, Cake.Core.IO.Path y) | |
{ | |
return StringComparer.Ordinal.Compare(x.FullPath, y.FullPath); | |
} | |
} | |
public class Paths | |
{ | |
public static Paths paths; | |
public DirectoryPath root { private set; get; } | |
public FilePath tests_xml { private set; get; } | |
public DirectoryPath output { private set; get; } | |
public DirectoryPath cmake_output_path { set; get; } | |
public DirectoryPath reference { private set; get; } | |
public DirectoryPath tools { private set; get; } | |
public DirectoryPath cmake_bin { private set; get; } | |
public FilePath cmake_exe { private set; get; } | |
public DirectoryPath repositories { private set; get; } | |
public DirectoryPath glew_dir { private set; get; } | |
public DirectoryPath glfixes_dir { private set; get; } | |
public DirectoryPath open_gl_registry_dir { private set; get; } | |
public DirectoryPath egl_registry_dir { private set; get; } | |
public DirectoryPath pugixml_dir { private set; get; } | |
public DirectoryPath gtest_dir { private set; get; } | |
public FilePath egl_xml { private set; get; } | |
public ICollection<DirectoryPath> bin_paths { private set; get; } | |
public SortedDictionary<System.Version, SortedSet<DirectoryPath>> version_and_outputs { private set; get; } | |
public static string Normalize(string path) | |
{ | |
if ('/' != System.IO.Path.DirectorySeparatorChar) | |
{ | |
path = path.Replace('/', System.IO.Path.DirectorySeparatorChar); | |
} | |
return path; | |
} | |
public static string Normalize(Cake.Core.IO.Path path) | |
{ | |
return Normalize(path.FullPath); | |
} | |
private Paths(ICakeContext context) | |
{ | |
root = context.Environment.WorkingDirectory; | |
// | |
tests_xml = root.CombineWithFilePath("tests.xml"); | |
output = root.Combine("output"); | |
cmake_output_path = output; | |
reference = root.Combine("reference"); | |
tools = root.Combine("tools"); | |
if (PlatformID.Unix == Environment.OSVersion.Platform) | |
{ | |
var unix_cmake_canditates = new FilePath[] { "/usr/bin/cmake", | |
"/usr/local/bin/cmake" }; | |
foreach (var path in unix_cmake_canditates) | |
{ | |
if (FileAliases.FileExists(context, path)) | |
{ | |
cmake_exe = path; | |
break; | |
} | |
} | |
} | |
else | |
{ | |
cmake_bin = tools.Combine("CMake.3.5.2").Combine("bin"); | |
cmake_exe = cmake_bin.CombineWithFilePath("cmake.exe"); | |
} | |
repositories = root.Combine("repositories"); | |
glew_dir = repositories.Combine("glew"); | |
glfixes_dir = repositories.Combine("glfixes"); | |
open_gl_registry_dir = repositories.Combine("OpenGL-Registry"); | |
egl_registry_dir = repositories.Combine("EGL-Registry"); | |
// | |
pugixml_dir = repositories.Combine("pugixml"); | |
gtest_dir = repositories.Combine("gtest"); | |
// | |
egl_xml = egl_registry_dir.Combine("api").CombineWithFilePath("egl.xml"); | |
// | |
bin_paths = new SortedSet<DirectoryPath>(new PathComparer()); | |
version_and_outputs = new SortedDictionary<System.Version, SortedSet<DirectoryPath>>(); | |
} | |
public static bool Init(ICakeContext context) | |
{ | |
if (null == paths) | |
{ | |
paths = new Paths(context); | |
} | |
return (null != paths); | |
} | |
} | |
public static class Git | |
{ | |
public static bool IsRepositoryExists(string aPath, out Repository aRepository, ICakeContext context) | |
{ | |
aRepository = null; | |
if (!DirectoryAliases.DirectoryExists(context, aPath)) | |
{ | |
return false; | |
} | |
try | |
{ | |
aRepository = new Repository(aPath); | |
} | |
catch (RepositoryNotFoundException) | |
{ | |
return false; | |
} | |
return true; | |
} | |
public static bool IsRepositoryContainsCommit(Repository aRepository, ObjectId aCommit) | |
{ | |
var commit = aRepository.Lookup(aCommit); | |
if (null == commit) | |
{ | |
return false; | |
} | |
if (commit is Commit) | |
{ | |
return true; | |
} | |
return false; | |
} | |
public static bool IsRepositoryContainsCommit(Repository aRepository, string aCommit) | |
{ | |
ObjectId commit = null; | |
try | |
{ | |
commit = new ObjectId(aCommit); | |
} | |
catch (ArgumentException) | |
{ | |
return false; | |
} | |
return IsRepositoryContainsCommit(aRepository, commit); | |
} | |
public static LibGit2Sharp.Handlers.CredentialsHandler CreateCredential(string aUserName, string aPassword) | |
{ | |
return new LibGit2Sharp.Handlers.CredentialsHandler( | |
(url, usernameFromUrl, types) => new UsernamePasswordCredentials() | |
{ | |
Username = aUserName, | |
Password = aPassword | |
}); | |
} | |
public static string Clone(string aSourceUrl, string aWorkdirPath, string aUserName = null, string aPassword = null) | |
{ | |
var cloneOptions = new CloneOptions(); | |
if (!string.IsNullOrEmpty(aUserName) && !string.IsNullOrEmpty(aPassword)) | |
{ | |
cloneOptions.CredentialsProvider = CreateCredential(aUserName, aPassword); | |
} | |
var pathToTheCreatedRepository = Repository.Clone(aSourceUrl, aWorkdirPath, cloneOptions); | |
return pathToTheCreatedRepository; | |
} | |
public static MergeResult Pull(Repository aRepository, string aUserName = null, string aPassword = null) | |
{ | |
var options = new PullOptions(); | |
if (!string.IsNullOrEmpty(aUserName) && !string.IsNullOrEmpty(aPassword)) | |
{ | |
options.FetchOptions = new FetchOptions(); | |
options.FetchOptions.CredentialsProvider = CreateCredential(aUserName, aPassword); | |
} | |
var merger = new Signature(Environment.UserName, $"{Environment.UserName}@{Environment.MachineName}", DateTimeOffset.UtcNow); | |
return Commands.Pull(aRepository, merger, options); | |
} | |
public static void EnsureRepositoriesExists(string[] urls, string[] dirs, string[] hashes, | |
string gitUserName, string gitUserPassword, ICakeContext context) | |
{ | |
if (dirs.Length != urls.Length || hashes.Length != urls.Length) | |
{ | |
throw new CakeException($"Length of dirs array '{dirs.Length}' not equal to the length of urls '{urls.Length}'."); | |
} | |
for (var i = 0; i < dirs.Length; ++i) | |
{ | |
Repository repository = null; | |
if (!Git.IsRepositoryExists(dirs[i], out repository, context)) | |
{ | |
context.Information($"'{dirs[i]}' not exists. Cloning from '{urls[i]}'."); | |
if (!string.IsNullOrEmpty(gitUserName) && !string.IsNullOrEmpty(gitUserPassword)) | |
{ | |
context.Information($"Will be used git user name '{gitUserName}'."); | |
} | |
var dir = Git.Clone(urls[i], dirs[i], gitUserName, gitUserPassword); | |
context.Information($"Cloned into '{dir}'."); | |
if (!Git.IsRepositoryExists(dirs[i], out repository, context)) | |
{ | |
throw new CakeException($"Could not find repository at '{dirs[i]}'."); | |
} | |
} | |
if (!Git.IsRepositoryContainsCommit(repository, hashes[i])) | |
{ | |
context.Information($"Commit with hash '{hashes[i]}' not exists at '{dirs[i]}'. Pull."); | |
if (!string.IsNullOrEmpty(gitUserName) && !string.IsNullOrEmpty(gitUserPassword)) | |
{ | |
context.Information($"Will be used git user name '{gitUserName}'."); | |
} | |
Git.Pull(repository, gitUserName, gitUserPassword); | |
if (!Git.IsRepositoryContainsCommit(repository, hashes[i])) | |
{ | |
throw new CakeException($"Could not find commit with hash '{hashes[i]}' at '{dirs[i]}' even after pull was provided. " | |
+ "That may indicate that commit with such hash not from that repository or from branch that actually not merged into master."); | |
} | |
} | |
} | |
} | |
public static bool Checkout(string path_to_repository, string commit_sha, ICakeContext context) | |
{ | |
Repository repository = null; | |
if (!IsRepositoryExists(path_to_repository, out repository, context)) | |
{ | |
return false; | |
} | |
var oid = new ObjectId(commit_sha); | |
var commit = repository.Lookup(oid); | |
if (!(commit is Commit)) | |
{ | |
return false; | |
} | |
var real_commit = commit as Commit; | |
if (repository.Head.Tip == real_commit) | |
{ | |
return true; | |
} | |
context.Information($"Checkout of '{path_to_repository}' onto '{commit_sha}'."); | |
Commands.Checkout(repository, real_commit); | |
return (repository.Head.Tip == real_commit); | |
} | |
private static long GetBlobContent(Blob blob, System.IO.Stream content) | |
{ | |
var blob_size = blob.Size; | |
if (0 < blob_size) | |
{ | |
blob.GetContentStream().CopyTo(content); | |
} | |
else | |
{ | |
blob_size = 0; | |
} | |
return blob_size; | |
} | |
private static void Walk(Tree tree, string real_root) | |
{ | |
foreach (var element in tree) | |
{ | |
var full_name = string.IsNullOrEmpty(real_root) ? element.Name : System.IO.Path.Combine(real_root, element.Name); | |
var element_target = element.Target; | |
if (TreeEntryTargetType.Tree == element.TargetType) | |
{ | |
Walk(element_target as Tree, full_name); | |
} | |
else if (TreeEntryTargetType.Blob == element.TargetType) | |
{ | |
if (!string.IsNullOrEmpty(real_root)) | |
{ | |
System.IO.Directory.CreateDirectory(real_root); | |
} | |
using (var fs = new System.IO.FileStream(full_name, System.IO.FileMode.Create)) | |
{ | |
GetBlobContent(element_target as Blob, fs); | |
} | |
} | |
} | |
} | |
public static bool SaveFilesFromRevision( | |
string path_to_repository, | |
string commit_sha, | |
string output_directory, | |
ICakeContext context) | |
{ | |
if (string.IsNullOrEmpty(path_to_repository) || | |
string.IsNullOrEmpty(commit_sha) || | |
string.IsNullOrEmpty(output_directory)) | |
{ | |
return false; | |
} | |
var oid = new ObjectId(commit_sha); | |
var repository = new Repository(path_to_repository); | |
var commit = repository.Lookup(oid); | |
if (!(commit is Commit)) | |
{ | |
return false; | |
} | |
context.Information($"Extracting from '{path_to_repository}' by hash '{commit_sha}' into '{output_directory}'."); | |
context.EnsureDirectoryExists(output_directory); | |
// | |
var real_commit = commit as Commit; | |
context.Information($"Repository : '{path_to_repository}'"); | |
context.Information($"Commit : '{commit_sha}'"); | |
context.Information($"Author : '{real_commit.Author.Name}'"); | |
context.Information($"Committer : '{real_commit.Committer.Name}'"); | |
context.Information($"Summary : '{real_commit.MessageShort}'"); | |
context.Information($"Will be stored at : '{output_directory}'"); | |
// | |
Walk(real_commit.Tree, output_directory); | |
return true; | |
} | |
} | |
public class SameFileNameStorage : ICollection<FilePath> | |
{ | |
private ICollection<FilePath> Storage = new SortedSet<FilePath>(new PathComparer()); | |
public int Count { get { return Storage.Count; } } | |
public bool IsReadOnly { get { return false; } } | |
public void Add(ICollection<string> item) | |
{ | |
var a = 0; | |
var itemToStorage = new FilePath[item.Count]; | |
foreach (var i in item) | |
{ | |
itemToStorage[a++] = new FilePath(i); | |
} | |
Add(itemToStorage); | |
} | |
public void Add(ICollection<FilePath> item) | |
{ | |
if (Storage.Count == 0) | |
{ | |
foreach (var i in item) | |
{ | |
Storage.Add(i); | |
} | |
} | |
else | |
{ | |
var pathsToAdd = new List<FilePath>(); | |
var pathsToRemove = new List<FilePath>(); | |
foreach (var storageItem in Storage) | |
{ | |
var exists = false; | |
foreach (var i in item) | |
{ | |
if (storageItem.GetFilename().FullPath == i.GetFilename().FullPath) | |
{ | |
exists = true; | |
pathsToAdd.Add(i); | |
break; | |
} | |
} | |
if (!exists) | |
{ | |
pathsToRemove.Add(storageItem); | |
} | |
} | |
foreach (var storageItem in pathsToRemove) | |
{ | |
Storage.Remove(storageItem); | |
} | |
foreach (var i in pathsToAdd) | |
{ | |
Storage.Add(i); | |
} | |
} | |
if (Storage.Count == 0) | |
{ | |
throw new Exception("Nothing to compare. Used collections with no common names."); | |
} | |
} | |
public void Add(FilePath item) | |
{ | |
Add(new FilePath[] { item }); | |
} | |
public void Clear() | |
{ | |
Storage.Clear(); | |
} | |
public bool Contains(FilePath item) | |
{ | |
return Storage.Contains(item); | |
} | |
public void CopyTo(FilePath[] array, int arrayIndex) | |
{ | |
throw new NotImplementedException(); | |
} | |
public IEnumerator<FilePath> GetEnumerator() | |
{ | |
return Storage.GetEnumerator(); | |
} | |
public bool Remove(FilePath item) | |
{ | |
if (Contains(item)) | |
{ | |
return Storage.Remove(item); | |
} | |
return false; | |
} | |
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
{ | |
throw new NotImplementedException(); | |
} | |
} | |
public static void AddExecPermission(FilePath path, ICakeContext context) | |
{ | |
var bash_arguments = new ProcessArgumentBuilder(); | |
bash_arguments.Append("-c"); | |
bash_arguments.Append($"\"chmod +x {path.GetFilename()}\""); | |
// | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 0, 15)).TotalMilliseconds); | |
processSettings.WorkingDirectory = path.GetDirectory(); | |
processSettings.Arguments = bash_arguments; | |
// | |
var fullPath = "bash"; | |
context.Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = context.StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
context.Warning($"Exit code was '{exitCode}'."); | |
} | |
} | |
private static CXToken[] ToTokens(IntPtr rawTokens, uint countOfTokens) | |
{ | |
var tokens = new CXToken[countOfTokens]; | |
for (int i = 0; i < countOfTokens; i++) | |
{ | |
tokens[i] = Marshal.PtrToStructure<CXToken>(rawTokens + i * Marshal.SizeOf<CXToken>()); | |
} | |
return tokens; | |
} | |
public static string GetLexicalAnalyze(string fileName) | |
{ | |
var index = clang.createIndex(0, 0); | |
CXUnsavedFile unsavedFiles; | |
var translationUnit = clang.parseTranslationUnit(index, fileName, null, 0, | |
out unsavedFiles, 0, (uint)CXTranslationUnit_Flags.CXTranslationUnit_None); | |
// | |
var translationUnitCursor = clang.getTranslationUnitCursor(translationUnit); | |
var cursorExtent = clang.getCursorExtent(translationUnitCursor); | |
IntPtr rawTokens = IntPtr.Zero; | |
uint countOfTokens = 0; | |
clang.tokenize(translationUnit, cursorExtent, out rawTokens, out countOfTokens); | |
var tokens = ToTokens(rawTokens, countOfTokens); | |
var output = new StringBuilder(); | |
for (uint i = 0; i < countOfTokens; ++i) | |
{ | |
var kind = clang.getTokenKind(tokens[i]); | |
switch (kind) | |
{ | |
case CXTokenKind.CXToken_Punctuation: | |
output.Append("A token that contains some kind of punctuation."); | |
break; | |
case CXTokenKind.CXToken_Keyword: | |
output.Append("A language keyword."); | |
break; | |
case CXTokenKind.CXToken_Identifier: | |
output.Append("An identifier (that is not a keyword)."); | |
break; | |
case CXTokenKind.CXToken_Literal: | |
output.Append("A numeric, string, or character literal."); | |
break; | |
case CXTokenKind.CXToken_Comment: | |
output.Append("A comment."); | |
break; | |
default: | |
output.Append("Unknown enum value of CXTokenKind."); | |
break; | |
} | |
var name = clang.getTokenSpelling(translationUnit, tokens[i]).ToString(); | |
output.AppendLine($" '{name}'"); | |
} | |
//clang.disposeTokens(translationUnit, out rawTokens, countOfTokens); | |
clang.disposeTranslationUnit(translationUnit); | |
clang.disposeIndex(index); | |
// | |
return output.ToString(); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// TASKS | |
////////////////////////////////////////////////////////////////////// | |
var generator_name = string.Empty; | |
string[] array_with_platforms = null; | |
string[] array_with_configs = null; | |
string[] array_with_targets = null; | |
ISet<System.Version> array_with_versions = null; | |
Setup(context => | |
{ | |
Paths.Init(context); | |
if (string.IsNullOrEmpty(generator)) | |
{ | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
generator_name = "Visual Studio 14 2015"; | |
} | |
else if (PlatformID.Unix == Environment.OSVersion.Platform) | |
{ | |
generator_name = "Eclipse CDT4 - Unix Makefiles"; | |
} | |
} | |
else | |
{ | |
generator_name = generator; | |
} | |
Paths.paths.cmake_output_path = Paths.paths.output.Combine(generator_name.Replace(" ", "_")); | |
if (generator_name.EndsWith("Makefiles")) | |
{ | |
array_with_platforms = new string[] { string.Empty }; | |
} | |
else | |
{ | |
array_with_platforms = platforms.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries); | |
} | |
if (generator_name.StartsWith("Visual") && 0 == array_with_platforms.Length) | |
{ | |
if (Environment.Is64BitOperatingSystem) | |
{ | |
array_with_platforms = new string[] { "x64", "Win32" }; | |
} | |
else | |
{ | |
array_with_platforms = new string[] { "Win32" }; | |
} | |
} | |
array_with_configs = configs.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries); | |
if (0 == array_with_configs.Length) | |
{ | |
array_with_configs = new string[] { "Debug", "Release" }; | |
} | |
array_with_targets = targets.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries); | |
if (array_with_targets.Length == 0) | |
{ | |
array_with_targets = new string[] { string.Empty }; | |
} | |
array_with_versions = Versions.FromArgumentToArray(versions); | |
if (array_with_versions.Count == 0) | |
{ | |
array_with_versions.Add(Versions.ver_1_13); | |
} | |
}); | |
Task("clean") | |
.Does(content => | |
{ | |
var files = new List<string>(); | |
foreach (var folder in new DirectoryPath[] { Paths.paths.output }) | |
{ | |
if (!DirectoryExists(folder)) | |
{ | |
continue; | |
} | |
files.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(folder), "*.*", System.IO.SearchOption.AllDirectories)); | |
} | |
foreach (var file in files) | |
{ | |
if (file.StartsWith(Paths.paths.cmake_output_path.FullPath)) | |
{ | |
continue; | |
} | |
Information(file); | |
var empty = false; | |
using (var fs = new FileStream(file, FileMode.Open)) | |
{ | |
if (0 == fs.Length) | |
{ | |
empty = true; | |
} | |
} | |
if (empty) | |
{ | |
System.IO.File.Delete(file); | |
} | |
else | |
{ | |
System.IO.File.WriteAllText(file, string.Empty); | |
} | |
} | |
}); | |
Task("get_data_repositories") | |
.Does(context => | |
{ | |
var urls = new string[] { glew_url, glfixes_url, open_gl_registry_url, egl_registry_url }; | |
var dirs = new string[] { Paths.Normalize(Paths.paths.glew_dir), | |
Paths.Normalize(Paths.paths.glfixes_dir), | |
Paths.Normalize(Paths.paths.open_gl_registry_dir), | |
Paths.Normalize(Paths.paths.egl_registry_dir) }; | |
// | |
var highest_version = Versions.GetHighestVersion(array_with_versions); | |
var str_ver = Versions.ToString(highest_version); | |
// | |
var glew_hash = Hashes.get_property_value_by_name($"glew_{str_ver}"); | |
var glfixes_hash = ((Versions.ver_2_1 < highest_version) ? Hashes.glfixes_2_1 : Hashes.get_property_value_by_name($"glfixes_{str_ver}")); | |
// | |
var hashes = new string[] { glew_hash, | |
glfixes_hash, | |
Hashes.open_gl_registry_hash_2_2, | |
Hashes.egl_registry_hash_2_2 }; | |
// | |
Git.EnsureRepositoriesExists(urls, dirs, hashes, gitUserName, gitUserPassword, context); | |
}); | |
Task("git_extractor") | |
.IsDependentOn("get_data_repositories") | |
.Does(context => | |
{ | |
foreach (var version in array_with_versions) | |
{ | |
Information($"Version - '{version}'."); | |
var str_ver = Versions.ToString(version); | |
// | |
var glew_output_dir = $"glew_{str_ver}"; | |
var glew_hash = Hashes.get_property_value_by_name(glew_output_dir); | |
glew_output_dir = Paths.Normalize(Paths.paths.repositories.Combine(glew_output_dir)); | |
if (!DirectoryExists(glew_output_dir)) | |
{ | |
if (!Git.SaveFilesFromRevision(Paths.Normalize(Paths.paths.glew_dir), glew_hash, glew_output_dir, context)) | |
{ | |
throw new CakeException($"Extracting was failed."); | |
} | |
} | |
/*TODO: if (Versions.ver_2_1 < version) | |
{ | |
continue; | |
}*/ | |
var glfixes_output_dir = $"glfixes_{str_ver}"; | |
var glfixes_hash = ((Versions.ver_2_1 < version) ? Hashes.glfixes_2_1 : Hashes.get_property_value_by_name($"glfixes_{str_ver}")); | |
glfixes_output_dir = System.IO.Path.Combine(glew_output_dir, "auto", "registry"); | |
if (!DirectoryExists(glfixes_output_dir)) | |
{ | |
if (!Git.SaveFilesFromRevision(Paths.Normalize(Paths.paths.glfixes_dir), glfixes_hash, glfixes_output_dir, context)) | |
{ | |
throw new CakeException($"Extracting was failed."); | |
} | |
} | |
} | |
//var highest_version = Versions.GetHighestVersion(array_with_versions); | |
//if (Versions.ver_2_1 < highest_version) | |
{ | |
if (!Git.Checkout(Paths.Normalize(Paths.paths.open_gl_registry_dir), Hashes.open_gl_registry_hash_2_2, context)) | |
{ | |
throw new CakeException($"Checkout was failed."); | |
} | |
if (!Git.Checkout(Paths.Normalize(Paths.paths.egl_registry_dir), Hashes.egl_registry_hash_2_2, context)) | |
{ | |
throw new CakeException($"Checkout was failed."); | |
} | |
} | |
}); | |
Task("get_pugixml_and_gtest") | |
.WithCriteria(() => FileExists(Paths.paths.tests_xml)) | |
.Does(context => | |
{ | |
var urls = new string[] { pugixml_url, gtest_url }; | |
var dirs = new string[] { Paths.Normalize(Paths.paths.pugixml_dir), Paths.Normalize(Paths.paths.gtest_dir) }; | |
var hashes = new string[] { Hashes.pugixml_hash, Hashes.gtest_hash }; | |
// | |
Git.EnsureRepositoriesExists(urls, dirs, hashes, gitUserName, gitUserPassword, context); | |
for (var i = 0; i < dirs.Length; ++i) | |
{ | |
if (!Git.Checkout(dirs[i], hashes[i], context)) | |
{ | |
throw new CakeException($"Checkout was failed."); | |
} | |
} | |
}); | |
Task("config") | |
.IsDependentOn("get_pugixml_and_gtest") | |
.Does(context => | |
{ | |
var cmakeSettings = new CMakeSettings(); | |
if (PlatformID.Unix == Environment.OSVersion.Platform) | |
{ | |
if (string.IsNullOrEmpty(Paths.paths.cmake_exe.FullPath)) | |
{ | |
throw new CakeException("Could not find cmake."); | |
} | |
cmakeSettings.ToolPath = Paths.paths.cmake_exe; | |
} | |
cmakeSettings.ToolTimeout = new TimeSpan(0, 1, 0); | |
cmakeSettings.Generator = generator_name; | |
if (FileExists(Paths.paths.tests_xml)) | |
{ | |
cmakeSettings.Options = new string[] { $"-DPUGIXML_PATH={Paths.paths.pugixml_dir}", | |
$"-DGTEST_PATH={Paths.paths.gtest_dir}" }; | |
} | |
foreach (var platform in array_with_platforms) | |
{ | |
cmakeSettings.OutputPath = Paths.paths.cmake_output_path; | |
if (cmakeSettings.Generator.StartsWith("Visual")) | |
{ | |
cmakeSettings.Platform = platform; | |
cmakeSettings.OutputPath = cmakeSettings.OutputPath.Combine(platform); | |
// | |
EnsureDirectoryExists(cmakeSettings.OutputPath); | |
Information($"Platform - '{platform}', output path - '{cmakeSettings.OutputPath}'."); | |
CMakeAliases.CMake(context, Paths.paths.root, cmakeSettings); | |
} | |
else if (cmakeSettings.Generator.EndsWith("Makefiles")) | |
{ | |
foreach (var config in array_with_configs) | |
{ | |
var currentOutputPath = cmakeSettings.OutputPath; | |
cmakeSettings.OutputPath = currentOutputPath.Combine(config); | |
// | |
var options = new string[1 + cmakeSettings.Options.Count]; | |
Array.Copy((cmakeSettings.Options as string[]), options, cmakeSettings.Options.Count); | |
options[options.Length - 1] = $"-DCMAKE_BUILD_TYPE=\"{config}\""; | |
// | |
EnsureDirectoryExists(cmakeSettings.OutputPath); | |
Information($"Platform - '{platform}', config - '{config}', output path - '{cmakeSettings.OutputPath}'."); | |
CMakeAliases.CMake(context, Paths.paths.root, cmakeSettings); | |
// | |
cmakeSettings.Options = new string[options.Length - 1]; | |
Array.Copy(options, (cmakeSettings.Options as string[]), cmakeSettings.Options.Count); | |
cmakeSettings.OutputPath = currentOutputPath; | |
} | |
} | |
} | |
}); | |
Task("make_binaries") | |
.IsDependentOn("config") | |
.Does(context => | |
{ | |
foreach (var target in array_with_targets) | |
{ | |
var outputPath = Paths.paths.cmake_output_path; | |
foreach (var platform in array_with_platforms) | |
{ | |
DirectoryPath outputPathWithPlatform = string.Empty; | |
if (generator_name.StartsWith("Visual")) | |
{ | |
outputPathWithPlatform = outputPath.Combine(platform); | |
} | |
else | |
{ | |
outputPathWithPlatform = outputPath; | |
} | |
foreach (var config in array_with_configs) | |
{ | |
DirectoryPath outputPathWithPlatformAndConfig = string.Empty; | |
if (generator_name.EndsWith("Makefiles")) | |
{ | |
outputPathWithPlatformAndConfig = outputPathWithPlatform.Combine(config); | |
} | |
else | |
{ | |
outputPathWithPlatformAndConfig = outputPathWithPlatform; | |
} | |
var processArgumentBuilder = new ProcessArgumentBuilder(); | |
processArgumentBuilder.Append("--build"); | |
processArgumentBuilder.Append(Paths.Normalize(outputPathWithPlatformAndConfig).Quote()); | |
if (!string.IsNullOrEmpty(target)) | |
{ | |
processArgumentBuilder.Append("--target"); | |
processArgumentBuilder.Append(target); | |
} | |
if (!generator_name.EndsWith("Makefiles")) | |
{ | |
processArgumentBuilder.Append("--config"); | |
processArgumentBuilder.Append(config); | |
} | |
var processSettings = new ProcessSettings(); | |
processSettings.Arguments = processArgumentBuilder; | |
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = outputPathWithPlatformAndConfig; | |
// | |
Information($"Platform - '{platform}', target - '{target}', config - '{config}' at '{outputPathWithPlatformAndConfig}'."); | |
var exitCode = StartProcess(Paths.Normalize(Paths.paths.cmake_exe), processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Build of '{outputPathWithPlatformAndConfig}' was failed."); | |
} | |
if (generator_name.EndsWith("Makefiles")) | |
{ | |
Paths.paths.bin_paths.Add(outputPathWithPlatformAndConfig); | |
} | |
else | |
{ | |
Paths.paths.bin_paths.Add(outputPathWithPlatformAndConfig.Combine(config)); | |
} | |
} | |
} | |
} | |
}); | |
Task("glew_generator_app") | |
.IsDependentOn("make_binaries") | |
.IsDependentOn("git_extractor") | |
.Does(context => | |
{ | |
foreach (var version in array_with_versions) | |
{ | |
var str_ver = Versions.ToString(version); | |
// | |
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}"); | |
var glfixes_dir = glew_dir.Combine("auto").Combine("registry"); | |
// | |
var glew_generator_arguments = new ProcessArgumentBuilder(); | |
glew_generator_arguments.Append(Paths.Normalize(glew_dir).Quote()); | |
glew_generator_arguments.Append(Paths.Normalize(glfixes_dir).Quote()); //TODO: Will be removed for Versions.ver_2_2 | |
if (Versions.ver_2_1 < version) | |
{ | |
glew_generator_arguments.Append(Paths.Normalize(Paths.paths.open_gl_registry_dir).Quote()); | |
glew_generator_arguments.Append(Paths.Normalize(Paths.paths.egl_registry_dir).Quote()); | |
} | |
var output = Paths.paths.output.Combine(str_ver); | |
if (generator_name.StartsWith("Visual")) | |
{ | |
output = output.Combine(generator_name.Replace(" ", "_")); | |
} | |
if (!Paths.paths.version_and_outputs.ContainsKey(version)) | |
{ | |
Paths.paths.version_and_outputs.Add(version, new SortedSet<DirectoryPath>(new PathComparer())); | |
} | |
foreach (var bin_path in Paths.paths.bin_paths) | |
{ | |
var full_output = output; | |
if (2 < bin_path.Segments.Length) | |
{ | |
for (var i = bin_path.Segments.Length - 2; i < bin_path.Segments.Length; ++i) | |
{ | |
full_output = full_output.Combine(bin_path.Segments[i]); | |
} | |
} | |
EnsureDirectoryExists(full_output); | |
var arguments = ProcessArgumentBuilder.FromString(glew_generator_arguments.Render()); | |
arguments.Append(Paths.Normalize(full_output).Quote()); | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = bin_path; | |
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "glew_generator_app"); | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe"); | |
} | |
fullPath = Paths.Normalize(fullPath); | |
processSettings.Arguments = arguments; | |
Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Run of '{fullPath}' was failed."); | |
} | |
Paths.paths.version_and_outputs[version].Add(full_output); | |
} | |
} | |
}); | |
Task("tests_xml") | |
.IsDependentOn("make_binaries") | |
.WithCriteria(() => FileExists(Paths.paths.tests_xml)) | |
.Does(context => | |
{ | |
var tests_xml_arguments = new ProcessArgumentBuilder(); | |
tests_xml_arguments.Append($"--tests.xml={Paths.Normalize(Paths.paths.tests_xml).Quote()}"); | |
if (!string.IsNullOrEmpty(test_filter)) | |
{ | |
tests_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}"); | |
} | |
foreach (var bin_path in Paths.paths.bin_paths) | |
{ | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 1, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = bin_path; | |
// | |
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "tests_xml"); | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe"); | |
} | |
fullPath = Paths.Normalize(fullPath); | |
processSettings.Arguments = tests_xml_arguments; | |
Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Run of '{fullPath}' was failed."); | |
} | |
} | |
}); | |
Task("tests_xml_by_version") | |
.IsDependentOn("make_binaries") | |
.IsDependentOn("git_extractor") | |
.WithCriteria(() => FileExists(Paths.paths.tests_xml)) | |
.Does(context => | |
{ | |
foreach (var version in array_with_versions) | |
{ | |
var str_ver = Versions.ToString(version); | |
// | |
var tests_xml = Paths.paths.tests_xml.GetDirectory().CombineWithFilePath($"tests_{str_ver}.xml"); | |
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}"); | |
var glfixes_dir = glew_dir.Combine("auto").Combine("registry"); | |
// | |
var tests_xml_arguments = new ProcessArgumentBuilder(); | |
tests_xml_arguments.Append($"--tests.xml={Paths.Normalize(tests_xml).Quote()}"); | |
tests_xml_arguments.Append($"--glew_path={Paths.Normalize(glew_dir).Quote()}"); | |
tests_xml_arguments.Append($"--glfixes_path={Paths.Normalize(glfixes_dir).Quote()}"); | |
if (!string.IsNullOrEmpty(test_filter)) | |
{ | |
tests_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}"); | |
} | |
foreach (var bin_path in Paths.paths.bin_paths) | |
{ | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = bin_path; | |
// | |
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "tests_xml_by_version"); | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe"); | |
} | |
fullPath = Paths.Normalize(fullPath); | |
processSettings.Arguments = tests_xml_arguments; | |
Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Run of '{fullPath}' was failed."); | |
} | |
} | |
} | |
}); | |
Task("tests_parse_xml") | |
.IsDependentOn("make_binaries") | |
.IsDependentOn("git_extractor") | |
.WithCriteria(() => FileExists(Paths.paths.tests_xml)) | |
.Does(context => | |
{ | |
//foreach (var version in array_with_versions) | |
{ | |
var version = Versions.ver_2_2; | |
var str_ver = Versions.ToString(version); | |
var tests_parse_xml = Paths.paths.root.CombineWithFilePath($"tests_parse_xml_{str_ver}.xml"); | |
if (!FileExists(tests_parse_xml)) | |
{ | |
return; | |
} | |
var tests_parse_xml_arguments = new ProcessArgumentBuilder(); | |
tests_parse_xml_arguments.Append($"--tests.xml={Paths.Normalize(tests_parse_xml).Quote()}"); | |
tests_parse_xml_arguments.Append($"--input.xml={Paths.Normalize(Paths.paths.egl_xml).Quote()}"); | |
if (!string.IsNullOrEmpty(test_filter)) | |
{ | |
tests_parse_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}"); | |
} | |
foreach (var bin_path in Paths.paths.bin_paths) | |
{ | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 5, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = bin_path; | |
foreach (var target in ((array_with_targets.Length == 0) ? new string[] { "tests_parse_xml" } : array_with_targets)) | |
{ | |
if (!target.StartsWith("tests_parse_xml")) | |
{ | |
continue; | |
} | |
var fullPath = System.IO.Path.Combine(bin_path.FullPath, target); | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe"); | |
} | |
fullPath = Paths.Normalize(fullPath); | |
processSettings.Arguments = tests_parse_xml_arguments; | |
Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Run of '{fullPath}' was failed."); | |
} | |
} | |
} | |
} | |
}); | |
Task("reference_output") | |
.IsDependentOn("git_extractor") | |
.WithCriteria(() => ((PlatformID.Unix == Environment.OSVersion.Platform) && FileExists("/usr/bin/make"))) | |
.Does(context => | |
{ | |
foreach (var version in array_with_versions) | |
{ | |
if (Versions.ver_2_1 < version) | |
{ | |
Warning($"Processing of version '{version}' not implemented in this task. Try to use version below or equal to the '{Versions.ver_2_1}'."); | |
continue; | |
} | |
if (!Paths.paths.version_and_outputs.ContainsKey(version)) | |
{ | |
Paths.paths.version_and_outputs.Add(version, new SortedSet<DirectoryPath>(new PathComparer())); | |
} | |
var str_ver = Versions.ToString(version); | |
// | |
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}"); | |
var auto_dir = glew_dir.Combine("auto"); | |
// | |
var file_list = new List<string>(); | |
file_list.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(auto_dir), "*.sh", System.IO.SearchOption.AllDirectories)); | |
file_list.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(auto_dir), "*.pl", System.IO.SearchOption.AllDirectories)); | |
foreach (var script in file_list) | |
{ | |
AddExecPermission(script, context); | |
} | |
var make_arguments = new ProcessArgumentBuilder(); | |
//make_arguments.Append($"-C {auto_dir.Quote()}"); | |
make_arguments.Append("--environment-overrides GIT_CLONE=@echo"); | |
// | |
var processSettings = new ProcessSettings(); | |
processSettings.Timeout = (int)((new TimeSpan(0, 5, 0)).TotalMilliseconds); | |
processSettings.WorkingDirectory = auto_dir; | |
processSettings.Arguments = make_arguments; | |
// | |
var fullPath = "/usr/bin/make"; | |
Information($"{fullPath} {processSettings.Arguments.Render()}"); | |
var exitCode = StartProcess(fullPath, processSettings); | |
if (0 != exitCode) | |
{ | |
throw new CakeException($"Run of '{fullPath}' was failed."); | |
} | |
Paths.paths.version_and_outputs[version].Add(glew_dir); | |
} | |
}); | |
Task("fix_ClangSharp.3.8.0") | |
.WithCriteria(() => (PlatformID.Win32NT == Environment.OSVersion.Platform)) | |
.Does(()=> | |
{ | |
var input_directory = Paths.paths.tools.Combine("Addins").Combine("ClangSharp.3.8.0").Combine("content"); | |
if (Environment.Is64BitOperatingSystem) | |
{ | |
input_directory = input_directory.Combine("x64"); | |
} | |
else | |
{ | |
input_directory = input_directory.Combine("x86"); | |
} | |
var value = Environment.GetEnvironmentVariable("PATH"); | |
value += $";{input_directory}"; | |
Environment.SetEnvironmentVariable("PATH", value); | |
value = Environment.GetEnvironmentVariable("PATH"); | |
}); | |
Task("analyze_sources") | |
.IsDependentOn("reference_output") | |
.IsDependentOn("glew_generator_app") | |
.IsDependentOn("fix_ClangSharp.3.8.0") | |
.Does(()=> | |
{ | |
foreach (var version_and_outputs in Paths.paths.version_and_outputs) | |
{ | |
var str_ver = Versions.ToString(version_and_outputs.Key); | |
var files = new SameFileNameStorage(); | |
foreach (var path in version_and_outputs.Value) | |
{ | |
files.Add(System.IO.Directory.GetFiles(path.FullPath, "*.*", System.IO.SearchOption.AllDirectories)); | |
} | |
if (PlatformID.Win32NT == Environment.OSVersion.Platform) | |
{ | |
var path = Paths.Normalize(Paths.paths.reference.Combine($"glew_{str_ver}")); | |
files.Add(System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories)); | |
} | |
foreach (var file in files) | |
{ | |
var fileExtension = file.GetExtension(); | |
if (fileExtension != ".c" && fileExtension != ".h") | |
{ | |
continue; | |
} | |
if (PlatformID.Win32NT != Environment.OSVersion.Platform) | |
{ | |
if (!file.FullPath.StartsWith(Paths.paths.output.FullPath)) | |
{ | |
var reference_output = Paths.paths.reference; | |
if (3 < file.Segments.Length) | |
{ | |
for (var i = file.Segments.Length - 4; i < file.Segments.Length - 1; ++i) | |
{ | |
if ("repositories" == file.Segments[i]) | |
{ | |
continue; | |
} | |
reference_output = reference_output.Combine(file.Segments[i]); | |
} | |
} | |
EnsureDirectoryExists(reference_output); | |
var reference_file_name = reference_output.CombineWithFilePath(file.GetFilename()); | |
Information($"Reference file - '{file}'."); | |
CopyFile(file, reference_file_name); | |
} | |
continue; | |
} | |
var analyze = GetLexicalAnalyze(file.FullPath); | |
var outputFile = file.ChangeExtension($"{file.GetExtension()}.txt"); | |
// | |
Information($"Analyze of '{file}' will be saved at '{outputFile}'."); | |
System.IO.File.WriteAllText(outputFile.FullPath, analyze); | |
} | |
} | |
}); | |
Task("Default") | |
.IsDependentOn("clean") | |
.IsDependentOn("tests_xml") | |
.IsDependentOn("tests_xml_by_version") | |
.IsDependentOn("tests_parse_xml") | |
.IsDependentOn("analyze_sources"); | |
////////////////////////////////////////////////////////////////////// | |
// EXECUTION | |
////////////////////////////////////////////////////////////////////// | |
RunTarget(target); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<!-- | |
########################################################################## | |
# This is the Cake bootstrapper script for MSBuild environment. | |
# This file was downloaded from https://github.com/cake-build/resources (at current time under review https://github.com/cake-build/resources/pull/67 ) | |
# Feel free to change this file to fit your needs. | |
########################################################################## | |
--> | |
<Project DefaultTargets="Bootstrap" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
<PropertyGroup> | |
<CakeId Condition="'$(MSBuildRuntimeType)'=='Full'">Cake</CakeId> | |
<CakeId Condition="'$(MSBuildRuntimeType)'=='Core'">Cake.CoreCLR</CakeId> | |
<CakeVersion>0.32.1</CakeVersion> | |
</PropertyGroup> | |
<ItemGroup Condition="'$(ForceDownloaPackagesConfig)'==''"> | |
<packages_config Include="<?xml version="1.0" encoding="utf-8"?>" /> | |
<packages_config Include="<packages>" /> | |
<packages_config Include=" <package id="$(CakeId)" version="$(CakeVersion)" />" /> | |
<packages_config Include="</packages>" /> | |
</ItemGroup> | |
<PropertyGroup Condition="'$(ForceDownloadNuGetFile)'==''"> | |
<NuGetVersion>4.9.4</NuGetVersion> | |
</PropertyGroup> | |
<PropertyGroup> | |
<NuGetCommandArguments></NuGetCommandArguments> | |
<NuGet_ConfigFile></NuGet_ConfigFile> | |
</PropertyGroup> | |
<PropertyGroup Label="Define directories"> | |
<SCRIPT_DIR>$(MSBuildThisFileDirectory)</SCRIPT_DIR> | |
<TOOLS_DIR>$([System.IO.Path]::Combine($(SCRIPT_DIR), tools))</TOOLS_DIR> | |
<ADDINS_DIR>$([System.IO.Path]::Combine($(TOOLS_DIR), Addins))</ADDINS_DIR> | |
<MODULES_DIR>$([System.IO.Path]::Combine($(TOOLS_DIR), Modules))</MODULES_DIR> | |
<NUGET_EXE>$([System.IO.Path]::Combine($(TOOLS_DIR), nuget.exe))</NUGET_EXE> | |
<CAKE_EXE Condition="'$(CakeId)'=='Cake'">$([System.IO.Path]::Combine($(TOOLS_DIR), Cake, Cake.exe))</CAKE_EXE> | |
<CAKE_EXE Condition="'$(CakeId)'=='Cake.CoreCLR'">$([System.IO.Path]::Combine($(TOOLS_DIR), Cake.CoreCLR, Cake.dll))</CAKE_EXE> | |
<PACKAGES_CONFIG>$([System.IO.Path]::Combine($(TOOLS_DIR), packages.config))</PACKAGES_CONFIG> | |
<PACKAGES_CONFIG_MD5>$([System.IO.Path]::Combine($(TOOLS_DIR), packages.config.md5sum))</PACKAGES_CONFIG_MD5> | |
<ADDINS_PACKAGES_CONFIG>$([System.IO.Path]::Combine($(ADDINS_DIR), packages.config))</ADDINS_PACKAGES_CONFIG> | |
<MODULES_PACKAGES_CONFIG>$([System.IO.Path]::Combine($(MODULES_DIR), packages.config))</MODULES_PACKAGES_CONFIG> | |
</PropertyGroup> | |
<PropertyGroup Label="Define default arguments"> | |
<SCRIPT>build.cake</SCRIPT> | |
<SCRIPT_FULL_PATH>$([System.IO.Path]::Combine($(SCRIPT_DIR), $(SCRIPT)))</SCRIPT_FULL_PATH> | |
<CAKE_ARGUMENTS></CAKE_ARGUMENTS> | |
</PropertyGroup> | |
<!-- Define md5 --> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core'"> | |
<NetCoreAppVersion>netcoreapp2.1</NetCoreAppVersion> | |
</PropertyGroup> | |
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Full'"> | |
<csproj Include="<?xml version="1.0" encoding="utf-8"?>" /> | |
<csproj Include="<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">" /> | |
</ItemGroup> | |
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Core'"> | |
<csproj Include="<Project Sdk="Microsoft.NET.Sdk">" /> | |
<csproj Include=" " /> | |
<csproj Include=" <PropertyGroup>" /> | |
<csproj Include=" <OutputType>Exe</OutputType>" /> | |
<csproj Include=" <TargetFramework>$(NetCoreAppVersion)</TargetFramework>" /> | |
<csproj Include=" </PropertyGroup>" /> | |
<csproj Include=" " /> | |
</ItemGroup> | |
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'=='' And '$(MSBuildRuntimeType)'=='Full'"> | |
<csproj Include=" <Import Project="$(MSBuildBinPath)\Microsoft.Common.CurrentVersion.targets" />" /> | |
</ItemGroup> | |
<!-- Cake.Bakery -Version 0.3.0 / 0.2.0 / 0.1.2 / 0.1.1 / 0.1.0 --> | |
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'==''"> | |
<csproj Include=" <ItemGroup>" /> | |
<csproj Include=" <PackageReference Include="NuGet.CommandLine" Version="$(NuGetVersion)" />" /> | |
<csproj Include=" </ItemGroup>" /> | |
</ItemGroup> | |
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'=='' And '$(MSBuildRuntimeType)'=='Full'"> | |
<csproj Include=" <Target Name="Build" DependsOnTargets="Restore">" /> | |
</ItemGroup> | |
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'!='' And '$(MSBuildRuntimeType)'=='Full'"> | |
<csproj Include=" <Target Name="Build">" /> | |
</ItemGroup> | |
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Full'"> | |
<csproj Include=" <Csc" /> | |
<csproj Include=" Sources="$([System.IO.Path]::Combine($(SCRIPT_DIR), tools, MD5HashFile.cs))"" /> | |
<csproj Include=" OutputAssembly="$([System.IO.Path]::Combine($(SCRIPT_DIR), tools, MD5HashFile.exe))" />" /> | |
<csproj Include=" </Target> "/> | |
</ItemGroup> | |
<ItemGroup> | |
<csproj Include="</Project>" /> | |
</ItemGroup> | |
<ItemGroup> | |
<cs Include="using System%3b" /> | |
<cs Include="using System.IO%3b" /> | |
<cs Include=" " /> | |
<cs Include="namespace ConsoleApplication" /> | |
<cs Include="{" /> | |
<cs Include=" class Program" /> | |
<cs Include=" {" /> | |
<cs Include=" public static string MD5HashFile(string filePath)" /> | |
<cs Include=" {" /> | |
<cs Include=" if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))" /> | |
<cs Include=" {" /> | |
<cs Include=" return string.Empty%3b" /> | |
<cs Include=" }" /> | |
<cs Include=" " /> | |
<cs Include=" using (var md5 = System.Security.Cryptography.MD5.Create())" /> | |
<cs Include=" {" /> | |
<cs Include=" using (var file = File.OpenRead(filePath))" /> | |
<cs Include=" {" /> | |
<cs Include=" return BitConverter.ToString(md5.ComputeHash(file))%3b" /> | |
<cs Include=" }" /> | |
<cs Include=" }" /> | |
<cs Include=" }" /> | |
<cs Include=" " /> | |
<cs Include=" public static void SaveContents(string filePath, string contents)" /> | |
<cs Include=" {" /> | |
<cs Include=" if (string.IsNullOrEmpty(filePath))" /> | |
<cs Include=" {" /> | |
<cs Include=" return%3b" /> | |
<cs Include=" }" /> | |
<cs Include=" " /> | |
<cs Include=" File.WriteAllText(filePath, contents)%3b" /> | |
<cs Include=" }" /> | |
<cs Include=" " /> | |
<cs Include=" public static void Main(string[] args)" /> | |
<cs Include=" {" /> | |
<cs Include=" if (2 == args.Length) SaveContents(args[1], MD5HashFile(args[0]))%3b" /> | |
<cs Include=" }" /> | |
<cs Include=" }" /> | |
<cs Include="}" /> | |
</ItemGroup> | |
<PropertyGroup Label="MD5HashFile Project"> | |
<MD5HashFile_cs>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.cs))</MD5HashFile_cs> | |
<MD5HashFile_csproj>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.csproj))</MD5HashFile_csproj> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Full'"> | |
<MD5_Binary>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.exe))</MD5_Binary> | |
<MD5>"$(MD5_Binary)"</MD5> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core'"> | |
<BuildTool Condition="Exists('$(DOTNET_HOST_PATH)')">$(DOTNET_HOST_PATH)</BuildTool> | |
<MD5_Binary>$([System.IO.Path]::Combine($(TOOLS_DIR), bin, Release, $(NetCoreAppVersion), MD5HashFile.dll))</MD5_Binary> | |
<MD5>"$(BuildTool)" "$(MD5_Binary)"</MD5> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix'"> | |
<UnixExecutor>mono</UnixExecutor> | |
</PropertyGroup> | |
<PropertyGroup> | |
<Verbosity>-verbosity=</Verbosity> | |
</PropertyGroup> | |
<Target Name="ValidateVerbosity" Condition="$(CAKE_ARGUMENTS.Contains('$(Verbosity)'))"> | |
<PropertyGroup> | |
<Length>$(Verbosity.Length)</Length> | |
<Index>$(CAKE_ARGUMENTS.IndexOf('$(Verbosity)'))</Index> | |
<Index>$([MSBuild]::Add($(Index), $(Length)))</Index> | |
<IndexOfSpace>$(CAKE_ARGUMENTS.IndexOf(' ', $(Index)))</IndexOfSpace> | |
<Length Condition="'$(IndexOfSpace)'!='-1'">$([MSBuild]::Subtract($(IndexOfSpace), $(Index)))</Length> | |
<VerbosityValue Condition="'$(IndexOfSpace)'!='-1'">$(CAKE_ARGUMENTS.Substring($(Index), $(Length)))</VerbosityValue> | |
<VerbosityValue Condition="'$(IndexOfSpace)'=='-1'">$(CAKE_ARGUMENTS.Substring($(Index)))</VerbosityValue> | |
</PropertyGroup> | |
<Error | |
Text="'$(Verbosity)' can be set to one of the following values: 'Quiet', 'Minimal', 'Normal', 'Verbose' or 'Diagnostic'. Instead it equal to the '$(VerbosityValue)'." | |
Condition="'$(VerbosityValue)'!='Quiet' And '$(VerbosityValue)'!='Minimal' And '$(VerbosityValue)'!='Normal' And '$(VerbosityValue)'!='Verbose' And '$(VerbosityValue)'!='Diagnostic'" /> | |
</Target> | |
<Target Name="MD5Tool" Condition="!Exists('$(MD5_Binary)')"> | |
<WriteLinesToFile | |
File="$(MD5HashFile_csproj)" | |
Lines="@(csproj)" | |
Overwrite="true" | |
WriteOnlyWhenDifferent="true" /> | |
<WriteLinesToFile | |
File="$(MD5HashFile_cs)" | |
Lines="@(cs)" | |
Overwrite="true" | |
WriteOnlyWhenDifferent="true" /> | |
<MSBuild | |
Condition="'$(MSBuildRuntimeType)'=='Full'" | |
BuildInParallel="true" | |
Projects="$(MD5HashFile_csproj)" | |
Properties="Configuration=Release;OutputPath=$(TOOLS_DIR)" /> | |
<MSBuild | |
Condition="'$(MSBuildRuntimeType)'=='Core'" | |
BuildInParallel="true" | |
Projects="$(MD5HashFile_csproj)" | |
Targets="Restore;Build" | |
Properties="Configuration=Release" /> | |
</Target> | |
<Import Project="$(MSBuildBinPath)\Microsoft.Common.CurrentVersion.targets" Condition="'$(MSBuildRuntimeType)'=='Full'"/> | |
<Import Project="$(MSBuildToolsPath)/NuGet.targets" Condition="'$(MSBuildRuntimeType)'=='Core'"/> | |
<Target Name="Bootstrap" DependsOnTargets="ValidateVerbosity"> | |
<!-- Make sure the tools folder exist --> | |
<MakeDir | |
Condition="!Exists('$(TOOLS_DIR)')" | |
Directories="$(TOOLS_DIR)" /> | |
<CallTarget Targets="MD5Tool" /> | |
<Error | |
Text="Version of MSBuild should be 15.8 or above - instead it equal to the '$(MSBuildVersion)'." | |
Condition="$(MSBuildVersion) < 15.8" /> | |
<!-- Make sure that packages.config exist --> | |
<DownloadFile | |
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'!=''" | |
SourceUrl="https://cakebuild.net/download/bootstrapper/packages" | |
DestinationFolder="$(TOOLS_DIR)"> | |
<Output TaskParameter="DownloadedFile" PropertyName="DOWNLOADED_PACKAGES_CONFIG" /> | |
</DownloadFile> | |
<Move | |
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'!='' And Exists('$(DOWNLOADED_PACKAGES_CONFIG)') And '$(DOWNLOADED_PACKAGES_CONFIG)'!='$(PACKAGES_CONFIG)'" | |
SourceFiles="$(DOWNLOADED_PACKAGES_CONFIG)" | |
DestinationFiles="$(PACKAGES_CONFIG)" /> | |
<WriteLinesToFile | |
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'==''" | |
File="$(PACKAGES_CONFIG)" | |
Lines="@(packages_config)" | |
Overwrite="true" | |
WriteOnlyWhenDifferent="true" /> | |
<!-- Make sure that packages.config exist at this point --> | |
<Error | |
Text="Could not find packages.config at '$(PACKAGES_CONFIG)'." | |
Condition="!Exists('$(PACKAGES_CONFIG)')" /> | |
<!-- Download NuGet if it does not exist --> | |
<DownloadFile | |
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'!=''" | |
SourceUrl="https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" | |
DestinationFolder="$(TOOLS_DIR)"> | |
<Output TaskParameter="DownloadedFile" PropertyName="DOWNLOADED_NUGET_EXE" /> | |
</DownloadFile> | |
<Move | |
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'!='' And Exists('$(DOWNLOADED_NUGET_EXE)') And '$(DOWNLOADED_NUGET_EXE)'!='$(NUGET_EXE)'" | |
SourceFiles="$(DOWNLOADED_NUGET_EXE)" | |
DestinationFiles="$(NUGET_EXE)" /> | |
<GetRestoreSettingsTask | |
Condition="'$(ForceDownloadNuGetFile)'==''" | |
ProjectUniqueName="$(MSBuildProjectFullPath)" | |
MSBuildStartupDirectory="$(MSBuildStartupDirectory)"> | |
<Output | |
TaskParameter="OutputPackagesPath" | |
PropertyName="_OutputPackagesPath" /> | |
</GetRestoreSettingsTask> | |
<PropertyGroup Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'==''"> | |
<DOWNLOADED_NUGET_EXE>$([System.IO.Path]::Combine($(_OutputPackagesPath), nuget.commandline, $(NuGetVersion), tools, NuGet.exe))</DOWNLOADED_NUGET_EXE> | |
</PropertyGroup> | |
<Copy | |
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'=='' And Exists('$(DOWNLOADED_NUGET_EXE)') And '$(DOWNLOADED_NUGET_EXE)'!='$(NUGET_EXE)'" | |
SourceFiles="$(DOWNLOADED_NUGET_EXE)" | |
DestinationFiles="$(NUGET_EXE)" /> | |
<ReadLinesFromFile | |
Condition="Exists('$(PACKAGES_CONFIG_MD5)')" | |
File="$(PACKAGES_CONFIG_MD5)"> | |
<Output | |
TaskParameter="Lines" | |
ItemName="currentMd5Hash" /> | |
</ReadLinesFromFile> | |
<Exec | |
Command="$(MD5) "$(PACKAGES_CONFIG)" "$(PACKAGES_CONFIG_MD5)"" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
<ReadLinesFromFile | |
Condition="Exists('$(PACKAGES_CONFIG_MD5)')" | |
File="$(PACKAGES_CONFIG_MD5)"> | |
<Output | |
TaskParameter="Lines" | |
ItemName="newMd5Hash" /> | |
</ReadLinesFromFile> | |
<Message Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'" Text="Missing or changed package.config hash..." /> | |
<ItemGroup Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'"> | |
<AllFiles Include="$(TOOLS_DIR)\**" /> | |
<AllFiles Remove="$(TOOLS_DIR)\bin\**" /> | |
<AllFiles Remove="$(TOOLS_DIR)\obj\**" /> | |
<AllFiles Remove="$(MD5HashFile_cs)" /> | |
<AllFiles Remove="$(MD5HashFile_csproj)" /> | |
<AllFiles Condition="'$(MSBuildRuntimeType)'=='Full'" Remove="$(MD5_Binary)" /> | |
<AllFiles Remove="$(PACKAGES_CONFIG)" /> | |
<AllFiles Remove="$(PACKAGES_CONFIG_MD5)" /> | |
<AllFiles Remove="$(ADDINS_PACKAGES_CONFIG)" /> | |
<AllFiles Remove="$(MODULES_PACKAGES_CONFIG)" /> | |
<AllFiles Remove="$(NUGET_EXE)" /> | |
<AllFiles Remove="$([System.IO.Path]::Combine($(TOOLS_DIR), Cake.Bakery))" /> | |
</ItemGroup> | |
<Delete | |
Condition="'@(AllFiles)'!=''" | |
Files="@(AllFiles)" | |
TreatErrorsAsWarnings="true"> | |
<Output | |
TaskParameter="DeletedFiles" | |
ItemName="DeletedFiles" /> | |
</Delete> | |
<Message Condition="'@(DeletedFiles)'!='' And '@(DeletedFiles)'!='@(AllFiles)'" Text="Some files was not be deleted." /> | |
<Message Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'" Text="Restoring tools from NuGet..." /> | |
<!-- Make sure that NuGet has been installed --> | |
<Error | |
Text="Could not find nuget.exe at '$(NUGET_EXE)'." | |
Condition="!Exists('$(NUGET_EXE)')" /> | |
<Exec | |
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')" | |
ContinueOnError="True" | |
Command=""$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(TOOLS_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)"> | |
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" /> | |
</Exec> | |
<Exec | |
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')" | |
ContinueOnError="True" | |
Command="$(UnixExecutor) "$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(TOOLS_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)"> | |
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" /> | |
</Exec> | |
<WriteLinesToFile | |
Condition="Exists('$(PACKAGES_CONFIG_MD5)') And '@(currentMd5Hash)'!='@(newMd5Hash)' And '$(ErrorCode)'!='0'" | |
File="$(PACKAGES_CONFIG_MD5)" | |
Lines="@(currentMd5Hash)" | |
Overwrite="true" | |
WriteOnlyWhenDifferent="true" /> | |
<Error | |
Text="Failed to restore tools from NuGet." | |
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(ErrorCode)'!='0'" /> | |
<Message Condition="Exists('$(ADDINS_PACKAGES_CONFIG)')" Text="Restoring addins from NuGet..." /> | |
<Exec | |
Condition="Exists('$(ADDINS_PACKAGES_CONFIG)') And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')" | |
Command=""$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(ADDINS_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
<Exec | |
Condition="Exists('$(ADDINS_PACKAGES_CONFIG)') And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')" | |
Command="$(UnixExecutor) "$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(ADDINS_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
<Message Condition="Exists('$(MODULES_PACKAGES_CONFIG)')" Text="Restoring modules from NuGet..." /> | |
<Exec | |
Condition="Exists('$(MODULES_PACKAGES_CONFIG)') And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')" | |
Command=""$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(MODULES_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
<Exec | |
Condition="Exists('$(MODULES_PACKAGES_CONFIG)') And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')" | |
Command="$(UnixExecutor) "$(NUGET_EXE)" install -ExcludeVersion -OutputDirectory "$(MODULES_DIR)" $(NuGetCommandArguments)" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
<!-- Make sure that Cake has been installed --> | |
<Error | |
Text="Could not find Cake.exe at '$(CAKE_EXE)'." | |
Condition="!Exists('$(CAKE_EXE)')" /> | |
<PropertyGroup Condition="'$(OS)'!='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)')"> | |
<CakeCommand>"$(CAKE_EXE)" "$(SCRIPT_FULL_PATH)" $(CAKE_ARGUMENTS)</CakeCommand> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)') And '$(CakeId)'=='Cake'"> | |
<CakeCommand>$(UnixExecutor) "$(CAKE_EXE)" "$(SCRIPT_FULL_PATH)" $(CAKE_ARGUMENTS)</CakeCommand> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)') And '$(CakeId)'=='Cake.CoreCLR'"> | |
<CakeCommand>$(BuildTool) "$(CAKE_EXE)" "$(SCRIPT_FULL_PATH)" $(CAKE_ARGUMENTS)</CakeCommand> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(NuGet_ConfigFile)'!=''"> | |
<CakeCommand>$(CakeCommand) --NuGet_ConfigFile="$(NuGet_ConfigFile)"</CakeCommand> | |
</PropertyGroup> | |
<!-- Start Cake --> | |
<Exec | |
Command="$(CakeCommand)" | |
WorkingDirectory="$(TOOLS_DIR)" /> | |
</Target> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 2.8.12) | |
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) | |
message(FATAL_ERROR "Configuration process cannot start from project source directory.") | |
endif() | |
project("glew_generator") | |
# glew_generator | |
add_library(glew_generator STATIC | |
"${CMAKE_SOURCE_DIR}/blacklist.cpp" | |
"${CMAKE_SOURCE_DIR}/blacklist.h" | |
"${CMAKE_SOURCE_DIR}/common.cpp" | |
"${CMAKE_SOURCE_DIR}/common.h" | |
"${CMAKE_SOURCE_DIR}/descriptor.cpp" | |
"${CMAKE_SOURCE_DIR}/descriptor.h" | |
"${CMAKE_SOURCE_DIR}/input_output.cpp" | |
"${CMAKE_SOURCE_DIR}/input_output.h" | |
"${CMAKE_SOURCE_DIR}/interpreter.cpp" | |
"${CMAKE_SOURCE_DIR}/interpreter.h" | |
"${CMAKE_SOURCE_DIR}/parse_xml.cpp" | |
"${CMAKE_SOURCE_DIR}/parse_xml.h" | |
"${CMAKE_SOURCE_DIR}/path.cpp" | |
"${CMAKE_SOURCE_DIR}/path.h" | |
"${CMAKE_SOURCE_DIR}/procedure.cpp" | |
"${CMAKE_SOURCE_DIR}/procedure.h" | |
"${CMAKE_SOURCE_DIR}/version.cpp" | |
"${CMAKE_SOURCE_DIR}/version.h") | |
# glew_generator_app | |
add_executable(glew_generator_app | |
"${CMAKE_SOURCE_DIR}/descriptors.cpp" | |
"${CMAKE_SOURCE_DIR}/descriptors.h" | |
"${CMAKE_SOURCE_DIR}/filler.cpp" | |
"${CMAKE_SOURCE_DIR}/filler.h" | |
"${CMAKE_SOURCE_DIR}/generator.cpp" | |
"${CMAKE_SOURCE_DIR}/generator.h" | |
"${CMAKE_SOURCE_DIR}/main.cpp") | |
target_link_libraries(glew_generator_app glew_generator) | |
if((NOT MSVC) AND (${CMAKE_VERSION} GREATER 3.0)) | |
set_target_properties(glew_generator PROPERTIES CXX_STANDARD 11) | |
set_target_properties(glew_generator_app PROPERTIES CXX_STANDARD 11) | |
endif() | |
# | |
if(DEFINED ENV{PUGIXML_PATH}) | |
string(REPLACE "\\" "/" pugixml_Path $ENV{PUGIXML_PATH}) | |
elseif(DEFINED PUGIXML_PATH) | |
string(REPLACE "\\" "/" pugixml_Path ${PUGIXML_PATH}) | |
else() | |
message(WARNING "PUGIXML_PATH not set. Targets that use pugixml will not be avaliable.") | |
endif() | |
if(pugixml_Path) | |
if (EXISTS ${pugixml_Path}/CMakeLists.txt) | |
add_subdirectory(${pugixml_Path} ${CMAKE_BINARY_DIR}/pugixml) | |
else() | |
add_subdirectory(${pugixml_Path}/scripts ${CMAKE_BINARY_DIR}/pugixml) | |
endif() | |
add_executable(glew_generator_xml_app | |
"${CMAKE_SOURCE_DIR}/descriptors.cpp" | |
"${CMAKE_SOURCE_DIR}/descriptors.h" | |
"${CMAKE_SOURCE_DIR}/filler.cpp" | |
"${CMAKE_SOURCE_DIR}/filler.h" | |
"${CMAKE_SOURCE_DIR}/generator.cpp" | |
"${CMAKE_SOURCE_DIR}/generator.h" | |
"${CMAKE_SOURCE_DIR}/main.cpp") | |
target_include_directories(glew_generator_xml_app SYSTEM PRIVATE ${pugixml_Path}/src) | |
target_link_libraries(glew_generator_xml_app glew_generator pugixml) | |
target_compile_definitions(glew_generator_xml_app PRIVATE PUGIXML) | |
if((NOT MSVC) AND (${CMAKE_VERSION} GREATER 3.0)) | |
set_target_properties(glew_generator_xml_app PROPERTIES CXX_STANDARD 11) | |
endif() | |
endif() | |
if(MSVC) | |
set(FLAGS "${FLAGS} /W4 /GS") | |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS}") | |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS}") | |
if(CMAKE_CL_64) | |
set(LINK_FLAGS "${LINK_FLAGS} /DynamicBase /NXCompat") | |
else() | |
set(LINK_FLAGS "${LINK_FLAGS} /SafeSEH /DynamicBase /NXCompat") | |
endif() | |
else() | |
set(FLAGS "${FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unknown-pragmas") | |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS}") | |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS}") | |
if(${CMAKE_VERSION} LESS 3.0) | |
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") | |
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |
endif() | |
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "common.h" | |
#include <cctype> | |
#include <sstream> | |
#include <iterator> | |
void remove(std::string& string, char to_be_removed) | |
{ | |
if (string.empty()) | |
{ | |
return; | |
} | |
auto match = string.size(); | |
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i) | |
{ | |
if (to_be_removed == string[i]) | |
{ | |
--match; | |
if (std::string::npos == current) | |
{ | |
current = i; | |
} | |
continue; | |
} | |
if (std::string::npos != current && current != i) | |
{ | |
string[current++] = string[i]; | |
} | |
} | |
if (match != string.size()) | |
{ | |
string.resize(match); | |
} | |
} | |
void remove(std::string& string, const std::set<char>& to_be_removed) | |
{ | |
if (string.empty() || to_be_removed.empty()) | |
{ | |
return; | |
} | |
auto match = string.size(); | |
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i) | |
{ | |
if (to_be_removed.count(string[i])) | |
{ | |
--match; | |
if (std::string::npos == current) | |
{ | |
current = i; | |
} | |
continue; | |
} | |
if (std::string::npos != current && current != i) | |
{ | |
string[current++] = string[i]; | |
} | |
} | |
if (match != string.size()) | |
{ | |
string.resize(match); | |
} | |
} | |
void remove(std::string& string, const std::string& to_be_removed) | |
{ | |
if (string.empty() || to_be_removed.empty()) | |
{ | |
return; | |
} | |
auto match = string.size(); | |
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match, | |
count_2 = to_be_removed.size(); i < count; ++i) | |
{ | |
if (i + count_2 - 1 < count) | |
{ | |
auto j = i; | |
bool isMatch = false; | |
for (const auto& ch : to_be_removed) | |
{ | |
isMatch = (ch == string[j++]); | |
if (!isMatch) | |
{ | |
break; | |
} | |
} | |
if (isMatch) | |
{ | |
match -= count_2; | |
if (std::string::npos == current) | |
{ | |
current = i; | |
} | |
i += count_2 - 1; | |
continue; | |
} | |
} | |
if (std::string::npos != current && current != i) | |
{ | |
string[current++] = string[i]; | |
} | |
} | |
if (match != string.size()) | |
{ | |
string.resize(match); | |
} | |
} | |
void replace_double_char_by_single(std::string& string, char to_be_replaced) | |
{ | |
if (string.empty()) | |
{ | |
return; | |
} | |
auto match = string.size(); | |
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i) | |
{ | |
if (i + 1 < count && to_be_replaced == string[i + 1] && to_be_replaced == string[i]) | |
{ | |
--match; | |
if (std::string::npos == current) | |
{ | |
current = i; | |
} | |
continue; | |
} | |
if (std::string::npos != current && current != i) | |
{ | |
string[current++] = string[i]; | |
} | |
} | |
if (match != string.size()) | |
{ | |
string.resize(match); | |
} | |
} | |
void replace(std::string& string, const std::string& to_be_replaced, const std::string& by_replacement) | |
{ | |
const auto to_be_replaced_length = to_be_replaced.size(); | |
const auto by_replacement_length = by_replacement.size(); | |
auto previous_position = static_cast<std::size_t>(0); | |
auto current_position = previous_position; | |
if (to_be_replaced_length < by_replacement_length) | |
{ | |
auto string_length = string.size(); | |
const auto diff = by_replacement_length - to_be_replaced_length; | |
string.resize(string_length + string_length * diff); | |
while ((current_position = string.find(to_be_replaced, previous_position)) < string_length) | |
{ | |
previous_position = current_position + by_replacement_length; | |
std::copy(string.cbegin() + current_position + to_be_replaced_length, | |
string.cbegin() + string_length, | |
string.begin() + previous_position); | |
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position); | |
string_length += diff; | |
} | |
string.resize(string_length); | |
} | |
else if (to_be_replaced_length == by_replacement_length) | |
{ | |
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position))) | |
{ | |
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position); | |
previous_position = current_position + to_be_replaced_length; | |
} | |
} | |
else | |
{ | |
auto string_length = string.size(); | |
const auto diff = to_be_replaced_length - by_replacement_length; | |
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position))) | |
{ | |
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position); | |
previous_position = current_position + to_be_replaced_length; | |
if (string_length > previous_position) | |
{ | |
std::copy(string.cbegin() + previous_position, | |
string.cbegin() + string_length, | |
string.begin() + current_position + by_replacement_length); | |
} | |
string_length -= diff; | |
string.resize(string_length); | |
} | |
} | |
} | |
void replace(std::string& string, char to_be_replaced, char by_replacement) | |
{ | |
auto previous_position = static_cast<std::size_t>(0); | |
auto current_position = previous_position; | |
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position))) | |
{ | |
string[current_position] = by_replacement; | |
previous_position = current_position + 1; | |
} | |
} | |
std::string::const_iterator find_phrase_start(const std::string& input, const char& value) | |
{ | |
return std::find_if(input.cbegin(), input.cend(), [&value](const char& ch) | |
{ | |
return ch == value; | |
}); | |
} | |
std::string::const_iterator find_phrase_start(const | |
std::pair<std::string::const_iterator, std::string::const_iterator>& input, const char& value) | |
{ | |
return std::find_if(std::get<0>(input), std::get<1>(input), [&value](const char& ch) | |
{ | |
return ch == value; | |
}); | |
} | |
template <class T> | |
std::list<std::string> split_T(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
input, | |
const std::set<T>& separators, bool do_not_add_empty_strings) | |
{ | |
std::list<std::string> result; | |
std::set<std::string::const_iterator> offs; | |
for (const auto& separator : separators) | |
{ | |
auto off = std::get<0>(input); | |
while (std::get<1>(input) != (off = find_phrase_start(std::make_pair(off, std::get<1>(input)), separator))) | |
{ | |
offs.insert(off); | |
std::advance(off, 1); | |
} | |
} | |
if (offs.empty()) | |
{ | |
if (!do_not_add_empty_strings || std::get<0>(input) != std::get<1>(input)) | |
{ | |
result.push_back(std::string(std::get<0>(input), std::get<1>(input))); | |
} | |
} | |
else | |
{ | |
auto prev_off = std::get<0>(input); | |
for (auto off = offs.cbegin(); off != offs.cend();) | |
{ | |
if (!do_not_add_empty_strings || prev_off != (*off)) | |
{ | |
result.push_back(std::string(prev_off, (*off))); | |
} | |
prev_off = (*off); | |
do | |
{ | |
std::advance(prev_off, 1); | |
off = offs.erase(off); | |
} | |
while (0 != offs.count(prev_off) && std::get<1>(input) != prev_off); | |
} | |
if (!do_not_add_empty_strings || prev_off != std::get<1>(input)) | |
{ | |
result.push_back(std::string(prev_off, std::get<1>(input))); | |
} | |
} | |
return result; | |
} | |
template <class T> | |
std::list<std::string> split_T(const std::string& input, | |
const std::set<T>& separators, bool do_not_add_empty_strings) | |
{ | |
std::list<std::string> result; | |
std::set<std::size_t> offs; | |
for (const auto& separator : separators) | |
{ | |
auto off = static_cast<std::size_t>(0); | |
while (std::string::npos != (off = input.find(separator, off))) | |
{ | |
offs.insert(off); | |
++off; | |
} | |
} | |
if (offs.empty()) | |
{ | |
if (!do_not_add_empty_strings || !input.empty()) | |
{ | |
result.push_back(input); | |
} | |
} | |
else | |
{ | |
auto prev_off = static_cast<std::size_t>(0); | |
for (auto off = offs.cbegin(); off != offs.cend();) | |
{ | |
if (!do_not_add_empty_strings || prev_off != (*off)) | |
{ | |
result.push_back(input.substr(prev_off, (*off) - prev_off)); | |
} | |
prev_off = (*off); | |
do | |
{ | |
++prev_off; | |
off = offs.erase(off); | |
} | |
while (0 != offs.count(prev_off) && input.size() != prev_off); | |
} | |
if (!do_not_add_empty_strings || prev_off != input.size()) | |
{ | |
result.push_back(input.substr(prev_off, input.size() - prev_off)); | |
} | |
} | |
return result; | |
} | |
template <class T> | |
std::list<std::string> split_T(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
input, | |
const T& separator, bool do_not_add_empty_strings) | |
{ | |
std::list<std::string> result; | |
auto off = find_phrase_start(input, separator); | |
if (std::get<1>(input) == off) | |
{ | |
if (!do_not_add_empty_strings || std::get<0>(input) != std::get<1>(input)) | |
{ | |
result.push_back(std::string(std::get<0>(input), std::get<1>(input))); | |
} | |
} | |
else | |
{ | |
auto prev_off = std::get<0>(input); | |
do | |
{ | |
if (!do_not_add_empty_strings || prev_off != off) | |
{ | |
result.push_back(std::string(prev_off, off)); | |
} | |
prev_off = off; | |
std::advance(prev_off, 1); | |
} | |
while (std::get<1>(input) != (off = find_phrase_start(std::make_pair(prev_off, std::get<1>(input)), | |
separator))); | |
if (!do_not_add_empty_strings || prev_off != std::get<1>(input)) | |
{ | |
result.push_back(std::string(prev_off, std::get<1>(input))); | |
} | |
} | |
return result; | |
} | |
template <class T> | |
std::list<std::string> split_T(const std::string& input, const T& separator, | |
bool do_not_add_empty_strings) | |
{ | |
std::list<std::string> result; | |
auto off = input.find(separator); | |
if (std::string::npos == off) | |
{ | |
if (!do_not_add_empty_strings || !input.empty()) | |
{ | |
result.push_back(input); | |
} | |
} | |
else | |
{ | |
auto prev_off = static_cast<std::size_t>(0); | |
do | |
{ | |
if (!do_not_add_empty_strings || prev_off != off) | |
{ | |
result.push_back(input.substr(prev_off, off - prev_off)); | |
} | |
prev_off = off + 1; | |
} | |
while (std::string::npos != (off = input.find(separator, prev_off))); | |
if (!do_not_add_empty_strings || prev_off != input.size()) | |
{ | |
result.push_back(input.substr(prev_off)); | |
} | |
} | |
return result; | |
} | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::set<std::string>& separators, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separators, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::string& input, | |
const std::set<std::string>& separators, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separators, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& separator, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separator, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::string& input, const std::string& separator, | |
bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separator, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::set<char>& separators, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separators, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::string& input, | |
const std::set<char>& separators, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separators, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const char& separator, bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separator, do_not_add_empty_strings); | |
} | |
std::list<std::string> split(const std::string& input, const char& separator, | |
bool do_not_add_empty_strings) | |
{ | |
return split_T(input, separator, do_not_add_empty_strings); | |
} | |
bool starts_with(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& value) | |
{ | |
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))); | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (input_size < value.size()) | |
{ | |
return false; | |
} | |
return 0 == std::memcmp(&(*std::get<0>(input)), value.c_str(), value.size()); | |
} | |
bool starts_with(const std::string& input, const std::string& value) | |
{ | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (value.size() > input.size()) | |
{ | |
return false; | |
} | |
return 0 == std::memcmp(input.c_str(), value.c_str(), value.size()); | |
} | |
bool starts_with(const std::string& input, std::size_t position, const std::string& value) | |
{ | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (input.size() < position || input.size() - position < value.size()) | |
{ | |
return false; | |
} | |
return 0 == std::memcmp(&input[position], value.c_str(), value.size()); | |
} | |
bool ends_with(const std::string& input, const std::string& value) | |
{ | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (value.size() > input.size()) | |
{ | |
return false; | |
} | |
return 0 == std::memcmp(&input[input.size() - value.size()], value.c_str(), value.size()); | |
} | |
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& value) | |
{ | |
if (std::get<0>(value) > std::get<1>(value)) | |
{ | |
return false; | |
} | |
if (std::get<0>(value) == std::get<1>(value)) | |
{ | |
return true; | |
} | |
if (!(std::get<0>(input) < std::get<1>(input))) | |
{ | |
return false; | |
} | |
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))); | |
const auto value_size = static_cast<std::size_t>(std::distance(std::get<0>(value), std::get<1>(value))); | |
if (value_size > input_size) | |
{ | |
return false; | |
} | |
if (value_size == input_size) | |
{ | |
return (0 == std::memcmp(&(*std::get<0>(input)), &(*std::get<0>(value)), value_size)); | |
} | |
for (auto i = static_cast<std::size_t>(0); | |
i < 1 + input_size - value_size; ++i) | |
{ | |
if (0 == std::memcmp(&(*std::get<0>(input)) + i, &(*std::get<0>(value)), value_size)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& value) | |
{ | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (!(std::get<0>(input) < std::get<1>(input))) | |
{ | |
return false; | |
} | |
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))); | |
const auto value_size = value.size(); | |
if (value_size > input_size) | |
{ | |
return false; | |
} | |
if (value_size == input_size) | |
{ | |
return (0 == std::memcmp(&(*std::get<0>(input)), value.c_str(), value_size)); | |
} | |
for (auto i = static_cast<std::size_t>(0); | |
i < 1 + input_size - value_size; ++i) | |
{ | |
if (0 == std::memcmp(&(*std::get<0>(input)) + i, value.c_str(), value_size)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool contains(const std::string& input, const std::string& value) | |
{ | |
if (value.empty()) | |
{ | |
return true; | |
} | |
if (value.size() > input.size()) | |
{ | |
return false; | |
} | |
if (value.size() == input.size()) | |
{ | |
return (0 == std::memcmp(&input.front(), value.c_str(), value.size())); | |
} | |
for (auto i = static_cast<std::size_t>(0), | |
count = input.size(), | |
value_count = value.size(); | |
i < 1 + count - value_count; ++i) | |
{ | |
if (0 == std::memcmp(&input[i], value.c_str(), value_count)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
void trim(std::string& string) | |
{ | |
const auto chars_to_trim = std::set<char>({ '\0', '\t', ' ', '\n' }); | |
// | |
const auto pos = std::find_if(string.cbegin(), string.cend(), | |
[&chars_to_trim](const char& ch) | |
{ | |
return 0 == chars_to_trim.count(ch); | |
}); | |
// | |
const auto rpos = std::find_if(string.crbegin(), string.crend(), | |
[&chars_to_trim](const char& ch) | |
{ | |
return 0 == chars_to_trim.count(ch); | |
}); | |
// | |
const auto start_from = static_cast<std::size_t>(std::distance(string.cbegin(), pos)); | |
const auto finish_at = static_cast<std::size_t>(std::distance(string.crbegin(), rpos)); | |
if (start_from > 0 || finish_at > 0) | |
{ | |
auto count = static_cast<std::size_t>(0); | |
if (0 == start_from) | |
{ | |
count = string.size() - finish_at; | |
} | |
else | |
{ | |
for (auto i = start_from; i < string.size() - finish_at; ++i, ++count) | |
{ | |
string[i - start_from] = string[i]; | |
} | |
} | |
string.resize(count); | |
} | |
} | |
std::string join(const std::string& separator, | |
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& values) | |
{ | |
if (values.empty()) | |
{ | |
return std::string(); | |
} | |
auto value = values.cbegin(); | |
if (1 == values.size()) | |
{ | |
return std::string(std::get<0>(*value), std::get<1>(*value)); | |
} | |
std::ostringstream oss; | |
for (auto i = static_cast<std::size_t>(0), count = values.size() - 1; i < count; ++i, ++value) | |
{ | |
oss << std::string(std::get<0>(*value), std::get<1>(*value)) << separator; | |
} | |
oss << std::string(std::get<0>(*value), std::get<1>(*value)); | |
return oss.str(); | |
} | |
std::string join(const std::string& separator, const std::list<std::string>& values) | |
{ | |
if (values.empty()) | |
{ | |
return std::string(); | |
} | |
auto value = values.cbegin(); | |
if (1 == values.size()) | |
{ | |
return (*value); | |
} | |
std::ostringstream oss; | |
for (auto i = static_cast<std::size_t>(0), count = values.size() - 1; i < count; ++i, ++value) | |
{ | |
oss << (*value) << separator; | |
} | |
oss << (*value); | |
return oss.str(); | |
} | |
std::string tolower(const std::string& input) | |
{ | |
std::string result(input.size(), '\0'); | |
result.clear(); | |
for (const auto& ch : input) | |
{ | |
result.push_back(static_cast<char>(std::tolower(ch))); | |
} | |
return result; | |
} | |
std::string toupper(const std::string& input) | |
{ | |
std::string result(input.size(), '\0'); | |
result.clear(); | |
for (const auto& ch : input) | |
{ | |
result.push_back(static_cast<char>(std::toupper(ch))); | |
} | |
return result; | |
} | |
std::string::const_iterator find_phrase_start(const std::string& input, const std::string& value) | |
{ | |
auto result = input.cbegin(); | |
if (input.empty() || value.empty() || input.size() < value.size()) | |
{ | |
return input.cend(); | |
} | |
do | |
{ | |
result = std::find_if(result, input.cend(), [&value](const char& ch) | |
{ | |
return ch == value.front(); | |
}); | |
if (result == input.cend()) | |
{ | |
break; | |
} | |
if (value.size() <= static_cast<std::size_t>(std::distance(result, input.cend()))) | |
{ | |
if (0 == std::memcmp(value.c_str(), &(*result), value.size())) | |
{ | |
break; | |
} | |
} | |
std::advance(result, 1); | |
} | |
while (result != input.cend()); | |
return result; | |
} | |
std::string::const_iterator find_phrase_start(const | |
std::pair<std::string::const_iterator, std::string::const_iterator>& input, const std::string& value) | |
{ | |
auto result = std::get<0>(input); | |
if ((std::get<0>(input) == std::get<1>(input)) || | |
value.empty() || | |
static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))) < value.size()) | |
{ | |
return std::get<1>(input); | |
} | |
do | |
{ | |
result = std::find_if(result, std::get<1>(input), [&value](const char& ch) | |
{ | |
return ch == value.front(); | |
}); | |
if (result == std::get<1>(input)) | |
{ | |
break; | |
} | |
if (value.size() <= static_cast<std::size_t>(std::distance(result, std::get<1>(input)))) | |
{ | |
if (0 == std::memcmp(value.c_str(), &(*result), value.size())) | |
{ | |
break; | |
} | |
} | |
std::advance(result, 1); | |
} | |
while (result != std::get<1>(input)); | |
return result; | |
} | |
std::string::const_reverse_iterator rfind_phrase_start( | |
const std::pair<std::string::const_reverse_iterator, std::string::const_reverse_iterator>& input, | |
const std::string& value) | |
{ | |
if ((std::get<0>(input) == std::get<1>(input)) || | |
value.empty() || | |
static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))) < value.size()) | |
{ | |
return std::get<1>(input); | |
} | |
auto result = std::get<0>(input); | |
std::advance(result, value.size() - 1); | |
do | |
{ | |
if (0 == std::memcmp(value.c_str(), &(*result), value.size())) | |
{ | |
break; | |
} | |
std::advance(result, 1); | |
} | |
while (result != std::get<1>(input)); | |
return result; | |
} | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_line( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& range, | |
std::string::const_iterator& next_line) | |
{ | |
auto result = range; | |
// | |
std::get<1>(result) = std::find_if(std::get<0>(range), std::get<1>(range), | |
[](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
// | |
next_line = std::get<1>(result); | |
if (std::get<1>(range) != next_line) | |
{ | |
std::advance(next_line, 1); | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _COMMON_H_ | |
#define _COMMON_H_ | |
#include <set> | |
#include <list> | |
#include <string> | |
#include <cstring> | |
#include <utility> | |
#include <algorithm> | |
void remove(std::string& string, char to_be_removed); | |
void remove(std::string& string, const std::set<char>& to_be_removed); | |
void remove(std::string& string, const std::string& to_be_removed); | |
void replace_double_char_by_single(std::string& string, char to_be_replaced); | |
void replace(std::string& string, const std::string& to_be_replaced, const std::string& by_replacement); | |
void replace(std::string& string, char to_be_replaced, char by_replacement); | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::set<std::string>& separators, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::string& input, | |
const std::set<std::string>& separators, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& separator, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::string& input, const std::string& separator, | |
bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::set<char>& separators, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::string& input, | |
const std::set<char>& separators, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const char& separator, bool do_not_add_empty_strings); | |
std::list<std::string> split(const std::string& input, const char& separator, | |
bool do_not_add_empty_strings); | |
bool starts_with(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& value); | |
bool starts_with(const std::string& input, const std::string& value); | |
bool starts_with(const std::string& input, std::size_t position, const std::string& value); | |
template <class T> | |
bool starts_with_T(const std::string& input, const T& value) | |
{ | |
for (const auto& v : value) | |
{ | |
if (starts_with(input, v)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool ends_with(const std::string& input, const std::string& value); | |
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& value); | |
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
const std::string& value); | |
bool contains(const std::string& input, const std::string& value); | |
void trim(std::string& string); | |
std::string join(const std::string& separator, | |
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& values); | |
std::string join(const std::string& separator, const std::list<std::string>& values); | |
std::string tolower(const std::string& input); | |
std::string toupper(const std::string& input); | |
std::string::const_iterator find_phrase_start(const std::string& input, const std::string& value); | |
std::string::const_iterator find_phrase_start( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, const std::string& value); | |
std::string::const_reverse_iterator rfind_phrase_start( | |
const std::pair<std::string::const_reverse_iterator, std::string::const_reverse_iterator>& input, | |
const std::string& value); | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_line( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& range, | |
std::string::const_iterator& next_line); | |
template <class T> | |
T find_any_symbol_like_or_not_like_that(const std::pair<T, T>& input, const std::set<char>& that, bool like) | |
{ | |
return std::find_if(std::get<0>(input), std::get<1>(input), [&that, &like](const char& ch) | |
{ | |
return (like == (0 != that.count(ch))); | |
}); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "descriptor.h" | |
#include "input_output.h" | |
#include "path.h" | |
#include "common.h" | |
#include "blacklist.h" | |
#include "interpreter.h" | |
#include "procedure.h" | |
#include <cctype> | |
#include <cstdlib> | |
#include <cstring> | |
#include <cassert> | |
#include <iterator> | |
#include <algorithm> | |
enum class SECTION_TYPE | |
{ | |
NAME = 1, | |
NAME_STRINGS, | |
PROCEDURES_AND_FUNCTIONS, | |
TYPES, | |
TOKENS, | |
UNKNOWN | |
}; | |
static std::list<std::pair<std::string, std::string>> type_map; | |
static std::list<std::pair<std::string, std::string>> taboo_tokens; | |
static std::list<std::pair<std::string, std::string>> fnc_ignore_list; | |
bool init_typemap(std::istream& content_stream) | |
{ | |
if (type_map.empty() && taboo_tokens.empty() && fnc_ignore_list.empty()) | |
{ | |
content_stream.seekg(0); | |
type_map = get_typemap(content_stream); | |
content_stream.seekg(0); | |
taboo_tokens = get_taboo_tokens(content_stream); | |
content_stream.seekg(0); | |
fnc_ignore_list = get_fnc_ignore_list(content_stream); | |
return true; | |
} | |
return false; | |
} | |
void release_typemap() | |
{ | |
type_map.clear(); | |
taboo_tokens.clear(); | |
fnc_ignore_list.clear(); | |
} | |
std::pair<std::string, std::pair<std::string, long>> str_to_token( | |
const std::string::const_iterator& token_begin, | |
const std::string::const_iterator& token_end) | |
{ | |
auto token = std::make_pair(std::string(), std::make_pair(std::string(), static_cast<long>(0))); | |
auto space_position = std::find_if(token_begin, token_end, [](const char& ch) | |
{ | |
return (ch == ' ' || ch == '\t'); | |
}); | |
if (space_position != token_end) | |
{ | |
std::get<0>(token) = std::string(token_begin, space_position); | |
space_position = std::find_if(space_position, token_end, [](const char& ch) | |
{ | |
return (ch != '=' && ch != ' ' && ch != '\t'); | |
}); | |
const auto value = std::string(space_position, token_end); | |
auto new_value = std::string(value.size(), '\0'); | |
const char* start_ch = value.c_str(); | |
char* ch = nullptr; | |
std::get<1>(std::get<1>(token)) = std::strtol(start_ch, &ch, 16); | |
if ((ch == start_ch) && std::isdigit(*start_ch)) | |
{ | |
new_value.clear(); | |
do | |
{ | |
new_value += (*start_ch); | |
++start_ch; | |
} | |
while (std::isdigit(*start_ch) && new_value.size() < value.size()); | |
start_ch = new_value.c_str(); | |
std::get<1>(std::get<1>(token)) = std::strtol(start_ch, &ch, 16); | |
} | |
const std::size_t str_size = ch - start_ch; | |
if (0 < str_size) | |
{ | |
std::get<0>(std::get<1>(token)) = std::string(start_ch, str_size); | |
} | |
else | |
{ | |
std::get<0>(std::get<1>(token)) = value; | |
} | |
} | |
else | |
{ | |
std::get<0>(token) = std::string(token_begin, token_end); | |
} | |
return token; | |
} | |
SECTION_TYPE determine_section_type(const std::string::const_iterator& name_begin, | |
const std::string::const_iterator& name_end) | |
{ | |
switch (std::distance(name_begin, name_end)) | |
{ | |
case 4: | |
if (!std::memcmp(&(*name_begin), "Name", 4)) | |
{ | |
return SECTION_TYPE::NAME; | |
} | |
break; | |
case 9: | |
if (!std::memcmp(&(*name_begin), "New Types", 9)) | |
{ | |
return SECTION_TYPE::TYPES; | |
} | |
break; | |
case 10: | |
if (!std::memcmp(&(*name_begin), "New Tokens", 10)) | |
{ | |
return SECTION_TYPE::TOKENS; | |
} | |
break; | |
case 11: | |
if (!std::memcmp(&(*name_begin), "Name String", 11)) | |
{ | |
return SECTION_TYPE::NAME_STRINGS; | |
} | |
break; | |
case 12: | |
if (!std::memcmp(&(*name_begin), "Name Strings", 12)) | |
{ | |
return SECTION_TYPE::NAME_STRINGS; | |
} | |
break; | |
case 27: | |
if (!std::memcmp(&(*name_begin), "New Procedure and Functions", 27)) | |
{ | |
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS; | |
} | |
break; | |
case 28: | |
if (!std::memcmp(&(*name_begin), "New Procedures And Functions", 28) | |
|| !std::memcmp(&(*name_begin), "New Functions and Procedures", 28) | |
|| !std::memcmp(&(*name_begin), "New Procedures and Functions", 28)) | |
{ | |
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS; | |
} | |
break; | |
case 41: | |
if (!std::memcmp(&(*name_begin), "New Procedures, Functions and Structures:", 41)) | |
{ | |
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS; | |
} | |
break; | |
default: | |
break; | |
} | |
return SECTION_TYPE::UNKNOWN; | |
} | |
std::string::const_iterator get_section_start(const std::string& content, | |
const std::string::const_iterator& offset) | |
{ | |
auto setction_start = offset; | |
while (content.cend() != setction_start) | |
{ | |
setction_start = std::find_if(setction_start, content.cend(), [](const char& ch) | |
{ | |
return ('A' <= ch && ch <= 'Z'); | |
}); | |
if (content.cend() == setction_start) | |
{ | |
break; | |
} | |
if ((0 == std::distance(content.cbegin(), setction_start)) || (*(setction_start - 1)) == '\n') | |
{ | |
break; | |
} | |
std::advance(setction_start, 1); | |
} | |
return setction_start; | |
} | |
#ifndef NDEBUG | |
std::string::const_iterator get_section(const std::string& content, SECTION_TYPE section_type) | |
{ | |
auto offset = content.cbegin(); | |
while (offset != content.cend()) | |
{ | |
offset = get_section_start(content, offset); | |
if (content.cend() == offset) | |
{ | |
break; | |
} | |
const auto new_line = std::find_if(offset, content.cend(), [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
if (content.cend() == new_line) | |
{ | |
return new_line; | |
} | |
if (section_type == determine_section_type(offset, new_line)) | |
{ | |
break; | |
} | |
offset = new_line; | |
} | |
return offset; | |
} | |
#endif | |
void get_name(const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
std::string& name) | |
{ | |
const auto section_begin = std::find_if(first, last, [](const char& ch) | |
{ | |
return (ch != ' ' && ch != '\t' && ch != '\n'); | |
}); | |
if (section_begin == last) | |
{ | |
return; | |
} | |
const auto section_end = std::find_if(section_begin, last, [](const char& ch) | |
{ | |
return (ch == ' ' || ch == '\t' || ch == '\n'); | |
}); | |
// | |
std::copy(section_begin, (section_end != last) ? section_end : last, std::back_inserter(name)); | |
} | |
void get_name_strings(const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
std::list<std::string>& name_strings) | |
{ | |
const auto section_begin = std::find_if(first, last, [](const char& ch) | |
{ | |
return (ch != ' ' && ch != '\t' && ch != '\n'); | |
}); | |
if (section_begin == last) | |
{ | |
return; | |
} | |
auto section_end = last; | |
while (section_end != section_begin) | |
{ | |
const auto ch = (*section_end); | |
if (ch != ' ' && ch != '\t' && ch != '\n') | |
{ | |
break; | |
} | |
std::advance(section_end, -1); | |
} | |
if (section_end == section_begin) | |
{ | |
return; | |
} | |
auto section_text = std::string(section_begin, section_end); | |
auto character_position = section_text.find("none"); | |
if (std::string::npos != character_position) | |
{ | |
section_text = section_text.substr(0, character_position); | |
} | |
character_position = section_text.find("None"); | |
if (std::string::npos != character_position) | |
{ | |
section_text = section_text.substr(0, character_position); | |
} | |
character_position = section_text.find("NOTE"); | |
if (std::string::npos != character_position) | |
{ | |
section_text = section_text.substr(0, character_position); | |
} | |
character_position = section_text.find("Note"); | |
if (std::string::npos != character_position) | |
{ | |
section_text = section_text.substr(0, character_position); | |
} | |
character_position = section_text.find("(legacy)"); | |
if (std::string::npos != character_position) | |
{ | |
section_text = section_text.substr(0, character_position); | |
} | |
remove(section_text, std::set<char>({ '\t', ' ', '(' })); | |
name_strings = split(section_text, std::set<char>({ '\n', ',' }), true); | |
} | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_function_name( | |
const std::set<char>& white_space, | |
const std::string::const_iterator& return_start, | |
const std::string::const_iterator& function_start) | |
{ | |
auto function_name = std::make_pair(return_start, function_start); | |
while (std::get<1>(function_name) != return_start) | |
{ | |
std::advance(std::get<1>(function_name), -1); | |
if (0 == white_space.count(*std::get<1>(function_name))) | |
{ | |
std::advance(std::get<1>(function_name), +1); | |
break; | |
} | |
} | |
std::get<0>(function_name) = std::get<1>(function_name); | |
while (std::get<0>(function_name) != return_start) | |
{ | |
std::advance(std::get<0>(function_name), -1); | |
if (0 != white_space.count(*std::get<0>(function_name))) | |
{ | |
std::advance(std::get<0>(function_name), +1); | |
break; | |
} | |
} | |
return function_name; | |
} | |
bool is_function_end_correct( | |
const std::string::const_iterator& function_start, | |
const std::string::const_iterator& function_end) | |
{ | |
if (')' == (*function_end)) | |
{ | |
return true; | |
} | |
auto position = function_end; | |
while (position != function_start) | |
{ | |
std::advance(position, -1); | |
if (')' == (*position)) | |
{ | |
break; | |
} | |
else if (std::isdigit(*position) || | |
('a' <= (*position) && (*position) <= 'z') || | |
('A' <= (*position) && (*position) <= 'Z')) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
void get_procedures_functions(const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
const char function_should_start_from, | |
std::list<_procedure>& procedures) | |
{ | |
const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' }); | |
const auto chars_at_line_end = std::set<char>({ '\n', '/', ';' }); | |
const auto chars_not_for_procedure = std::set<char>({ '"', '&', '/', ':', ';', '<', '=', '>' }); | |
for (auto position = first; position != last;) | |
{ | |
auto function_start = std::find_if(position, last, [&function_should_start_from](const char& ch) | |
{ | |
return function_should_start_from == ch; | |
}); | |
if (function_start != last) | |
{ | |
auto return_start = function_start; | |
auto is_only_white_space = true; | |
do | |
{ | |
std::advance(return_start, -1); | |
if (is_only_white_space) | |
{ | |
is_only_white_space = (0 != tab_space_new_line.count(*return_start)); | |
} | |
} | |
while ((is_only_white_space && position != return_start) || | |
('\n' != (*return_start) && position != return_start)); | |
return_start = std::find_if(return_start, function_start, [&tab_space_new_line](const char& ch) | |
{ | |
return 0 == tab_space_new_line.count(ch); | |
}); | |
if ('*' != (*return_start) && return_start != function_start) | |
{ | |
auto function_end = std::find_if(function_start, last, [](const char& ch) | |
{ | |
return ')' == ch; | |
}); | |
const auto function_name = get_function_name(tab_space_new_line, return_start, function_start); | |
if (function_end != last && !std::isdigit(*(std::get<0>(function_name)))) | |
{ | |
const auto function_end_ = std::find_if(function_start, last, [](const char& ch) | |
{ | |
return ';' == ch; | |
}); | |
if (function_end_ != last && function_end_ < function_end) | |
{ | |
function_end = function_end_; | |
} | |
auto line_end = std::find_if(function_end, last, [&chars_at_line_end](const char& ch) | |
{ | |
return 0 != chars_at_line_end.count(ch); | |
}); | |
if (line_end != last) | |
{ | |
std::advance(line_end, -1); | |
function_end = line_end; | |
} | |
const auto find_result = std::find_if(return_start, function_end, [&chars_not_for_procedure](const char& ch) | |
{ | |
return 0 != chars_not_for_procedure.count(ch); | |
}); | |
if (find_result == function_end && 0 == chars_not_for_procedure.count(*function_end)) | |
{ | |
std::advance(function_end, 1); | |
auto opened = 0; | |
auto closed = 0; | |
for (auto p = return_start; p != function_end; ++p) | |
{ | |
if (function_should_start_from == (*p)) | |
{ | |
++opened; | |
} | |
else if (')' == (*p)) | |
{ | |
++closed; | |
} | |
} | |
if ((function_end_ <= function_end) || (opened == closed && | |
is_function_end_correct(function_start, function_end))) | |
{ | |
if (1 == opened && std::get<0>(function_name) == return_start && | |
contains(std::make_pair(function_start, function_end), "*")) | |
{ | |
for (auto i = 0; i < 2 && return_start != position; ++i) | |
{ | |
do | |
{ | |
std::advance(return_start, -1); | |
if ('\n' == (*return_start)) | |
{ | |
break; | |
} | |
} | |
while (return_start != position); | |
} | |
return_start = std::find_if(return_start, std::get<0>(function_name), [&tab_space_new_line](const char& ch) | |
{ | |
return 0 == tab_space_new_line.count(ch); | |
}); | |
} | |
std::string procedure(std::distance(return_start, function_end), '\0'); | |
procedure.clear(); | |
for (auto p = return_start; p != function_end; ++p) | |
{ | |
if ('\t' != (*p) && '\n' != (*p)) | |
{ | |
if (procedure.empty() && ' ' == (*p)) | |
{ | |
continue; | |
} | |
else if (' ' == (*p) && !procedure.empty() && (' ' == procedure[procedure.size() - 1] || | |
'(' == procedure[procedure.size() - 1])) | |
{ | |
continue; | |
} | |
else if (' ' == (*p) && p + 1 != function_end && ')' == *(p + 1)) | |
{ | |
continue; | |
} | |
procedure += (*p); | |
if (contains(procedure, "(") && p + 1 != function_end && ',' == procedure.back() && ' ' != *(p + 1)) | |
{ | |
procedure += ' '; | |
} | |
} | |
} | |
if (!procedure.empty()) | |
{ | |
const auto procedure_ = disassemble_procedure(procedure); | |
if (!procedure_.name.empty()) | |
{ | |
const auto exists_procedure = std::find_if(procedures.cbegin(), procedures.cend(), | |
[&procedure_](const _procedure & _procedure) | |
{ | |
return procedure_ == _procedure; | |
}); | |
if (exists_procedure == procedures.cend()) | |
{ | |
procedures.push_back(procedure_); | |
} | |
} | |
} | |
} | |
} | |
else | |
{ | |
std::advance(function_end, 1); | |
} | |
} | |
position = function_end; | |
} | |
else | |
{ | |
position = function_start; | |
std::advance(position, 1); | |
} | |
} | |
else | |
{ | |
break; | |
} | |
} | |
} | |
void get_procedures_functions_structures_types(const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
specification& spec, SECTION_TYPE section_type) | |
{ | |
auto prev_border = first; | |
for (auto i = first; i < last; ++i) | |
{ | |
auto new_line = std::find_if(i, last, [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
if (last != new_line) | |
{ | |
std::advance(new_line, 1); | |
auto next_line = std::find_if(new_line, last, [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
if (last != next_line) | |
{ | |
auto is_border = true; | |
for (auto j = new_line; j < next_line; j++) | |
{ | |
const auto ch = (*j); | |
if (ch != ' ' && ch != '\t' && ch != '\n') | |
{ | |
is_border = false; | |
break; | |
} | |
} | |
if (is_border) | |
{ | |
i = next_line; | |
prev_border = std::find_if(prev_border, next_line, [](const char& ch) | |
{ | |
return ch != ' ' && ch != '\t' && ch != '\n'; | |
}); | |
if (prev_border == next_line) | |
{ | |
continue; | |
} | |
while (next_line != prev_border) | |
{ | |
const auto ch = (*next_line); | |
if (ch != ' ' && ch != '\t' && ch != '\n') | |
{ | |
std::advance(next_line, 1); | |
break; | |
} | |
std::advance(next_line, -1); | |
} | |
if (prev_border == next_line) | |
{ | |
continue; | |
} | |
auto procedures_or_types = split(std::string(prev_border, next_line), ';', true); | |
prev_border = i; | |
if (!procedures_or_types.empty() && (starts_with(procedures_or_types.front(), "None") || | |
starts_with(procedures_or_types.front(), "none") || | |
starts_with(procedures_or_types.front(), "(None") || | |
starts_with(procedures_or_types.front(), "NOTE:"))) | |
{ | |
continue; | |
} | |
auto enough = false; | |
while (!enough) | |
{ | |
for (auto& pot : procedures_or_types) | |
{ | |
replace(pot, '\t', ' '); | |
replace(pot, '\n', ' '); | |
replace_double_char_by_single(pot, ' '); | |
trim(pot); | |
auto sub_pot = split(pot, ") ", true); | |
if (sub_pot.size() > 1) | |
{ | |
procedures_or_types.remove(pot); | |
for (auto& spot : sub_pot) | |
{ | |
if (!spot.empty() && spot[spot.size() - 1] != ')') | |
{ | |
spot += ')'; | |
} | |
trim(spot); | |
} | |
std::copy(sub_pot.cbegin(), sub_pot.cend(), std::back_inserter(procedures_or_types)); | |
enough = true; | |
break; | |
} | |
} | |
enough = !enough; | |
} | |
procedures_or_types.remove_if([§ion_type](const std::string & pot) | |
{ | |
return pot.empty() || starts_with(pot, "<") || | |
((SECTION_TYPE::PROCEDURES_AND_FUNCTIONS == section_type) && | |
(!contains(pot, "(") || !contains(pot, ")") || | |
contains(pot, "\"") || contains(pot, "(if any)") || | |
(!contains(pot, "...") && contains(pot, ".")))); | |
}); | |
if (SECTION_TYPE::PROCEDURES_AND_FUNCTIONS == section_type) | |
{ | |
//spec._procedures.insert(spec._procedures.end(), procedures_or_types.cbegin(), procedures_or_types.cend()); | |
} | |
else if (SECTION_TYPE::TYPES == section_type) | |
{ | |
spec._types.insert(spec._types.end(), procedures_or_types.cbegin(), procedures_or_types.cend()); | |
} | |
} | |
} | |
} | |
} | |
} | |
void get_tokens(const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
specification& spec) | |
{ | |
for (auto i = first; i < last; ++i) | |
{ | |
auto line_begin = std::find_if(i, last, [](const char& ch) | |
{ | |
return (ch == '\n'); | |
}); | |
if (line_begin == last) | |
{ | |
break; | |
} | |
std::advance(line_begin, 1); | |
auto line_end = line_begin; | |
line_end = std::find_if(line_end, last, [](const char& ch) | |
{ | |
return (ch == '\n' || ch == '(' || ch == '/'); | |
}); | |
i = line_end; | |
std::advance(i, -1); | |
auto token_begin = std::find_if(line_begin, line_end, [](const char& ch) | |
{ | |
return std::isupper(ch) || std::isdigit(ch); | |
}); | |
if (token_begin == line_end) | |
{ | |
continue; | |
} | |
auto token_begin_ = token_begin; | |
std::advance(token_begin_, -1); | |
if (std::isdigit(*token_begin_)) | |
{ | |
token_begin = token_begin_; | |
} | |
auto token_end = std::find_if(line_begin, token_begin, [](const char& ch) | |
{ | |
return (ch != ' ' && ch != '\t'); | |
}); | |
if (token_end != token_begin) | |
{ | |
continue; | |
} | |
bool wrong_token = false; | |
for (; token_end != line_end; ++token_end) | |
{ | |
char ch = *token_end; | |
if (!std::isupper(ch) && ch != '_' && | |
ch != ' ' && ch != '\t' && | |
ch != '=' && !std::isdigit(ch) && ch != 'x' && | |
ch != 'u' && ch != 'l') | |
{ | |
wrong_token = true; | |
break; | |
} | |
} | |
if (wrong_token) | |
{ | |
continue; | |
} | |
spec._tokens.push_back(str_to_token(token_begin, token_end)); | |
} | |
} | |
void read_spec(const std::string& content, bool read_types, specification& spec) | |
{ | |
for (auto section_start = content.cbegin(); section_start != content.cend();) | |
{ | |
section_start = get_section_start(content, section_start); | |
if (content.cend() == section_start) | |
{ | |
break; | |
} | |
auto new_line = std::find_if(section_start, content.cend(), [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
if (content.cend() == new_line) | |
{ | |
break; | |
} | |
auto next_section_start = get_section_start(content, new_line); | |
while (new_line != section_start) | |
{ | |
const auto ch = (*new_line); | |
if (ch != ' ' && ch != '\t' && ch != '\n') | |
{ | |
std::advance(new_line, 1); | |
break; | |
} | |
std::advance(new_line, -1); | |
} | |
switch (determine_section_type(section_start, new_line)) | |
{ | |
case SECTION_TYPE::NAME: | |
get_name(new_line, next_section_start, spec._name); | |
break; | |
case SECTION_TYPE::NAME_STRINGS: | |
get_name_strings(new_line, next_section_start, spec._name_strings); | |
break; | |
case SECTION_TYPE::PROCEDURES_AND_FUNCTIONS: | |
{ | |
const auto next_section_start_ = std::find_if(new_line, next_section_start, [](const char& ch) | |
{ | |
return '#' == ch; | |
}); | |
//TODO: | |
get_procedures_functions(new_line, next_section_start_, '(', spec._procedures); | |
get_procedures_functions(new_line, next_section_start_, '{', spec._procedures); | |
// | |
spec._procedures.sort([](const _procedure & a, const _procedure & b) | |
{ | |
return a.name < b.name; | |
}); | |
} | |
break; | |
case SECTION_TYPE::TYPES: | |
if (read_types) | |
{ | |
get_procedures_functions_structures_types(new_line, next_section_start, spec, | |
SECTION_TYPE::TYPES); | |
} | |
break; | |
case SECTION_TYPE::TOKENS: | |
get_tokens(new_line, next_section_start, spec); | |
prepare_tokens(spec._tokens); //TODO: | |
break; | |
default: | |
break; | |
} | |
section_start = next_section_start; | |
} | |
} | |
void read_ext(const std::string& content, extension& ext) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
auto start_position = content.cbegin(); | |
auto line_begin = start_position; | |
char i = 0; | |
while (content.cend() != (start_position = find_any_symbol_like_or_not_like_that( | |
std::make_pair(start_position, content.cend()), tab_space, false))) | |
{ | |
auto line_end = std::find_if(start_position, content.cend(), [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
switch (i) | |
{ | |
case 0: | |
++i; | |
ext._name = std::string(start_position, line_end); | |
break; | |
case 1: | |
++i; | |
ext._url = std::string(start_position, line_end); | |
break; | |
case 2: | |
++i; | |
if (start_position != line_end) | |
{ | |
ext._name_strings.push_back(std::string(start_position, line_end)); | |
} | |
break; | |
case 3: | |
++i; | |
#if defined(__GNUC__) && 7 <= __GNUC__ | |
#pragma message("Not implemented!") | |
break; | |
#else | |
if (!starts_with(std::make_pair(line_begin, line_end), "\t") && | |
!starts_with(std::make_pair(line_begin, line_end), " ")) | |
{ | |
ext._reuse = split( | |
std::make_pair(start_position, line_end), std::set<char>({ '\t', ' ', ',' }), true); | |
break; | |
} | |
#endif | |
default: | |
if (start_position == line_end) | |
{ | |
break; | |
} | |
if (contains(std::make_pair(start_position, line_end), "typedef")) | |
{ | |
ext._types.push_back(std::string(start_position, line_end)); | |
} | |
else if (contains(std::make_pair(start_position, line_end), "(")) | |
{ | |
const auto procedure = disassemble_procedure(std::make_pair(start_position, line_end)); | |
if (contains(procedure.name, "[") && contains(procedure.name, "]")) | |
{ | |
break; | |
} | |
if (!contains(procedure.return_type, "(") && !procedure.name.empty()) | |
{ | |
auto is_parameters_only_digital = false; | |
for (const auto& param : procedure.parameters) | |
{ | |
for (const auto& ch : param) | |
{ | |
if (' ' == ch || '\t' == ch) | |
{ | |
continue; | |
} | |
is_parameters_only_digital = ('-' == ch || ('0' <= ch && ch <= '9')); | |
break; | |
} | |
if (is_parameters_only_digital) | |
{ | |
break; | |
} | |
} | |
if (!is_parameters_only_digital) | |
{ | |
ext._procedures.push_back(procedure); | |
} | |
} | |
else if (!procedure.parameters.empty()) | |
{ | |
ext._types.push_back(std::string(start_position, line_end)); | |
} | |
} | |
else | |
{ | |
ext._tokens.push_back(str_to_token(start_position, line_end)); | |
} | |
break; | |
} | |
if (content.cend() != line_end) | |
{ | |
std::advance(line_end, 1); | |
} | |
start_position = line_end; | |
line_begin = start_position; | |
} | |
ext._procedures.sort([](const _procedure & a, const _procedure & b) | |
{ | |
return a.name < b.name; | |
}); | |
// | |
ext._types.sort(); //TODO: | |
prepare_tokens(ext._tokens); //TODO: | |
} | |
bool is_procedure_should_be_ignored(const std::string& extension_name, const std::string& procedure_name) | |
{ | |
assert(!fnc_ignore_list.empty()); | |
// | |
const auto find_result = std::find_if(fnc_ignore_list.cbegin(), fnc_ignore_list.cend(), | |
[&procedure_name, &extension_name](const std::pair<std::string, std::string>& procedure_to_ignore) | |
{ | |
return (procedure_name == std::get<0>(procedure_to_ignore) && | |
extension_name != std::get<1>(procedure_to_ignore)); | |
}); | |
// | |
return fnc_ignore_list.cend() != find_result; | |
} | |
bool is_token_taboo(const std::pair<std::string, std::pair<std::string, long>>& token) | |
{ | |
assert(!taboo_tokens.empty()); | |
// | |
const auto find_result = std::find_if(taboo_tokens.cbegin(), taboo_tokens.cend(), | |
[&token](const std::pair<std::string, std::string>& taboo_token) | |
{ | |
return (std::get<0>(token) == std::get<0>(taboo_token) && | |
std::get<0>(std::get<1>(token)) == std::get<1>(taboo_token)); | |
}); | |
return taboo_tokens.cend() != find_result; | |
} | |
struct internal_extension | |
{ | |
std::string _name_string; | |
std::string _prefix; | |
std::list<std::string> _tokens; | |
std::list<_procedure> _procedures; | |
}; | |
std::list<std::pair<std::string, std::string>> specification_to_extensions( | |
const specification& spec, const std::string& url, std::string& tmp_output) | |
{ | |
static const std::set<std::string> common_prefix({ /*"agl",*/ "gl", /*"glu",*/ "glX", "wgl" }); | |
static const std::set<std::string> common_tprefix({ /*"AGL",*/ "GL", /*"GLU",*/ "GLX", "WGL" }); | |
std::list<internal_extension> extensions_; | |
const auto name_strings = (spec._name_strings.empty() ? std::list<std::string>({ spec._name }) : | |
spec._name_strings); | |
for (const auto& name_string : name_strings) | |
{ | |
if (name_string.empty()) | |
{ | |
continue; | |
} | |
internal_extension ext; | |
ext._name_string = name_string; | |
// | |
const auto prefix_end = std::find_if(name_string.cbegin(), name_string.cend(), | |
[](const char& ch) | |
{ | |
return '_' == ch; | |
}); | |
// | |
ext._prefix = std::string(name_string.cbegin(), prefix_end); | |
extensions_.push_back(ext); | |
} | |
std::list<std::string> not_used_tokens; | |
for (const auto& token : spec._tokens) | |
{ | |
if (is_token_taboo(token)) | |
{ | |
continue; | |
} | |
const auto str_token = std::get<0>(token) + ' ' + std::get<0>(std::get<1>(token)); | |
auto added = false; | |
for (auto& ext : extensions_) | |
{ | |
if (ext._prefix.length() < std::get<0>(token).length() && | |
std::get<0>(token)[ext._prefix.length()] == '_' && | |
starts_with(std::get<0>(token), ext._prefix)) | |
{ | |
ext._tokens.push_back(str_token); | |
added = true; | |
} | |
} | |
if (!added) | |
{ | |
not_used_tokens.push_back((*common_tprefix.cbegin()) + "_" + str_token); | |
} | |
} | |
if (1 == extensions_.size() && | |
0 == common_tprefix.count(extensions_.front()._prefix)) | |
{ | |
extensions_.front()._prefix = (*common_tprefix.cbegin()); | |
extensions_.front()._name_string = (*common_tprefix.cbegin()) + "_" + extensions_.front()._name_string; | |
} | |
for (const auto& str_token : not_used_tokens) | |
{ | |
for (auto& ext : extensions_) | |
{ | |
if ((*common_tprefix.cbegin()) == ext._prefix) | |
{ | |
ext._tokens.push_back(str_token); | |
} | |
} | |
} | |
auto procedures = spec._procedures; //TODO: work direct with procedures from specification | |
for (auto& ext : extensions_) | |
{ | |
for (auto& procedure : procedures) | |
{ | |
if (is_procedure_template(procedure) || is_procedure_should_be_ignored( | |
((*common_tprefix.crbegin()) == ext._prefix || | |
ext._name_string.size() <= ext._prefix.size()) ? ext._name_string : ext._name_string.substr( | |
ext._prefix.size() + 1), | |
procedure.name)) | |
{ | |
continue; | |
} | |
if (!starts_with_T(procedure.name, common_prefix)) | |
{ | |
procedure.name = (*common_prefix.cbegin()) + procedure.name; | |
} | |
if (starts_with(tolower(procedure.name), tolower(ext._prefix))) | |
{ | |
ext._procedures.push_back(procedure); | |
} | |
} | |
} | |
for (auto& ext1 : extensions_) | |
{ | |
for (auto& ext2 : extensions_) | |
{ | |
if (ext1._prefix == ext2._prefix) | |
{ | |
continue; | |
} | |
for (auto p1 = ext1._procedures.cbegin(); p1 != ext1._procedures.cend();) | |
{ | |
auto step1 = false; | |
for (auto p2 = ext2._procedures.cbegin(); p1 != ext1._procedures.cend() && p2 != ext2._procedures.cend();) | |
{ | |
if (p1->return_type == p2->return_type && p1->name == p2->name && p1->parameters == p2->parameters) | |
{ | |
if (ext1._prefix.size() > ext2._prefix.size()) | |
{ | |
p2 = ext2._procedures.erase(p2); | |
} | |
else | |
{ | |
p1 = ext1._procedures.erase(p1); | |
step1 = true; | |
} | |
} | |
else | |
{ | |
++p2; | |
} | |
} | |
if (!step1) | |
{ | |
++p1; | |
} | |
} | |
} | |
} | |
std::list<std::pair<std::string, std::string>> extensions; | |
for (const auto& ext : extensions_) | |
{ | |
tmp_output.clear(); | |
if (!ext._name_string.empty() && !url.empty()) | |
{ | |
tmp_output += ext._name_string + '\n'; | |
tmp_output += url + '\n'; | |
tmp_output += ext._name_string + '\n'; | |
} | |
if (!ext._tokens.empty()) | |
{ | |
tmp_output += '\t' + join("\n\t", ext._tokens) + '\n'; | |
} | |
for (auto procedure : ext._procedures) | |
{ | |
if (ext._prefix == (*common_tprefix.cbegin())) | |
{ | |
replace_parameters_type(type_map, procedure.return_type); | |
replace_parameters_type(type_map, procedure.parameters); | |
} | |
tmp_output += '\t' + procedure.return_type + ' ' + procedure.name + | |
" (" + join(", ", procedure.parameters) + ")\n"; | |
} | |
extensions.push_back(std::make_pair(ext._name_string, tmp_output)); | |
} | |
return extensions; | |
} | |
void prepare_tokens(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens) | |
{ | |
tokens.remove_if([&tokens](const std::pair<std::string, std::pair<std::string, long>>& token) | |
{ | |
for (const auto& _token : tokens) | |
{ | |
if ((&_token) == (&token)) | |
{ | |
continue; | |
} | |
if (std::get<0>(_token) == std::get<0>(token) && | |
((!(std::get<0>(std::get<1>(_token)).empty()) && std::get<0>(std::get<1>(token)).empty()) || | |
(std::get<1>(std::get<1>(_token)) == std::get<1>(std::get<1>(token))))) | |
{ | |
return true; | |
} | |
} | |
return false; | |
}); | |
tokens.sort(); | |
tokens.sort([](const std::pair<std::string, std::pair<std::string, long>>& token1, | |
const std::pair<std::string, std::pair<std::string, long>>& token2) | |
{ | |
return std::get<1>(std::get<1>(token1)) < std::get<1>(std::get<1>(token2)); | |
}); | |
} | |
void prepare_tokens2(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens) | |
{ | |
tokens.remove_if([](const std::pair<std::string, std::pair<std::string, long>>& token) | |
{ | |
return (std::get<0>(std::get<1>(token)).empty() || | |
contains(std::get<0>(std::get<1>(token)), "XXXX")); | |
}); | |
} | |
std::list<std::pair<std::string, std::string>> update_ext( | |
std::list<std::string>& registry_list, | |
std::istream& blacklist, | |
std::istream& parse_spec, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
std::list<std::pair<std::string, std::string>> extensions; | |
if (registry_list.empty()) | |
{ | |
return extensions; | |
} | |
registry_list.remove_if([](const std::string & file_path) | |
{ | |
return !ends_with(file_path, ".txt"); | |
}); | |
if (registry_list.empty()) | |
{ | |
return extensions; | |
} | |
apply_black_list(blacklist, registry_list); | |
if (registry_list.empty()) | |
{ | |
return extensions; | |
} | |
auto reg_http = get_reg_http(parse_spec); | |
remove(reg_http, '"'); | |
init_typemap(parse_spec); | |
for (const auto& file_path : registry_list) | |
{ | |
tmp_output.clear(); | |
if (!read_from_file(file_path, tmp_output)) | |
{ | |
log << "[Warning]: Unable to read from file '" | |
<< file_path << "'." << std::endl; | |
continue; | |
} | |
specification spec; | |
read_spec(tmp_output, false, spec); | |
prepare_tokens2(spec._tokens); | |
// | |
static const auto count_of_path_components = 2; | |
const auto url = reg_http + get_relative_path(file_path, count_of_path_components); | |
add_extensions(extensions, specification_to_extensions(spec, url, tmp_output), log); | |
} | |
return extensions; | |
} | |
bool filter(std::istream& script_stream, | |
std::list<std::pair<std::string, std::string>>& extensions, std::ostream& log) | |
{ | |
return execute_script(script_stream, extensions, log); | |
} | |
std::list<std::pair<std::string, std::string>> get_core_ext(const std::string& core, | |
std::list<std::pair<std::string, std::string>>& gl_core_spec) | |
{ | |
std::list<std::pair<std::string, std::string>> extensions; | |
// | |
std::list<std::string> file_list; | |
get_files_by_pattern(core, file_list); | |
if (file_list.empty()) | |
{ | |
return extensions; | |
} | |
file_list.sort(); | |
std::string content(1024 * 1024, '\0'); | |
file_list.remove_if([&content, &gl_core_spec](const std::string & file_path) | |
{ | |
const auto file_name = get_file_name(file_path); | |
if (starts_with(file_name, "GL_VERSION")) | |
{ | |
content.clear(); | |
read_from_file(file_path, content); | |
if (!content.empty()) | |
{ | |
gl_core_spec.push_back(std::make_pair(file_name, content)); | |
} | |
return true; | |
} | |
return contains(file_path, "~"); | |
}); | |
if (file_list.empty()) | |
{ | |
return extensions; | |
} | |
for (const auto& file_path : file_list) | |
{ | |
content.clear(); | |
read_from_file(file_path, content); | |
if (!content.empty()) | |
{ | |
extensions.push_back(std::make_pair(get_file_name(file_path), content)); | |
} | |
} | |
return extensions; | |
} | |
std::list<std::pair<std::string, std::string>> get_ext_spec( | |
const std::string& name_prefix, | |
const std::list<std::pair<std::string, std::string>>& extensions) | |
{ | |
std::list<std::pair<std::string, std::string>> gl_ext_spec; | |
for (const auto& ext : extensions) | |
{ | |
if (starts_with(std::get<0>(ext), name_prefix)) | |
{ | |
gl_ext_spec.push_back(ext); | |
} | |
} | |
return gl_ext_spec; | |
} | |
void add_extensions(std::list<std::pair<std::string, std::string>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& addition_extensions, std::ostream& log) | |
{ | |
for (const auto& addition_extension : addition_extensions) | |
{ | |
const auto name = std::get<0>(addition_extension); | |
// | |
const auto find_result = std::find_if(extensions.begin(), extensions.end(), | |
[&name](const std::pair<std::string, std::string>& element) | |
{ | |
return name == std::get<0>(element); | |
}); | |
if (extensions.cend() == find_result) | |
{ | |
extensions.push_back(addition_extension); | |
} | |
else | |
{ | |
log << "[Warning]: extension '"; | |
log << name; | |
log << "' already exists. Content will be replaced with last one." << std::endl; | |
std::get<1>(*find_result) = std::get<1>(addition_extension); | |
} | |
} | |
} | |
std::list<extension> str_extensions_to_extensions( | |
const std::list<std::pair<std::string, std::string>>& str_extensions) | |
{ | |
std::list<extension> extensions; | |
for (const auto& str_ext : str_extensions) | |
{ | |
extension ext; | |
read_ext(std::get<1>(str_ext), ext); | |
if (!ext._name.empty() && std::get<0>(str_ext) == ext._name) | |
{ | |
extensions.push_back(ext); | |
} | |
} | |
return extensions; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _DESCRIPTOR_H_ | |
#define _DESCRIPTOR_H_ | |
#include <set> | |
#include <list> | |
#include <string> | |
#include <utility> | |
#include <istream> | |
#include <ostream> | |
struct _procedure | |
{ | |
std::string return_type; | |
std::string name; | |
std::list<std::string> parameters; | |
//std::list<std::pair<std::string, std::string>> parameters; | |
friend inline bool operator==(const _procedure& lhs, const _procedure& rhs) | |
{ | |
if (lhs.name != rhs.name || | |
lhs.return_type != rhs.return_type || | |
lhs.parameters.size() != rhs.parameters.size()) | |
{ | |
return false; | |
} | |
if (lhs.parameters.empty()) | |
{ | |
return true; | |
} | |
for (auto lhs_parameter = lhs.parameters.cbegin(), | |
rhs_parameter = rhs.parameters.cbegin(); | |
lhs_parameter != lhs.parameters.cend() && | |
rhs_parameter != rhs.parameters.cend(); | |
++lhs_parameter, ++rhs_parameter) | |
{ | |
if ((*lhs_parameter) != (*rhs_parameter)) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
}; | |
struct specification | |
{ | |
std::string _name; | |
std::list<std::string> _name_strings; | |
std::list<std::string> _reuse; | |
std::list<_procedure> _procedures; | |
std::list<std::string> _types; | |
std::list<std::pair<std::string, std::pair<std::string, long>>> _tokens; | |
}; | |
struct extension : specification | |
{ | |
std::string _url; | |
}; | |
bool init_typemap(std::istream& content_stream); | |
void release_typemap(); | |
std::pair<std::string, std::pair<std::string, long>> str_to_token( | |
const std::string::const_iterator& token_begin, | |
const std::string::const_iterator& token_end); | |
/*SECTION_TYPE determine_section_type( | |
const std::string::const_iterator& name_begin, | |
const std::string::const_iterator& name_end);*/ | |
std::string::const_iterator get_section_start( | |
const std::string& content, const std::string::const_iterator& offset); | |
//std::string::const_iterator get_section(const std::string& content, SECTION_TYPE section_type); | |
void get_name( | |
const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
std::string& name); | |
void get_name_strings( | |
const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
std::list<std::string>& name_strings); | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_function_name( | |
const std::set<char>& white_space, | |
const std::string::const_iterator& return_start, | |
const std::string::const_iterator& function_start); | |
bool is_function_end_correct( | |
const std::string::const_iterator& function_start, | |
const std::string::const_iterator& function_end); | |
void get_procedures_functions( | |
const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
const char function_should_start_from, | |
std::list<std::string>& procedures); | |
/*void get_procedures_functions_structures_types( | |
const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
specification& spec, SECTION_TYPE section_type);*/ | |
void get_tokens( | |
const std::string::const_iterator& first, | |
const std::string::const_iterator& last, | |
specification& spec); | |
void read_spec(const std::string& content, bool read_types, specification& spec); | |
void read_ext(const std::string& content, extension& ext); | |
bool is_procedure_should_be_ignored(const std::string& extension_name, const std::string& procedure_name); | |
bool is_token_taboo(const std::pair<std::string, std::pair<std::string, long>>& token); | |
std::list<std::pair<std::string, std::string>> specification_to_extensions( | |
const specification& spec, const std::string& url, std::string& tmp_output); | |
void prepare_tokens(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens); | |
void prepare_tokens2(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens); | |
std::list<std::pair<std::string, std::string>> update_ext( | |
std::list<std::string>& registry_list, | |
std::istream& blacklist, | |
std::istream& parse_spec, | |
std::string& tmp_output, | |
std::ostream& log); | |
bool filter(std::istream& script_stream, | |
std::list<std::pair<std::string, std::string>>& extensions, std::ostream& log); | |
std::list<std::pair<std::string, std::string>> get_core_ext(const std::string& core, | |
std::list<std::pair<std::string, std::string>>& gl_core_spec); | |
std::list<std::pair<std::string, std::string>> get_ext_spec( | |
const std::string& name_prefix, | |
const std::list<std::pair<std::string, std::string>>& extensions); | |
void add_extensions(std::list<std::pair<std::string, std::string>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& addition_extensions, std::ostream& log); | |
std::list<extension> str_extensions_to_extensions( | |
const std::list<std::pair<std::string, std::string>>& str_extensions); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "descriptors.h" | |
#include "descriptor.h" | |
#include "path.h" | |
#include "common.h" | |
#include "parse_xml.h" | |
#include <cassert> | |
#include <fstream> | |
#include <utility> | |
#include <iterator> | |
#include <algorithm> | |
std::list<std::list<extension>> create_descriptors( | |
const std::string& glew_path, | |
const std::string& glfixes_path, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
std::list<std::list<extension>> result; | |
// | |
const auto registry = combine(std::list<std::string>({ glfixes_path, "/gl/specs/*" })); | |
auto blacklist = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/blacklist" }))); | |
if (!blacklist.is_open()) | |
{ | |
return result; | |
} | |
auto parse_spec = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/parse_spec.pl" }))); | |
if (!parse_spec.is_open()) | |
{ | |
blacklist.close(); | |
return result; | |
} | |
std::list<std::string> registry_list; | |
get_files_by_pattern(registry, registry_list); | |
// | |
auto extensions = update_ext( | |
registry_list, | |
blacklist, | |
parse_spec, | |
tmp_output, | |
log); | |
// | |
blacklist.close(); | |
parse_spec.close(); | |
// | |
auto filter_gl_ext = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/filter_gl_ext.sh" }))); | |
if (!filter_gl_ext.is_open()) | |
{ | |
return result; | |
} | |
filter(filter_gl_ext, extensions, log); | |
filter_gl_ext.close(); | |
// | |
std::list<std::pair<std::string, std::string>> gl_core_spec; | |
add_extensions(extensions, | |
get_core_ext(combine(std::list<std::string>({ glew_path, "/auto/core/gl/*" })), gl_core_spec), | |
log); | |
// | |
result.push_back(str_extensions_to_extensions(gl_core_spec)); | |
// | |
extensions.sort([](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b) | |
{ | |
return std::get<0>(a) < std::get<0>(b); | |
}); | |
// | |
result.push_back(str_extensions_to_extensions(get_ext_spec("GL_", extensions))); | |
result.push_back(str_extensions_to_extensions(get_ext_spec("WGL_", extensions))); | |
result.push_back(str_extensions_to_extensions(get_ext_spec("GLX_", extensions))); | |
// | |
std::list<extension> sub_extensions; | |
// | |
result.back().remove_if([&sub_extensions](const extension & ext) | |
{ | |
if (starts_with(ext._name, "GLX_VERSION")) | |
{ | |
sub_extensions.push_back(ext); | |
return true; | |
} | |
return false; | |
}); | |
// | |
auto pos = result.begin(); | |
std::advance(pos, result.size() - 1); | |
result.insert(pos, sub_extensions); | |
sub_extensions.clear(); | |
// | |
sub_extensions = str_extensions_to_extensions(get_ext_spec("EGL_", extensions)); | |
if (!sub_extensions.empty()) | |
{ | |
result.push_back(sub_extensions); | |
sub_extensions.clear(); | |
// | |
result.back().remove_if([&sub_extensions](const extension & ext) | |
{ | |
if (starts_with(ext._name, "EGL_VERSION")) | |
{ | |
sub_extensions.push_back(ext); | |
return true; | |
} | |
return false; | |
}); | |
// | |
pos = result.begin(); | |
std::advance(pos, result.size() - 1); | |
result.insert(pos, sub_extensions); | |
sub_extensions.clear(); | |
} | |
#ifndef NDEBUG | |
auto count = static_cast<std::size_t>(0); | |
for (const auto& ext : result) | |
{ | |
assert(!ext.empty()); | |
count += ext.size(); | |
} | |
assert(!gl_core_spec.empty()); | |
assert(gl_core_spec.size() < count); | |
count -= gl_core_spec.size(); | |
assert(count == extensions.size()); | |
#endif | |
return result; | |
} | |
bool mv(std::list<std::string>& src, std::list<std::string>& dst) | |
{ | |
const auto is_src_empty = src.empty(); | |
dst.splice(dst.cend(), src); | |
return !is_src_empty && src.empty() && !dst.empty(); | |
} | |
std::list<std::list<extension>> create_descriptors( | |
const std::string& glew_path, | |
const std::string& glfixes_path, | |
const std::string& opengl_registry_path, | |
const std::string& egl_registry_path, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
std::list<std::list<extension>> result; | |
// | |
std::list<std::string> registry_list; | |
get_files_by_pattern(combine(std::list<std::string>({ opengl_registry_path, "/extensions/*" })), | |
registry_list); | |
// | |
std::list<std::string> glfixes_files; | |
get_files_by_pattern(combine(std::list<std::string>({ glfixes_path, "/gl/specs/ANGLE/*" })), glfixes_files); | |
mv(glfixes_files, registry_list); | |
// | |
get_files_by_pattern(combine(std::list<std::string>({ glfixes_path, "/gl/specs/REGAL/*" })), glfixes_files); | |
mv(glfixes_files, registry_list); | |
// | |
auto blacklist = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/blacklist" }))); | |
if (!blacklist.is_open()) | |
{ | |
return result; | |
} | |
auto parse_spec = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/parse_spec.pl" }))); | |
if (!parse_spec.is_open()) | |
{ | |
blacklist.close(); | |
return result; | |
} | |
registry_list.sort(); | |
auto extensions = update_ext(registry_list, blacklist, parse_spec, tmp_output, log); | |
// | |
const auto egl_xml = combine(std::list<std::string>({ egl_registry_path, "/api/egl.xml" })); | |
add_extensions(extensions, parse_xml(egl_xml, parse_xml_option::extensions, tmp_output, log), log); | |
// | |
auto filter_gl_ext = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/filter_gl_ext.sh" }))); | |
if (!filter_gl_ext.is_open()) | |
{ | |
return result; | |
} | |
filter(filter_gl_ext, extensions, log); | |
filter_gl_ext.close(); | |
// | |
std::list<std::pair<std::string, std::string>> gl_core_spec; | |
add_extensions(extensions, | |
get_core_ext(combine(std::list<std::string>({ glew_path, "/auto/core/gl/*" })), gl_core_spec), | |
log); | |
// | |
result.push_back(str_extensions_to_extensions(gl_core_spec)); | |
// | |
extensions.sort([](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b) | |
{ | |
return std::get<0>(a) < std::get<0>(b); | |
}); | |
// | |
result.push_back(str_extensions_to_extensions(get_ext_spec("GL_", extensions))); | |
result.push_back(str_extensions_to_extensions(get_ext_spec("WGL_", extensions))); | |
result.push_back(str_extensions_to_extensions(get_ext_spec("GLX_", extensions))); | |
// | |
std::list<extension> sub_extensions; | |
// | |
result.back().remove_if([&sub_extensions](const extension & ext) | |
{ | |
if (starts_with(ext._name, "GLX_VERSION")) | |
{ | |
sub_extensions.push_back(ext); | |
return true; | |
} | |
return false; | |
}); | |
// | |
auto pos = result.begin(); | |
std::advance(pos, result.size() - 1); | |
result.insert(pos, sub_extensions); | |
sub_extensions.clear(); | |
// | |
sub_extensions = str_extensions_to_extensions(get_ext_spec("EGL_", extensions)); | |
if (!sub_extensions.empty()) | |
{ | |
result.push_back(sub_extensions); | |
sub_extensions.clear(); | |
// | |
result.back().remove_if([&sub_extensions](const extension & ext) | |
{ | |
if (starts_with(ext._name, "EGL_VERSION")) | |
{ | |
sub_extensions.push_back(ext); | |
return true; | |
} | |
return false; | |
}); | |
if (!sub_extensions.empty()) | |
{ | |
pos = result.begin(); | |
std::advance(pos, result.size() - 1); | |
result.insert(pos, sub_extensions); | |
sub_extensions.clear(); | |
} | |
} | |
#ifndef NDEBUG | |
auto count = static_cast<std::size_t>(0); | |
for (const auto& ext : result) | |
{ | |
assert(!ext.empty()); | |
count += ext.size(); | |
} | |
assert(!gl_core_spec.empty()); | |
assert(gl_core_spec.size() < count); | |
count -= gl_core_spec.size(); | |
assert(count == extensions.size()); | |
#endif | |
return result; | |
} | |
std::list<extension> get_extensions_by_group_name( | |
const std::list<std::list<extension>>& extensions, | |
const std::string& extensions_group_name) | |
{ | |
const auto find_result = std::find_if(extensions.cbegin(), extensions.cend(), | |
[&extensions_group_name](const std::list<extension>& sub_extensions) | |
{ | |
return !sub_extensions.empty() && | |
starts_with(sub_extensions.cbegin()->_name, extensions_group_name); | |
}); | |
if (extensions.cend() != find_result) | |
{ | |
return (*find_result); | |
} | |
return std::list<extension>(); | |
} | |
std::list<extension> get_extensions_by_group_name( | |
const std::list<std::list<extension>>& extensions, | |
const std::string& extensions_group_name, | |
const std::string& except_group_name) | |
{ | |
const auto find_result = std::find_if(extensions.cbegin(), extensions.cend(), | |
[&extensions_group_name, &except_group_name](const std::list<extension>& sub_extensions) | |
{ | |
return !sub_extensions.empty() && | |
starts_with(sub_extensions.cbegin()->_name, extensions_group_name) && | |
!starts_with(sub_extensions.cbegin()->_name, except_group_name); | |
}); | |
if (extensions.cend() != find_result) | |
{ | |
return (*find_result); | |
} | |
return std::list<extension>(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _DESCRIPTORS_H_ | |
#define _DESCRIPTORS_H_ | |
#include <list> | |
#include <string> | |
#include <ostream> | |
struct extension; | |
std::list<std::list<extension>> create_descriptors( | |
const std::string& glew_path, | |
const std::string& glfixes_path, | |
std::string& tmp_output, | |
std::ostream& log); | |
std::list<std::list<extension>> create_descriptors( | |
const std::string& glew_path, | |
const std::string& glfixes_path, | |
const std::string& opengl_registry_path, | |
const std::string& egl_registry_path, | |
std::string& tmp_output, | |
std::ostream& log); | |
std::list<extension> get_extensions_by_group_name( | |
const std::list<std::list<extension>>& extensions, | |
const std::string& extensions_group_name); | |
std::list<extension> get_extensions_by_group_name( | |
const std::list<std::list<extension>>& extensions, | |
const std::string& extensions_group_name, | |
const std::string& except_group_name); | |
#define get_gl_core_spec(A) (get_extensions_by_group_name((A), "GL_VERSION")) | |
#define get_gl_ext_spec(A) (get_extensions_by_group_name((A), "GL_", "GL_VERSION")) | |
#define get_egl_core_spec(A) (get_extensions_by_group_name((A), "EGL_VERSION")) | |
#define get_egl_ext_spec(A) (get_extensions_by_group_name((A), "EGL", "EGL_VERSION")) | |
#define get_wgl_ext_spec(A) (get_extensions_by_group_name((A), "WGL_")) | |
#define get_glx_core_spec(A) (get_extensions_by_group_name((A), "GLX_VERSION")) | |
#define get_glx_ext_spec(A) (get_extensions_by_group_name((A), "GLX_", "GLX_VERSION")) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "filler.h" | |
#include "common.h" | |
#include "version.h" | |
#include "procedure.h" | |
#include "descriptor.h" | |
#include <set> | |
#include <list> | |
#include <iterator> | |
#include <algorithm> | |
void add_define_start(const std::string& name, std::string& content) | |
{ | |
content += '\n'; | |
content += '\n'; | |
content += "#ifndef " + name + "\n"; | |
content += "#define " + name + " 1\n"; | |
content += '\n'; | |
} | |
void add_define_finish(const std::string& name, std::string& content) | |
{ | |
content += '\n'; | |
content += "#endif /* " + name + " */\n"; | |
content += '\n'; | |
} | |
void add_types(const std::list<std::string>& types, std::string& content) | |
{ | |
for (const auto& type_ : types) | |
{ | |
auto pos1 = type_.find(';'); | |
auto pos2 = pos1; | |
if (std::string::npos != pos1) | |
{ | |
pos2++; | |
pos2 = type_.find(';', pos2); | |
} | |
if (std::string::npos != pos2 && pos1 < pos2 && contains(type_, "{")) | |
{ | |
auto start = type_.cbegin(); | |
pos2 = type_.find('{'); | |
if (pos2 < pos1) | |
{ | |
pos2++; | |
std::advance(start, pos2); | |
std::copy(type_.cbegin(), | |
start, | |
std::back_inserter(content)); | |
content.push_back('\n'); | |
} | |
do | |
{ | |
auto finish = type_.cbegin(); | |
if (pos1 < type_.size() - 1) | |
{ | |
pos1 += 2; | |
} | |
else | |
{ | |
++pos1; | |
} | |
std::advance(finish, pos1); | |
std::copy(start, | |
finish, | |
std::back_inserter(content)); | |
content.push_back('\n'); | |
start = finish; | |
} | |
while (pos1 < type_.size() - 1 && std::string::npos != (pos1 = type_.find(';', pos1))); | |
if (0 < std::distance(start, type_.cend())) | |
{ | |
std::copy(start, | |
type_.cend(), | |
std::back_inserter(content)); | |
auto pos = std::find_if(start, type_.cend(), | |
[](const char& ch) | |
{ | |
return ';' == ch; | |
}); | |
if (type_.cend() == pos) | |
{ | |
content.push_back(';'); | |
} | |
else | |
{ | |
const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' }); | |
std::advance(pos, 1); | |
// | |
pos = std::find_if(pos, type_.cend(), | |
[&tab_space_new_line](const char& ch) | |
{ | |
return 0 == tab_space_new_line.count(ch); | |
}); | |
if (type_.cend() != pos) | |
{ | |
content.push_back(';'); | |
} | |
} | |
content.push_back('\n'); | |
} | |
} | |
else | |
{ | |
content += type_; | |
if (std::string::npos == type_.rfind(';')) | |
{ | |
content += ';'; | |
} | |
} | |
content += '\n'; | |
} | |
} | |
void add_tokens(const std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens, | |
std::string& content) | |
{ | |
for (const auto& token : tokens) | |
{ | |
content += "#define " + std::get<0>(token) + | |
(std::get<0>(std::get<1>(token)).empty() ? "" : " " + std::get<0>(std::get<1>(token))); | |
content += '\n'; | |
} | |
} | |
std::string get_glew_name(const std::string& name, const std::string& type) | |
{ | |
std::string glew_name(2 + name.size(), '\0'); | |
glew_name.clear(); | |
if (type.size() < name.size()) | |
{ | |
if (!type.empty()) | |
{ | |
std::copy(type.cbegin(), type.cend(), std::back_inserter(glew_name)); | |
} | |
glew_name += "EW"; | |
std::copy(name.cbegin() + type.size(), name.cend(), std::back_inserter(glew_name)); | |
} | |
return glew_name; | |
} | |
std::pair<std::string, std::string> serialize_procedure( | |
const _procedure& procedure, const std::string& api, const std::string& type) | |
{ | |
static const auto gl_word = std::string("gl"); | |
// | |
std::string gl_name_upper(7 + procedure.name.size(), '\0'); | |
gl_name_upper.clear(); | |
gl_name_upper += "PFN"; | |
gl_name_upper += toupper(procedure.name); | |
gl_name_upper += "PROC"; | |
// | |
std::string typedef_("typedef "); | |
typedef_ += procedure.return_type + " (" + api + " * " + gl_name_upper + ") " + "(" + join(", ", | |
procedure.parameters); | |
if (')' != typedef_.back()) | |
{ | |
typedef_ += ')'; | |
} | |
if (std::string::npos == typedef_.rfind(';')) | |
{ | |
typedef_ += ';'; | |
} | |
std::string glew_name(4 + procedure.name.size(), '\0'); | |
glew_name.clear(); | |
glew_name += "__"; | |
const auto pos = procedure.name.find(gl_word); | |
if (std::string::npos != pos) | |
{ | |
for (auto i = static_cast<std::size_t>(0); i < pos; ++i) | |
{ | |
glew_name += procedure.name[i]; | |
} | |
glew_name += "glew"; | |
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i) | |
{ | |
glew_name += procedure.name[i]; | |
} | |
} | |
auto define_ = "#define " + procedure.name + " " + type + "EW_GET_FUN(" + glew_name + ")"; | |
return std::make_pair(typedef_, define_); | |
} | |
void add_procedures(const std::list<_procedure>& procedures, const std::string& api, const std::string& type, | |
std::string& content) | |
{ | |
std::list<std::pair<std::string, std::string>> typedefs_and_defines; | |
for (const auto& procedure : procedures) | |
{ | |
typedefs_and_defines.push_back(serialize_procedure(procedure, api, type)); | |
} | |
typedefs_and_defines.sort([](const std::pair<std::string, std::string>& a, | |
const std::pair<std::string, std::string>& b) | |
{ | |
return std::get<1>(a) < std::get<1>(b); | |
}); | |
// | |
typedefs_and_defines.unique(); | |
for (const auto& typedef_ : typedefs_and_defines) | |
{ | |
content += std::get<0>(typedef_); | |
content += '\n'; | |
} | |
if (!typedefs_and_defines.empty()) | |
{ | |
content += '\n'; | |
} | |
for (const auto& define_ : typedefs_and_defines) | |
{ | |
content += std::get<1>(define_); | |
content += '\n'; | |
} | |
} | |
void add_variable(const std::string& name, const std::string& type, std::string& content) | |
{ | |
const auto glew_name = get_glew_name(name, type); | |
content += "#define " + glew_name + " " + type + "EW_GET_VAR(__" + glew_name + ")\n"; | |
} | |
void add_section_head(const std::string& head, std::string& content) | |
{ | |
if (head.empty()) | |
{ | |
content.push_back('/'); | |
content.push_back('*'); | |
content.push_back(' '); | |
std::string head_(73, '-'); | |
std::copy(head_.cbegin(), head_.cend(), std::back_inserter(content)); | |
content.push_back(' '); | |
content.push_back('*'); | |
content.push_back('/'); | |
} | |
else if (head.size() < 72) | |
{ | |
std::string head_(79, '-'); | |
head_[0] = '/'; | |
head_[1] = '*'; | |
head_[2] = ' '; | |
std::size_t start_position = static_cast<std::size_t>(39) - | |
static_cast<std::size_t>(0.5f + static_cast<float>(head.size()) / 2); | |
head_[start_position++] = ' '; | |
std::copy(head.cbegin(), head.cend(), head_.begin() + start_position); | |
head_[start_position + head.size()] = ' '; | |
head_[76] = ' '; | |
head_[77] = '*'; | |
head_[78] = '/'; | |
std::copy(head_.cbegin(), head_.cend(), std::back_inserter(content)); | |
} | |
else | |
{ | |
content.push_back('/'); | |
content.push_back('*'); | |
content.push_back(' '); | |
std::copy(head.cbegin(), head.cend(), std::back_inserter(content)); | |
content.push_back(' '); | |
content.push_back('*'); | |
content.push_back('/'); | |
} | |
} | |
void add_content_separator(std::string& content) | |
{ | |
if (content.size() < 2) | |
{ | |
content += "\n\n"; | |
} | |
else if (content.size() - 2 != content.rfind("\n\n", content.size() - 2)) | |
{ | |
content += '\n'; | |
if (content.size() - 2 != content.rfind("\n\n", content.size() - 2)) | |
{ | |
content += '\n'; | |
} | |
} | |
} | |
void make_head_content_from_ext(const specification& spec, const std::string& api, const std::string& type, | |
std::string& content) | |
{ | |
add_section_head(spec._name, content); | |
add_define_start(spec._name, content); | |
// | |
add_tokens(spec._tokens, content); | |
add_content_separator(content); | |
add_types(spec._types, content); | |
add_content_separator(content); | |
add_procedures(spec._procedures, api, type, content); | |
add_content_separator(content); | |
add_variable(spec._name, type, content); | |
// | |
add_define_finish(spec._name, content); | |
} | |
void make_header(const std::string& api, const std::string& type, | |
const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
make_head_content_from_ext(ext, api, type, output); | |
} | |
} | |
void make_struct_fun(const std::string& prefix, const std::string& suffix, | |
const std::list<extension>& extensions, std::ostream& output) | |
{ | |
static const auto gl_word = std::string("gl"); | |
for (const auto& ext : extensions) | |
{ | |
if (ext._procedures.empty()) | |
{ | |
continue; | |
} | |
for (const auto& procedure : ext._procedures) | |
{ | |
if (!prefix.empty()) | |
{ | |
output << prefix << ' '; | |
} | |
output << "PFN"; | |
output << toupper(procedure.name); | |
output << "PROC "; | |
output << "__"; | |
// | |
const auto pos = procedure.name.find(gl_word); | |
if (std::string::npos != pos) | |
{ | |
for (auto i = static_cast<std::size_t>(0); i < pos; ++i) | |
{ | |
output << procedure.name[i]; | |
} | |
output << "glew"; | |
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i) | |
{ | |
output << procedure.name[i]; | |
} | |
} | |
if (!suffix.empty()) | |
{ | |
output << ' ' << suffix; | |
} | |
output << ";" << std::endl; | |
} | |
output << std::endl; | |
} | |
} | |
void make_struct_fun(const std::string& prefix, const std::string& suffix, | |
const std::list<extension>& extensions, std::string& output) | |
{ | |
static const auto gl_word = std::string("gl"); | |
for (const auto& ext : extensions) | |
{ | |
if (ext._procedures.empty()) | |
{ | |
continue; | |
} | |
for (const auto& procedure : ext._procedures) | |
{ | |
const auto current_size = output.size(); | |
if (!prefix.empty()) | |
{ | |
output += prefix + ' '; | |
} | |
output += "PFN"; | |
output += toupper(procedure.name); | |
output += "PROC "; | |
output += "__"; | |
// | |
const auto pos = procedure.name.find(gl_word); | |
if (std::string::npos != pos) | |
{ | |
for (auto i = static_cast<std::size_t>(0); i < pos; ++i) | |
{ | |
output += procedure.name[i]; | |
} | |
output += "glew"; | |
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i) | |
{ | |
output += procedure.name[i]; | |
} | |
} | |
if (!suffix.empty()) | |
{ | |
output += ' ' + suffix; | |
} | |
output += ";\n"; | |
const auto str_procedure = output.substr(current_size); | |
const auto procedure_position = output.find(str_procedure); | |
if (procedure_position != current_size) | |
{ | |
output.resize(current_size); | |
//TODO: deal with GL_VERSION_4_5 and GL_KHR_robustness that both have GetGraphicsResetStatus function. | |
//TODO: Reference implementation deal with this moment. | |
} | |
} | |
output.push_back('\n'); | |
} | |
} | |
void make_struct_var(const std::string& prefix, const std::string& suffix, | |
const std::string& type, | |
const std::list<extension>& extensions, std::ostream& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
if (!prefix.empty()) | |
{ | |
output << prefix << ' '; | |
} | |
output << "GLboolean __"; | |
output << get_glew_name(ext._name, type); | |
if (!suffix.empty()) | |
{ | |
output << ' ' << suffix; | |
} | |
output << ";" << std::endl; | |
} | |
} | |
void make_struct_var(const std::string& prefix, const std::string& suffix, | |
const std::string& type, | |
const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
if (!prefix.empty()) | |
{ | |
output += prefix + ' '; | |
} | |
output += "GLboolean __"; | |
output += get_glew_name(ext._name, type); | |
if (!suffix.empty()) | |
{ | |
output += ' ' + suffix; | |
} | |
output += ";\n"; | |
} | |
} | |
void make_init(const std::string& type, const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
if (ext._procedures.empty()) | |
{ | |
continue; | |
} | |
output += "#ifdef " + ext._name + "\n\n"; | |
output += "static GLboolean _glewInit_" + ext._name; | |
if (type.empty()) | |
{ | |
output += " ()\n{\n "; | |
} | |
else | |
{ | |
output += " (" + type; | |
output += "EW_CONTEXT_ARG_DEF_INIT)\n{\n "; | |
} | |
output += "GLboolean r = GL_FALSE;\n"; | |
output.push_back('\n'); | |
if (!ext._reuse.empty()) | |
{ | |
output += " r = _glewInit_"; | |
output += join("() || r;\n r = _glewInit_", ext._reuse); | |
output += "() || r;\n\n"; | |
} | |
for (const auto& procedure : ext._procedures) | |
{ | |
output += " r = ((" + procedure.name + | |
" = (PFN" + toupper(procedure.name) + | |
"PROC)glewGetProcAddress((const GLubyte*)\"" + procedure.name + | |
"\")) == NULL) || r;"; | |
output.push_back('\n'); | |
} | |
output += "\n return r;\n}\n\n"; | |
output += "#endif /* " + ext._name + " */\n\n"; | |
} | |
} | |
void make_init(const std::list<extension>& extensions, std::string& output) | |
{ | |
make_init("", extensions, output); | |
} | |
void make_initd(const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
if (ext._procedures.empty()) | |
{ | |
continue; | |
} | |
output += "static GLboolean _glewInit_" + ext._name + " ();\n"; | |
} | |
} | |
std::string get_ext_var(const std::string& name) | |
{ | |
static const std::list<std::string> prefixes({ "EGL_", "WGL_", "GLX_", "GL_" }); | |
for (const auto& prefix : prefixes) | |
{ | |
if (starts_with(name, prefix)) | |
{ | |
return get_glew_name(name, prefix.substr(0, prefix.size() - 1)); | |
} | |
} | |
return get_glew_name(name, ""); | |
} | |
void make_list(const extension& ext, std::string& output) | |
{ | |
output += "#ifdef " + ext._name + '\n'; | |
const auto ext_var = get_ext_var(ext._name); | |
if (!ext._name_strings.empty()) | |
{ | |
output += " " + ext_var + " = _glewSearchExtension(\"" + | |
ext._name_strings.front() + "\", extStart, extEnd);\n"; | |
} | |
if (!ext._procedures.empty()) | |
{ | |
if (starts_with(ext._name, "WGL_")) | |
{ | |
output += " if (glewExperimental || " + ext_var + "|| crippled) " | |
+ ext_var + "= !_glewInit_" + ext._name + "(GLEW_CONTEXT_ARG_VAR_INIT);\n"; | |
} | |
else | |
{ | |
output += " if (glewExperimental || " + ext_var + ") " | |
+ ext_var + " = !_glewInit_" + ext._name + "(GLEW_CONTEXT_ARG_VAR_INIT);\n"; | |
} | |
} | |
output += "#endif /* " + ext._name + " */\n"; | |
} | |
void make_list_2_2_2(const extension& ext, std::string& output) | |
{ | |
if (ext._procedures.empty() && starts_with(ext._name, "GL_")) | |
{ | |
return; | |
} | |
if (!ext._name_strings.empty() || !ext._procedures.empty()) | |
{ | |
output += "#ifdef " + ext._name + '\n'; | |
const auto ext_var = get_ext_var(ext._name); | |
if (!ext._name_strings.empty() && !starts_with(ext._name, "GL_")) | |
{ | |
output += " " + ext_var + " = _glewSearchExtension(\"" + ext._name_strings.front() + | |
"\", extStart, extEnd);\n"; | |
} | |
if (!ext._procedures.empty()) | |
{ | |
if (starts_with(ext._name, "WGL_")) | |
{ | |
output += " if (glewExperimental || " + ext_var + "|| crippled) " | |
+ ext_var + "= !_glewInit_" + ext._name + "();\n"; | |
} | |
else | |
{ | |
output += " if (glewExperimental || " + ext_var + ") " | |
+ ext_var + " = !_glewInit_" + ext._name + "();\n"; | |
} | |
} | |
output += "#endif /* " + ext._name + " */\n"; | |
} | |
} | |
void make_list(const std::list<extension>& extensions, std::string& output, const _version& version) | |
{ | |
if (version_1_13_0 == version) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
make_list(ext, output); | |
} | |
} | |
else if (version_2_2_2 == version) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
make_list_2_2_2(ext, output); | |
} | |
} | |
} | |
void make_list(const std::string& extension_name, const std::list<extension>& extensions, std::string& output, | |
const _version& version) | |
{ | |
const auto required_extension = std::find_if(extensions.cbegin(), extensions.cend(), | |
[&extension_name](const extension & ext) | |
{ | |
return extension_name == ext._name; | |
}); | |
if (extensions.cbegin() != required_extension) | |
{ | |
if (version_1_13_0 == version) | |
{ | |
make_list(*required_extension, output); | |
} | |
else if (version_2_2_2 == version) | |
{ | |
make_list_2_2_2(*required_extension, output); | |
} | |
} | |
} | |
void make_list2(const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
if (ext._name_strings.empty() || ext._name_strings.front() == ext._name) | |
{ | |
continue; | |
} | |
const auto ext_var = get_ext_var(ext._name); | |
const auto parent = get_ext_var(ext._name_strings.front()); | |
// | |
output += "#ifdef " + ext._name + "\n"; | |
output += " " + ext_var + " = " + parent + ";\n"; | |
output += "#endif /* " + ext._name + " */\n"; | |
} | |
} | |
void make_str(const std::list<extension>& extensions, std::string& output) | |
{ | |
std::string exttype; | |
for (const auto& ext : extensions) | |
{ | |
std::string extrem(ext._name.size(), '\0'); | |
extrem.clear(); | |
// | |
auto pos = std::find_if(ext._name.cbegin(), ext._name.cend(), | |
[](const char& ch) | |
{ | |
return '_' == ch; | |
}); | |
if (ext._name.cend() != pos) | |
{ | |
std::advance(pos, 1); | |
auto prev_pos = pos; | |
// | |
pos = std::find_if(pos, ext._name.cend(), | |
[](const char& ch) | |
{ | |
return '_' == ch; | |
}); | |
if (ext._name.cend() != pos) | |
{ | |
std::advance(pos, 1); | |
if (static_cast<std::size_t>(std::distance(prev_pos, pos)) != exttype.size() || | |
!contains(std::make_pair(prev_pos, pos), exttype)) | |
{ | |
if (!exttype.empty()) | |
{ | |
output += " }\n"; | |
} | |
exttype.clear(); | |
std::copy(prev_pos, | |
pos, | |
std::back_inserter(exttype)); | |
// | |
output += " if (_glewStrSame2(&pos, &len, (const GLubyte*)\"" + exttype + "\", " + std::to_string( | |
exttype.size()) + "))\n"; | |
output += " {\n"; | |
} | |
} | |
} | |
std::copy(pos, | |
ext._name.cend(), | |
std::back_inserter(extrem)); | |
// | |
const auto ext_var = get_ext_var(ext._name); | |
output += "#ifdef " + ext._name + "\n"; | |
output += " if (_glewStrSame3(&pos, &len, (const GLubyte*)\"" + extrem + "\", " + std::to_string( | |
extrem.size()) + "))\n"; | |
output += " {\n"; | |
output += " ret = " + ext_var + ";\n"; | |
output += " continue;\n"; | |
output += " }\n"; | |
output += "#endif\n"; | |
} | |
output += " }\n"; | |
} | |
void make_info(const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
output += "#ifdef " + ext._name + "\n\n"; | |
output += "static void _glewInfo_" + ext._name + " (void)\n{\n"; | |
const auto ext_var = get_ext_var(ext._name); | |
if (contains(ext_var, "VERSION")) | |
{ | |
output += " glewPrintExt(\"" + ext._name + "\", " + ext_var + ", " + ext_var + ", " + ext_var + ");\n"; | |
} | |
else | |
{ | |
static const std::list<std::string> prefixes({ "GLX", "GLW", "GL" }); | |
std::string extpre; | |
for (const auto& prefix : prefixes) | |
{ | |
const auto pos = find_phrase_start(ext._name, prefix); | |
if (ext._name.cend() != pos) | |
{ | |
if (ext._name.cbegin() != pos) | |
{ | |
std::copy( | |
ext._name.cbegin(), | |
pos, | |
std::back_inserter(extpre)); | |
} | |
std::copy( | |
prefix.cbegin(), | |
prefix.cend(), | |
std::back_inserter(extpre)); | |
// | |
extpre = tolower(extpre); | |
break; | |
} | |
} | |
output += std::string(" glewPrintExt(\"" + ext._name + "\", " + ext_var + ", " + extpre) + | |
std::string("ewIsSupported(\"" + ext._name + "\"), " + extpre) + | |
std::string("ewGetExtension(\"" + join("", ext._name_strings) + "\"));\n"); | |
} | |
if (!ext._procedures.empty()) | |
{ | |
output.push_back('\n'); | |
} | |
for (const auto& procedure : ext._procedures) | |
{ | |
output += " glewInfoFunc(\"" + procedure.name + "\", " + procedure.name + " == NULL);"; | |
output.push_back('\n'); | |
} | |
output += "}\n\n"; | |
output += "#endif /* " + ext._name + " */\n\n"; | |
} | |
} | |
void make_info_list(const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
output += "#ifdef " + ext._name + "\n"; | |
output += " _glewInfo_" + ext._name + "();\n"; | |
output += "#endif /* " + ext._name + " */\n"; | |
} | |
} | |
void make_index(const std::list<extension>& extensions, std::string& output) | |
{ | |
for (const auto& ext : extensions) | |
{ | |
output += "#ifdef " + ext._name + "\n"; | |
output += " \"" + ext._name + "\",\n"; | |
output += "#endif\n"; | |
} | |
} | |
void make_index(const std::list<extension>& extensions1, const std::list<extension>& extensions2, | |
std::string& output) | |
{ | |
for (auto a = extensions1.cbegin(), b = extensions2.cbegin(); ;) | |
{ | |
const std::string* ext_name = nullptr; | |
if (extensions1.cend() != a && extensions2.cend() != b) | |
{ | |
if (a->_name < b->_name) | |
{ | |
ext_name = &(a->_name); | |
++a; | |
} | |
else | |
{ | |
ext_name = &(b->_name); | |
++b; | |
} | |
} | |
else if (extensions1.cend() != a) | |
{ | |
ext_name = &(a->_name); | |
++a; | |
} | |
else if (extensions2.cend() != b) | |
{ | |
ext_name = &(b->_name); | |
++b; | |
} | |
else | |
{ | |
break; | |
} | |
output += "#ifdef " + (*ext_name) + "\n"; | |
output += " \"" + (*ext_name) + "\",\n"; | |
output += "#endif\n"; | |
} | |
} | |
void make_enable_index(const std::list<extension>& extensions1, const std::list<extension>& extensions2, | |
std::string& output) | |
{ | |
output += "/* Detected in the extension string or strings */\n"; | |
output += "static GLboolean _glewExtensionString[" + | |
std::to_string(extensions1.size() + extensions2.size()) + "];\n"; | |
output += "/* Detected via extension string or experimental mode */\n"; | |
output += "static GLboolean* _glewExtensionEnabled[] = {\n"; | |
for (auto a = extensions1.cbegin(), b = extensions2.cbegin(); ;) | |
{ | |
const std::string* ext_name = nullptr; | |
if (extensions1.cend() != a && extensions2.cend() != b) | |
{ | |
if (a->_name < b->_name) | |
{ | |
ext_name = &(a->_name); | |
++a; | |
} | |
else | |
{ | |
ext_name = &(b->_name); | |
++b; | |
} | |
} | |
else if (extensions1.cend() != a) | |
{ | |
ext_name = &(a->_name); | |
++a; | |
} | |
else if (extensions2.cend() != b) | |
{ | |
ext_name = &(b->_name); | |
++b; | |
} | |
else | |
{ | |
break; | |
} | |
const auto ext_var = get_ext_var(*ext_name); | |
output += "#ifdef " + (*ext_name) + "\n"; | |
output += " &__" + ext_var + ",\n"; | |
output += "#endif\n"; | |
} | |
output += " NULL\n};\n\n"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _FILLER_H_ | |
#define _FILLER_H_ | |
#include <list> | |
#include <string> | |
#include <utility> | |
#include <ostream> | |
struct _procedure; | |
struct specification; | |
struct extension; | |
struct _version; | |
void add_define_start(const std::string& name, std::string& content); | |
void add_define_finish(const std::string& name, std::string& content); | |
void add_types(const std::list<std::string>& types, std::string& content); | |
void add_tokens(const std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens, | |
std::string& content); | |
std::string get_glew_name(const std::string& name, const std::string& type); | |
std::pair<std::string, std::string> serialize_procedure( | |
const _procedure& procedure, const std::string& api, const std::string& type); | |
void add_procedures(const std::list<_procedure>& procedures, const std::string& api, const std::string& type, | |
std::string& content); | |
void add_variable(const std::string& name, const std::string& type, std::string& content); | |
void add_section_head(const std::string& head, std::string& content); | |
void add_content_separator(std::string& content); | |
void make_head_content_from_ext(const specification& spec, const std::string& api, const std::string& type, | |
std::string& content); | |
void make_header(const std::string& api, const std::string& type, | |
const std::list<extension>& extensions, std::string& output); | |
void make_struct_fun(const std::string& prefix, const std::string& suffix, | |
const std::list<extension>& extensions, std::ostream& output); | |
void make_struct_fun(const std::string& prefix, const std::string& suffix, | |
const std::list<extension>& extensions, std::string& output); | |
void make_struct_var(const std::string& prefix, const std::string& suffix, | |
const std::string& type, | |
const std::list<extension>& extensions, std::ostream& output); | |
void make_struct_var(const std::string& prefix, const std::string& suffix, | |
const std::string& type, | |
const std::list<extension>& extensions, std::string& output); | |
#define make_def_fun(extensions, output) make_struct_fun("", "= NULL", (extensions), (output)) | |
#define make_def_var(type, extensions, output) make_struct_var("", "= GL_FALSE", (type), (extensions), (output)) | |
void make_init(const std::string& type, const std::list<extension>& extensions, std::string& output); | |
void make_init(const std::list<extension>& extensions, std::string& output); | |
void make_initd(const std::list<extension>& extensions, std::string& output); | |
std::string get_ext_var(const std::string& name); | |
void make_list(const extension& ext, std::string& output); | |
void make_list(const std::list<extension>& extensions, std::string& output, const _version& version); | |
void make_list(const std::string& extension_name, const std::list<extension>& extensions, | |
std::string& output, const _version& version); | |
void make_list2(const std::list<extension>& extensions, std::string& output); | |
void make_str(const std::list<extension>& extensions, std::string& output); | |
void make_info(const std::list<extension>& extensions, std::string& output); | |
void make_info_list(const std::list<extension>& extensions, std::string& output); | |
void make_index(const std::list<extension>& extensions, std::string& output); | |
void make_index(const std::list<extension>& extensions1, | |
const std::list<extension>& extensions2, std::string& output); | |
void make_enable_index(const std::list<extension>& extensions1, | |
const std::list<extension>& extensions2, std::string& output); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "generator.h" | |
#include "filler.h" | |
#include "common.h" | |
#include "input_output.h" | |
#include "path.h" | |
#include "version.h" | |
#include "interpreter.h" | |
#include <fstream> | |
#include <iterator> | |
std::list<std::list<extension>>::const_iterator get_next_extensions( | |
const std::list<std::list<extension>>::const_iterator& current_extensions, | |
const std::list<std::list<extension>>& extensions, | |
const std::string& extensions_group_name, | |
std::ostream& log) | |
{ | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), current_extensions))) | |
{ | |
log << "[Error]: there is no '" | |
<< extensions_group_name | |
<< "' at extensions list." | |
<< std::endl; | |
return current_extensions; | |
} | |
auto next = current_extensions; | |
std::advance(next, 1); | |
return next; | |
} | |
bool glew_h(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
const auto ver = str_version_to_version(version); | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "mesa_license.h" })), | |
combine(std::list<std::string>({ src, "khronos_license.h" })), | |
combine(std::list<std::string>({ src, "glew_head.h" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
read_from_file(file_path, output); | |
} | |
if (extensions.empty()) | |
{ | |
log << "[Error]: no extensions passed. Generation of content halted." << std::endl; | |
return false; | |
} | |
const auto gl_core_spec = extensions.cbegin(); | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_core_spec))) | |
{ | |
log << "[Error]: there is no 'GL_EXT_SPEC' at extensions list. Generation of content halted." << | |
std::endl; | |
return false; | |
} | |
auto gl_ext_spec = gl_core_spec; | |
std::advance(gl_ext_spec, 1); | |
// | |
make_header("GLAPIENTRY", "GL", *gl_core_spec, output); | |
make_header("GLAPIENTRY", "GL", *gl_ext_spec, output); | |
if (ver == version_1_13_0) | |
{ | |
echo("/* ------------------------------------------------------------------------- */\n\n#if defined(GLEW_MX) && defined(_WIN32)\n#define GLEW_FUN_EXPORT\n#else\n#define GLEW_FUN_EXPORT GLEWAPI\n#endif /* GLEW_MX */\n", | |
output); | |
echo("#if defined(GLEW_MX)\n#define GLEW_VAR_EXPORT\n#else\n#define GLEW_VAR_EXPORT GLEWAPI\n#endif /* GLEW_MX */\n", | |
output); | |
echo("#if defined(GLEW_MX) && defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */", output); | |
} | |
else | |
{ | |
echo("/* ------------------------------------------------------------------------- */\n\n", output); | |
output.push_back('\n'); | |
} | |
make_struct_fun("GLEW_FUN_EXPORT", "", *gl_core_spec, output); | |
make_struct_fun("GLEW_FUN_EXPORT", "", *gl_ext_spec, output); | |
// | |
output.pop_back(); | |
if (ver == version_1_13_0) | |
{ | |
echo("\n#if defined(GLEW_MX) && !defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */\n", | |
output); | |
} | |
make_struct_var("GLEW_VAR_EXPORT", "", "GL", *gl_core_spec, output); | |
make_struct_var("GLEW_VAR_EXPORT", "", "GL", *gl_ext_spec, output); | |
if (ver == version_1_13_0) | |
{ | |
echo("\n#ifdef GLEW_MX\n}; /* GLEWContextStruct */\n#endif /* GLEW_MX */\n", output); | |
} | |
static const auto parameter = | |
std::string("s/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;\nGLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/"); | |
if (!perl(output, parameter)) | |
{ | |
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl; | |
} | |
const auto glew_tail = combine(std::list<std::string>({ src, "glew_tail.h" })); | |
std::ifstream file_stream(glew_tail); | |
if (file_stream.is_open()) | |
{ | |
std::list<std::string> parameters; | |
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g")); | |
if (!perl(file_stream, parameters, version, output, log)) | |
{ | |
log << "[Warning]: Command 'perl -e " << join("\nperl -e ", | |
parameters) << "' was not be applied." << std::endl; | |
result = false; | |
} | |
file_stream.close(); | |
} | |
else | |
{ | |
log << "[Warning]: Unable to open '" << glew_tail << "'." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool glew_c_2_2_2(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "glew_head.c" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
} | |
if (extensions.empty()) | |
{ | |
log << "[Error]: no extensions passed. Generation of content halted." << std::endl; | |
return false; | |
} | |
output.push_back('\n'); | |
const auto gl_core_spec = extensions.cbegin(); | |
make_def_fun(*gl_core_spec, output); | |
// | |
const auto gl_ext_spec = get_next_extensions(gl_core_spec, extensions, "GL_EXT_SPEC", log); | |
if (gl_core_spec == gl_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_def_fun(*gl_ext_spec, output); | |
// | |
output.pop_back(); | |
echo("\nGLboolean __GLEW_VERSION_1_1 = GL_FALSE;", output); | |
// | |
make_def_var("GL", *gl_core_spec, output); | |
make_def_var("GL", *gl_ext_spec, output); | |
// | |
echo("\nstatic const char * _glewExtensionLookup[] = {", output); | |
// | |
make_index(*gl_core_spec, *gl_ext_spec, output); | |
// | |
echo(" NULL\n};\n\n", output); | |
// | |
make_enable_index(*gl_core_spec, *gl_ext_spec, output); | |
// | |
make_initd(*gl_core_spec, output); | |
make_initd(*gl_ext_spec, output); | |
// | |
echo("", output); | |
// | |
make_init(*gl_core_spec, output); | |
make_init(*gl_ext_spec, output); | |
// | |
auto file_path = combine(std::list<std::string>({ src, "glew_init_gl.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_list(*gl_core_spec, output, version_2_2_2); //| grep - v '\"GL_VERSION' >> $@ | |
make_list(*gl_ext_spec, output, version_2_2_2); | |
make_list2(*gl_ext_spec, output); | |
// | |
echo("\n return GLEW_OK;\n}\n", output); | |
echo("\n#if defined(GLEW_OSMESA)", output); | |
echo("\n#elif defined(GLEW_EGL)", output); | |
output.push_back('\n'); | |
// | |
auto egl_core_spec = extensions.crbegin(); | |
std::advance(egl_core_spec, 1); | |
const auto egl_ext_spec = extensions.crbegin(); | |
// | |
make_def_fun(*egl_core_spec, output); | |
make_def_fun(*egl_ext_spec, output); | |
// | |
make_def_var("EGL", *egl_core_spec, output); | |
make_def_var("EGL", *egl_ext_spec, output); | |
// | |
make_init(*egl_core_spec, output); | |
make_init(*egl_ext_spec, output); | |
// | |
file_path = combine(std::list<std::string>({ src, "glew_init_egl.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_list(*egl_core_spec, output, version_2_2_2); | |
make_list(*egl_ext_spec, output, version_2_2_2); | |
// | |
echo("\n return GLEW_OK;\n}", output); | |
echo("\n#elif defined(_WIN32)", output); | |
// | |
output.push_back('\n'); | |
// | |
const auto wgl_ext_spec = get_next_extensions(gl_ext_spec, extensions, "WGL_EXT_SPEC", log); | |
if (gl_ext_spec == wgl_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_def_fun(*wgl_ext_spec, output); | |
make_def_var("WGL", *wgl_ext_spec, output); | |
make_init(*wgl_ext_spec, output); | |
// | |
file_path = combine(std::list<std::string>({ src, "glew_init_wgl.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_list(*wgl_ext_spec, output, version_2_2_2); | |
// | |
echo("\n return GLEW_OK;\n}", output); | |
echo("\n#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))", | |
output); | |
// | |
const auto glx_core_spec = get_next_extensions(wgl_ext_spec, extensions, "GLX_CORE_SPEC", log); | |
if (wgl_ext_spec == glx_core_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
output.push_back('\n'); | |
make_def_fun(*glx_core_spec, output); | |
const auto glx_ext_spec = get_next_extensions(glx_core_spec, extensions, "GLX_EXT_SPEC", log); | |
if (glx_core_spec == glx_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_def_fun(*glx_ext_spec, output); | |
// | |
output.pop_back(); | |
echo("\nGLboolean __GLXEW_VERSION_1_0 = GL_FALSE;", output); | |
echo("GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;", output); | |
// | |
make_def_var("GLX", *glx_core_spec, output); | |
make_def_var("GLX", *glx_ext_spec, output); | |
// | |
make_init(*glx_core_spec, output); | |
make_init(*glx_ext_spec, output); | |
// | |
file_path = combine(std::list<std::string>({ src, "glew_init_glx.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
std::string sub_output; | |
make_list("GLX_VERSION_1_3", *glx_core_spec, sub_output, version_2_2_2); | |
grep(sub_output, "\"GLX_VERSION", true, output); | |
sub_output.clear(); | |
// | |
make_list(*glx_ext_spec, output, version_2_2_2); | |
// | |
echo("\n return GLEW_OK;\n}", output); | |
echo("\n#endif /* !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */\n", | |
output); | |
// | |
file_path = combine(std::list<std::string>({ src, "glew_init_tail.c" })); | |
std::ifstream file_stream(file_path); | |
if (file_stream.is_open()) | |
{ | |
std::list<std::string> parameters; | |
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g")); | |
if (!perl(file_stream, parameters, version, output, log)) | |
{ | |
log << "[Warning]: Command 'perl -e " | |
<< join("\nperl -e ", parameters) | |
<< "' was not be applied." << std::endl; | |
result = false; | |
} | |
file_stream.close(); | |
} | |
else | |
{ | |
log << "[Warning]: Unable to open '" << file_path << "'." << std::endl; | |
result = false; | |
} | |
file_path = combine(std::list<std::string>({ src, "glew_str_head.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_str(*gl_core_spec, output); | |
make_str(*gl_ext_spec, output); | |
file_path = combine(std::list<std::string>({ src, "glew_str_wgl.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_str(*wgl_ext_spec, output); | |
file_path = combine(std::list<std::string>({ src, "glew_str_glx.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_str(*glx_core_spec, output); | |
make_str(*glx_ext_spec, output); | |
file_path = combine(std::list<std::string>({ src, "glew_str_egl.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
make_str(*egl_core_spec, output); | |
make_str(*egl_ext_spec, output); | |
file_path = combine(std::list<std::string>({ src, "glew_str_tail.c" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
file_path = | |
"s/GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader\\(\\);/{ GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader(); _glewInit_GL_ARB_vertex_program(); }/g"; | |
if (!perl(output, file_path)) | |
{ | |
log << "[Warning]: Command 'perl -e " << file_path << "' was not be applied." << std::endl; | |
result = false; | |
} | |
file_path = | |
"s/\\(\\(glColorSubTable = /((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)\"glBlendEquation\")) == NULL) || r;\n r = ((glColorSubTable = /g"; | |
if (!perl(output, file_path)) | |
{ | |
log << "[Warning]: Command 'perl -e " << file_path << "' was not be applied." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool glew_c(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const auto ver = str_version_to_version(version); | |
if (version_2_2_2 == ver) | |
{ | |
return glew_c_2_2_2(src, extensions, version, output, log); | |
} | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "glew_head.c" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
read_from_file(file_path, output); | |
} | |
echo("\n#if !defined(_WIN32) || !defined(GLEW_MX)", output); | |
// | |
output.push_back('\n'); | |
if (extensions.empty()) | |
{ | |
log << "[Error]: no extensions passed. Generation of content halted." << std::endl; | |
return false; | |
} | |
const auto gl_core_spec = extensions.cbegin(); | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_core_spec))) | |
{ | |
log << "[Error]: there is no 'GL_EXT_SPEC' at extensions list. Generation of content halted." << | |
std::endl; | |
return false; | |
} | |
auto gl_ext_spec = gl_core_spec; | |
std::advance(gl_ext_spec, 1); | |
// | |
make_def_fun(*gl_core_spec, output); | |
make_def_fun(*gl_ext_spec, output); | |
// | |
output.pop_back(); | |
// | |
echo("\n#endif /* !WIN32 || !GLEW_MX */", output); | |
// | |
echo("\n#if !defined(GLEW_MX)", output); | |
echo("\nGLboolean __GLEW_VERSION_1_1 = GL_FALSE;", output); | |
// | |
make_def_var("GL", *gl_core_spec, output); | |
make_def_var("GL", *gl_ext_spec, output); | |
// | |
echo("\n#endif /* !GLEW_MX */\n", output); | |
// | |
make_init("GL", *gl_core_spec, output); | |
make_init("GL", *gl_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_init_gl.c" })), | |
output); | |
// | |
make_list(*gl_core_spec, output, ver);//| grep -v '\"GL_VERSION' | |
make_list(*gl_ext_spec, output, ver); | |
// | |
echo("\n return GLEW_OK;\n}\n", output); | |
echo("\n#if defined(_WIN32)", output); | |
echo("\n#if !defined(GLEW_MX)", output); | |
// | |
output.push_back('\n'); | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_ext_spec))) | |
{ | |
log << "[Error]: there is no 'WGL_EXT_SPEC' at extensions list. Generation of content halted." << | |
std::endl; | |
return false; | |
} | |
auto wgl_ext_spec = gl_ext_spec; | |
std::advance(wgl_ext_spec, 1); | |
// | |
make_def_fun(*wgl_ext_spec, output);//"WGL", | |
output.pop_back(); | |
make_def_var("WGL", *wgl_ext_spec, output); | |
// | |
echo("\n#endif /* !GLEW_MX */\n", output); | |
make_init("WGL", *wgl_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_init_wgl.c" })), | |
output); | |
make_list(*wgl_ext_spec, output, ver); | |
// | |
echo("\n return GLEW_OK;\n}", output); | |
echo("\n#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))", | |
output); | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), wgl_ext_spec))) | |
{ | |
log << "[Error]: there is no 'GLX_CORE_SPEC' at extensions list. Generation of content halted." << | |
std::endl; | |
return false; | |
} | |
auto glx_core_spec = wgl_ext_spec; | |
std::advance(glx_core_spec, 1); | |
if (extensions.size() < | |
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), glx_core_spec))) | |
{ | |
log << "[Error]: there is no 'GLX_EXT_SPEC' at extensions list. Generation of content halted." << | |
std::endl; | |
return false; | |
} | |
auto glx_ext_spec = glx_core_spec; | |
std::advance(glx_ext_spec, 1); | |
// | |
output.push_back('\n'); | |
// | |
make_def_fun(*glx_core_spec, output);//"GLX", | |
make_def_fun(*glx_ext_spec, output);//"GLX", | |
// | |
output.pop_back(); | |
// | |
echo("\n#if !defined(GLEW_MX)", output); | |
echo("\nGLboolean __GLXEW_VERSION_1_0 = GL_FALSE;", output); | |
echo("GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;", output); | |
// | |
make_def_var("GLX", *glx_core_spec, output); | |
make_def_var("GLX", *glx_ext_spec, output); | |
// | |
echo("\n#endif /* !GLEW_MX */\n", output); | |
// | |
make_init("GLX", *glx_core_spec, output); | |
make_init("GLX", *glx_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_init_glx.c" })), | |
output); | |
// | |
std::string sub_output; | |
make_list("GLX_VERSION_1_3", *glx_core_spec, sub_output, ver); | |
grep(sub_output, "\"GLX_VERSION", true, output); | |
sub_output.clear(); | |
// | |
make_list(*glx_ext_spec, output, ver); | |
// | |
echo("\n return GLEW_OK;\n}", output); | |
echo("\n#endif /* !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */\n", | |
output); | |
// | |
const auto glew_init_tail = combine(std::list<std::string>({ src, "glew_init_tail.c" })); | |
std::ifstream file_stream(glew_init_tail); | |
if (file_stream.is_open()) | |
{ | |
std::list<std::string> parameters; | |
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g")); | |
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g")); | |
if (!perl(file_stream, parameters, version, output, log)) | |
{ | |
log << "[Warning]: Command 'perl -e " | |
<< join("\nperl -e ", parameters) | |
<< "' was not be applied." << std::endl; | |
result = false; | |
} | |
file_stream.close(); | |
} | |
else | |
{ | |
log << "[Warning]: Unable to open '" << glew_init_tail << "'." << std::endl; | |
result = false; | |
} | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_str_head.c" })), | |
output); | |
// | |
make_str(*gl_core_spec, output); | |
make_str(*gl_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_str_wgl.c" })), | |
output); | |
// | |
make_str(*wgl_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_str_glx.c" })), | |
output); | |
// | |
make_str(*glx_core_spec, output); | |
make_str(*glx_ext_spec, output); | |
// | |
read_from_file( | |
combine(std::list<std::string>({ src, "glew_str_tail.c" })), | |
output); | |
// | |
auto parameter = | |
std::string("s/GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader\\(GLEW_CONTEXT_ARG_VAR_INIT\\);/{ GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); _glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); }/g"); | |
if (!perl(output, parameter)) | |
{ | |
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl; | |
result = false; | |
} | |
parameter = | |
std::string("s/\\(\\(glColorSubTable = /((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)\"glBlendEquation\")) == NULL) || r;\n r = ((glColorSubTable = /g"); | |
if (!perl(output, parameter)) | |
{ | |
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool wglew_h(const std::string& src, | |
const std::list<extension>& wgl_ext_spec, | |
const _version& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "khronos_license.h" })), | |
combine(std::list<std::string>({ src, "wglew_head.h" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
} | |
make_header("WINAPI", "WGL", wgl_ext_spec, output); | |
// | |
auto file_path = combine(std::list<std::string>({ src, "wglew_mid.h" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
if (version == version_1_13_0) | |
{ | |
echo("\n#ifdef GLEW_MX\nstruct WGLEWContextStruct\n{\n#endif /* GLEW_MX */", output); | |
} | |
output.push_back('\n'); | |
make_struct_fun("WGLEW_FUN_EXPORT", "", wgl_ext_spec, output); | |
output.pop_back(); | |
make_struct_var("WGLEW_VAR_EXPORT", "", "WGL", wgl_ext_spec, output); | |
if (version == version_1_13_0) | |
{ | |
echo("\n#ifdef GLEW_MX\n}; /* WGLEWContextStruct */\n#endif /* GLEW_MX */\n", output); | |
} | |
file_path = combine(std::list<std::string>({ src, "wglew_tail.h" })); | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool glxew_h(const std::string& src, | |
const std::list<extension>& glx_core_spec, | |
const std::list<extension>& glx_ext_spec, | |
const _version& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "mesa_license.h" })), | |
combine(std::list<std::string>({ src, "khronos_license.h" })), | |
combine(std::list<std::string>({ src, "glxew_head.h" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
read_from_file(file_path, output); | |
} | |
make_header("", "GLX", glx_core_spec, output); | |
make_header("", "GLX", glx_ext_spec, output); | |
// | |
read_from_file(combine(std::list<std::string>({ src, "glxew_mid.h" })), output); | |
// | |
output.push_back('\n'); | |
make_struct_fun("GLXEW_FUN_EXPORT", "", glx_core_spec, output); | |
make_struct_fun("GLXEW_FUN_EXPORT", "", glx_ext_spec, output); | |
// | |
output.pop_back(); | |
if (version == version_1_13_0) | |
{ | |
echo("\n#if defined(GLEW_MX)\nstruct GLXEWContextStruct\n{\n#endif /* GLEW_MX */\n", output); | |
} | |
make_struct_var("GLXEW_VAR_EXPORT", "", "GLX", glx_core_spec, output); | |
make_struct_var("GLXEW_VAR_EXPORT", "", "GLX", glx_ext_spec, output); | |
if (version == version_1_13_0) | |
{ | |
echo("\n#ifdef GLEW_MX\n}; /* GLXEWContextStruct */\n#endif /* GLEW_MX */\n", output); | |
} | |
static const auto parameter = | |
std::string("s/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_0;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_1;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/"); | |
if (!perl(output, parameter)) | |
{ | |
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl; | |
result = false; | |
} | |
read_from_file(combine(std::list<std::string>({ src, "glxew_tail.h" })), output); | |
// | |
return result; | |
} | |
bool eglew_h(const std::string& src, | |
const std::list<extension>& egl_core_spec, | |
const std::list<extension>& egl_ext_spec, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "mesa_license.h" })), | |
combine(std::list<std::string>({ src, "khronos_license.h" })), | |
combine(std::list<std::string>({ src, "eglew_head.h" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
if (!read_from_file(file_path, output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
result = false; | |
} | |
} | |
make_header("", "EGL", egl_core_spec, output); | |
make_header("", "EGL", egl_ext_spec, output); | |
if (!read_from_file(combine(std::list<std::string>({ src, "eglew_mid.h" })), output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << combine(std::list<std::string>({ src, "eglew_mid.h" })); | |
log << "'." << std::endl; | |
result = false; | |
} | |
// | |
output.push_back('\n'); | |
make_struct_fun("EGLEW_FUN_EXPORT", "", egl_core_spec, output); | |
make_struct_fun("EGLEW_FUN_EXPORT", "", egl_ext_spec, output); | |
// | |
output.pop_back(); | |
make_struct_var("EGLEW_VAR_EXPORT", "", "EGL", egl_core_spec, output); | |
make_struct_var("EGLEW_VAR_EXPORT", "", "EGL", egl_ext_spec, output); | |
if (!read_from_file(combine(std::list<std::string>({ src, "eglew_tail.h" })), output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << combine(std::list<std::string>({ src, "eglew_tail.h" })); | |
log << "'." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool glewinfo_c(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const _version& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
const std::list<std::string> start_content_files( | |
{ | |
combine(std::list<std::string>({ src, "glew_license.h" })), | |
combine(std::list<std::string>({ src, "glewinfo_head.c" })) | |
}); | |
for (const auto& file_path : start_content_files) | |
{ | |
read_from_file(file_path, output); | |
} | |
if (extensions.empty()) | |
{ | |
log << "[Error]: no extensions passed. Generation of content halted." << std::endl; | |
return false; | |
} | |
const auto gl_core_spec = extensions.cbegin(); | |
make_info(*gl_core_spec, output); | |
// | |
const auto gl_ext_spec = get_next_extensions(gl_core_spec, extensions, "GL_EXT_SPEC", log); | |
if (gl_core_spec == gl_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_info(*gl_ext_spec, output); | |
// | |
auto egl_core_spec = extensions.crbegin(); | |
std::advance(egl_core_spec, 1); | |
const auto egl_ext_spec = extensions.crbegin(); | |
if (version_2_2_2 == version) | |
{ | |
echo("#if defined(GLEW_EGL)\n", output); | |
// | |
make_info(*egl_core_spec, output); | |
make_info(*egl_ext_spec, output); | |
// | |
echo("#elif _WIN32\n", output); | |
} | |
else if (version_1_13_0 == version) | |
{ | |
echo("#ifdef _WIN32\n", output); | |
} | |
const auto wgl_ext_spec = get_next_extensions(gl_ext_spec, extensions, "WGL_EXT_SPEC", log); | |
if (gl_ext_spec == wgl_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_info(*wgl_ext_spec, output); | |
echo("#else /* _UNIX */\n", output); | |
// | |
const auto glx_core_spec = get_next_extensions(wgl_ext_spec, extensions, "GLX_CORE_SPEC", log); | |
if (wgl_ext_spec == glx_core_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_info(*glx_core_spec, output); | |
// | |
const auto glx_ext_spec = get_next_extensions(glx_core_spec, extensions, "GLX_EXT_SPEC", log); | |
if (glx_core_spec == glx_ext_spec) | |
{ | |
log << "[Error]: generation of content halted." << std::endl; | |
return false; | |
} | |
make_info(*glx_ext_spec, output); | |
echo("#endif /* _WIN32 */\n", output); | |
// | |
read_from_file(combine(std::list<std::string>({ src, "glewinfo_gl.c" })), output); | |
// | |
make_info_list(*gl_core_spec, output); | |
make_info_list(*gl_ext_spec, output); | |
// | |
read_from_file(combine(std::list<std::string>({ src, "glewinfo_wgl.c" })), output); | |
// | |
make_info_list(*wgl_ext_spec, output); | |
// | |
read_from_file(combine(std::list<std::string>({ src, "glewinfo_glx.c" })), output); | |
// | |
make_info_list(*glx_core_spec, output); | |
make_info_list(*glx_ext_spec, output); | |
if (version_2_2_2 == version) | |
{ | |
read_from_file(combine(std::list<std::string>({ src, "glewinfo_egl.c" })), output); | |
// | |
make_info_list(*egl_core_spec, output); | |
make_info_list(*egl_ext_spec, output); | |
} | |
read_from_file(combine(std::list<std::string>({ src, "glewinfo_tail.c" })), output); | |
// | |
static const auto parameter = | |
std::string("s/\"glColorSubTable\"/\"glBlendEquation\", glBlendEquation == NULL);\n glewInfoFunc(\"glColorSubTable\"/g"); | |
if (!perl(output, parameter)) | |
{ | |
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl; | |
result = false; | |
} | |
return result; | |
} | |
bool rc(const std::string& src, | |
const std::string& dst, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
auto result = true; | |
// | |
std::list<std::string> parameters; | |
parameters.push_back("s/GLEW_MAJOR/$(GLEW_MAJOR)/g"); | |
parameters.push_back("s/GLEW_MINOR/$(GLEW_MINOR)/g"); | |
parameters.push_back("s/GLEW_MICRO/$(GLEW_MICRO)/g"); | |
// | |
std::list<std::string> file_list; | |
get_files_by_pattern(combine(std::list<std::string>({ src, "*.rc" })), file_list); | |
#ifndef _WIN32 | |
file_list.remove_if( | |
[](const std::string & file_parth) | |
{ | |
return !ends_with(file_parth, ".rc"); | |
}); | |
#endif | |
for (const auto& file_path : file_list) | |
{ | |
std::ifstream file_stream(file_path); | |
if (file_stream.is_open()) | |
{ | |
tmp_output.clear(); | |
if (!perl(file_stream, parameters, version, tmp_output, log)) | |
{ | |
log << "[Warning]: Command 'perl -e " | |
<< join("\nperl -e ", parameters) | |
<< "' was not be applied to file '" << file_path << "'." << std::endl; | |
result = false; | |
} | |
file_stream.close(); | |
const auto file_dst = combine(std::list<std::string>({ dst, get_file_name(file_path) })); | |
if (!write_to_file(file_dst, tmp_output)) | |
{ | |
log << "[Warning]: Unable write to file '" << file_dst << "'." << std::endl; | |
result = false; | |
} | |
} | |
else | |
{ | |
log << "[Warning]: Unable to open '" << file_path << "'." << std::endl; | |
result = false; | |
} | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _GENERATOR_H_ | |
#define _GENERATOR_H_ | |
#include <list> | |
#include <string> | |
#include <utility> | |
#include <ostream> | |
struct extension; | |
struct _version; | |
bool glew_h(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log); | |
bool glew_c(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log); | |
bool wglew_h(const std::string& src, | |
const std::list<extension>& wgl_ext_spec, | |
const _version& version, | |
std::string& output, | |
std::ostream& log); | |
bool glxew_h(const std::string& src, | |
const std::list<extension>& glx_core_spec, | |
const std::list<extension>& glx_ext_spec, | |
const _version& version, | |
std::string& output, | |
std::ostream& log); | |
bool eglew_h(const std::string& src, | |
const std::list<extension>& egl_core_spec, | |
const std::list<extension>& egl_ext_spec, | |
std::string& output, | |
std::ostream& log); | |
bool glewinfo_c(const std::string& src, | |
const std::list<std::list<extension>>& extensions, | |
const _version& version, | |
std::string& output, | |
std::ostream& log); | |
bool rc(const std::string& src, | |
const std::string& dst, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& tmp_output, | |
std::ostream& log); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<Project InitialTargets="OpenGL-Registry" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
<PropertyGroup Condition="'$(Configuration)'==''"> | |
<Configuration>Release</Configuration> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(Platform)'==''"> | |
<Platform>Win32</Platform> | |
</PropertyGroup> | |
<ItemGroup Label="ProjectConfigurations"> | |
<ProjectConfiguration Include="Release|Win32"> | |
<Configuration>Release</Configuration> | |
<Platform>Win32</Platform> | |
</ProjectConfiguration> | |
<ProjectConfiguration Include="Release|x64"> | |
<Configuration>Release</Configuration> | |
<Platform>x64</Platform> | |
</ProjectConfiguration> | |
</ItemGroup> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | |
<ConfigurationType>Application</ConfigurationType> | |
<UseDebugLibraries>false</UseDebugLibraries> | |
<!--PlatformToolset>v120</PlatformToolset--> | |
</PropertyGroup> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |
<ItemGroup> | |
<ClInclude Include="$(ProjectDir)blacklist.h" /> | |
<ClInclude Include="$(ProjectDir)common.h" /> | |
<ClInclude Include="$(ProjectDir)descriptor.h" /> | |
<ClInclude Include="$(ProjectDir)descriptors.h" /> | |
<ClInclude Include="$(ProjectDir)filler.h" /> | |
<ClInclude Include="$(ProjectDir)generator.h" /> | |
<ClInclude Include="$(ProjectDir)interpreter.h" /> | |
<ClInclude Include="$(ProjectDir)parse_xml.h" /> | |
<ClInclude Include="$(ProjectDir)procedure.h" /> | |
<ClInclude Include="$(ProjectDir)version.h" /> | |
</ItemGroup> | |
<ItemGroup> | |
<ClCompile Include="$(ProjectDir)blacklist.cpp" /> | |
<ClCompile Include="$(ProjectDir)common.cpp" /> | |
<ClCompile Include="$(ProjectDir)descriptor.cpp" /> | |
<ClCompile Include="$(ProjectDir)descriptors.cpp" /> | |
<ClCompile Include="$(ProjectDir)filler.cpp" /> | |
<ClCompile Include="$(ProjectDir)generator.cpp" /> | |
<ClCompile Include="$(ProjectDir)interpreter.cpp" /> | |
<ClCompile Include="$(ProjectDir)main.cpp" /> | |
<ClCompile Include="$(ProjectDir)parse_xml.cpp" /> | |
<ClCompile Include="$(ProjectDir)procedure.cpp" /> | |
<ClCompile Include="$(ProjectDir)version.cpp" /> | |
</ItemGroup> | |
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | |
<ClCompile> | |
<WarningLevel>Level4</WarningLevel> | |
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
</ClCompile> | |
<Link> | |
<SubSystem>Console</SubSystem> | |
</Link> | |
</ItemDefinitionGroup> | |
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |
<ClCompile> | |
<WarningLevel>Level4</WarningLevel> | |
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |
</ClCompile> | |
<Link> | |
<SubSystem>Console</SubSystem> | |
</Link> | |
</ItemDefinitionGroup> | |
<PropertyGroup Label="glew_repository"> | |
<glew_url Condition="'$(LOCAL_FOLDER)'==''">https://github.com/nigels-com/glew.git</glew_url> | |
<glew_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glew</glew_url> | |
<glew_destination>$(ProjectDir)..\glew</glew_destination> | |
<glew_destination Condition="''!='$(NO_GIT)'">$(glew_url)</glew_destination> | |
<glew_hash>7f65a36866f4e24dd1446fe1c9d21424f28bcabd</glew_hash> | |
</PropertyGroup> | |
<PropertyGroup Label="OpenGL-Registry_repository"> | |
<url_1 Condition="'$(LOCAL_FOLDER)'==''">https://github.com/KhronosGroup/OpenGL-Registry.git</url_1> | |
<url_1 Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\OpenGL-Registry</url_1> | |
<destination_1>$(ProjectDir)..\OpenGL-Registry</destination_1> | |
<destination_1 Condition="''!='$(NO_GIT)'">$(url_1)</destination_1> | |
<hash_1>39e37f83823d5d04dd727ab1c146158a9888adb7</hash_1> | |
</PropertyGroup> | |
<PropertyGroup Label="EGL-Registry_repository"> | |
<url_2 Condition="'$(LOCAL_FOLDER)'==''">https://github.com/KhronosGroup/EGL-Registry.git</url_2> | |
<url_2 Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\EGL-Registry</url_2> | |
<destination_2>$(ProjectDir)..\EGL-Registry</destination_2> | |
<destination_2 Condition="''!='$(NO_GIT)'">$(url_2)</destination_2> | |
<hash_2>9ed2ec4c6746e622207f48c898a92fda8b122da5</hash_2> | |
</PropertyGroup> | |
<PropertyGroup Label="glfixes_repository"> | |
<glfixes_url Condition="'$(LOCAL_FOLDER)'==''">https://github.com/nigels-com/glfixes</glfixes_url> | |
<glfixes_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glfixes</glfixes_url> | |
<glfixes_destination>$(ProjectDir)..\glfixes</glfixes_destination> | |
<glfixes_destination Condition="''!='$(NO_GIT)'">$(glfixes_url)</glfixes_destination> | |
<glfixes_hash>970b8145acd42ebd86ff025e1eb8c8cbcd1fc6a2</glfixes_hash> | |
</PropertyGroup> | |
<PropertyGroup> | |
<Index Condition="''!='$(MSBuildThisFileDirectory)'">$(MSBuildThisFileDirectory.LastIndexOf('\'))</Index> | |
<ParentDirectory Condition="-1!=$(Index)">$(MSBuildThisFileDirectory.Substring(0, $(Index)))</ParentDirectory> | |
<Index Condition="''!='$(ParentDirectory)'">$(ParentDirectory.LastIndexOf('\'))</Index> | |
<ParentDirectory Condition="-1!=$(Index)">$(ParentDirectory.Substring(0, $(Index)))</ParentDirectory> | |
</PropertyGroup> | |
<PropertyGroup Condition="$(ParentDirectory.EndsWith('auto'))"> | |
<Index Condition="''!='$(ParentDirectory)'">$(ParentDirectory.LastIndexOf('\'))</Index> | |
<ParentDirectory Condition="-1!=$(Index)">$(ParentDirectory.Substring(0, $(Index)))</ParentDirectory> | |
<glew_destination>$(ParentDirectory)</glew_destination> | |
</PropertyGroup> | |
<PropertyGroup Label="Destination_folder"> | |
<DestinationFolder>$(ProjectDir)</DestinationFolder> | |
<DestinationFolder Condition="Exists('$(ProjectDir)..\..\auto')">$([System.IO.Path]::GetFullPath('$(ProjectDir)..\..\'))</DestinationFolder> | |
</PropertyGroup> | |
<Target Name="OpenGL-Registry" Condition="''=='$(NO_GIT)'"> | |
<Message Importance="normal" Text="--------------------------------------------------------------------" /> | |
<Message Importance="normal" Text="Downloading OpenGL-Registry" /> | |
<Message Importance="normal" Text="--------------------------------------------------------------------" /> | |
<Message Importance="low" Text="git clone $(glew_url) $(glew_destination)" /> | |
<Message Importance="low" Text="git clone $(url_1) $(destination_1)" /> | |
<Message Importance="low" Text="git clone $(url_2) $(destination_2)" /> | |
<Message Importance="low" Text="git clone --branch glew $(glfixes_url) $(glfixes_destination)" /> | |
<Exec | |
Command="git --version" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="!$(ParentDirectory.EndsWith('auto')) And !Exists('$(glew_destination)\.git\HEAD')" | |
Command="git clone $(glew_url) $(glew_destination)" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="!Exists('$(destination_1)\.git\HEAD')" | |
Command="git clone $(url_1) $(destination_1)" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="!Exists('$(destination_2)\.git\HEAD')" | |
Command="git clone $(url_2) $(destination_2)" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="!Exists('$(glfixes_destination)\.git\HEAD')" | |
Command="git clone $(glfixes_url) $(glfixes_destination)" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="$(ParentDirectory.EndsWith('auto')) And Exists('$(glew_destination)\.git\HEAD')" | |
Command="git log -1 --pretty=oneline" | |
WorkingDirectory="$(glew_destination)" /> | |
<Exec | |
Condition="Exists('$(destination_1)\.git\HEAD')" | |
Command="git log -1 --pretty=oneline" | |
WorkingDirectory="$(destination_1)" /> | |
<Exec | |
Condition="Exists('$(destination_2)\.git\HEAD')" | |
Command="git log -1 --pretty=oneline" | |
WorkingDirectory="$(destination_2)" /> | |
<Exec | |
Condition="Exists('$(glfixes_destination)\.git\HEAD')" | |
Command="git log -1 --pretty=oneline" | |
WorkingDirectory="$(glfixes_destination)" /> | |
</Target> | |
<Target Name="AfterBuild" Condition="Exists('$(TargetPath)')"> | |
<Message Importance="normal" Text="Executing '$(TargetPath) $(glew_destination) $(glfixes_destination) $(destination_1) $(destination_2) $(DestinationFolder)' at '$(OutDir)'" /> | |
<Exec | |
Command="$(TargetPath) $(glew_destination) $(glfixes_destination) $(destination_1) $(destination_2) $(DestinationFolder)" | |
WorkingDirectory="$(OutDir)" /> | |
</Target> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "input_output.h" | |
#include <cstring> | |
#include <utility> | |
#include <ostream> | |
#include <sstream> | |
#include <istream> | |
#include <fstream> | |
#include <iostream> | |
#include <iterator> | |
#include <algorithm> | |
void read_from_stream(std::istream& stream, std::string& content) | |
{ | |
std::copy(std::istreambuf_iterator<char>(stream), | |
std::istreambuf_iterator<char>(), std::back_inserter(content)); | |
} | |
bool write_to_stream(std::ostream& stream, const std::string& content) | |
{ | |
return !std::copy(content.cbegin(), content.cend(), | |
std::ostreambuf_iterator<char>(stream)).failed(); | |
} | |
void read_from_cin(std::string& content) | |
{ | |
read_from_stream(std::cin, content); | |
} | |
bool write_to_cout(const std::string& content) | |
{ | |
return write_to_stream(std::cout, content); | |
} | |
#if 0 | |
void read_from_file(const std::string& file_name, std::stringstream& content) | |
{ | |
std::ifstream file_stream(file_name); | |
if (file_stream.is_open()) | |
{ | |
content << file_stream.rdbuf(); | |
} | |
} | |
bool write_to_file(const std::string& file_name, const std::stringstream& content) | |
{ | |
std::ofstream file_stream(file_name); | |
if (file_stream.is_open()) | |
{ | |
file_stream << content.str(); | |
return true; | |
/* | |
const auto str = content.str(); | |
return !std::copy(str.cbegin(), str.cend(), | |
std::ostreambuf_iterator<char>(file_stream)).failed();*/ | |
} | |
return false; | |
} | |
#endif | |
bool read_from_file(const std::string& file_name, std::string& content) | |
{ | |
std::ifstream file_stream(file_name); | |
if (file_stream.is_open()) | |
{ | |
read_from_stream(file_stream, content); | |
file_stream.close(); | |
return true; | |
} | |
return false; | |
} | |
bool write_to_file(const std::string& file_name, const std::string& content) | |
{ | |
std::ofstream file_stream(file_name); | |
if (file_stream.is_open()) | |
{ | |
return write_to_stream(file_stream, content); | |
} | |
return false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include <string> | |
#ifndef _INPUT_OUTPUT_H_ | |
#define _INPUT_OUTPUT_H_ | |
void read_from_cin(std::string& content); | |
bool write_to_cout(const std::string& content); | |
bool read_from_file(const std::string& file_name, std::string& content); | |
bool write_to_file(const std::string& file_name, const std::string& content); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "interpreter.h" | |
#include "input_output.h" | |
#include "path.h" | |
#include "common.h" | |
#include <set> | |
#include <regex> | |
#include <cctype> | |
#include <cassert> | |
#include <cstdlib> | |
#include <iterator> | |
#include <algorithm> | |
std::regex create_regex(const std::string& str_pattern, bool& is_created) //TODO: add std::ostream& log | |
{ | |
is_created = false; | |
try | |
{ | |
const auto pattern = std::regex(str_pattern); | |
is_created = true; | |
return pattern; | |
} | |
catch (const std::regex_error& exc) | |
{ | |
write_to_cout( | |
std::string("[Error]: std::regex_error caught '") + exc.what() + "' for expression '" + str_pattern + "'.\n"); | |
switch (exc.code()) | |
{ | |
case std::regex_constants::error_collate: | |
write_to_cout(std::string("\tThe expression contains an invalid collating element name.\n")); | |
break; | |
case std::regex_constants::error_ctype: | |
write_to_cout(std::string("\tThe expression contains an invalid character class name.\n")); | |
break; | |
case std::regex_constants::error_escape: | |
write_to_cout(std::string("\tThe expression contains an invalid escaped character or a trailing escape.\n")); | |
break; | |
case std::regex_constants::error_backref: | |
write_to_cout(std::string("\tThe expression contains an invalid back reference.\n")); | |
break; | |
case std::regex_constants::error_brack: | |
write_to_cout(std::string("\tThe expression contains mismatched square brackets ('[' and ']').\n")); | |
break; | |
case std::regex_constants::error_paren: | |
write_to_cout(std::string("\tThe expression contains mismatched parentheses ('(' and ')').\n")); | |
break; | |
case std::regex_constants::error_brace: | |
write_to_cout(std::string("\tThe expression contains mismatched curly braces ('{' and '}').\n")); | |
break; | |
case std::regex_constants::error_badbrace: | |
write_to_cout(std::string("\tThe expression contains an invalid range in a {} expression.\n")); | |
break; | |
case std::regex_constants::error_range: | |
write_to_cout(std::string("\tThe expression contains an invalid character range (e.g. [b-a]).\n")); | |
break; | |
case std::regex_constants::error_space: | |
write_to_cout( | |
std::string("\tThere was not enough memory to convert the expression into a finite state machine.\n")); | |
break; | |
case std::regex_constants::error_badrepeat: | |
write_to_cout(std::string("\tOne of *?+{ was not preceded by a valid regular expression.\n")); | |
break; | |
case std::regex_constants::error_complexity: | |
write_to_cout(std::string("\tThe complexity of an attempted match exceeded a predefined level.\n")); | |
break; | |
case std::regex_constants::error_stack: | |
write_to_cout(std::string("\tThere was not enough memory to perform a match.\n")); | |
break; | |
default: | |
//std::regex_constants::error_parse: | |
//std::regex_constants::error_syntax: | |
break; | |
} | |
} | |
return std::regex(); | |
} | |
std::string get_name_of_output( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& command, bool& create_new_content) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
auto pos = find_phrase_start(command, ">>"); | |
if (std::get<1>(command) == pos) | |
{ | |
pos = std::find_if(std::get<0>(command), std::get<1>(command), | |
[](const char& ch) | |
{ | |
return '>' == ch; | |
}); | |
if (std::get<1>(command) == pos) | |
{ | |
return std::string(); | |
} | |
create_new_content = true; | |
std::advance(pos, 1); | |
} | |
else | |
{ | |
create_new_content = false; | |
std::advance(pos, 2); | |
} | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, true); | |
if (std::get<1>(command) == pos) | |
{ | |
return std::string(); | |
} | |
std::advance(pos, 1); | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, false); | |
if (std::get<1>(command) == pos) | |
{ | |
return std::string(); | |
} | |
const auto value_start = pos; | |
std::advance(pos, 1); | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, true); | |
if (std::get<1>(command) == pos) | |
{ | |
return std::string(value_start, std::get<1>(command)); | |
} | |
std::advance(pos, 1); | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, false); | |
if (std::get<1>(command) == pos) | |
{ | |
auto tmp = std::string(pos, std::get<1>(command)); | |
trim(tmp); | |
return tmp; | |
} | |
return std::string(); | |
} | |
std::string get_name_of_output(const std::string& command, bool& create_new_content) | |
{ | |
return get_name_of_output(std::make_pair(command.cbegin(), command.cend()), create_new_content); | |
} | |
bool echo(const std::string& text, std::ostream& output) | |
{ | |
output << text << std::endl; | |
return true; | |
} | |
bool echo(const std::string& text, std::string& output) | |
{ | |
output += text + '\n'; | |
return true; | |
} | |
bool grep(std::istream& input, const std::string& target, bool should_be_contains, std::ostream& output) | |
{ | |
auto was_command_be_apply = false; | |
for (std::string line; std::getline(input, line);) | |
{ | |
if (should_be_contains == contains(line, target)) | |
{ | |
continue; | |
} | |
output << line << std::endl; | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool grep(const std::string& input, const std::string& target, bool should_be_contains, std::string& output) | |
{ | |
auto was_command_be_apply = false; | |
auto value_pair = std::make_pair(input.cbegin(), input.cend()); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
if (should_be_contains == contains(line, target)) | |
{ | |
continue; | |
} | |
std::copy(std::get<0>(line), | |
std::get<1>(line), | |
std::back_inserter(output)); | |
output.push_back('\n'); | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool grep(std::istream& source, std::istream& target, std::ostream& output) | |
{ | |
auto was_command_be_apply = false; | |
std::set<std::string> source_lines; | |
for (std::string source_line; std::getline(source, source_line);) | |
{ | |
source_lines.insert(source_line); | |
} | |
for (std::string taget_line; std::getline(target, taget_line);) | |
{ | |
if (0 != source_lines.count(taget_line)) | |
{ | |
continue; | |
} | |
output << taget_line << std::endl; | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool grep(const std::string& source, const std::string& target, std::string& output) | |
{ | |
auto was_command_be_apply = false; | |
auto value_pair = make_pair(source.cbegin(), source.cend()); | |
std::list<std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>> | |
source_lines; | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
const auto line_size = static_cast<std::size_t>(std::distance(std::get<0>(line), std::get<1>(line))); | |
// | |
const auto exists_line = std::find_if(source_lines.cbegin(), source_lines.cend(), | |
[&line, &line_size](const | |
std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>& source_line) | |
{ | |
return line_size == std::get<0>(source_line) && contains(line, std::get<1>(source_line)); | |
}); | |
if (source_lines.cend() == exists_line) | |
{ | |
source_lines.push_back(std::make_pair(line_size, line)); | |
} | |
} | |
value_pair = make_pair(target.cbegin(), target.cend()); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
const auto line_size = static_cast<std::size_t>(std::distance(std::get<0>(line), std::get<1>(line))); | |
// | |
const auto exists_line = std::find_if(source_lines.cbegin(), source_lines.cend(), | |
[&line, &line_size](const | |
std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>& source_line) | |
{ | |
return line_size == std::get<0>(source_line) && contains(line, std::get<1>(source_line)); | |
}); | |
if (source_lines.cend() != exists_line) | |
{ | |
continue; | |
} | |
std::copy(std::get<0>(line), | |
std::get<1>(line), | |
std::back_inserter(output)); | |
output.push_back('\n'); | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool egrep(std::istream& input, const std::string& pattern_target, std::ostream& output) | |
{ | |
auto was_command_be_apply = false; | |
const auto pattern = create_regex(pattern_target, was_command_be_apply); | |
if (!was_command_be_apply) | |
{ | |
return was_command_be_apply; | |
} | |
was_command_be_apply = false; | |
for (std::string line; std::getline(input, line);) | |
{ | |
if (std::regex_search(line, pattern)) | |
{ | |
continue; | |
} | |
output << line << std::endl; | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool egrep(const std::string& input, const std::string& pattern_target, std::string& output) | |
{ | |
auto was_command_be_apply = false; | |
const auto pattern = create_regex(pattern_target, was_command_be_apply); | |
if (!was_command_be_apply) | |
{ | |
return was_command_be_apply; | |
} | |
was_command_be_apply = false; | |
auto value_pair = std::make_pair(input.cbegin(), input.cend()); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
if (std::regex_search(std::string(std::get<0>(line), std::get<1>(line)), pattern)) | |
{ | |
continue; | |
} | |
std::copy(std::get<0>(line), | |
std::get<1>(line), | |
std::back_inserter(output)); | |
output.push_back('\n'); | |
was_command_be_apply = true; | |
} | |
return was_command_be_apply; | |
} | |
bool cat(std::istream& input, const std::string& text, std::ostream& output) | |
{ | |
const auto copy_ok = !std::copy(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>(), | |
std::ostreambuf_iterator<char>(output)).failed(); | |
if (copy_ok && !text.empty()) | |
{ | |
output << text; | |
} | |
return copy_ok; | |
} | |
bool cat(const std::string& input, std::string& output) | |
{ | |
std::copy( | |
input.cbegin(), | |
input.cend(), | |
std::back_inserter(output)); | |
return !input.empty() && !output.empty(); | |
} | |
bool head(std::istream& input, const std::string& command, std::ostream& output) | |
{ | |
static const auto key_n = std::string("-n"); | |
auto command_start = find_phrase_start(command, key_n); | |
if (command_start != command.cend()) | |
{ | |
std::advance(command_start, key_n.size()); | |
// | |
command_start = std::find_if(command_start, command.cend(), [](const char& ch) | |
{ | |
return std::isdigit(ch); | |
}); | |
if (command_start != command.cend()) | |
{ | |
char* ch = nullptr; | |
const auto count = std::strtol(&(*command_start), &ch, 10); | |
if (ch != &(*command_start)) | |
{ | |
auto i = static_cast<long>(0); | |
for (std::string line; std::getline(input, line) && i < count; ++i) | |
{ | |
output << line << std::endl; | |
} | |
return (0 != count); | |
} | |
} | |
} | |
return false; | |
} | |
bool head(const std::string& input, const std::string& command, std::string& output) | |
{ | |
auto n = static_cast<long>(0); | |
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i) | |
{ | |
if (!std::isdigit(command[i])) | |
{ | |
continue; | |
} | |
char* ch = nullptr; | |
n = std::strtol(&command[i], &ch, 10); | |
if (ch != &command[i]) | |
{ | |
break; | |
} | |
} | |
auto step = static_cast<long>(0); | |
auto value_pair = std::make_pair(input.cbegin(), input.cend()); | |
while ((std::get<1>(value_pair) != std::get<0>(value_pair)) && step < n) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
std::copy(std::get<0>(line), | |
std::get<1>(line), | |
std::back_inserter(output)); | |
output.push_back('\n'); | |
++step; | |
} | |
return (0 != n); | |
} | |
bool tail(std::istream& input, const std::string& command, std::ostream& output) | |
{ | |
auto was_command_be_apply = false; | |
auto n = static_cast<long>(0); | |
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i) | |
{ | |
if (!std::isdigit(command[i])) | |
{ | |
continue; | |
} | |
char* ch = nullptr; | |
n = std::strtol(&command[i], &ch, 10); | |
if (ch != &command[i]) | |
{ | |
break; | |
} | |
} | |
auto line_num = static_cast<long>(1); | |
for (std::string line; std::getline(input, line);) | |
{ | |
if (was_command_be_apply || n == line_num || 0 == n) | |
{ | |
was_command_be_apply = true; | |
output << line << std::endl; | |
} | |
else | |
{ | |
++line_num; | |
} | |
} | |
return was_command_be_apply; | |
} | |
bool tail(const std::string& input, const std::string& command, std::string& output) | |
{ | |
auto was_command_be_apply = false; | |
auto n = static_cast<long>(0); | |
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i) | |
{ | |
if (!std::isdigit(command[i])) | |
{ | |
continue; | |
} | |
char* ch = nullptr; | |
n = std::strtol(&command[i], &ch, 10); | |
if (ch != &command[i]) | |
{ | |
break; | |
} | |
} | |
auto line_num = static_cast<long>(1); | |
auto value_pair = std::make_pair(input.cbegin(), input.cend()); | |
while ((std::get<1>(value_pair) != std::get<0>(value_pair))) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
if (was_command_be_apply || n == line_num || 0 == n) | |
{ | |
was_command_be_apply = true; | |
std::copy(std::get<0>(line), | |
std::get<1>(line), | |
std::back_inserter(output)); | |
output.push_back('\n'); | |
} | |
else | |
{ | |
++line_num; | |
} | |
} | |
return was_command_be_apply; | |
} | |
std::pair<std::string, std::string> disassemble_perl_parameter( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& parameter) | |
{ | |
const auto parameter_size = static_cast<std::size_t>(std::distance(std::get<0>(parameter), | |
std::get<1>(parameter))); | |
auto result = std::make_pair(std::string(parameter_size, '\0'), std::string(parameter_size, '\0')); | |
std::get<0>(result).clear(); | |
std::get<1>(result).clear(); | |
if (parameter_size < 2 || 's' != *std::get<0>(parameter)) | |
{ | |
return result; | |
} | |
auto split_position = std::get<0>(parameter); | |
std::advance(split_position, 1); | |
const auto split_symbol = std::string(1, *split_position); | |
auto value_pair = std::make_pair(find_phrase_start(parameter, split_symbol), std::get<1>(parameter)); | |
auto current = &(std::get<0>(result)); | |
for (auto i = 0; i < 2; ++i) | |
{ | |
std::advance(std::get<0>(value_pair), 1); | |
auto value_start = std::get<0>(value_pair); | |
std::get<0>(value_pair) = find_phrase_start(value_pair, split_symbol); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return result; | |
} | |
auto prev_symbol = std::get<0>(value_pair); | |
std::advance(prev_symbol, -1); | |
if ('\\' == (*prev_symbol)) | |
{ | |
--i; | |
(*current) += std::string(value_start, std::get<0>(value_pair)) + split_symbol; | |
continue; | |
} | |
(*current) += std::string(value_start, std::get<0>(value_pair)); | |
current = &(std::get<1>(result)); | |
} | |
replace(std::get<0>(result), std::string("\\") + split_symbol, split_symbol); | |
replace(std::get<1>(result), std::string("\\") + split_symbol, split_symbol); | |
// | |
return result; | |
} | |
std::pair<std::string, std::string> disassemble_perl_parameter(const std::string& parameter) | |
{ | |
return disassemble_perl_parameter(std::make_pair(parameter.cbegin(), parameter.cend())); | |
} | |
bool perl(std::istream& input, const std::string& command, std::ostream& output) | |
{ | |
static const auto key_s = std::string("'s"); | |
static const auto key_s_ = std::string("\"s"); | |
assert(key_s.size() == key_s_.size()); | |
auto was_command_be_apply = false; | |
auto command_start = find_phrase_start(command, key_s); | |
if (command_start == command.cend()) | |
{ | |
command_start = find_phrase_start(command, key_s_); | |
} | |
if (command_start != command.cend()) | |
{ | |
std::advance(command_start, 1); | |
const auto parameter_elements = disassemble_perl_parameter(std::make_pair(command_start, command.cend())); | |
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply); | |
if (!was_command_be_apply) | |
{ | |
return was_command_be_apply; | |
} | |
was_command_be_apply = false; | |
for (std::string line, old_line; std::getline(input, line);) | |
{ | |
if (!was_command_be_apply) | |
{ | |
old_line = line; | |
} | |
line = std::regex_replace(line, pattern, std::get<1>(parameter_elements)); | |
if (!was_command_be_apply) | |
{ | |
if (old_line != line) | |
{ | |
was_command_be_apply = true; | |
old_line.clear(); | |
} | |
} | |
output << line << std::endl; | |
} | |
} | |
return was_command_be_apply; | |
} | |
bool perl(const std::string& input, const std::string& parameter, std::string& output) | |
{ | |
auto was_command_be_apply = false; | |
const auto parameter_elements = disassemble_perl_parameter(parameter); | |
if (std::get<0>(parameter_elements).empty()) | |
{ | |
return was_command_be_apply; | |
} | |
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply); | |
if (!was_command_be_apply) | |
{ | |
return was_command_be_apply; | |
} | |
was_command_be_apply = false; | |
auto value_pair = std::make_pair(input.cbegin(), input.cend()); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
const auto line = get_line(value_pair, std::get<0>(value_pair)); | |
const auto new_line = std::regex_replace( | |
std::string(std::get<0>(line), std::get<1>(line)), | |
pattern, std::get<1>(parameter_elements)); | |
if (!was_command_be_apply) | |
{ | |
if (std::string(std::get<0>(line), std::get<1>(line)) != new_line) | |
{ | |
was_command_be_apply = true; | |
} | |
} | |
output += new_line; | |
output.push_back('\n'); | |
} | |
return was_command_be_apply; | |
} | |
bool perl(std::string& content, const std::string& parameter) | |
{ | |
auto was_command_be_apply = false; | |
const auto parameter_elements = disassemble_perl_parameter(parameter); | |
if (std::get<0>(parameter_elements).empty()) | |
{ | |
return was_command_be_apply; | |
} | |
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply); | |
if (!was_command_be_apply) | |
{ | |
return was_command_be_apply; | |
} | |
was_command_be_apply = false; | |
auto content_position = content.cbegin(); | |
std::sregex_iterator pos(content_position, content.cend(), pattern); | |
std::sregex_iterator end; | |
for (; pos != end;) | |
{ | |
was_command_be_apply = true; | |
const auto absolute_position = std::distance(content.cbegin(), content_position) + pos->position(); | |
const auto distance = absolute_position + std::get<1>(parameter_elements).size(); | |
if (static_cast<std::size_t>(pos->length()) < std::get<1>(parameter_elements).size()) | |
{ | |
const auto delta = std::get<1>(parameter_elements).size() - pos->length(); | |
const auto count = content.size() + delta; | |
content.resize(count); | |
// | |
std::copy(content.cbegin() + absolute_position + pos->length(), | |
content.cbegin() + count - delta, | |
content.begin() + absolute_position + std::get<1>(parameter_elements).size()); | |
// | |
std::copy(std::get<1>(parameter_elements).cbegin(), | |
std::get<1>(parameter_elements).cend(), | |
content.begin() + absolute_position); | |
} | |
else | |
{ | |
std::copy(std::get<1>(parameter_elements).cbegin(), | |
std::get<1>(parameter_elements).cend(), | |
content.begin() + absolute_position); | |
if (std::get<1>(parameter_elements).size() < static_cast<std::size_t>(pos->length())) | |
{ | |
const auto delta = pos->length() - std::get<1>(parameter_elements).size(); | |
const auto count = content.size() - delta; | |
for (auto i = distance; i < count; ++i) | |
{ | |
content[i] = content[i + delta]; | |
} | |
content.resize(count); | |
} | |
} | |
content_position = content.cbegin(); | |
std::advance(content_position, distance); | |
pos = std::sregex_iterator(content_position, content.cend(), pattern); | |
} | |
return was_command_be_apply; | |
} | |
#define process_target(value_pair, value_start, quote, tab_space) \ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
\ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
\ | |
if (0 != quote.count(*std::get<0>(value_pair))) \ | |
{ \ | |
const auto key_symbol = std::string(1, *std::get<0>(value_pair)); \ | |
std::advance(std::get<0>(value_pair), 1); \ | |
value_start = std::get<0>(value_pair); \ | |
std::get<0>(value_pair) = find_phrase_start(value_pair, key_symbol); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
} \ | |
else \ | |
{ \ | |
value_start = std::get<0>(value_pair); \ | |
std::advance(std::get<0>(value_pair), 1); \ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
} \ | |
\ | |
const auto target = std::string(value_start, std::get<0>(value_pair)); | |
#define process_input(value_pair, value_start, data, tab_space) \ | |
std::advance(std::get<0>(value_pair), 1); \ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
\ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); \ | |
\ | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \ | |
{ \ | |
return false; \ | |
} \ | |
\ | |
value_start = std::get<0>(value_pair); \ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \ | |
\ | |
const auto path_separator = find_phrase_start( \ | |
std::make_pair(value_start, std::get<0>(value_pair)), "/"); \ | |
if (std::get<0>(value_pair) != path_separator) \ | |
{ \ | |
value_start = path_separator; \ | |
std::advance(value_start, 1); \ | |
} \ | |
\ | |
const auto input_name = std::string(value_start, std::get<0>(value_pair)); \ | |
const auto input = std::find_if(data.cbegin(), data.cend(), \ | |
[&input_name](const std::pair<std::string, std::string>& element) \ | |
{ \ | |
return element_name(element) == input_name; \ | |
}); \ | |
\ | |
if (data.end() == input) \ | |
{ \ | |
return false; \ | |
} | |
#define process_output(value_pair, data) \ | |
auto create_new_content = true; \ | |
const auto output_name = get_name_of_output(value_pair, create_new_content); \ | |
\ | |
if (output_name.empty()) \ | |
{ \ | |
return false; \ | |
} \ | |
\ | |
auto output = std::find_if(data.begin(), data.end(), \ | |
[&output_name](const std::pair<std::string, std::string>& element) \ | |
{ \ | |
return element_name(element) == output_name; \ | |
}); \ | |
\ | |
if (data.end() == output) \ | |
{ \ | |
output = data.begin(); \ | |
data.push_back(std::make_pair(output_name, std::string())); \ | |
std::advance(output, data.size() - 1); \ | |
} \ | |
\ | |
else if (create_new_content) \ | |
{ \ | |
std::get<1>(*output).clear(); \ | |
} | |
bool grep(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
static const auto quote = std::set<char>({ '"', '\'' }); | |
// | |
auto positions = std::set<std::string::const_iterator>( | |
{ | |
find_phrase_start(command, "-v"), | |
find_phrase_start(command, "-f"), | |
find_phrase_start(command, "-F"), | |
command.cend() | |
}); | |
positions.erase(positions.find(command.cend())); | |
if (positions.empty()) | |
{ | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
std::string::const_iterator value_start; | |
process_target(value_pair, value_start, quote, tab_space) | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return grep(std::get<1>(*input), target, false, std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
std::string str_output(std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = grep(std::get<1>(*input), target, false, str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
} | |
#endif | |
} | |
else if (1 == positions.size()) | |
{ | |
auto value_pair = std::make_pair(*positions.crbegin(), command.cend()); | |
std::string::const_iterator value_start; | |
process_target(value_pair, value_start, quote, tab_space) | |
std::advance(std::get<0>(value_pair), -1); //TODO: | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return grep(std::get<1>(*input), target, true, std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
std::string str_output(std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = grep(std::get<1>(*input), target, true, str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
} | |
#endif | |
} | |
else if (3 == positions.size()) | |
{ | |
auto value_pair = std::make_pair(*positions.crbegin(), command.cend()); | |
std::string::const_iterator value_start; | |
std::list<IEnumerableData::const_iterator> source_target; | |
for (auto i = 0; i < 2; ++i) | |
{ | |
process_input(value_pair, value_start, data, tab_space) | |
std::advance(std::get<0>(value_pair), -1); | |
source_target.push_back(input); | |
} | |
std::advance(std::get<0>(value_pair), 1); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return grep(std::get<1>(*(*source_target.cbegin())), std::get<1>(*(*source_target.crbegin())), | |
std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
const auto size = std::max(std::get<1>(*(*source_target.cbegin())).size(), | |
std::get<1>(*(*source_target.crbegin())).size()); | |
std::string str_output(size, '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = grep(std::get<1>(*(*source_target.cbegin())), | |
std::get<1>(*(*source_target.crbegin())), str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
} | |
#endif | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
write_to_cout("[Warning]: Used non supported scenario of command: '" + command + "'\n"); | |
} | |
#endif | |
return false; | |
} | |
bool egrep(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
// | |
auto value_pair = std::make_pair(find_phrase_start(command, "'"), command.cend()); | |
//TODO: use process_target, that have several variants for quote symbol | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
std::advance(std::get<0>(value_pair), 1); | |
auto value_start = std::get<0>(value_pair); | |
std::get<0>(value_pair) = find_phrase_start(value_pair, "'"); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair) || value_start == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
const auto pattern_target = std::string(value_start, std::get<0>(value_pair)); | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return egrep(std::get<1>(*input), pattern_target, std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
std::string str_output(std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = egrep(std::get<1>(*input), pattern_target, str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
#else | |
return false; | |
#endif | |
} | |
bool cat(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto key_shift = std::string(">>"); | |
static const auto key_EOT_start = std::string("<<EOT"); | |
static const auto key_EOT_finish = std::string("EOT"); | |
// | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
static const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' }); | |
if (contains(command, key_shift) && contains(command, key_EOT_start)) | |
{ | |
auto value_pair = std::make_pair(find_phrase_start(command, key_shift), command.cend()); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
std::advance(std::get<0>(value_pair), key_shift.size()); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
auto value_end = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); | |
if (std::get<1>(value_pair) == value_end) | |
{ | |
return false; | |
} | |
auto value_start = find_phrase_start(std::make_pair(std::get<0>(value_pair), value_end), "/"); | |
if (value_start != value_end) | |
{ | |
std::advance(value_start, 1); | |
std::get<0>(value_pair) = value_start; | |
} | |
if (value_start == value_end) | |
{ | |
return false; | |
} | |
const auto target_element = std::string(value_start, value_end); | |
std::get<0>(value_pair) = find_phrase_start(value_pair, key_EOT_start); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
std::advance(std::get<0>(value_pair), key_EOT_start.size()); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space_new_line, true); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
std::advance(std::get<0>(value_pair), 1); | |
const auto value_end_ = rfind_phrase_start(std::make_pair(command.crbegin(), command.crend()), | |
key_EOT_finish); | |
if (command.crend() == value_end_) | |
{ | |
return false; | |
} | |
const auto off = command.size() - 1 - static_cast<std::size_t>(std::distance(command.crbegin(), value_end_)); | |
value_end = command.cbegin(); | |
std::advance(value_end, off); | |
if (std::get<0>(value_pair) == value_end) | |
{ | |
return false; | |
} | |
const auto text = std::string(std::get<0>(value_pair), value_end); | |
const auto find_result = std::find_if(data.begin(), data.end(), | |
[&target_element](const std::pair<std::string, std::string>& element) | |
{ | |
return element_name(element) == target_element; | |
}); | |
if (data.cend() == find_result) | |
{ | |
return false; | |
} | |
std::get<1>(*find_result) += text; | |
return true; | |
} | |
else | |
{ | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
auto value_start = command.cbegin(); | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return cat(std::get<1>(*input), std::get<1>(*output)); | |
} | |
} | |
return false; | |
} | |
bool head(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
static const std::set<char> quote; | |
// | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
std::string::const_iterator value_start; | |
process_target(value_pair, value_start, quote, tab_space) | |
std::advance(std::get<0>(value_pair), -1); | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return head(std::get<1>(*input), target, std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
std::string str_output(std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = head(std::get<1>(*input), target, str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
} | |
#endif | |
return false; | |
} | |
bool tail(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
static const std::set<char> quote; | |
// | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
std::string::const_iterator value_start; | |
{ | |
process_target(value_pair, value_start, quote, tab_space) | |
} | |
process_target(value_pair, value_start, quote, tab_space) | |
std::advance(std::get<0>(value_pair), -1); | |
process_input(value_pair, value_start, data, tab_space) | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
process_output(value_pair, data) | |
return tail(std::get<1>(*input), target, std::get<1>(*output)); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
std::string str_output(std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = tail(std::get<1>(*input), target, str_output); | |
write_to_cout(str_output); | |
return was_command_be_apply; | |
} | |
#endif | |
return false; | |
} | |
bool perl(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
static const auto quote = std::string(1, '\''); | |
// | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
std::get<0>(value_pair) = find_phrase_start(value_pair, quote); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
std::advance(std::get<0>(value_pair), 1); | |
auto value_start = std::get<0>(value_pair); | |
std::get<0>(value_pair) = find_phrase_start(value_pair, quote); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
return false; | |
} | |
const auto target = std::string(value_start, std::get<0>(value_pair)); | |
std::advance(std::get<0>(value_pair), 1); | |
process_input(value_pair, value_start, data, tab_space) | |
if (!std::get<1>(*input).empty()) | |
{ | |
std::string str_output(2 * std::get<1>(*input).size(), '\0'); | |
str_output.clear(); | |
const auto was_command_be_apply = perl(std::get<1>(*input), target, str_output); | |
if (was_command_be_apply) | |
{ | |
const auto off = std::distance(data.cbegin(), input); | |
auto output = data.begin(); | |
std::advance(output, off); | |
assert(std::get<0>(*input) == std::get<0>(*output)); | |
if (std::get<0>(*input) != std::get<0>(*output)) | |
{ | |
return false; | |
} | |
std::get<1>(*output) = str_output; | |
} | |
return was_command_be_apply; | |
} | |
return false; | |
} | |
bool mv(const std::string& command, IEnumerableData& data) | |
{ | |
const auto command_components = split(command, std::set<char>({ '\t', ' ' }), true); | |
if (3 != command_components.size()) | |
{ | |
return false; | |
} | |
auto skip = true; | |
auto mv_pair = std::make_pair(std::string(), std::string()); | |
for (const auto& name : command_components) | |
{ | |
if (skip) | |
{ | |
skip = false; | |
continue; | |
} | |
auto name_components = split(name, '/', true); | |
if (name_components.empty() || name_components.back().empty()) | |
{ | |
continue; | |
} | |
if (std::get<0>(mv_pair).empty()) | |
{ | |
std::get<0>(mv_pair) = name_components.back(); | |
} | |
else | |
{ | |
std::get<1>(mv_pair) = name_components.back(); | |
break; | |
} | |
} | |
if (std::get<0>(mv_pair).empty() || std::get<1>(mv_pair).empty()) | |
{ | |
return false; | |
} | |
const auto extension_to_rename = std::find_if(data.begin(), data.end(), | |
[&mv_pair](const std::pair<std::string, std::string>& element) | |
{ | |
return std::get<0>(mv_pair) == element_name(element); | |
}); | |
if (extension_to_rename != data.cend()) | |
{ | |
const auto extension_with_exists_name = std::find_if(data.begin(), data.end(), | |
[&mv_pair](const std::pair<std::string, std::string>& element) | |
{ | |
return std::get<1>(mv_pair) == element_name(element); | |
}); | |
if (extension_with_exists_name != data.cend()) | |
{ | |
data.erase(extension_with_exists_name); | |
} | |
std::get<0>(*extension_to_rename) = std::get<1>(mv_pair); | |
return true; | |
} | |
return false; | |
} | |
bool rm(const std::string& command, IEnumerableData& data) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
// | |
const auto current_size = data.size(); | |
std::set<std::string> targets; | |
auto value_pair = std::make_pair(command.cbegin(), command.cend()); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair) && '-' != *std::get<0>(value_pair)) | |
{ | |
const auto value_start = std::get<0>(value_pair); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); | |
targets.insert(std::string(value_start, std::get<0>(value_pair))); | |
} | |
} | |
for (const auto& target : targets) | |
{ | |
auto name = get_file_name(target); | |
//TODO: in a future 'make interpreter' required full path. | |
if (1 < name.size() && '*' == name.front()) | |
{ | |
std::copy( | |
name.cbegin() + 1, | |
name.cend(), | |
name.begin()); | |
name.resize(name.size() - 1); | |
// | |
data.remove_if([&name](const std::pair<std::string, std::string>& element) | |
{ | |
return ends_with(element_name(element), name); | |
}); | |
} | |
else | |
{ | |
data.remove_if([&name](const std::pair<std::string, std::string>& element) | |
{ | |
return name == element_name(element); | |
}); | |
} | |
} | |
return current_size > data.size(); | |
} | |
std::pair<std::string, std::string> get_pipeline_names(const IEnumerableData& data, | |
const std::string& exit_pipeline_command) | |
{ | |
auto create_new_content = true; | |
auto name_size = get_name_of_output(exit_pipeline_command, create_new_content).size(); | |
for (const auto& element : data) | |
{ | |
name_size = std::max(name_size, element_name(element).size()); | |
} | |
++name_size; | |
return std::make_pair(std::string(name_size, 'i'), std::string(name_size, 'o')); | |
} | |
bool pipeline(const std::string& command, IEnumerableData& data, std::ostream& log) | |
{ | |
auto was_command_be_apply = false; | |
auto pipeline_commands = split(command, '|', true); | |
if (pipeline_commands.empty()) | |
{ | |
return was_command_be_apply; | |
} | |
const auto pipeline_names = get_pipeline_names(data, *pipeline_commands.crbegin()); | |
data.push_back(std::make_pair(std::get<0>(pipeline_names), std::string())); | |
data.push_back(std::make_pair(std::get<1>(pipeline_names), std::string())); | |
std::list<std::string> commands; | |
for (auto i = pipeline_commands.begin(); i != pipeline_commands.end(); ++i) | |
{ | |
if (i == pipeline_commands.cbegin()) | |
{ | |
if (!contains(*i, ">")) | |
{ | |
(*i) += " > " + std::get<1>(pipeline_names); | |
} | |
} | |
else if (1 == static_cast<std::size_t>(std::distance(i, pipeline_commands.end()))) | |
{ | |
auto pos = find_phrase_start(*i, ">"); | |
if (i->cend() != pos) | |
{ | |
const auto off = static_cast<std::size_t>(std::distance(i->cbegin(), pos)); | |
const auto data_size = i->size() - off; | |
const auto delta = std::get<0>(pipeline_names).size() + 2; | |
// | |
i->resize(i->size() + delta); | |
pos = i->cbegin(); | |
std::advance(pos, off); | |
// | |
std::fill(i->begin() + off + data_size, i->end(), ' '); | |
// | |
std::copy( | |
pos, | |
i->cbegin() + (i->size() - delta), | |
i->begin() + (i->size() - data_size)); | |
// | |
std::copy( | |
std::get<0>(pipeline_names).cbegin(), | |
std::get<0>(pipeline_names).cend(), | |
i->begin() + off); | |
} | |
} | |
else | |
{ | |
(*i) += " " + std::get<0>(pipeline_names); | |
(*i) += " > " + std::get<1>(pipeline_names); | |
} | |
trim(*i); | |
commands.clear(); | |
commands.push_back(*i); | |
// | |
was_command_be_apply = execute_bash_commands(commands, data, log); | |
const auto input = std::find_if(data.begin(), data.end(), | |
[&pipeline_names](const std::pair<std::string, std::string>& element) | |
{ | |
return std::get<0>(pipeline_names) == element_name(element); | |
}); | |
// | |
assert(data.end() != input); | |
if (data.end() == input) | |
{ | |
was_command_be_apply = false; | |
break; | |
} | |
const auto output = std::find_if(data.begin(), data.end(), | |
[&pipeline_names](const std::pair<std::string, std::string>& element) | |
{ | |
return std::get<1>(pipeline_names) == element_name(element); | |
}); | |
// | |
assert(data.end() != output); | |
if (data.end() == output) | |
{ | |
was_command_be_apply = false; | |
break; | |
} | |
std::get<1>(*input).clear(); | |
std::copy( | |
std::get<1>(*output).cbegin(), | |
std::get<1>(*output).cend(), | |
std::back_inserter(std::get<1>(*input))); | |
std::get<1>(*output).clear(); | |
} | |
auto current = &std::get<0>(pipeline_names); | |
for (auto i = 0; i < 2; ++i, current = &std::get<1>(pipeline_names)) | |
{ | |
const auto find_result = std::find_if(data.cbegin(), data.cend(), | |
[¤t](const std::pair<std::string, std::string>& element) | |
{ | |
return *current == element_name(element); | |
}); | |
// | |
assert(data.cend() != find_result); | |
if (data.cend() != find_result) | |
{ | |
data.erase(find_result); | |
} | |
else | |
{ | |
log << "[Error]: Pipeline unable to remove itself buffer '"; | |
log << (*current) << "' while execute command '"; | |
log << command << "'." << std::endl; | |
was_command_be_apply = false; | |
} | |
} | |
return was_command_be_apply; | |
} | |
std::list<std::string> for_operator(const std::string& command, const IEnumerableData& data) | |
{ | |
std::list<std::string> result; | |
const auto command_components = split(command, ';', true); | |
if (3 != command_components.size()) | |
{ | |
return result; | |
} | |
auto command_component = command_components.cbegin(); | |
const auto variable_environment = split((*command_component), std::set<char>({ '\t', ' ' }), true); | |
if (4 != variable_environment.size()) | |
{ | |
return result; | |
} | |
auto v = variable_environment.cbegin(); | |
std::advance(v, 1); | |
auto variable_name = (*v); | |
std::advance(v, 1); | |
if ("in" != (*v)) | |
{ | |
return result; | |
} | |
std::advance(v, 1); | |
auto name_mask = (*v); | |
auto nmc = split(name_mask, '/', true); | |
if (nmc.size() < 2) | |
{ | |
return result; | |
} | |
name_mask = (*nmc.crbegin()); | |
if (name_mask.empty() || '*' != name_mask.back()) | |
{ | |
return result; | |
} | |
name_mask.resize(name_mask.size() - 1); | |
variable_name = '$' + variable_name; | |
// | |
std::advance(command_component, 1); | |
static const auto key_do = std::string("do"); | |
auto for_command_start = find_phrase_start((*command_component), key_do); | |
if (for_command_start == command_component->cend()) | |
{ | |
return result; | |
} | |
std::advance(for_command_start, key_do.size()); | |
do | |
{ | |
std::advance(for_command_start, 1); | |
} | |
while (((*for_command_start) == ' ' || (*for_command_start) == '\t') && | |
for_command_start != command_component->cend()); | |
if (for_command_start == command_component->cend()) | |
{ | |
return result; | |
} | |
const auto for_command = std::string(for_command_start, command_component->cend()); | |
for (const auto& element : data) | |
{ | |
if (!starts_with(element_name(element), name_mask)) | |
{ | |
continue; | |
} | |
auto current_command = for_command; | |
replace(current_command, variable_name, element_name(element)); | |
result.push_back(current_command); | |
} | |
std::advance(command_component, 1); | |
auto done = (*command_component); | |
trim(done); | |
if ("done" != done) | |
{ | |
result.clear(); | |
} | |
return result; | |
} | |
bool execute_bash_commands(std::list<std::string>& bash_commands, IEnumerableData& data, std::ostream& log) | |
{ | |
auto result = true; | |
for (auto command = bash_commands.cbegin(); command != bash_commands.cend(); ++command) | |
{ | |
auto was_command_be_apply = false; | |
const auto str_command = *command; | |
if (contains(str_command, "|")) | |
{ | |
was_command_be_apply = pipeline(str_command, data, log); | |
} | |
else if (starts_with(str_command, "egrep")) | |
{ | |
was_command_be_apply = egrep(str_command, data); | |
} | |
else if (starts_with(str_command, "grep")) | |
{ | |
was_command_be_apply = grep(str_command, data); | |
} | |
else if (starts_with(str_command, "head")) | |
{ | |
was_command_be_apply = head(str_command, data); | |
} | |
else if (starts_with(str_command, "tail")) | |
{ | |
was_command_be_apply = tail(str_command, data); | |
} | |
else if (starts_with(str_command, "perl")) | |
{ | |
was_command_be_apply = perl(str_command, data); | |
} | |
else if (starts_with(str_command, "cat")) | |
{ | |
was_command_be_apply = cat(str_command, data); | |
} | |
else if (starts_with(str_command, "for")) | |
{ | |
auto commands = for_operator(str_command, data); | |
if (!commands.empty()) | |
{ | |
//TODO: add function append_commands. | |
const auto off = -1 * static_cast<long>(1 + commands.size()); | |
bash_commands.splice(command, commands); | |
command = bash_commands.erase(command); | |
std::advance(command, off); | |
was_command_be_apply = true; | |
} | |
} | |
else if (starts_with(str_command, "set")) | |
{ | |
continue; | |
} | |
else if (starts_with(str_command, "mv")) | |
{ | |
was_command_be_apply = mv(str_command, data); | |
} | |
else if (starts_with(str_command, "rm")) | |
{ | |
was_command_be_apply = rm(str_command, data); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
log << "[Warning]: Command '" << str_command << "' is unknown." << std::endl; | |
} | |
#endif | |
if (!was_command_be_apply) | |
{ | |
#ifndef NDEBUG | |
log << "[Warning]: Command '" << str_command << "' was not be applied." << std::endl; | |
#endif | |
result = was_command_be_apply; | |
} | |
} | |
return result; | |
} | |
bool execute_script(std::istream& script, IEnumerableData& data, std::ostream& log) | |
{ | |
auto bash_commands = get_bash_commands_from_stream(script); | |
return execute_bash_commands(bash_commands, data, log); | |
} | |
std::list<std::string> get_bash_commands_from_stream(std::istream& content_stream) | |
{ | |
static const auto key_EOT_start = std::string("<<EOT"); | |
static const auto key_EOT_finish = std::string("EOT"); | |
std::list<std::string> commands; | |
const std::set<char> command_should_not_start_from({ '\t', ' ', '\n', '#' }); | |
for (std::string line; std::getline(content_stream, line);) | |
{ | |
const auto command_begin = std::find_if(line.cbegin(), line.cend(), | |
[&command_should_not_start_from](const char& ch) | |
{ | |
return 0 == command_should_not_start_from.count(ch); | |
}); | |
if (line.cend() == command_begin) | |
{ | |
continue; | |
} | |
const auto comment_symbol = std::find_if(line.cbegin(), command_begin, | |
[](const char& ch) | |
{ | |
return '#' == ch; | |
}); | |
if (command_begin != comment_symbol) | |
{ | |
continue; | |
} | |
auto pos = find_phrase_start(std::make_pair(command_begin, line.cend()), key_EOT_start); | |
if (pos != line.cend()) | |
{ | |
std::advance(pos, key_EOT_start.size()); | |
std::string command(5 * line.size(), '\0'); | |
command.clear(); | |
command += std::string(command_begin, line.cend()); | |
command += '\n'; | |
while (std::getline(content_stream, line)) | |
{ | |
pos = find_phrase_start(std::make_pair(line.cbegin(), line.cend()), key_EOT_finish); | |
if (line.cend() != pos) | |
{ | |
std::advance(pos, key_EOT_finish.size()); | |
command += std::string(line.cbegin(), pos); | |
commands.push_back(command); | |
break; | |
} | |
else | |
{ | |
command += line + '\n'; | |
} | |
} | |
continue; | |
} | |
else | |
{ | |
const auto use_next_line_symbol = std::find_if(command_begin, line.cend(), [](const char& ch) | |
{ | |
return '\\' == ch; | |
}); | |
if (line.cend() != use_next_line_symbol) | |
{ | |
const auto find_result = std::find_if(use_next_line_symbol, line.cend(), [](const char& ch) | |
{ | |
return '\\' != ch && '\t' != ch && ' ' != ch; | |
}); | |
if (find_result == line.cend()) | |
{ | |
std::string command(2 * line.size(), '\0'); | |
command.clear(); | |
command += std::string(command_begin, line.cend()); | |
if (std::getline(content_stream, line)) | |
{ | |
command += '\n' + line; | |
commands.push_back(command); | |
continue; | |
} | |
} | |
} | |
} | |
commands.push_back(std::string(command_begin, line.cend())); | |
trim(commands.back()); | |
} | |
return commands; | |
} | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_bash_commands( | |
const std::string& content) | |
{ | |
static const auto key_EOT_start = std::string("<<EOT"); | |
static const auto key_EOT_finish = std::string("EOT"); | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> commands; | |
const std::set<char> command_should_not_start_from({ '\t', ' ', '\n', '#' }); | |
for (auto i = content.cbegin(); i != content.cend(); ++i) | |
{ | |
const auto command_begin = std::find_if(i, content.cend(), [&command_should_not_start_from](const char& ch) | |
{ | |
return 0 == command_should_not_start_from.count(ch); | |
}); | |
if (content.cend() == command_begin) | |
{ | |
break; | |
} | |
auto line_begin = command_begin; | |
while ((*line_begin) != '\n' && line_begin != i) | |
{ | |
line_begin--; | |
} | |
const auto comment_symbol = std::find_if(line_begin, command_begin, [](const char& ch) | |
{ | |
return '#' == ch; | |
}); | |
// | |
auto line_end = std::find_if(command_begin, content.cend(), [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
if (content.cend() == line_end) | |
{ | |
break; | |
} | |
if (command_begin != comment_symbol) | |
{ | |
i = line_end; | |
continue; | |
} | |
auto pos = find_phrase_start(std::make_pair(command_begin, line_end), key_EOT_start); | |
if (pos != line_end) | |
{ | |
std::advance(pos, key_EOT_start.size()); | |
pos = find_phrase_start(std::make_pair(pos, content.cend()), key_EOT_finish); | |
if (pos != content.cend()) | |
{ | |
std::advance(pos, key_EOT_finish.size()); | |
line_end = pos; | |
} | |
} | |
else | |
{ | |
const auto use_next_line_symbol = std::find_if(command_begin, line_end, [](const char& ch) | |
{ | |
return '\\' == ch; | |
}); | |
if (line_end != use_next_line_symbol) | |
{ | |
const auto find_result = std::find_if(use_next_line_symbol, line_end, [](const char& ch) | |
{ | |
return '\\' != ch && '\t' != ch && ' ' != ch; | |
}); | |
if (line_end == find_result) | |
{ | |
std::advance(line_end, 1); | |
line_end = std::find_if(line_end, content.cend(), [](const char& ch) | |
{ | |
return '\n' == ch; | |
}); | |
} | |
} | |
} | |
do | |
{ | |
std::advance(line_end, -1); | |
} | |
while (((*line_end) == '\n' || (*line_end) == ' ' || (*line_end) == '\t') && line_end != command_begin); | |
std::advance(line_end, 1); | |
commands.push_back(std::make_pair(command_begin, line_end)); | |
i = line_end; | |
} | |
return commands; | |
} | |
std::list<std::pair<std::string, std::string>> _get_map( | |
const std::string& content, | |
const std::string& start_phrase) | |
{ | |
static const auto pattern = std::regex("\\w+"); //TODO: std::regex("[\\w+ \\t\\*]*"); | |
std::list<std::pair<std::string, std::string>> map; | |
auto map_start = content.find(start_phrase); | |
if (std::string::npos != map_start) | |
{ | |
map_start += start_phrase.size(); | |
const auto map_end = content.find(");", map_start); | |
if (std::string::npos != map_end) | |
{ | |
const auto raw_map = split(std::make_pair(content.cbegin() + map_start, | |
content.cbegin() + map_end), '\n', true); | |
for (const auto& value : raw_map) | |
{ | |
if (contains(value, "#")) | |
{ | |
continue; | |
} | |
std::sregex_iterator pos(value.cbegin(), value.cend(), pattern); | |
std::sregex_iterator end; | |
const auto distance = std::distance(pos, end); | |
if (distance != 2) | |
{ | |
continue; | |
} | |
map.push_back(std::make_pair(std::string(), std::string())); | |
for (auto i = static_cast<char>(0); ; ++i, ++pos) | |
{ | |
if (!i) | |
{ | |
std::get<0>(map.back()) = pos->str(); | |
} | |
else | |
{ | |
std::get<1>(map.back()) = pos->str(); | |
break; | |
} | |
} | |
} | |
} | |
} | |
return map; | |
} | |
void add_pair_to_map(const std::string::const_iterator& cbegin, | |
const std::string::const_iterator& cend, | |
std::list<std::pair<std::string, std::string>>& map) | |
{ | |
static const auto pattern = std::regex("\\w+"); | |
const auto comment = find_if(cbegin, cend, [](const char& ch) | |
{ | |
return '#' == ch; | |
}); | |
if (cend != comment) | |
{ | |
auto find_result = find_if(cbegin, comment, [](const char& ch) | |
{ | |
return ' ' != ch && '\t' != ch; | |
}); | |
if (find_result == comment) | |
{ | |
return; | |
} | |
} | |
std::sregex_iterator pos(cbegin, cend, pattern); | |
std::sregex_iterator end; | |
if (2 == std::distance(pos, end)) | |
{ | |
auto pair_to_add = std::make_pair(pos->str(), std::string()); | |
std::advance(pos, 1); | |
std::get<1>(pair_to_add) = pos->str(); | |
map.push_back(pair_to_add); | |
} | |
} | |
std::list<std::pair<std::string, std::string>> _get_map(std::istream& content_stream, | |
const std::string& start_phrase) | |
{ | |
static const auto map_end_phrase = std::string(");"); | |
std::list<std::pair<std::string, std::string>> map; | |
for (std::string line; std::getline(content_stream, line);) | |
{ | |
auto map_start = line.cend(); | |
if (line.cend() != (map_start = find_phrase_start(line, start_phrase))) | |
{ | |
std::advance(map_start, start_phrase.size()); | |
auto map_end = find_phrase_start(std::make_pair(map_start, line.cend()), map_end_phrase); | |
add_pair_to_map(map_start, map_end, map); | |
for (; std::getline(content_stream, line) && | |
line.cend() == (map_end = find_phrase_start(line, map_end_phrase));) | |
{ | |
add_pair_to_map(line.cbegin(), map_end, map); | |
} | |
if (map_end != line.cend()) | |
{ | |
std::advance(map_end, map_end_phrase.size()); | |
} | |
add_pair_to_map(line.cbegin(), map_end, map); | |
break; | |
} | |
} | |
return map; | |
} | |
std::string get_variable(const std::string& content, const std::string& start_phrase) | |
{ | |
std::string result; | |
const auto variable_start = content.find(start_phrase); | |
if (std::string::npos != variable_start) | |
{ | |
const auto variable_end = content.find('\n', variable_start + start_phrase.length()); | |
if (std::string::npos != variable_start) | |
{ | |
result = content.substr(variable_start + start_phrase.size(), | |
variable_end - variable_start - start_phrase.size()); | |
remove(result, std::set<char>({ ' ', '=', ';' })); | |
} | |
} | |
return result; | |
} | |
std::string get_variable(std::istream& content_stream, const std::string& start_phrase) | |
{ | |
std::string result; | |
for (std::string line; std::getline(content_stream, line);) | |
{ | |
auto variable_start = line.cend(); | |
if (line.cend() != (variable_start = find_phrase_start(line, start_phrase))) | |
{ | |
std::advance(variable_start, start_phrase.size()); | |
result.reserve(std::distance(variable_start, line.cend())); | |
// | |
std::for_each(variable_start, line.cend(), [&result](const char& ch) | |
{ | |
if (ch != ' ' && ch != '=' && ch != ';') | |
{ | |
result += ch; | |
} | |
}); | |
// | |
break; | |
} | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _INTERPRETER_H_ | |
#define _INTERPRETER_H_ | |
#include <list> | |
#include <string> | |
#include <utility> | |
#include <istream> | |
#include <ostream> | |
using IEnumerableData = std::list<std::pair<std::string, std::string>>; | |
#define element_name(element) std::get<0>((element)) | |
std::string get_name_of_output(const | |
std::pair<std::string::const_iterator, std::string::const_iterator>& command, bool& create_new_content); | |
bool echo(const std::string& text, std::ostream& output); | |
bool echo(const std::string& text, std::string& output); | |
bool grep(std::istream& input, const std::string& target, bool should_be_contains, std::ostream& output); | |
bool grep(const std::string& input, const std::string& target, bool should_be_contains, std::string& output); | |
bool grep(std::istream& source, std::istream& target, std::ostream& output); | |
bool grep(const std::string& source, const std::string& target, std::string& output); | |
bool egrep(std::istream& input, const std::string& pattern_target, std::ostream& output); | |
bool egrep(const std::string& input, const std::string& pattern_target, std::string& output); | |
bool cat(std::istream& input, const std::string& text, std::ostream& output); | |
bool cat(const std::string& input, std::string& output); | |
bool head(std::istream& input, const std::string& command, std::ostream& output); | |
bool head(const std::string& input, const std::string& command, std::string& output); | |
bool tail(std::istream& input, const std::string& command, std::ostream& output); | |
bool tail(const std::string& input, const std::string& command, std::string& output); | |
bool perl(std::istream& input, const std::string& command, std::ostream& output); | |
bool perl(const std::string& input, const std::string& parameter, std::string& output); | |
bool perl(std::string& content, const std::string& parameter); | |
bool grep(const std::string& command, IEnumerableData& data); | |
bool egrep(const std::string& command, IEnumerableData& data); | |
bool cat(const std::string& command, IEnumerableData& data); | |
bool head(const std::string& command, IEnumerableData& data); | |
bool tail(const std::string& command, IEnumerableData& data); | |
bool perl(const std::string& command, IEnumerableData& data); | |
bool mv(const std::string& command, IEnumerableData& data); | |
bool rm(const std::string& command, IEnumerableData& data); | |
bool pipeline(const std::string& command, IEnumerableData& data, std::ostream& log); | |
std::list<std::string> for_operator(const std::string& command, const IEnumerableData& data); | |
bool execute_bash_commands(std::list<std::string>& bash_commands, IEnumerableData& data, std::ostream& log); | |
bool execute_script(std::istream& script, IEnumerableData& data, std::ostream& log); | |
std::list<std::string> get_bash_commands_from_stream(std::istream& content_stream); | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_bash_commands( | |
const std::string& content); | |
std::list<std::pair<std::string, std::string>> _get_map(const std::string& content, | |
const std::string& start_phrase); | |
std::list<std::pair<std::string, std::string>> _get_map(std::istream& content_stream, | |
const std::string& start_phrase); | |
std::string get_variable(const std::string& content, const std::string& start_phrase); | |
std::string get_variable(std::istream& content_stream, const std::string& start_phrase); | |
#define get_typemap(A) _get_map((A), "my %typemap") | |
//#define get_void_typemap(A) _get_map((A), "my %void_typemap") | |
#define get_taboo_tokens(A) _get_map((A), "my %taboo_tokens") | |
#define get_fnc_ignore_list(A) _get_map((A), "my %fnc_ignore_list") | |
#define get_reg_http(A) get_variable((A), "my $reg_http") | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "input_output.h" | |
#include "path.h" | |
#include "common.h" | |
#include "version.h" | |
#include "generator.h" | |
#include "descriptor.h" | |
#include "descriptors.h" | |
#include <list> | |
#include <string> | |
#include <cassert> | |
#include <cstdlib> | |
#include <ostream> | |
#include <utility> | |
#include <fstream> | |
#include <iostream> | |
#include <iterator> | |
#include <algorithm> | |
#define log std::cout | |
#define err_log std::cerr | |
std::list<std::pair<std::string, std::string>> read_version(const std::string& glew_path) | |
{ | |
std::list<std::pair<std::string, std::string>> result; | |
// | |
const auto version_file = combine(std::list<std::string>({ glew_path, "/config/version" })); | |
std::ifstream file_stream(version_file); | |
if (file_stream.is_open()) | |
{ | |
result = read_version(file_stream); | |
file_stream.close(); | |
} | |
else | |
{ | |
log << "[Warning]: Unable to open '" << version_file << "'." << std::endl; | |
} | |
return result; | |
} | |
int main(int argc, char** argv) | |
{ | |
if (argc < 4 || 6 < argc) | |
{ | |
std::cout << "Sample using: " << std::endl; | |
std::cout << argv[0]; | |
std::cout << "\t<path to glew> <path to glfixes> <destination>"; | |
std::cout << std::endl; | |
std::cout << argv[0]; | |
std::cout << | |
"\t<path to glew> <path to glfixes> <path to OpenGL-Registry> <path to EGL-Registry> <destination>"; | |
std::cout << std::endl; | |
// | |
return EXIT_FAILURE; | |
} | |
std::string content(1024 * 1024, '\0'); | |
const auto glew_path = combine(std::list<std::string>({ argv[1] })); | |
const auto glfixes_path = combine(std::list<std::string>({ argv[2] })); | |
// | |
std::list<std::list<extension>> extensions; | |
if (argc == 6) | |
{ | |
const auto opengl_registry_path = combine(std::list<std::string>({ argv[3] })); | |
const auto egl_registry_path = combine(std::list<std::string>({ argv[4] })); | |
// | |
extensions = create_descriptors(glew_path, | |
glfixes_path, | |
opengl_registry_path, | |
egl_registry_path, | |
content, | |
log); | |
// | |
content.clear(); | |
content += glew_path; | |
content.push_back('\n'); | |
content += glfixes_path; | |
content.push_back('\n'); | |
content += opengl_registry_path; | |
content.push_back('\n'); | |
content += egl_registry_path; | |
} | |
else if (argc == 4) | |
{ | |
extensions = create_descriptors(glew_path, glfixes_path, content, log); | |
// | |
content.clear(); | |
content += glew_path; | |
content.push_back('\n'); | |
content += glfixes_path; | |
} | |
assert(!extensions.empty()); | |
if (extensions.empty()) | |
{ | |
err_log << "[Error]: there are no extensions. Check input paths." << std::endl; | |
err_log << content << std::endl; | |
err_log << " Unable to continue any work. Exiting."; | |
err_log << std::endl; | |
// | |
return EXIT_FAILURE; | |
} | |
const auto destination = combine(std::list<std::string>({ argv[argc - 1] })); | |
const auto src = combine(std::list<std::string>({ glew_path, "/auto/src/" })); | |
// | |
const auto gl_core_spec = get_gl_core_spec(extensions); | |
const auto gl_ext_spec = get_gl_ext_spec(extensions); | |
const auto egl_core_spec = get_egl_core_spec(extensions); | |
const auto egl_ext_spec = get_egl_ext_spec(extensions); | |
const auto wgl_ext_spec = get_wgl_ext_spec(extensions); | |
const auto glx_core_spec = get_glx_core_spec(extensions); | |
const auto glx_ext_spec = get_glx_ext_spec(extensions); | |
// | |
assert(!gl_core_spec.empty()); | |
assert(!gl_ext_spec.empty()); | |
assert(!wgl_ext_spec.empty()); | |
assert(!glx_core_spec.empty()); | |
assert(!glx_ext_spec.empty()); | |
// | |
//auto count = gl_core_spec.size(); | |
//count += gl_ext_spec.size(); | |
//count += egl_core_spec.size(); | |
//count += egl_ext_spec.size(); | |
//count += wgl_ext_spec.size(); | |
//count += glx_core_spec.size(); | |
//count += glx_ext_spec.size(); | |
// | |
//assert(extensions_count == count); | |
// | |
const auto version = read_version(glew_path); | |
// | |
const auto i_dest = combine(std::list<std::string>({ destination, "/include/GL" })); | |
const auto s_dest = combine(std::list<std::string>({ destination, "/src" })); | |
//const auto d_dest = combine(std::list<std::string>({ destination, "/doc" })); | |
const auto b_dest = combine(std::list<std::string>({ destination, "/build" })); | |
if (!create_a_directory(i_dest)) | |
{ | |
log << "[Warning]: Unable to create a directory '" << i_dest << "'." << std::endl; | |
} | |
if (!create_a_directory(s_dest)) | |
{ | |
log << "[Warning]: Unable to create a directory '" << s_dest << "'." << std::endl; | |
} | |
/*if (!create_a_directory(d_dest)) | |
{ | |
log << "[Warning]: Unable to create a directory '" << d_dest << "'." << std::endl; | |
}*/ | |
if (!create_a_directory(b_dest)) | |
{ | |
log << "[Warning]: Unable to create a directory '" << b_dest << "'." << std::endl; | |
} | |
auto file_path = combine(std::list<std::string>({ i_dest, "glew.h" })); | |
content.clear(); | |
glew_h(src, extensions, version, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
file_path = combine(std::list<std::string>({ s_dest, "glew.c" })); | |
content.clear(); | |
glew_c(src, extensions, version, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
const auto ver = str_version_to_version(version); | |
if (!wgl_ext_spec.empty()) | |
{ | |
file_path = combine(std::list<std::string>({ i_dest, "wglew.h" })); | |
content.clear(); | |
wglew_h(src, wgl_ext_spec, ver, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
} | |
else | |
{ | |
err_log << "[Error]: there is no 'WGL_EXT_SPEC' at extensions list. "; | |
err_log << "Generation of file '" << file_path << "' impossible." << std::endl; | |
} | |
if (!glx_core_spec.empty() && !glx_ext_spec.empty()) | |
{ | |
file_path = combine(std::list<std::string>({ i_dest, "glxew.h" })); | |
content.clear(); | |
glxew_h(src, glx_core_spec, glx_ext_spec, ver, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
} | |
else | |
{ | |
err_log << "[Error]: there are no 'GLX_CORE_SPEC' or/and 'GLX_EXT_SPEC' at extensions list. "; | |
err_log << "Generation of file '" << file_path << "' impossible." << std::endl; | |
} | |
#ifndef NDEBUG | |
if (version_1_13_0 < ver) | |
{ | |
assert(!egl_core_spec.empty()); | |
assert(!egl_ext_spec.empty()); | |
} | |
#endif | |
if (version_1_13_0 < ver && !egl_core_spec.empty() && !egl_ext_spec.empty()) | |
{ | |
file_path = combine(std::list<std::string>({ i_dest, "eglew.h" })); | |
content.clear(); | |
eglew_h(src, egl_core_spec, egl_ext_spec, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
} | |
else if (version_1_13_0 < ver) | |
{ | |
err_log << "[Error]: there are no 'EGL_CORE_SPEC' or/and 'EGL_EXT_SPEC' at extensions list. "; | |
err_log << "Generation of file '" << file_path << "' impossible." << std::endl; | |
} | |
file_path = combine(std::list<std::string>({ s_dest, "glewinfo.c" })); | |
content.clear(); | |
glewinfo_c(src, extensions, ver, content, log); | |
if (!write_to_file(file_path, content)) | |
{ | |
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl; | |
} | |
content.clear(); | |
rc(src, b_dest, version, content, log); | |
// | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "parse_xml.h" | |
#include "common.h" | |
#include "input_output.h" | |
#include <regex> | |
#include <cassert> | |
#include <algorithm> | |
#ifndef PUGIXML | |
#include <set> | |
#include <iterator> | |
bool get_path_segment( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& path, | |
std::pair<std::string::const_iterator, std::string::const_iterator>& segment) | |
{ | |
std::get<0>(segment) = std::find_if(std::get<0>(path), std::get<1>(path), [](const char& ch) | |
{ | |
return '/' != ch; | |
}); | |
// | |
std::get<1>(segment) = std::find_if(std::get<0>(segment), std::get<1>(path), [](const char& ch) | |
{ | |
return '/' == ch; | |
}); | |
// | |
return std::get<1>(segment) != std::get<0>(segment); | |
} | |
bool go_to_comment_end_if_it_exists(std::string::const_iterator& current_position, | |
const std::string::const_iterator& end_position) | |
{ | |
static const std::string comment_start("<!--"); | |
static const std::string comment_end("-->"); | |
if (comment_start.size() < static_cast<std::size_t>(std::distance(current_position, end_position))) | |
{ | |
if (0 == std::memcmp(&(*current_position), comment_start.c_str(), comment_start.size())) | |
{ | |
std::advance(current_position, comment_start.size()); | |
current_position = find_phrase_start(std::make_pair(current_position, end_position), comment_end); | |
if (end_position != current_position) | |
{ | |
std::advance(current_position, comment_end.size()); | |
} | |
current_position = std::find_if(current_position, end_position, [](const char& ch) | |
{ | |
return '<' == ch; | |
}); | |
// | |
return go_to_comment_end_if_it_exists(current_position, end_position); | |
} | |
} | |
return end_position != current_position; | |
} | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_sub_nodes_elements( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& node) | |
{ | |
static const char declaration_start('?'); | |
static const char tag_close('/'); | |
// | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result; | |
std::size_t depth(0); | |
auto pos = std::get<0>(node); | |
while (std::get<1>(node) != (pos = std::find_if(pos, std::get<1>(node), [](const char& ch) | |
{ | |
return '<' == ch; | |
}))) | |
{ | |
if (!go_to_comment_end_if_it_exists(pos, std::get<1>(node))) | |
{ | |
return result; | |
} | |
else | |
{ | |
std::advance(pos, 1); | |
} | |
const auto tag_finish_pos = std::find_if(pos, std::get<1>(node), [](const char& ch) | |
{ | |
return '>' == ch; | |
}); | |
if (declaration_start == (*pos)) | |
{ | |
pos = tag_finish_pos; | |
continue; | |
} | |
if (tag_close == (*pos)) | |
{ | |
if (0 == depth) | |
{ | |
break; | |
} | |
--depth; | |
} | |
else | |
{ | |
if (0 == depth) | |
{ | |
result.push_back(std::make_pair(pos, tag_finish_pos)); | |
} | |
auto tag_finish_prev_pos = tag_finish_pos; | |
std::advance(tag_finish_prev_pos, -1); | |
if (tag_close != (*tag_finish_prev_pos)) | |
{ | |
++depth; | |
} | |
} | |
if (0 == depth) | |
{ | |
std::get<1>(*result.rbegin()) = tag_finish_pos; | |
} | |
pos = tag_finish_pos; | |
} | |
// | |
return result; | |
} | |
std::pair<std::string::const_iterator, std::string::const_iterator> tag_name( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& tag) | |
{ | |
static const auto tab_space_close_tag = std::set<char>({ '\t', ' ', '/', '>' }); | |
return std::make_pair( | |
std::get<0>(tag), find_any_symbol_like_or_not_like_that(tag, tab_space_close_tag, true)); | |
} | |
bool is_string_equal(const std::pair<std::string::const_iterator, std::string::const_iterator>& a, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& b) | |
{ | |
const auto length = std::distance(std::get<0>(a), std::get<1>(a)); | |
return ((0 < length) && | |
(length == std::distance(std::get<0>(b), std::get<1>(b))) && | |
(0 == std::memcmp(&(*std::get<0>(b)), &(*std::get<0>(a)), length))); | |
} | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> find_children( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& node, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& path, | |
std::size_t count) | |
{ | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result; | |
std::pair<std::string::const_iterator, std::string::const_iterator> segment; | |
if ((0 == count) || !get_path_segment(path, segment)) | |
{ | |
return result; | |
} | |
const auto sub_path = std::make_pair(std::get<1>(segment), std::get<1>(path)); | |
if (std::get<1>(sub_path) == std::get<0>(sub_path)) | |
{ | |
for (const auto& element : get_sub_nodes_elements(node)) | |
{ | |
if (count == result.size()) | |
{ | |
return result; | |
} | |
if (is_string_equal(tag_name(element), segment)) | |
{ | |
result.push_back(element); | |
} | |
} | |
} | |
else | |
{ | |
for (const auto& element : get_sub_nodes_elements(node)) | |
{ | |
if (count == result.size()) | |
{ | |
return result; | |
} | |
if (is_string_equal(tag_name(element), segment)) | |
{ | |
result.splice(result.cend(), find_children(element, sub_path, count)); | |
} | |
} | |
} | |
return result; | |
} | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_child_value( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& i) | |
{ | |
std::pair<std::string::const_iterator, std::string::const_iterator> value; | |
// | |
std::get<0>(value) = std::find_if(std::get<0>(i), std::get<1>(i), [](const char& ch) | |
{ | |
return '>' == ch; | |
}); | |
// | |
std::get<1>(value) = std::get<1>(i); | |
if (std::get<1>(i) == std::get<0>(value)) | |
{ | |
return value; | |
} | |
std::advance(std::get<0>(value), 1); | |
while (std::get<1>(value) != std::get<0>(value)) | |
{ | |
if ('<' == *std::get<1>(value)) | |
{ | |
break; | |
} | |
std::advance(std::get<1>(value), -1); | |
} | |
return value; | |
} | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> find_data( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& node, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& path, | |
std::size_t count) | |
{ | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result; | |
for (const auto& i : find_children(node, path, count)) | |
{ | |
result.push_back(get_child_value(i)); | |
} | |
return result; | |
} | |
std::pair<std::string, std::string> find_params( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& node) | |
{ | |
static const std::regex pointer_pattern("(.*)([ ]+)([*]+)"); | |
static const std::string name("name"); | |
static const std::string ptype("ptype"); | |
static const std::set<char> tag_chars({ '>', '<' }); | |
// | |
const auto n = find_data(node, std::make_pair(name.cbegin(), name.cend()), 1); | |
std::string t(std::distance(std::get<0>(node), std::get<1>(node)), '\0'); | |
t.clear(); | |
// | |
auto pos = std::find_if(std::get<0>(node), std::get<1>(node), [](const char& ch) | |
{ | |
return '>' == ch; | |
}); | |
// | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(node)), tag_chars, false); | |
for (const auto& element : get_sub_nodes_elements(node)) | |
{ | |
auto tag_position = std::get<0>(element); | |
std::advance(tag_position, -1); | |
if (0 < std::distance(pos, tag_position)) | |
{ | |
std::copy(pos, tag_position, std::back_inserter(t)); | |
} | |
if (is_string_equal(tag_name(element), std::make_pair(ptype.cbegin(), ptype.cend()))) | |
{ | |
const auto child_value = get_child_value(element); | |
std::copy(std::get<0>(child_value), std::get<1>(child_value), std::back_inserter(t));; | |
} | |
pos = find_any_symbol_like_or_not_like_that(std::make_pair(std::get<1>(element), std::get<1>(node)), | |
tag_chars, false); | |
} | |
if (t.empty()) | |
{ | |
auto child_value = get_child_value(node); | |
std::copy(pos, std::get<1>(child_value), std::back_inserter(t)); | |
} | |
trim(t); | |
std::smatch m; | |
if (std::regex_match(t, m, pointer_pattern) && 3 < m.size()) | |
{ | |
auto t_ = std::string(std::get<0>(m[1]), std::get<1>(m[1])); | |
t_ += std::string(std::get<0>(m[3]), std::get<1>(m[3])); | |
trim(t_); | |
t.clear(); | |
std::copy(t_.cbegin(), t_.cend(), std::back_inserter(t)); | |
} | |
return std::make_pair(t, (n.empty() ? "" : std::string(std::get<0>(n.front()), std::get<1>(n.front())))); | |
} | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_attributes( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input) | |
{ | |
static const auto quote = std::set<char>({ '"' }); | |
// | |
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result; | |
auto value_pair = input; | |
std::get<1>(value_pair) = std::find_if(std::get<0>(input), std::get<1>(input), | |
[](const char& ch) | |
{ | |
return '>' == ch; | |
}); | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
std::advance(std::get<0>(value_pair), 1); | |
} | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); | |
while (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
std::advance(std::get<0>(value_pair), 1); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); | |
if (std::get<1>(value_pair) == std::get<0>(value_pair)) | |
{ | |
break; | |
} | |
const auto value_start = std::get<0>(value_pair); | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, quote, true); | |
if (std::get<1>(value_pair) != std::get<0>(value_pair)) | |
{ | |
std::advance(std::get<0>(value_pair), 1); | |
} | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, quote, true); | |
// | |
result.push_back(std::make_pair(value_start, std::get<0>(value_pair))); | |
// | |
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); | |
} | |
return result; | |
} | |
std::pair<std::string::const_iterator, std::string::const_iterator> get_attribute_value( | |
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& input, | |
const std::string& name) | |
{ | |
static const auto quote = std::set<char>({ '"' }); | |
static const auto tab_space_equal = std::set<char>({ '\t', ' ', '=' }); | |
// | |
std::pair<std::string::const_iterator, std::string::const_iterator> value; | |
for (const auto& i : input) | |
{ | |
if (!starts_with(i, name)) | |
{ | |
continue; | |
} | |
const auto size = static_cast<std::size_t>(std::distance(std::get<0>(i), std::get<1>(i))); | |
if (size < name.size() + 1) | |
{ | |
continue; | |
} | |
std::get<0>(value) = std::get<0>(i); | |
std::advance(std::get<0>(value), name.size()); | |
if (0 == tab_space_equal.count(*std::get<0>(value))) | |
{ | |
continue; | |
} | |
std::get<0>(value) = find_any_symbol_like_or_not_like_that(std::make_pair(std::get<0>(value), std::get<1>(i)), | |
quote, true); | |
if (std::get<1>(i) != std::get<0>(value)) | |
{ | |
std::advance(std::get<0>(value), 1); | |
} | |
std::get<1>(value) = std::get<1>(i); | |
break; | |
} | |
return value; | |
} | |
std::list<enum_> find_enums(const std::pair<std::string::const_iterator, std::string::const_iterator>& node) | |
{ | |
static const std::string path("registry/enums/enum"); | |
static const std::string name("name"); | |
static const std::string value("value"); | |
// | |
std::list<enum_> result; | |
for (const auto& i : find_children(node, std::make_pair(path.cbegin(), path.cend()), std::string::npos)) | |
{ | |
const auto attributes = get_attributes(i); | |
const auto n = get_attribute_value(attributes, name); | |
const auto v = get_attribute_value(attributes, value); | |
result.push_back(std::make_pair(n, v)); | |
} | |
return result; | |
} | |
std::list<command> find_commands(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
node) | |
{ | |
static const std::string path("registry/commands/command"); | |
static const std::string proto("proto"); | |
static const std::string param("param"); | |
// | |
std::list<command> result; | |
const auto proto_ = std::make_pair(proto.cbegin(), proto.cend()); | |
const auto param_ = std::make_pair(param.cbegin(), param.cend()); | |
for (const auto& i : find_children(node, std::make_pair(path.cbegin(), path.cend()), std::string::npos)) | |
{ | |
const auto proto_node = find_children(i, proto_, 1); | |
if (proto_node.empty()) | |
{ | |
continue; | |
} | |
const auto r_n = find_params(proto_node.front()); | |
std::list<params> p; | |
for (const auto& j : find_children(i, param_, std::string::npos)) | |
{ | |
p.push_back(find_params(j)); | |
} | |
const auto c = std::make_pair(std::get<0>(r_n), p); | |
result.push_back(std::make_pair(std::get<1>(r_n), c)); | |
} | |
return result; | |
} | |
std::list<std::pair<range_, feature_extension>> find_features_extensions( | |
const range_& node, const range_& path) | |
{ | |
static const std::string enum_("require/enum"); | |
static const std::string command("require/command"); | |
static const std::string name("name"); | |
// | |
std::list<std::pair<range_, feature_extension>> result; | |
const auto enum__ = std::make_pair(enum_.cbegin(), enum_.cend()); | |
const auto command_ = std::make_pair(command.cbegin(), command.cend()); | |
for (const auto& i : find_children(node, path, std::string::npos)) | |
{ | |
const auto n = get_attribute_value(get_attributes(i), name); | |
std::list<range_> e; | |
std::list<range_> c; | |
for (const auto& j : find_children(i, enum__, std::string::npos)) | |
{ | |
e.push_back(get_attribute_value(get_attributes(j), name)); | |
} | |
for (const auto& j : find_children(i, command_, std::string::npos)) | |
{ | |
c.push_back(get_attribute_value(get_attributes(j), name)); | |
} | |
const auto f_e = std::make_pair(e, c); | |
result.push_back(std::make_pair(n, f_e)); | |
} | |
return result; | |
} | |
api find_api(const range_& node) | |
{ | |
static const std::string features_str("registry/feature"); | |
static const std::string extensions_str("registry/extensions/extension"); | |
// | |
const auto enums = find_enums(node); | |
const auto commands = find_commands(node); | |
const auto features = find_features_extensions(node, std::make_pair(features_str.cbegin(), | |
features_str.cend())); | |
const auto extensions = find_features_extensions(node, std::make_pair(extensions_str.cbegin(), | |
extensions_str.cend())); | |
// | |
return{ enums, commands, features, extensions }; | |
} | |
bool is_string_equal_slow_version(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
a, | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& b) | |
{ | |
//TODO: | |
const auto length = std::distance(std::get<0>(a), std::get<1>(a)); | |
if ((0 < length) && (length == std::distance(std::get<0>(b), std::get<1>(b)))) | |
{ | |
return std::string(std::get<0>(a), std::get<1>(a)) == std::string(std::get<0>(b), std::get<1>(b)); | |
} | |
return false; | |
} | |
bool is_string_equal_slow_version(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
a, const std::string& b) | |
{ | |
//TODO: | |
const auto length = std::distance(std::get<0>(a), std::get<1>(a)); | |
if ((0 < length) && (static_cast<std::size_t>(length) == b.size())) | |
{ | |
return std::string(std::get<0>(a), std::get<1>(a)) == b; | |
} | |
return false; | |
} | |
void write_extension(const range_& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::string& output) | |
{ | |
static const std::regex WGL_pattern("WGL_([A-Z0-9]+)_.*"); | |
// | |
output.clear(); | |
const std::string name_(std::get<0>(name), std::get<1>(name)); | |
output += name_; | |
output.push_back('\n'); | |
auto url = std::string("https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf"); | |
std::smatch m; | |
if (std::regex_match(name_, m, WGL_pattern) && 1 < m.size()) | |
{ | |
url.clear(); | |
url += "https://www.khronos.org/registry/OpenGL/extensions/"; | |
url += m[1]; | |
url.push_back('/'); | |
url += name_; | |
url + ".txt"; | |
} | |
output += url; | |
output.push_back('\n'); | |
if (!contains(name_, "_VERSION_")) | |
{ | |
output += name_; | |
output.push_back('\n'); | |
} | |
else | |
{ | |
output.push_back('\n'); | |
} | |
output.push_back('\n'); | |
std::list<enum_> enum_lines; | |
for (const auto& j : std::get<0>(extension)) | |
{ | |
const auto find_result = std::find_if(enums.cbegin(), enums.cend(), | |
[&j](const enum_ & e) | |
{ | |
//TODO: is_string_equal() is failed at operator* on const_iterator of string. | |
return is_string_equal_slow_version(j, std::get<0>(e)); | |
}); | |
if (enums.cend() == find_result) | |
{ | |
continue; | |
} | |
enum_lines.push_back(*find_result); | |
} | |
if (!enum_lines.empty()) | |
{ | |
enum_lines.sort([](const enum_ & a, const enum_ & b) | |
{ | |
//return std::get<1>(a) < std::get<1>(b); //TODO: direct comparing may failed for const_iterator. For more see TODO below. | |
return std::string(std::get<0>(std::get<1>(a)), std::get<1>(std::get<1>(a))) < | |
std::string(std::get<0>(std::get<1>(b)), std::get<1>(std::get<1>(b))); | |
}); | |
for (const auto& line : enum_lines) | |
{ | |
output.push_back('\t'); | |
std::copy(std::get<0>(std::get<0>(line)), std::get<1>(std::get<0>(line)), std::back_inserter(output)); | |
output.push_back(' '); | |
std::copy(std::get<0>(std::get<1>(line)), std::get<1>(std::get<1>(line)), std::back_inserter(output)); | |
output.push_back('\n'); | |
} | |
enum_lines.clear(); | |
} | |
std::list<command> commands_lines; | |
for (const auto& j : std::get<1>(extension)) | |
{ | |
const auto find_result = std::find_if(commands.cbegin(), commands.cend(), | |
[&j](const command & c) | |
{ | |
return is_string_equal_slow_version(j, std::get<0>(c)); | |
}); | |
if (commands.cend() == find_result) | |
{ | |
continue; | |
} | |
commands_lines.push_back(*find_result); | |
} | |
if (!commands_lines.empty()) | |
{ | |
commands_lines.sort([](const command & a, const command & b) | |
{ | |
return std::get<0>(a) < std::get<0>(b); | |
}); | |
for (const auto& line : commands_lines) | |
{ | |
std::list<std::string> params; | |
for (const auto& p : std::get<1>(std::get<1>(line))) | |
{ | |
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p)); | |
} | |
output.push_back('\t'); | |
output += std::get<0>(std::get<1>(line)); | |
output.push_back(' '); | |
// | |
output += std::get<0>(line); | |
output.push_back(' '); | |
output.push_back('('); | |
// | |
output += (params.empty() ? "void" : join(", ", params)); | |
output.push_back(')'); | |
output.push_back('\n'); | |
} | |
commands_lines.clear(); | |
} | |
} | |
std::list<std::pair<std::string, std::string>> parse_xml( | |
const std::string& file_path, | |
parse_xml_option option, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
std::list<std::pair<std::string, std::string>> result; | |
tmp_output.clear(); | |
if (!read_from_file(file_path, tmp_output)) | |
{ | |
log << "[Warning]: Unable to read from file '"; | |
log << file_path; | |
log << "'." << std::endl; | |
return result; | |
} | |
const auto api_ = find_api(std::make_pair(tmp_output.cbegin(), tmp_output.cend())); | |
if (api_.features.empty() && api_.extensions.empty()) | |
{ | |
log << "[Warning]: File '"; | |
log << file_path; | |
log << "' do not have information for parse_xml. Exiting." << std::endl; | |
return result; | |
} | |
log << "[Information]: Found "; | |
log << api_.enums.size() << " enums, "; | |
log << api_.commands.size() << " commands, "; | |
log << api_.features.size() << " features and "; | |
log << api_.extensions.size() << " extensions." << std::endl; | |
if (parse_xml_option::core == option || parse_xml_option::all == option) | |
{ | |
for (const auto& feature : api_.features) | |
{ | |
tmp_output.clear(); | |
write_extension(std::get<0>(feature), std::get<1>(feature), api_.enums, api_.commands, tmp_output); | |
result.push_back( | |
std::make_pair( | |
std::string(std::get<0>(std::get<0>(feature)), std::get<1>(std::get<0>(feature))), tmp_output)); | |
} | |
} | |
if (parse_xml_option::extensions == option || parse_xml_option::all == option) | |
{ | |
for (const auto& ext : api_.extensions) | |
{ | |
tmp_output.clear(); | |
write_extension(std::get<0>(ext), std::get<1>(ext), api_.enums, api_.commands, tmp_output); | |
result.push_back( | |
std::make_pair( | |
std::string(std::get<0>(std::get<0>(ext)), std::get<1>(std::get<0>(ext))), tmp_output)); | |
} | |
} | |
return result; | |
} | |
#else | |
std::list<pugi::xml_node> find_children( | |
const pugi::xml_node& node, const std::string& path, std::size_t count) | |
{ | |
std::list<pugi::xml_node> result; | |
if (0 == count) | |
{ | |
return result; | |
} | |
const auto path_size = path.find('/'); | |
for (const auto& i : node) | |
{ | |
if (pugi::xml_node_type::node_element != i.type()) | |
{ | |
continue; | |
} | |
const auto name_size = std::strlen(i.name()); | |
if (std::string::npos != path_size | |
&& (path_size == name_size) | |
&& (0 == std::memcmp(i.name(), path.c_str(), path_size))) | |
{ | |
result.splice(result.cend(), find_children(i, path.substr(path_size + 1), count)); | |
} | |
else if ((path.size() == name_size) | |
&& (0 == std::memcmp(i.name(), path.c_str(), path.size()))) | |
{ | |
result.push_back(i); | |
} | |
if (count == result.size()) | |
{ | |
break; | |
} | |
} | |
return result; | |
} | |
std::list<std::string> find_data(const pugi::xml_node& node, const std::string& path, std::size_t count) | |
{ | |
std::list<std::string> result; | |
if (0 == count) | |
{ | |
return result; | |
} | |
const auto nodes = find_children(node, path, count); | |
for (const auto& i : nodes) | |
{ | |
result.push_back(std::string(i.first_child().value())); | |
if (count == result.size()) | |
{ | |
break; | |
} | |
} | |
return result; | |
} | |
std::pair<std::string, std::string> find_params(const pugi::xml_node& node) | |
{ | |
static const std::regex pointer_pattern("(.*)([ ]+)([*]+)"); | |
static const std::string ptype("ptype"); | |
// | |
const auto n = find_data(node, "name"); | |
std::string t; | |
for (const auto& i : node) | |
{ | |
if (pugi::xml_node_type::node_pcdata == i.type()) | |
{ | |
t += i.value(); | |
} | |
else if (pugi::xml_node_type::node_element == i.type() | |
&& ptype.size() == std::strlen(i.name()) | |
&& 0 == std::memcmp(i.name(), ptype.c_str(), ptype.size())) | |
{ | |
t += i.first_child().value(); | |
} | |
} | |
trim(t); | |
std::smatch m; | |
if (std::regex_match(t, m, pointer_pattern) && 3 < m.size()) | |
{ | |
auto t_ = std::string(std::get<0>(m[1]), std::get<1>(m[1])); | |
t_ += std::string(std::get<0>(m[3]), std::get<1>(m[3])); | |
trim(t_); | |
t.clear(); | |
std::copy(t_.cbegin(), t_.cend(), std::back_inserter(t)); | |
} | |
return std::make_pair(t, (n.empty() ? "" : n.front())); | |
} | |
std::list<enum_> find_enums(const pugi::xml_node& node) | |
{ | |
static const std::string path("registry/enums/enum"); | |
// | |
std::list<std::pair<std::string, std::string>> result; | |
for (const auto& i : find_children(node, path, std::string::npos)) | |
{ | |
const auto n = std::string(i.attribute("name").value()); | |
const auto v = std::string(i.attribute("value").value()); | |
result.push_back(std::make_pair(n, v)); | |
} | |
return result; | |
} | |
std::list<command> find_commands(const pugi::xml_node& node) | |
{ | |
static const std::string path("registry/commands/command"); | |
static const std::string proto("proto"); | |
static const std::string param("param"); | |
// | |
std::list<command> result; | |
for (const auto& i : find_children(node, path, std::string::npos)) | |
{ | |
const auto proto_node = find_children(i, proto, 1); | |
if (proto_node.empty()) | |
{ | |
continue; | |
} | |
const auto r_n = find_params(proto_node.front()); | |
std::list<std::pair<std::string, std::string>> p; | |
for (const auto& j : find_children(i, param, std::string::npos)) | |
{ | |
p.push_back(find_params(j)); | |
} | |
const auto c = std::make_pair(std::get<0>(r_n), p); | |
result.push_back(std::make_pair(std::get<1>(r_n), c)); | |
} | |
return result; | |
} | |
std::list<std::pair<std::string, feature_extension>> find_features_extensions( | |
const pugi::xml_node& node, const std::string& path) | |
{ | |
static const std::string _enum("require/enum"); | |
static const std::string _command("require/command"); | |
// | |
std::list<std::pair<std::string, feature_extension>> result; | |
for (const auto& i : find_children(node, path, std::string::npos)) | |
{ | |
const auto n = std::string(i.attribute("name").value()); | |
std::list<std::string> e; | |
std::list<std::string> c; | |
for (const auto& j : find_children(i, _enum, std::string::npos)) | |
{ | |
e.push_back(std::string(j.attribute("name").value())); | |
} | |
for (const auto& j : find_children(i, _command, std::string::npos)) | |
{ | |
c.push_back(std::string(j.attribute("name").value())); | |
} | |
const auto f_e = std::make_pair(e, c); | |
result.push_back(std::make_pair(n, f_e)); | |
} | |
return result; | |
} | |
api find_api(const pugi::xml_node& node) | |
{ | |
const auto enums = find_enums(node); | |
const auto commands = find_commands(node); | |
const auto features = find_features(node); | |
const auto extensions = find_extensions(node); | |
// | |
return{ enums, commands, features, extensions }; | |
} | |
void write_extension(const std::string& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::ostream& output) | |
{ | |
output << name << std::endl; | |
output << "https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf" << std::endl; | |
if (!contains(name, "_VERSION_")) | |
{ | |
output << name << std::endl; | |
} | |
else | |
{ | |
output << std::endl; | |
} | |
output << std::endl; | |
std::list<enum_> enum_lines; | |
for (const auto& j : std::get<0>(extension)) | |
{ | |
const auto find_result = std::find_if(enums.cbegin(), enums.cend(), | |
[&j](const enum_ & e) | |
{ | |
return j == std::get<0>(e); | |
}); | |
if (enums.cend() == find_result) | |
{ | |
continue; | |
} | |
enum_lines.push_back(*find_result); | |
} | |
if (!enum_lines.empty()) | |
{ | |
enum_lines.sort([](const enum_ & a, const enum_ & b) | |
{ | |
return std::get<1>(a) < std::get<1>(b); | |
}); | |
for (const auto& line : enum_lines) | |
{ | |
output << '\t' << std::get<0>(line) << ' ' << std::get<1>(line) << std::endl; | |
} | |
enum_lines.clear(); | |
} | |
std::list<command> commands_lines; | |
for (const auto& j : std::get<1>(extension)) | |
{ | |
const auto find_result = std::find_if(commands.cbegin(), commands.cend(), | |
[&j](const command & c) | |
{ | |
return j == std::get<0>(c); | |
}); | |
if (commands.cend() == find_result) | |
{ | |
continue; | |
} | |
commands_lines.push_back(*find_result); | |
} | |
if (!commands_lines.empty()) | |
{ | |
commands_lines.sort([](const command & a, const command & b) | |
{ | |
return std::get<0>(a) < std::get<0>(b); | |
}); | |
for (const auto& line : commands_lines) | |
{ | |
std::list<std::string> params; | |
for (const auto& p : std::get<1>(std::get<1>(line))) | |
{ | |
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p)); | |
} | |
output << '\t' << std::get<0>(std::get<1>(line)); | |
output << ' ' << std::get<0>(line) << ' '; | |
output << '(' << (params.empty() ? "void" : join(", ", params)) << ')' << std::endl; | |
} | |
commands_lines.clear(); | |
} | |
} | |
void write_extension(const std::string& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::string& output) | |
{ | |
output += name; | |
output.push_back('\n'); | |
output += "https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf"; | |
output.push_back('\n'); | |
if (!contains(name, "_VERSION_")) | |
{ | |
output += name; | |
output.push_back('\n'); | |
} | |
else | |
{ | |
output.push_back('\n'); | |
} | |
output.push_back('\n'); | |
std::list<enum_> enum_lines; | |
for (const auto& j : std::get<0>(extension)) | |
{ | |
const auto find_result = std::find_if(enums.cbegin(), enums.cend(), | |
[&j](const enum_ & e) | |
{ | |
return j == std::get<0>(e); | |
}); | |
if (enums.cend() == find_result) | |
{ | |
continue; | |
} | |
enum_lines.push_back(*find_result); | |
} | |
if (!enum_lines.empty()) | |
{ | |
enum_lines.sort([](const enum_ & a, const enum_ & b) | |
{ | |
return std::get<1>(a) < std::get<1>(b); | |
}); | |
for (const auto& line : enum_lines) | |
{ | |
output.push_back('\t'); | |
output += std::get<0>(line); | |
output.push_back(' '); | |
output += std::get<1>(line); | |
output.push_back('\n'); | |
} | |
enum_lines.clear(); | |
} | |
std::list<command> commands_lines; | |
for (const auto& j : std::get<1>(extension)) | |
{ | |
const auto find_result = std::find_if(commands.cbegin(), commands.cend(), | |
[&j](const command & c) | |
{ | |
return j == std::get<0>(c); | |
}); | |
if (commands.cend() == find_result) | |
{ | |
continue; | |
} | |
commands_lines.push_back(*find_result); | |
} | |
if (!commands_lines.empty()) | |
{ | |
commands_lines.sort([](const command & a, const command & b) | |
{ | |
return std::get<0>(a) < std::get<0>(b); | |
}); | |
for (const auto& line : commands_lines) | |
{ | |
std::list<std::string> params; | |
for (const auto& p : std::get<1>(std::get<1>(line))) | |
{ | |
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p)); | |
} | |
output.push_back('\t'); | |
output += std::get<0>(std::get<1>(line)); | |
output.push_back(' '); | |
// | |
output += std::get<0>(line); | |
output.push_back(' '); | |
output.push_back('('); | |
// | |
output += (params.empty() ? "void" : join(", ", params)); | |
output.push_back(')'); | |
output.push_back('\n'); | |
} | |
commands_lines.clear(); | |
} | |
} | |
std::list<std::pair<std::string, std::string>> parse_xml( | |
const std::string& file_path, | |
parse_xml_option option, | |
std::string& tmp_output, | |
std::ostream& log) | |
{ | |
std::list<std::pair<std::string, std::string>> result; | |
pugi::xml_document doc; | |
const auto load_result = doc.load_file( | |
file_path.c_str(), pugi::parse_default | pugi::parse_ws_pcdata); | |
assert(pugi::xml_parse_status::status_ok == load_result.status); | |
if (pugi::status_ok != load_result.status) | |
{ | |
log << "[Warning]: Unable to read file '"; | |
log << file_path; | |
log << "' as xml." << std::endl; | |
return result; | |
} | |
const auto api_ = find_api(doc); | |
if (api_.features.empty() && api_.extensions.empty()) | |
{ | |
log << "[Warning]: File '"; | |
log << file_path; | |
log << "' do not have information for parse_xml. Exiting." << std::endl; | |
return result; | |
} | |
log << "[Information]: Found "; | |
log << api_.enums.size() << " enums, "; | |
log << api_.commands.size() << " commands, "; | |
log << api_.features.size() << " features and "; | |
log << api_.extensions.size() << " extensions." << std::endl; | |
if (parse_xml_option::core == option || parse_xml_option::all == option) | |
{ | |
for (const auto& feature : api_.features) | |
{ | |
tmp_output.clear(); | |
write_extension(std::get<0>(feature), std::get<1>(feature), api_.enums, api_.commands, tmp_output); | |
result.push_back(std::make_pair(std::get<0>(feature), tmp_output)); | |
} | |
} | |
if (parse_xml_option::extensions == option || parse_xml_option::all == option) | |
{ | |
for (const auto& ext : api_.extensions) | |
{ | |
tmp_output.clear(); | |
write_extension(std::get<0>(ext), std::get<1>(ext), api_.enums, api_.commands, tmp_output); | |
result.push_back(std::make_pair(std::get<0>(ext), tmp_output)); | |
} | |
} | |
return result; | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _PARSE_XML_H_ | |
#define _PARSE_XML_H_ | |
#ifdef PUGIXML | |
#include <pugixml.hpp> | |
#endif | |
#include <list> | |
#include <string> | |
#include <cstring> | |
#include <utility> | |
#include <ostream> | |
enum class parse_xml_option : char | |
{ | |
core = 1, | |
extensions, | |
all | |
}; | |
using params = std::pair<std::string, std::string>; | |
using command = std::pair<std::string, std::pair<std::string, std::list<params>>>; | |
#ifndef PUGIXML | |
using range_ = std::pair<std::string::const_iterator, std::string::const_iterator>; | |
using enum_ = std::pair<range_, range_>; | |
using feature_extension = std::pair<std::list<range_>, std::list<range_>>; | |
struct api | |
{ | |
const std::list<enum_> enums; | |
const std::list<command> commands; | |
const std::list<std::pair<range_, feature_extension>> features; | |
const std::list<std::pair<range_, feature_extension>> extensions; | |
}; | |
std::list<range_> find_children( | |
const range_& node, | |
const range_& path, | |
std::size_t count = std::string::npos); | |
std::list<range_> find_data( | |
const range_& node, | |
const range_& path, | |
std::size_t count = 1); | |
params find_params(const range_& node); | |
std::list<enum_> find_enums(const range_& node); | |
std::list<command> find_commands(const range_& node); | |
std::list<std::pair<range_, feature_extension>> find_features_extensions( | |
const range_& node, const range_& path); | |
api find_api(const range_& node); | |
void write_extension(const range_& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::string& output); | |
#else | |
using enum_ = params; | |
using feature_extension = std::pair<std::list<std::string>, std::list<std::string>>; | |
struct api | |
{ | |
const std::list<enum_> enums; | |
const std::list<command> commands; | |
const std::list<std::pair<std::string, feature_extension>> features; | |
const std::list<std::pair<std::string, feature_extension>> extensions; | |
}; | |
std::list<pugi::xml_node> find_children( | |
const pugi::xml_node& node, const std::string& path, std::size_t count = std::string::npos); | |
std::list<std::string> find_data(const pugi::xml_node& node, const std::string& path, std::size_t count = 1); | |
params find_params(const pugi::xml_node& node); | |
std::list<enum_> find_enums(const pugi::xml_node& node); | |
std::list<command> find_commands(const pugi::xml_node& node); | |
std::list<std::pair<std::string, feature_extension>> find_features_extensions( | |
const pugi::xml_node& node, const std::string& path); | |
#define find_features(A) find_features_extensions((A), "registry/feature") | |
#define find_extensions(A) find_features_extensions((A), "registry/extensions/extension") | |
api find_api(const pugi::xml_node& node); | |
void write_extension(const std::string& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::ostream& output); | |
void write_extension(const std::string& name, | |
const feature_extension& extension, | |
const std::list<enum_>& enums, | |
const std::list<command>& commands, | |
std::string& output); | |
#endif | |
std::list<std::pair<std::string, std::string>> parse_xml( | |
const std::string& file_path, | |
parse_xml_option option, | |
std::string& tmp_output, | |
std::ostream& log); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "path.h" | |
#include "common.h" | |
#include <sstream> | |
#include <utility> | |
#include <iterator> | |
#include <algorithm> | |
#ifdef _WIN32 | |
#include <windows.h> | |
#else | |
#include <ftw.h> | |
#include <dirent.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#endif | |
std::string combine(const std::list<std::string>& paths) | |
{ | |
auto path = join("/", paths); | |
#ifdef _WIN32 | |
replace(path, '\\', '/'); | |
#endif | |
replace_double_char_by_single(path, '/'); | |
#ifdef _WIN32 | |
if (!path.empty() && '/' == path.front()) | |
{ | |
if (path.size() == 1) | |
{ | |
path.clear(); | |
} | |
else | |
{ | |
auto pos = path.cbegin(); | |
std::advance(pos, 1); | |
std::copy( | |
pos, | |
path.cend(), | |
path.begin()); | |
path.resize(path.size() - 1); | |
} | |
} | |
#endif | |
return path; | |
} | |
std::string get_directory_name(const std::string& path) | |
{ | |
const auto pos = path.rfind('/'); | |
if (std::string::npos != pos) | |
{ | |
return path.substr(0, pos); | |
} | |
return path; | |
} | |
std::string get_file_name(const std::string& path) | |
{ | |
const auto pos = path.rfind('/'); | |
if (std::string::npos != pos) | |
{ | |
return path.substr(1 + pos); | |
} | |
return path; | |
} | |
std::string get_relative_path(const std::string& path, std::size_t count_of_components) | |
{ | |
const auto elements_from_paths = split(path, '/', true); | |
std::ostringstream relative_path; | |
if (0 != count_of_components && count_of_components < elements_from_paths.size()) | |
{ | |
auto component = elements_from_paths.crbegin(); | |
std::advance(component, count_of_components - 1); | |
for (; component != elements_from_paths.crbegin(); --component) | |
{ | |
relative_path << (*component) << '/'; | |
} | |
relative_path << (*component); | |
} | |
else if (0 != count_of_components) | |
{ | |
return path; | |
} | |
return relative_path.str(); | |
} | |
#ifdef _WIN32 | |
void get_files_by_pattern( | |
const std::string& file_pattern, std::list<std::string>& file_list) | |
{ | |
WIN32_FIND_DATAA file_data; | |
std::memset(&file_data, 0, sizeof(file_data)); | |
auto file_handle = FindFirstFileA(file_pattern.c_str(), &file_data); | |
if (INVALID_HANDLE_VALUE != file_handle) | |
{ | |
std::string directory_name(MAX_PATH, '\0'); | |
directory_name.clear(); | |
const auto character_position = file_pattern.rfind('/'); | |
if (std::string::npos != character_position) | |
{ | |
directory_name += file_pattern.substr(0, 1 + character_position); //TODO: made copy instead substr | |
} | |
const auto current_size = directory_name.size(); | |
do | |
{ | |
if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) | |
{ | |
directory_name += file_data.cFileName; | |
file_list.push_back(directory_name); | |
} | |
else if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && | |
std::memcmp(".", file_data.cFileName, 1) && | |
std::memcmp("..", file_data.cFileName, 2)) | |
{ | |
directory_name += file_data.cFileName; | |
directory_name += '/'; | |
if (std::string::npos != character_position) | |
{ | |
directory_name += file_pattern.substr(1 + character_position); //TODO: made copy instead substr | |
} | |
get_files_by_pattern(directory_name, file_list); | |
} | |
directory_name.resize(current_size); | |
std::memset(&file_data, 0, sizeof(file_data)); | |
} | |
while (FindNextFileA(file_handle, &file_data)); | |
FindClose(file_handle); | |
file_handle = INVALID_HANDLE_VALUE; | |
} | |
} | |
bool is_path_a_directory(const std::string& path) | |
{ | |
auto is_directory = false; | |
WIN32_FIND_DATAA file_data; | |
std::memset(&file_data, 0, sizeof(file_data)); | |
auto file_handle = FindFirstFileA(path.c_str(), &file_data); | |
if (INVALID_HANDLE_VALUE != file_handle) | |
{ | |
is_directory = (0 != (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); | |
FindClose(file_handle); | |
std::memset(&file_data, 0, sizeof(file_data)); | |
file_handle = INVALID_HANDLE_VALUE; | |
} | |
return is_directory; | |
} | |
bool create_a_directory_(const std::string& path) | |
{ | |
const auto status = CreateDirectoryA(path.c_str(), nullptr); | |
return 0 != status; | |
} | |
#else | |
static std::list<std::string> gFile_list; | |
static std::string gFile_pattern; | |
int fn(const char* fpath, const struct stat* sb, int typeflag) | |
{ | |
(void)sb; | |
const auto fpath_ = std::string(fpath); | |
if (FTW_F == typeflag && std::string::npos != fpath_.find(gFile_pattern)) | |
{ | |
gFile_list.push_back(fpath_); | |
} | |
return 0; | |
} | |
void get_files_by_pattern(const std::string& file_pattern, std::list<std::string>& file_list) | |
{ | |
gFile_list.clear(); | |
//gFile_pattern.clear(); | |
//gFile_pattern.reserve(file_pattern.size()); | |
auto character_position = file_pattern.rfind('*'); | |
if (std::string::npos != character_position) | |
{ | |
gFile_pattern = file_pattern.substr(0, character_position); | |
//std::copy(file_pattern.cbegin(), | |
// file_pattern.cbegin() + character_position, | |
// std::back_inserter(gFile_pattern)); | |
auto character_position_ = character_position; | |
character_position = file_pattern.rfind('/'); | |
if (std::string::npos != character_position) | |
{ | |
ftw(file_pattern.substr(0, character_position).c_str(), fn, 1); | |
} | |
else | |
{ | |
ftw(file_pattern.substr(0, character_position_).c_str(), fn, 1); | |
} | |
} | |
else | |
{ | |
gFile_pattern = file_pattern; | |
ftw(file_pattern.c_str(), fn, 1); | |
} | |
std::copy(gFile_list.cbegin(), gFile_list.cend(), std::back_inserter(file_list)); | |
} | |
bool is_path_a_directory(const std::string& path) | |
{ | |
auto is_directory = false; | |
DIR* dir = nullptr; | |
if (nullptr != (dir = opendir(path.c_str()))) | |
{ | |
closedir(dir); | |
dir = nullptr; | |
is_directory = true; | |
} | |
return is_directory; | |
} | |
bool create_a_directory_(const std::string& path) | |
{ | |
static const auto mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; | |
const auto status = mkdir(path.c_str(), mode); | |
return 0 == status; | |
} | |
#endif // _WIN32 | |
bool create_a_directory(const std::string& path) | |
{ | |
if (path.empty() || | |
"/" == path || | |
is_path_a_directory(path) || | |
create_a_directory_(path)) | |
{ | |
return true; | |
} | |
auto pos = path.cbegin(); | |
auto is_created = false; | |
std::string current_directory(FILENAME_MAX, '\0'); | |
while (path.cend() != (pos = find_phrase_start(std::make_pair(pos, path.cend()), "/"))) | |
{ | |
current_directory.clear(); | |
// | |
std::copy( | |
path.cbegin(), | |
pos, | |
std::back_inserter(current_directory)); | |
// | |
std::advance(pos, 1); | |
if (current_directory.empty() || is_path_a_directory(current_directory)) | |
{ | |
continue; | |
} | |
if (false == (is_created = create_a_directory_(current_directory))) | |
{ | |
break; | |
} | |
} | |
if (!is_created) | |
{ | |
return false; | |
} | |
return create_a_directory_(path); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include <list> | |
#include <string> | |
#include <cstring> | |
#ifndef _PATH_H_ | |
#define _PATH_H_ | |
std::string combine(const std::list<std::string>& paths); | |
std::string get_directory_name(const std::string& path); | |
std::string get_file_name(const std::string& path); | |
std::string get_relative_path(const std::string& path, std::size_t count_of_components); | |
void get_files_by_pattern(const std::string& file_pattern, std::list<std::string>& file_list); | |
bool is_path_a_directory(const std::string& path); | |
bool create_a_directory(const std::string& path); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "procedure.h" | |
#include "common.h" | |
#include "descriptor.h" | |
#include <set> | |
#include <cctype> | |
#include <cassert> | |
#include <iterator> | |
#include <algorithm> | |
void get_return_type_and_name( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, std::string& return_type, | |
std::string& name) | |
{ | |
static const auto tab_space = std::set<char>({ '\t', ' ' }); | |
// | |
return_type.clear(); | |
name.clear(); | |
if (std::get<0>(input) == std::get<1>(input)) | |
{ | |
return; | |
} | |
return_type.reserve(static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input)))); | |
name.reserve(static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input)))); | |
// | |
auto pos = std::get<1>(input); | |
std::set<std::string::const_iterator> positions; | |
do | |
{ | |
std::advance(pos, -1); | |
if (positions.empty()) | |
{ | |
if (0 != tab_space.count(*pos)) | |
{ | |
while (std::get<0>(input) != pos) | |
{ | |
std::advance(pos, -1); | |
if (0 == tab_space.count(*pos)) | |
{ | |
break; | |
} | |
} | |
} | |
std::advance(pos, 1); | |
positions.insert(pos); | |
} | |
else if (0 != tab_space.count(*pos)) | |
{ | |
std::advance(pos, 1); | |
positions.insert(pos); | |
break; | |
} | |
} | |
while (std::get<0>(input) != pos); | |
if (positions.size() == 2 && std::get<0>(input) != *positions.cbegin()) | |
{ | |
pos = *positions.cbegin(); | |
while ('*' == *pos && pos != *positions.crbegin()) | |
{ | |
std::advance(pos, 1); | |
} | |
name += std::string(pos, *positions.crbegin()); | |
do | |
{ | |
std::advance(pos, -1); | |
if (0 == tab_space.count(*pos)) | |
{ | |
break; | |
} | |
} | |
while (std::get<0>(input) != pos); | |
std::advance(pos, 1); | |
return_type += std::string(std::get<0>(input), pos); | |
} | |
} | |
void get_parameters( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
std::list<std::string>& parameters) | |
{ | |
auto input_ = input; | |
parameters.clear(); | |
// | |
std::get<0>(input_) = std::find_if(std::get<0>(input), std::get<1>(input), | |
[](const char& ch) | |
{ | |
return '(' == ch; | |
}); | |
if (std::get<1>(input) == std::get<0>(input_)) | |
{ | |
return; | |
} | |
std::advance(std::get<0>(input_), 1); | |
std::get<1>(input_) = std::find_if(std::get<0>(input_), std::get<1>(input), | |
[](const char& ch) | |
{ | |
return ')' == ch; | |
}); | |
// | |
parameters = split(input_, ',', false); | |
for (auto& parameter : parameters) | |
{ | |
trim(parameter); | |
} | |
} | |
_procedure disassemble_procedure(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
procedure) | |
{ | |
_procedure procedure_; | |
//TODO: See next commented code, check closed symbol - instead this contains. | |
if (contains(procedure, "typedef")) | |
{ | |
return procedure_; | |
} | |
static const std::set<char> function_should_start_from({ '(', '{' }); | |
//static const std::set<char> function_should_finish_with({ ')', '}' }); | |
std::set<std::string::const_iterator> positions; | |
for (const auto& ch : function_should_start_from) | |
{ | |
for (auto pos = std::get<0>(procedure); pos != std::get<1>(procedure); ++pos) | |
{ | |
if (ch == (*pos)) | |
{ | |
positions.insert(pos); | |
} | |
} | |
if (!positions.empty()) | |
{ | |
break; | |
} | |
} | |
if (positions.empty()) | |
{ | |
return procedure_; | |
} | |
else if (positions.size() == 1) | |
{ | |
get_return_type_and_name(std::make_pair(std::get<0>(procedure), *positions.cbegin()), procedure_.return_type, | |
procedure_.name); | |
get_parameters(std::make_pair(*positions.cbegin(), std::get<1>(procedure)), procedure_.parameters); | |
} | |
else if (3 == positions.size()) | |
{ | |
auto pos = positions.cbegin(); | |
std::advance(pos, 1); | |
// | |
get_return_type_and_name(std::make_pair(std::get<0>(procedure), *pos), procedure_.return_type, | |
procedure_.name); | |
get_parameters(std::make_pair(*pos, std::get<1>(procedure)), procedure_.parameters); | |
} | |
#ifndef NDEBUG | |
else | |
{ | |
//TODO: | |
} | |
#endif | |
return procedure_; | |
} | |
_procedure disassemble_procedure(const std::string& procedure) | |
{ | |
return disassemble_procedure(std::make_pair(procedure.cbegin(), procedure.cend())); | |
} | |
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map, | |
std::string& parameter) | |
{ | |
assert(!type_map.empty()); | |
auto next_param = false; | |
for (const auto& type_pair : type_map) | |
{ | |
auto parameter_begin = std::find_if(parameter.cbegin(), parameter.cend(), [](const char& ch) | |
{ | |
return ' ' != ch; | |
}); | |
while (parameter_begin != parameter.cend()) | |
{ | |
if (starts_with(std::make_pair(parameter_begin, parameter.cend()), std::get<0>(type_pair)) && | |
(static_cast<std::size_t>(std::distance(parameter_begin, parameter.cend())) == std::get<0>(type_pair).size() | |
|| ' ' == *(parameter_begin + std::get<0>(type_pair).size()) | |
|| '*' == *(parameter_begin + std::get<0>(type_pair).size()))) | |
{ | |
parameter = std::string(parameter.cbegin(), | |
parameter_begin) + std::get<1>(type_pair) + (¶meter[std::distance(parameter.cbegin(), | |
parameter_begin) + std::get<0>(type_pair).size()]); | |
next_param = true; | |
break; | |
} | |
parameter_begin = std::find_if(parameter_begin, parameter.cend(), [](const char& ch) | |
{ | |
return ' ' == ch; | |
}); | |
// | |
parameter_begin = std::find_if(parameter_begin, parameter.cend(), [](const char& ch) | |
{ | |
return ' ' != ch; | |
}); | |
} | |
if (next_param) | |
{ | |
break; | |
} | |
} | |
} | |
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map, | |
std::list<std::string>& parameters) | |
{ | |
for (auto& parameter : parameters) | |
{ | |
replace_parameters_type(type_map, parameter); | |
} | |
} | |
bool is_procedure_template(const std::string& procedure) | |
{ | |
const auto i = procedure.find('{'); | |
if (std::string::npos != i && 2 < procedure.size() && 1 < i && i < procedure.size() - 1 && | |
!std::isspace(procedure[i - 1]) && !std::isspace(procedure[i + 1])) | |
{ | |
const auto j = procedure.find('}', i + 1); | |
if (std::string::npos != j && j < procedure.size() - 1 && !std::isspace(procedure[j - 1]) && | |
!std::isspace(procedure[j + 1])) | |
{ | |
const auto k = procedure.find('(', j + 1); | |
if (std::string::npos != k) | |
{ | |
const auto m = procedure.find('T', k); | |
if (m < procedure.size() - 1) | |
{ | |
return true; | |
} | |
} | |
} | |
} | |
return false; | |
} | |
bool is_procedure_template(const _procedure& procedure) | |
{ | |
return is_procedure_template( | |
std::string(procedure.return_type + ' ' + procedure.name + '(' + join(", ", procedure.parameters) + ')')); | |
/*auto is_template = is_procedure_template(procedure.return_type); | |
if (is_template) | |
{ | |
return is_template; | |
} | |
return is_procedure_template(procedure.name);*/ | |
} | |
void get_type_name(char prefix, std::string& type_name) | |
{ | |
switch (prefix) | |
{ | |
case 'b': | |
case 'B': | |
type_name += "byte"; | |
break; | |
case 'd': | |
case 'D': | |
type_name += "double"; | |
break; | |
case 'f': | |
case 'F': | |
type_name += "float"; | |
break; | |
case 'i': | |
case 'I': | |
type_name += "int"; | |
break; | |
case 's': | |
case 'S': | |
type_name += "short"; | |
break; | |
default: | |
break; | |
} | |
} | |
void realize_template_procedure(std::list<std::string>& procedures) | |
{ | |
for (auto procedure = procedures.cbegin(); procedure != procedures.cend(); ++procedure) | |
{ | |
std::list<std::string> procedures_; | |
realize_template_procedure(*procedure, procedures_); | |
if (!procedures_.empty()) | |
{ | |
procedures.splice(procedure, procedures_); | |
procedure = procedures.erase(procedure); | |
std::advance(procedure, -1); | |
} | |
} | |
} | |
void realize_template_procedure(const std::string& procedure, std::list<std::string>& procedures) | |
{ | |
const auto i = procedure.find('{'); | |
if (std::string::npos != i && 2 < procedure.size() && 1 < i && i < procedure.size() - 1 && | |
!std::isspace(procedure[i - 1]) && !std::isspace(procedure[i + 1])) | |
{ | |
const auto j = procedure.find('}', i + 1); | |
if (std::string::npos != j && j < procedure.size() - 1 && !std::isspace(procedure[j - 1]) && | |
!std::isspace(procedure[j + 1])) | |
{ | |
const auto k = procedure.find('(', j + 1); | |
if (std::string::npos != k) | |
{ | |
const auto m = procedure.find('T', k); | |
if (m < procedure.size() - 1) | |
{ | |
std::string type_name(24, '\0'); | |
std::string new_procedure(128, '\0'); | |
for (auto l = i + 1; l < j; ++l) | |
{ | |
if (',' == procedure[l]) | |
{ | |
continue; | |
} | |
else if (std::isdigit((int)procedure[l])) | |
{ | |
new_procedure.clear(); | |
new_procedure += procedure.substr(0, i) + procedure[l] + procedure.substr(j + 1); | |
realize_template_procedure(new_procedure, procedures); | |
} | |
else | |
{ | |
type_name.clear(); | |
get_type_name(procedure[l], type_name); | |
if (type_name.empty() && ( | |
starts_with(procedure, l, "ub") || | |
starts_with(procedure, l, "us") || | |
starts_with(procedure, l, "ui"))) | |
{ | |
type_name += "unsigned "; | |
++l; | |
get_type_name(procedure[l], type_name); | |
} | |
else if (type_name.empty()) | |
{ | |
continue; | |
} | |
new_procedure.clear(); | |
new_procedure += procedure.substr(0, i) + procedure[l] + procedure.substr(j + 1, | |
m - 1 - j) + type_name + procedure.substr(m + 1); | |
procedures.push_back(new_procedure); | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _PROCEDURE_H_ | |
#define _PROCEDURE_H_ | |
#include <list> | |
#include <string> | |
#include <utility> | |
struct _procedure; | |
void get_return_type_and_name( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
std::string& return_type, std::string& name); | |
void get_parameters( | |
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, | |
std::list<std::string>& parameters); | |
_procedure disassemble_procedure(const std::pair<std::string::const_iterator, std::string::const_iterator>& | |
procedure); | |
_procedure disassemble_procedure(const std::string& procedure); | |
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map, | |
std::string& parameter); | |
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map, | |
std::list<std::string>& parameters); | |
bool is_procedure_template(const std::string& procedure); | |
bool is_procedure_template(const _procedure& procedure); | |
void get_type_name(char prefix, std::string& type_name); | |
void realize_template_procedure(std::list<std::string>& procedures); | |
void realize_template_procedure(const std::string& procedure, | |
std::list<std::string>& procedures); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<Project InitialTargets="download_glew_generator;glew_generator" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |
<PropertyGroup Condition="'$(Configuration)'==''"> | |
<Configuration>Release</Configuration> | |
</PropertyGroup> | |
<PropertyGroup Condition="'$(Platform)'==''"> | |
<Platform>Win32</Platform> | |
</PropertyGroup> | |
<ItemGroup Label="ProjectConfigurations"> | |
<ProjectConfiguration Include="Release|Win32"> | |
<Configuration>Release</Configuration> | |
<Platform>Win32</Platform> | |
</ProjectConfiguration> | |
<ProjectConfiguration Include="Release|x64"> | |
<Configuration>Release</Configuration> | |
<Platform>x64</Platform> | |
</ProjectConfiguration> | |
</ItemGroup> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | |
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |
<PropertyGroup Label="glew_generator_repository"> | |
<glew_generator_url Condition="'$(LOCAL_FOLDER)'==''">https://gist.github.com/421cb7df499b7515e6f5e278e4335b87.git</glew_generator_url> | |
<glew_generator_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glew_generator</glew_generator_url> | |
<glew_generator_destination>$(ProjectDir)glew_generator</glew_generator_destination> | |
<glew_generator_destination Condition="Exists('$(ProjectDir)..\..\auto')">$(ProjectDir)..\..\auto\glew_generator</glew_generator_destination> | |
<glew_generator_destination Condition="''!='$(NO_GIT)'">$(glew_generator_url)</glew_generator_destination> | |
<glew_generator_hash>...</glew_generator_hash> | |
</PropertyGroup> | |
<Target Name="download_glew_generator" Condition="''=='$(NO_GIT)'"> | |
<Message Importance="normal" Text="--------------------------------------------------------------------" /> | |
<Message Importance="normal" Text="Downloading glew_generator" /> | |
<Message Importance="normal" Text="--------------------------------------------------------------------" /> | |
<Message Importance="low" Text="git clone $(glew_generator_url) $(glew_generator_destination)" /> | |
<Exec | |
Command="git --version" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="!Exists('$(glew_generator_destination)\.git\HEAD')" | |
Command="git clone $(glew_generator_url) $(glew_generator_destination)" | |
WorkingDirectory="$(ProjectDir)" /> | |
<Exec | |
Condition="Exists('$(glew_generator_destination)\.git\HEAD')" | |
Command="git log -1 --pretty=oneline" | |
WorkingDirectory="$(glew_generator_destination)" /> | |
</Target> | |
<ItemGroup Label="ProjectsToBuild"> | |
<ProjectsToBuild Include="$(glew_generator_destination)\glew_generator.vcxproj" /> | |
</ItemGroup> | |
<Target Name="glew_generator"> | |
<Message Importance="low" Text="MSBuildToolsVersion is $(MSBuildToolsVersion)" /> | |
<Message Importance="low" Text="Platform is $(Platform)" /> | |
<Message Importance="low" Text="PlatformToolset is $(PlatformToolset)" /> | |
<Message Importance="low" Text="LOCAL_FOLDER is $(LOCAL_FOLDER)" /> | |
<Message Importance="low" Text="NO_GIT is $(NO_GIT)" /> | |
<MSBuild | |
Condition="'$(Platform)' == 'Win32' Or '$(Platform)' == 'x64'" | |
BuildInParallel="true" | |
Projects="@(ProjectsToBuild)" | |
Properties="Configuration=Release;Platform=$(Platform);PlatformToolset=$(PlatformToolset);LOCAL_FOLDER=$(LOCAL_FOLDER);NO_GIT=$(NO_GIT)" /> | |
<MSBuild | |
Condition="'$(Platform)' != 'Win32' And '$(Platform)' != 'x64'" | |
BuildInParallel="true" | |
Projects="@(ProjectsToBuild)" | |
Properties="Configuration=Release;Platform=Win32;PlatformToolset=$(PlatformToolset);LOCAL_FOLDER=$(LOCAL_FOLDER);NO_GIT=$(NO_GIT)" /> | |
</Target> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#include "version.h" | |
#include "common.h" | |
#include "interpreter.h" | |
#include <cstdlib> | |
#include <iterator> | |
#include <algorithm> | |
//TODO: in a future probably will be a part of hypothetic "make interpreter". | |
void assign_variable(const std::list<std::pair<std::string, std::string>>& variables, std::string& variable) | |
{ | |
static const auto key_phrase = std::string("$("); | |
// | |
auto pos1 = variable.cbegin(); | |
while (variable.cend() != (pos1 = find_phrase_start( | |
std::make_pair(pos1, variable.cend()), key_phrase))) | |
{ | |
std::advance(pos1, key_phrase.size()); | |
// | |
const auto pos2 = std::find_if(pos1, variable.cend(), [](const char& ch) | |
{ | |
return ')' == ch; | |
}); | |
// | |
auto key = std::string(pos1, pos2); | |
// | |
const auto early_added_pair = std::find_if(variables.cbegin(), variables.cend(), | |
[&key](const std::pair<std::string, std::string>& version_pair) | |
{ | |
return std::get<0>(version_pair) == key; | |
}); | |
if (variables.cend() == early_added_pair) | |
{ | |
break; | |
} | |
key = key_phrase + key + ')'; | |
replace(variable, key, std::get<1>(*early_added_pair)); | |
pos1 = variable.cbegin(); | |
} | |
} | |
std::list<std::pair<std::string, std::string>> read_version(std::istream& input) | |
{ | |
std::list<std::pair<std::string, std::string>> result; | |
for (std::string line; std::getline(input, line);) | |
{ | |
if (line.empty()) | |
{ | |
continue; | |
} | |
auto raw_pair = split(line, '=', true); | |
if (raw_pair.size() != 2) | |
{ | |
continue; | |
} | |
trim(raw_pair.front()); | |
trim(raw_pair.back()); | |
// | |
assign_variable(result, raw_pair.back()); | |
// | |
auto exists_pair = std::find_if(result.begin(), result.end(), | |
[&raw_pair](const std::pair<std::string, std::string>& version_pair) | |
{ | |
return std::get<0>(version_pair) == raw_pair.front(); | |
}); | |
if (result.end() != exists_pair) | |
{ | |
std::get<1>(*exists_pair) = raw_pair.back(); | |
} | |
else | |
{ | |
result.push_back(std::make_pair(raw_pair.front(), raw_pair.back())); | |
} | |
} | |
return result; | |
} | |
_version str_version_to_version(const std::list<std::pair<std::string, std::string>>& version) | |
{ | |
const auto version_info = std::find_if(version.cbegin(), version.cend(), | |
[](const std::pair<std::string, std::string> element) | |
{ | |
return ends_with(std::get<0>(element), "_VERSION"); | |
}); | |
// | |
auto ver = _version{ 0, 0, 0 }; | |
if (version.cend() != version_info && !std::get<1>(*version_info).empty()) | |
{ | |
auto str_ver = std::get<1>(*version_info).cbegin(); | |
for (auto i = 0; i < 3 && str_ver != std::get<1>(*version_info).cend(); ++i) | |
{ | |
if ('.' == (*str_ver)) | |
{ | |
--i; | |
++str_ver; | |
continue; | |
} | |
char* ch = nullptr; | |
const auto l = std::strtol(&(*str_ver), &ch, 10); | |
const auto distance = static_cast<size_t>(const_cast<const char*>(ch) - (&(*str_ver))); | |
if (0 == distance || | |
static_cast<size_t>(std::distance(str_ver, std::get<1>(*version_info).cend())) < distance) | |
{ | |
return ver; | |
} | |
std::advance(str_ver, distance); | |
switch (i) | |
{ | |
case 0: | |
ver.major = l; | |
break; | |
case 1: | |
ver.minor = l; | |
break; | |
case 2: | |
ver.micro = l; | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
return ver; | |
} | |
bool perl(std::istream& input, | |
std::list<std::string>& parameters, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log) | |
{ | |
(void)log; | |
auto was_command_be_apply = false; | |
for (auto& parameter : parameters) | |
{ | |
if (parameter.empty()) | |
{ | |
continue; | |
} | |
assign_variable(version, parameter); | |
} | |
for (std::string line; std::getline(input, line);) | |
{ | |
for (const auto& parameter : parameters) | |
{ | |
//was_command_be_apply = perl(line, parameter); | |
//TODO: one of parameter may failed, | |
//add log to this function to monitor which exactly. | |
const auto result = perl(line, parameter); | |
if (!was_command_be_apply && result) | |
{ | |
was_command_be_apply = result; | |
} | |
} | |
output += line + '\n'; | |
} | |
return was_command_be_apply; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* | |
* Copyright (c) 2016 - 2019 https://github.com/TheVice/ | |
* | |
*/ | |
#ifndef _VERSION_H_ | |
#define _VERSION_H_ | |
#include <list> | |
#include <string> | |
#include <utility> | |
#include <istream> | |
#include <ostream> | |
struct _version | |
{ | |
int major; | |
int minor; | |
int micro; | |
friend bool operator==(const _version& a, const _version& b) | |
{ | |
return (a.major == b.major && a.minor == b.minor && a.micro == b.micro); | |
} | |
friend bool operator!=(const _version& a, const _version& b) | |
{ | |
return !(operator==(a, b)); | |
} | |
friend bool operator<(const _version& a, const _version& b) | |
{ | |
if (a.major < b.major) | |
{ | |
return true; | |
} | |
else if (a.major == b.major && a.minor < b.minor) | |
{ | |
return true; | |
} | |
else if (a.major == b.major && a.minor == b.minor && a.micro < b.micro) | |
{ | |
return true; | |
} | |
return false; | |
} | |
friend bool operator>(const _version& a, const _version& b) | |
{ | |
return !(operator<(a, b)); | |
} | |
}; | |
static const _version version_1_3_0{ 1, 3, 0 }; | |
static const _version version_1_13_0{ 1, 13, 0 }; | |
static const _version version_2_2_0{ 2, 2, 0 }; | |
static const _version version_2_2_2{ 2, 2, 2 }; | |
void assign_variable(const std::list<std::pair<std::string, std::string>>& variables, std::string& variable); | |
std::list<std::pair<std::string, std::string>> read_version(std::istream& input); | |
_version str_version_to_version(const std::list<std::pair<std::string, std::string>>& version); | |
bool perl(std::istream& input, | |
std::list<std::string>& parameters, | |
const std::list<std::pair<std::string, std::string>>& version, | |
std::string& output, | |
std::ostream& log); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment